概述

这几天一直在搭建一个web端的直播平台,需求是无插件,低延迟,开源免费。

但是网上的教程,大多比较零散,没有整合成一套解决方案。

所以搜索了很多资料,也问了不少群里的大佬。本篇博客是一个资源整合贴,也是一个避坑贴。

最终选定的解决方案:ffmpeg推流——>nginx-http-flv-module流服务器——>flv.js前端播放器

直播流协议:http-flv。优势:延迟低,无插件播放。

方案优势:所有组件均为开源免费。ffmpeg成熟、资料多。nginx-http-flv-module流服务器作者仍在维护,功能强大。flv.js是b站的开源播放器,GitHub有1W多star,可以无插件播放http-flv直播流。

下面分别讲解。

nginx-http-flv-module流服务器搭建

我的服务器环境是 Ubuntu 16.04.3 LTS + nginx-1.1.17 + nginx-http-flv-module最新版。具体配置方法如下:

centos7下,nginx-1.1.17不适用,出现各种异常,最后换为nginx-1.8.1.tar.gz解决问题。浪费大量时间!

1.nginx和nginx-http-flv-module的编译安装

下载NGINX和nginx-http-flv-module。

将它们解压到某一路径。

打开NGINX的源代码路径并执行:

将模块编译进NGINX

./configure --add-module=/path/to/nginx-http-flv-module
make
make install

来自nginx-http-flv-module的官方GitHub

作者大da一笔带过的事,可花费我了很长时间尝试。

总结:

  • /path/to应该修改成你的nginx-http-flv-module文件夹的位置。
  • nginx和nginx-http-flv-module源码下载命令
wget http://nginx.org/download/nginx-1.1.17.tar.gz

git clone git://github.com/winshining/nginx-http-flv-module.git
  • 解压后的两个文件夹应在同一目录下。

2.修改nginx的配置文件

  • 打开配置文件
vim /usr/local/nginx/conf/nginx.conf #打开配置文件

...

http {
    include       mime.types;
    default_type  application/octet-stream;

    keepalive_timeout  65;

    server {
        listen       80; #http-flv的拉流端口

        ...
        
        # http-flv的相关配置
        location /live {
            flv_live on; #打开HTTP播放FLV直播流功能
            chunked_transfer_encoding on; #支持'Transfer-Encoding: chunked'方式回复

            add_header 'Access-Control-Allow-Origin' '*'; #添加额外的HTTP头
            add_header 'Access-Control-Allow-Credentials' 'true'; #添加额外的HTTP头
        }

        ...
    }
}

rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /tmp;

rtmp {
    out_queue           4096;
    out_cork            8;
    max_streams         128;
    timeout             15s;
    drop_idle_publisher 15s;

    log_interval 5s; #log模块在access.log中记录日志的间隔时间,对调试非常有用
    log_size     1m; #log模块用来记录日志的缓冲区大小

    server {
        listen 1935;
        server_name www.test.*; #用于虚拟主机名后缀通配

        #ffmpeg推流的application 
        application myapp {
            live on;
            gop_cache on; #打开GOP缓存,减少首屏等待时间
        }

       ...
    }

   ...
}
  • 注意gop_cache这个参数,on时延迟高,但第一帧画面加载快。off时正好相反,延迟低,第一帧加载略慢。
  • 还有很多参数我还不懂怎么调
  • 配置完成!

ffmpeg推流设置

ffmpeg -f dshow -i video="Integrated Webcam" -g 25 -vcodec libx264  -preset:v ultrafast -tune:v zerolatency -f flv rtmp://127.0.0.1:1935/myapp/mystream

-g 25:每隔25帧,插入一个关键帧,可提高缓冲速度。而且延迟不会明显增加。

  • url根据nginx配置文件的不同,而改变。
    rtmp://example.com[:port]/appname/streamname

flv.js的配置

<script src="https://cdn.bootcss.com/flv.js/1.5.0/flv.js"></script>
var flvPlayer = flvjs.createPlayer({
                type: 'flv',
                enableWorker: true,     //浏览器端开启flv.js的worker,多进程运行flv.js
                isLive: true,           //直播模式
                hasAudio: false,        //关闭音频             
                hasVideo: true,
                stashInitialSize: 128,  
                enableStashBuffer: false, //播放flv时,设置是否启用播放缓存,只在直播起作用。
                url: ''
            });
  • 各参数详细含义可百度。。
  • url由nginx配置文件决定,格式
    http://example.com:8080/live?port=1935&app=myapp&stream=mystream

    至此,整个解决方案已完成搭建。可以根据实际使用情况调整各参数。

效果图:

================================================================================================

++flv.js播放器累计时延的尝试消除

问题:使用中发现,如果最小化播放器的页面,或者进行浏览器页面切换,会增加播放器时延。正如以下资料中描述的“切换前后台带来的累积延时”。转自:http://www.samirchen.com/live-delay-optimization/

优化切换前后台带来的累积延时

在直播场景中,有一种情况是切换前后台造成累积延时。这里举个例子:在前台时,直播视频在播放,然后退到后台,此时暂停播放器,音视频数据继续缓存,当回到前台时,继续从刚才退出时的视频流数据开始播放,而实际的直播现在已经不在这个时间点了。这段前后台切换的时间里,就积累了一段延时。

对于这种延时改怎么处理呢?

  • 第一种方案是播放器采用视频同步音频的策略,然后退到后台时保持音频继续播放(在 iOS 平台需要开启 App 的 Background Audio 能力来配合)。这样可以保持音频一直播放不产生延时,而当回到前台时,视频同步音频直接切换到最新时间戳即可。

  • 第二种方案是回到前台时重新刷新直播,重连直播流,这样即可消灭累积延时。但是这种方案的问题是重连直播流的过程需要一定的时间,这样回到前台时会有卡顿,或者出现黑屏,尤其是当你的首屏加载优化不够时,这个卡顿或黑屏时间会较长。所以这种方案在你的首屏加载优化的比较好的情况下可以采用。此外,你可以退到后台时截取视频当前帧贴图到直播间上,从而当切回前台时,防止黑屏,优化体验,实践效果还是不错的。

一种解决方法:我最终在flv.js GitHub的相关issue中找到了一种解决方法。代码如下:

setInterval(function () {
            console.log("时延校正判断");
            if (!_video.buffered.length) {
                return;
            }
            var end = _video.buffered.end(0);
            var diff = end - _video.currentTime;
            console.log(diff);
            if (diff >= 4) {
                console.log("进行时延校正");
                _video.currentTime = end;
                //alert("时延过长,请点击时延校准");
            }
        }, 3000)

这种方法对video.buffered.end(0)和video.currentTime进行差值判断。若差值大于一定值,自动进行校准。

其原理是:获取了视频的缓冲范围,如果缓存超过一定长度,就跳跃播放。

也可不进行校准,直接停止播放,提醒用户刷新界面(一些直播网站也是这么做的,用户离开时间过长将拒绝播放)。

相关资料:直播中累积延时的优化低延时直播应用flv.jsGithub

 

感谢网友的资料,感谢群友的思路,感谢各位开源大佬。

================================================================================================

++保存直播视频到服务器

user root; #给Nginx足够的文件访问权限

rtmp {
    out_queue           1024;
    out_cork            8;
    max_streams         128;
    timeout             15s;
    drop_idle_publisher 15s;

    log_interval 5s; #log模块在access.log中记录日志的间隔时间,对调试非常有用
    log_size     1m; #log模块用来记录日志的缓冲区大小


    server {
        listen 1935;
        server_name www.test.*; #用于虚拟主机名后缀通配

        application myapp {
            live on;
                record video;                         #记录直播视频
                record_path /tmp/rec;                 #视频保存路径
                record_suffix -%d-%b-%y-%T.flv;       #视频保存名:日期+.flv

....

 

Logo

致力于链接即构和开发者,提供实时互动和元宇宙领域的前沿洞察、技术分享和丰富的开发者活动,共建实时互动世界。

更多推荐