在angular框架下使用flv.js播放http-flv实时流直播视频

目录

说明

总体思路

FFmpeg

Nginx

flv.js

效果展示

总结


  • 说明

前段时间,我写了一篇在angular框架下使用videojs播放RTMP视频流的文章,虽然播放起来流畅度较好,但仍然有一个缺陷:

由于RTMP协议本身属于Adobe公司且未开源,因而必须调用Flash才能播放并得到最好的支持,即使引入了video.js以及videojs-flash两个库作为兼容并使用了HTML5中的

同时,由于Flash本身的设计缺陷,Adobe公司和各大主流浏览器对Flash的支持也在减少甚至是直接移除了Flash插件,并趋向于采用原生HTML5标准中的

因而,本着提高用户体验和便于后期维护的方针,通过查阅资料,我采用了当下比较流行的直播方案进行改造,该方案为FFmpeg-nginx-Http-flv的组合。

  • 总体思路

如下图所示:

在angular框架下使用flv.js播放http-flv实时流直播视频_第1张图片 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)  以质量为基础的VBR,取值0.01-255,约小质量越好,即qscale 4和-qscale 6,4的质量比6高 。此参数使用次数较多,实际使用时发现,qscale是种固定量化因子,设置qscale之后,前面设置的-b好像就无效了,而是自动调整了比特率。

ffmpeg进入推流状态:

在angular框架下使用flv.js播放http-flv实时流直播视频_第2张图片

 

  • 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主机的链接地址:

  1. rtmp:固定的前置格式;
  2. 127.0.0.1:IP地址,由于是测试环境,我的Nginx也部署在windows的本机,故用本地地址,这个地址根据实际情况进行修改,FFmpeg推流也通过这个IP地址以及下面的Mylive应用名称进行nginx主机寻址来推给Nginx主机;
  3. Mylive:应用名称;
  4. 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;  
        }  
    }
}

整个配置文件我们最关心的是这几个参数:

  1. rtmp -> server -> listen 1935 #rtmp监听端口,后面的flvjs需要该参数进行连接;
  2. rtmp -> server -> application Mylive #这个和上面的FFmpeg输入输出参数进行对应,后面的flvjs需要该参数进行连接;
  3. 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标签:


| |

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

参数说明:

  1. 127.0.0.1:IP地址,由于Nginx运行在本地计算机上,故采用该IP;
  2. 8080:端口,该端口和Nginx主机中的http -> server -> listen端口一致;
  3. live?:固定直播格式;
  4. port=1935:端口,该端口和Nginx中的rtmp -> server -> listen端口一致;
  5. app=Mylive:该参数名称和Nginx中的rtmp -> server -> application一致;
  6. stream=text:流名称,该参数和FFmpeg推流中的test名称一致。

上述参数除第3个外均可根据实际情况进行修改,但注意和FFmpeg、Nginx主机的对应。如果搭建完成无法显示图像,请首先检查参数是否正确和一一对应。

  • 效果展示

效果如下图所示:

在angular框架下使用flv.js播放http-flv实时流直播视频_第3张图片

在windows环境下运行Nginx,延迟在3~4秒左右,并注意到有丢包的现象,这个可以通过后期参数进行优化;如果是在linux环境下运行Nginx,延迟会压缩到1~2秒。该延时也和nginx-http-flv-module官方介绍的延时一致。

  • 总结

本文介绍了FFmpeg-nginx-Http-flv的组合实现直播的方案,并将几个“独立的轮子”组装在了一起,让大家对这种比较主流的直播方案有一个比较直观的认识,方便以后的定制和优化。

完整资源地址

希望这篇文章对你有所帮助。也感谢这几位造这几个“轮子”的大神。同时也欢迎大家给我指正文中不正确的地方,谢谢。

 

你可能感兴趣的:(Angular,Live)