flv.js
目录
说明
总体思路
FFmpeg
Nginx
效果展示
总结
-
说明
前段时间,我写了一篇在angular框架下使用videojs播放RTMP视频流的文章,虽然播放起来流畅度较好,但仍然有一个缺陷:
由于RTMP协议本身属于Adobe公司且未开源,因而必须调用Flash才能播放并得到最好的支持,即使引入了video.js以及videojs-flash两个库作为兼容并使用了HTML5中的<video>标签,但实质仍然使用的是Flash播放器。在合并入项目过程当中带来了一个问题,即angular框架属于单页应用程序(SPA),在浏览器端有很多微服务且大幅减少了网页刷新(用户按下F5)的频率,所有的内容基本都在一个网页当中进行展示,实际项目中由于使用了angular的RouterLink功能切换页面,当有视频播放且从有Flash播放器的组件(component)页切换到其他组件页后,再切回Flash的组件页,会出现flash加载失败的情况,必须进行网页刷新(F5)才能正常重新加载Flash插件,这极大地降低了用户体验。我也没有找到其他的解决方案。
同时,由于Flash本身的设计缺陷,Adobe公司和各大主流浏览器对Flash的支持也在减少甚至是直接移除了Flash插件,并趋向于采用原生HTML5标准中的<video>标签进行替换来进行音视频的播放。
因而,本着提高用户体验和便于后期维护的方针,通过查阅资料,我采用了当下比较流行的直播方案进行改造,该方案为FFmpeg-nginx-Http-flv的组合。
-
总体思路
如下图所示:
具体为由FFmpeg拉取海康相机的RTSP流,通过转换推出RTMP流,接着nginx主机模块拉取这个RTMP流,通过转换推出Http-flv流给浏览器中的flv.js包进行拉取播放。
下面我对这个方案的各个部分进行逐一的描述:
-
FFmpeg
FFmpeg拉取海康相机的RTSP流,只需要遵循海康相机的RTSP流拉取规范,即对于FFmpeg来说需要输入输出参数,一条完整的FFmpeg输入输出参数如下所示:
ffmpeg -i rtsp://admin:[email protected]:554/h264/ch1/main/av_stream -vcodec copy -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -s 1280x720 -q 10 -f flv rtmp://127.0.0.1/Mylive/test
调出控制台,转到ffmpeg.exe程序所在的文件夹,输入或贴入上述参数即可,admin改为海康相机的登陆账号,密码改为海康相机的登陆密码。
对参数命令的部分解释,其他参数设置可以参考FFmpeg官方参数说明:
参数 |
解释 |
-i filename |
输入文件 |
-f fmt |
强制采用格式fmt |
-vcodec (codec) (copy) |
-vcodec codec 强制使用codec格式编解码方式,如-vcodec xvid 使用xvid压缩 如果用copy表示原始编解码数据必须被拷贝。 |
-acodec (codec) (copy) |
使用codec编解码 如:-acodec AAC 使用AAC音频编码 |
-ar rate int |
设置音频采样率(单位:Hz),PSP只认24000 |
-strict strictness int |
遵循的严格标准等级(from INT_MIN to INT_MAX) |
-ac channels int |
设置声道数,1就是单声道,2就是立体声,转换单声道的TVrip可以用1(节省一半容量),高品质的DVDrip就可以用2 |
-s size 1280x720 |
制定分辨率 |
-qscale int |
使用固定的视频量化标度(VBR) 以<q>质量为基础的VBR,取值0.01-255,约小质量越好,即qscale 4和-qscale 6,4的质量比6高 。此参数使用次数较多,实际使用时发现,qscale是种固定量化因子,设置qscale之后,前面设置的-b好像就无效了,而是自动调整了比特率。 |
ffmpeg进入推流状态:
-
Nginx
Nginx我使用的是未央千城大神的模块方案——基于nginx-rtmp-module模块实现的HTTP-FLV直播模块nginx-http-flv-module,相较于已有的nginx-rtmp-module方案,其具有不少优势,具体可以参阅他的博文,这里是github地址。
在上面的FFmpeg环节已经对完整的FFmpeg输入输出参数进行了一个简单的介绍。我们再来看看这条参数,红色部分我未在上面作说明:
ffmpeg -i rtsp://admin:[email protected]:554/h264/ch1/main/av_stream -vcodec copy -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -s 1280x720 -q 10 -f flv rtmp://127.0.0.1/Mylive/test
这部分是推给nginx主机的链接地址:
- rtmp:固定的前置格式;
- 127.0.0.1:IP地址,由于是测试环境,我的Nginx也部署在windows的本机,故用本地地址,这个地址根据实际情况进行修改,FFmpeg推流也通过这个IP地址以及下面的Mylive应用名称进行nginx主机寻址来推给Nginx主机;
- Mylive:应用名称;
- test:流名称。
对应Nginx主机配置文件的几个部分,用记事本打开nginx.conf进行文件:
worker_processes 4;
ERROR_log logs/error.log error;
events {
worker_connections 1024;
}
rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /tmp;
rtmp {
out_queue 4096;
out_cork 8;
max_streams 128;
timeout 10s;
server {
listen 1935;
#chunk_size 4096;
APPlication Mylive {
live on;
gop_cache on;
}
application hls {
live on;
allow publish all;
allow play all;
hls on;
hls_path temp/hls;
hls_fragment 8s;
}
}
}
http {
server {
listen 8080;
location / {
root html;
}
location /live {
flv_live on;
chunked_transfer_encoding on; #支持'Transfer-Encoding: chunked'方式回复
add_header 'Access-Control-Allow-Origin' '*'; #添加额外的HTTP头
add_header 'Access-Control-Allow-Credentials' 'true';
}
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root html;
}
location /hls {
#server hls fragments
types{
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias temp/hls;
expires -1;
}
}
}
整个配置文件我们最关心的是这几个参数:
- rtmp -> server -> listen 1935 #rtmp监听端口,后面的flvjs需要该参数进行连接;
- rtmp -> server -> application Mylive #这个和上面的FFmpeg输入输出参数进行对应,后面的flvjs需要该参数进行连接;
- http -> server -> listen 8080 #http监听端口,后面的flvjs需要该参数进行连接。
其他参数可以根据官方文档自行调整。
-
flv.js
完成了前面FFmpeg和Nginx主机的搭建,我们就可以进行前端的呈现了,这里我选择的是由bilibili开源的flv.js库:Github地址。
建立一个angular项目,在项目中引入flv.js库:
npm install --save flv.js
在组件component中:
Html中加入video标签:
<p style=" width: 1280px; height: 720px">
<video #videoelement id="videoElement" controls="controls" x5-video-player-fullscreen="true" x5-video-orientation="landscape" width="1280" height="720">Your browser is too old to support HTML5 video.</video>
</p>
<br/>
<p class="controls">
<button (click)="start()">开始</button> |
<button (click)="pause()">暂停</button> |
<button (click)="stop()">停止</button>
</p>
Typescript中引入flvjs对象并使用,值得注意的是flv.js已经对Typescript进行了适配,故直接引入即可:
import * as flvjs from 'flv.js';
title = 'app';
player: any;
flvPlayer: any;
ngOnInit(): void {
// 获取DOM对象
this.player = document.getelementbyid('videoElement');
if (flvjs.default.isSupported()) {
// 创建flvjs对象
this.flvPlayer = flvjs.default.createPlayer({
type: 'flv', // 指定视频类型
isLive: true, // 开启直播
hasAudio: false, // 关闭声音
cors: true, // 开启跨域访问
url: 'http://127.0.0.1:8080/live?port=1935&app=Mylive&stream=test', // 指定流链接
});
// 将flvjs对象和DOM对象绑定
this.flvPlayer.attachMediaElement(this.player);
// 加载视频
this.flvPlayer.load();
// 播放视频
this.flvPlayer.play();
}
console.log(flvjs.default.getFeatureList());
}
start(): void {
this.flvPlayer.play();
}
pause(): void {
this.flvPlayer.pause();
}
stop(): void {
this.flvPlayer.pause();
this.flvPlayer.unload();
// 卸载DOM对象
this.flvPlayer.detachMediaElement();
// 销毁flvjs对象
this.flvPlayer.destroy();
}
这里要特别说明的是在创建flvjs对象时的url连接,为了能够顺利播放视频,因此链接必须正确,这里对链接中的参数进行说明:
完整链接:http://127.0.0.1:8080/live?port=1935&app=Mylive&stream=test
参数说明:
- 127.0.0.1:IP地址,由于Nginx运行在本地计算机上,故采用该IP;
- 8080:端口,该端口和Nginx主机中的http -> server -> listen端口一致;
- live?:固定直播格式;
- port=1935:端口,该端口和Nginx中的rtmp -> server -> listen端口一致;
- app=Mylive:该参数名称和Nginx中的rtmp -> server -> application一致;
- stream=text:流名称,该参数和FFmpeg推流中的test名称一致。
上述参数除第3个外均可根据实际情况进行修改,但注意和FFmpeg、Nginx主机的对应。如果搭建完成无法显示图像,请首先检查参数是否正确和一一对应。
-
效果展示
效果如下图所示:
在windows环境下运行Nginx,延迟在3~4秒左右,并注意到有丢包的现象,这个可以通过后期参数进行优化;如果是在linux环境下运行Nginx,延迟会压缩到1~2秒。该延时也和nginx-http-flv-module官方介绍的延时一致。
-
总结
本文介绍了FFmpeg-nginx-Http-flv的组合实现直播的方案,并将几个“独立的轮子”组装在了一起,让大家对这种比较主流的直播方案有一个比较直观的认识,方便以后的定制和优化。
完整资源地址
希望这篇文章对你有所帮助。也感谢这几位造这几个“轮子”的大神。同时也欢迎大家给我指正文中不正确的地方,谢谢。
文章最后发布于: 2018-11-30 13:42:00
相关阅读
商机无限,出于同样的原因,一个淘宝,淘宝就无法从宣传销售淘宝客户的分开是因为不解体的互联网时代的产品。如果你想做淘宝,淘宝的客户
首先 jstorm得概念请参考官网:点击打开链接,官网实例:点击打开链接 运行Jstorm可分为本地调试和分布式环境 1.先说分布式环境,首先搭
1,报错,<token 类似的错误。 这个是数据返回时的报错。 修改: uploadHttpData: function( r, type ) { var data = !type;
一、流媒体协议实时传输协议(Real-time Transport Protocol,PRT)是在Internet上处理多媒体数据流的一种网络协议,利用它能够在一对一(u
1.1 什么是Jetty Jetty是一个提供HHTP服务器、HTTP客户端和javax.servlet容器的开源项目。这个入门教程分为五个部分: 第一部分部