以下是客户端拉流播放视频的三种媒流体协议,我这边选取的是HTTP-FLV,RTMP需要借住Flash插件,不建议使用。
1.HLS
HLS 全称是 HTTP Live Streaming。这是 Apple 提出的直播流协议,是通过视频流切片成文件片段来直播的。目前,IOS 和 高版本 Android 都支持 HLS。HLS 主要的两块内容是 .m3u8 文件和 .ts 播放文件。其中 .m3u8 作为索引文件(确保包的顺序)。接受服务器会将接受到的视频流进行缓存,然后缓存到一定程度后,会将这些视频流进行编码格式化,同时会生成一份 .m3u8 文件和其它很多的 .ts 文件。客户端首先会请求一个m3u8文件,里面会有不同码率的流,或者直接是ts文件列表,通过给出的ts文件地址去依次播放。在直播的时候,客户端会不断请求m3u8文件,检查ts列表是否有新的ts切片。这种方式的实时性较差,不过优势是H5、IOS、Android都原生支持。
2.RTMP
全称 Real Time Messaging Protocol,即实时消息传送协议。纯 RTMP 使用 TCP 连接,默认端口为 1935,是 Adobe Systems 公司为 Flash 播放器和服务器之间音频、视频和数据传输开发的开放协议。协议基于 TCP,是一个协议族,包括 RTMP 基本协议及 RTMPT/RTMPS/RTMPE 等多种变种。RTMP 由于借由 TCP 长连接协议,所以,客户端向服务端推流这些操作而言,延时性很低。它会将上传的流分成不同的分片,这些分片的大小,有时候变,有时候不会变。默认情况下就是,64B 的音频数据 + 128B 的视频数据 + 其它数据(比如 头,协议标签等)。但 RTMP 具体传输的时候,会将分片进一步划分为包,即,视频包,音频包,协议包等。因为,RTMP 在进行传输的时候,会建立不同的通道,来进行数据的传输,这样对于不同的资源,对不同的通道设置相关的带宽上限。RTMP 是一种设计用来进行实时数据通信的网络协议,主要用来在 Flash/AIR 平台和支持 RTMP 协议的流媒体/交互服务器之间进行音视频和数据通信。这种方式的实时性比较强,基本能保证延迟在 1-2s 内,是现在国内直播主要采用的方式之一。不过使用这种协议,就必须安装 flash,而 H5、IOS、Android 并不能原生支持 flash,因此这种协议能流行多久,就不得而知了。
3.HTTP-FLV
HTTP-FLV 就是对 RTMP 协议的封装,都是针对于 FLV 视频格式做的直播分发流。相比于 RTMP,它是一个开放的协议,因此他具备了 RTMP 的实时性和 RTMP 不具备的开发性。而且随着 flv.js 的出现,使得浏览器在不依赖 flash 的情况下,播放 flv 视频,从而兼容了移动端,所以现在很多直播平台,尤其是手机直播平台,都会选择它。因为 RTMP 发的包很容易处理,通常 RTMP 协议会作为视频上传端来处理,然后经由服务器转换为 FLV 文件,通过 HTTP-FLV 下发给用户。
SRS 是一个简单高效的实时视频服务器,支持RTMP/WebRTC/HLS/HTTP-FLV/SRT协议
需要的小伙伴可以从百度网盘中下载,里面包含了SRS包,Ffmpeg包,以及Ffmpeg所需要用到的类库包
链接:https://pan.baidu.com/s/1vftY_dzu4IQ2eY-Yuw4sJw?pwd=uqlg
提取码:uqlg
注:以配置文件方式启动的话,启动, 查看状态,停止,重启,查看日志都必须要到trunk目录下
#解压srs压缩包
unzip srs-4.0release.zip
#进入srs文件夹中的trunk目录下
cd srs-4.0release/trunk
#使用配置文件srs.conf启动
./objs/srs -c conf/srs.conf
# 查看SRS的状态
./etc/init.d/srs status
#停止SRS
./etc/init.d/srs stop
#重启SRS
./etc/init.d/srs restart
# 或者看SRS的日志
tail -n 30 -f ./objs/srs.log
打开浏览器可以访问,有个控制台页面
http://192.168.13.170:8080/
SRS默认端口为8080 也可以在turnk目录下的conf目录下修改默认端口
修改完成之后重启SRS
#重启SRS
./etc/init.d/srs restart
进入SRS控制台
2.编译安装FFmpeg
FFmpeg是一套由c语言编写的,可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序,自身采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案,包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。
#需要在有互联网的机器上下载FFmpeg和对应的依赖库包。您可以在这个网站上下载
https://pkgs.org/download/ffmpeg。下载的文件包括FFmpeg源代码(ffmpeg-5.5.)、zlib-devel12.7-18.el7.x86_64.rpm)、freetype(freetype-devel-2.8-14.el7.x86_64.rpm)、x264(x264-devel-0.148-1.el7_4.1.x86_64.rpm)、x265(x265-devel-2.6-1.el7.x86_64.rpm)和opus(opus-devel-1.3-0.el7.x86_64.rpm)。通过USB、CD或其他传输介质将这些文件复制到没有互联网的CentOS 7系统上。
#下载的包复制到CentOS 7系统上,然后使用以下命令安装它们
yum local-.2.7-18.el7.x86_64.rpm freetype-devel-2.8-14.el7.x86_64.rpm x264-devel-0.148-1.el7_4.1.x86_64.rpm x265-devel-2.6-1.el7.x86_64.rpm opus-devel-1.3-0.el7.x86_64.rpm。
#解压下载的FFmpeg源代码包
tar -xf ffmpeg-5.5.1.tar.bz2。
#进入解压后的FFmpeg源代码目录
cd ffmpeg-5.5.1。
#配置编译参数:
./configure --prefix=/usr/local/ffmpeg --enable-shared --enable-gpl --enable-libx264 --enable-libx265 --enable-libmp3lame --enable-libopus --enable-libfreetype。
#运行make命令编译FFmpeg
make
#运行make install命令安装FFmpeg
make install。
#配置动态链接库
"/usr/local/ffmpeg/lib" >> /etc/ld.so.conf.d/ffmpeg.conf && ldconfig
#查看版本是否安装成功
ffmpeg -version
3.Linux上Java使用ffmpeg推流
{
/** ffmpeg 命令详解
* ffmpeg [[options][`-i’ input_file]] {[options] output_file}
* options:
* -i: url 输入文件网址
* -vcodec: 设置视频编解码器 -codec:v -c:v
* (强制使用codec编解码方式,如-vcodec xvid 使用xvid压缩 如果用copy表示原始编解码数据必须被拷贝)
* -acodec: 设置音频编解码器 -codec:a -c:a
* -f: fmt 强制输入或输出文件格式
*/
}
#推流代码
@Async("asyncTaskExecutor")
public void plugFlow(String rtspUrl,String myStream) {
BufferedReader br = null;
try {
String basePath = "/usr/local/ffmpeg/bin/";
String command = basePath + "ffmpeg -re " +
"-rtsp_transport tcp " +
"-i " + rtspUrl +" "+
"-c:v copy -c:a copy -f flv " +
"rtmp://127.0.0.1/live/"+myStream;
log.info("【command】:{}",command);
log.info("rtmp://127.0.0.1/live/"+myStream);
Process process = Runtime.getRuntime().exec(command);
br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while ((line = br.readLine()) != null) {
log.info("视频推流信息{}", line);
}
} catch (Exception e) {
log.error("ffmpeg推流失败:",e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
log.error("RequestUtil,IOException:",e);
}
}
}
}
#拉流代码
@SneakyThrows
public String getPlayBackUrl(String rtspUrl) {
String myStream = IdUtil.simpleUUID();
asynchronization.plugFlow(rtspUrl,myStream);
return "http://127.0.0.1:8080/live/" + myStream + ".flv";
}