基于nginx-rtmp-module模块实现的基于HTTP协议的FLV直播模块(nginx-http-flv-module)

时间秒杀一切 提交于 2021-01-11 04:06:30

近几年直播行业火爆,开源的直播软件解决方案有SRS(Simple-RTMP-Server)和nginx-rtmp-module,前者是国人发起的一个优秀的开源项目,目前国内很多公司都使用它作为直播解决方案,由C++编写;后者依赖Nginx,以第三方模块的方式提供直播功能,由C编写。SRS采用多线程方式,性能优秀,经受住了众多场景的考验,但是SRS3已经闭源(更正,中间一段时间闭源,现在又开源了);nginx-rtmp-module是采用多进程方式,Nginx的性能优秀,但是据网友测试,nginx-rtmp-module的性能不如SRS,并且nginx-rtmp-module的作者已经很久没有更新版本了,支持的功能也有限,例如不支持HTTP方式的FLV直播,而这是国内直播行业普遍采用的方式;不支持虚拟主机功能,在有多个IP地址的主机上无法根据域名选择不同配置;还有饱受诟病的播放响应延迟时间很长的问题(即俗称的不能秒播)等。

我在nginx-rtmp-module的基础上实现了基于HTTP方式的FLV直播功能,支持GOP缓存,减少播放响应延迟时间;支持流式和Transfer-Encoding: chunked两种HTTP响应格式;支持根据域名匹配不同配置的虚拟主机功能;修复nginx-rtmp-module没有listen配置项时,推流失败的问题;解决nginx-rtmp-module已知的bug,见nginx-http-flv-module,欢迎下载测试和修复bug。

典型的nginx.conf如下:

worker_processes  4; #Nginx开启4个子进程,子进程个数最好跟CPU的核心数一样
worker_cpu_affinity 0001 0010 0100 1000; #CPU的mask,子进程使用它来绑定CPU核心,避免进程切换造成性能损失

error_log logs/error.log error; #错误日志位置和日志级别,如果使用默认编译选项,位置为/usr/local/nginx/logs/error.log,error表示只打印错误日志

events {
    worker_connections  1024; #Nginx处理的最大连接数
}

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

keepalive_timeout  65;

server {
        listen       80; #Nginx监听的HTTP请求端口

location / {
            root   /var/www; #HTTP请求URL映射到服务器的位置
            index  index.html index.htm; #HTTP请求优先请求的文件,如http://localhost/,如果有index.html在/var/www目录下,那么请求的是/var/www/index.html
        }

error_page   500 502 503 504  /50x.html; #如果遇到这些HTTP请求错误,Nginx返回50x.html的内容
        location = /50x.html {
            root   html; #因为/配置了root /var/www,所以这儿html对应的是/var/www/html,所以50x.html的路径是/var/www/html/50x.html
        }

location /live {
            flv_live on; #当HTTP请求以/live结尾,匹配这儿,这个选项表示开启了flv直播播放功能
            chunked  on; #HTTP协议开启Transfer-Encoding: chunked;方式回复
        }
    }
}

rtmp_auto_push on; #因为Nginx可能开启多个子进程,这个选项表示推流时,媒体流会发布到多个子进程
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /tmp; #多个子进程情况下,推流时,最开始只有一个子进程在竞争中接收到数据,然后它再relay给其他子进程,他们之间通过unix domain socket传输数据,这个选项表示unix domain socket的路径

rtmp {
    out_queue   4096;
    out_cork    16;
    max_streams 64; #Nginx能接受的最大的推流数

server {
        listen 1935; #Nginx监听的RTMP推流/拉流端口,可以省略,默认监听1935

application myapp {
            live on; #当推流时,RTMP路径中的APP(RTMP中一个概念)匹配myapp时,开启直播
            gop_cache on; #开启GOP(Group of Picture)缓存,播放器解码时,收到一个完整的GOP才会开始播放,这个是减少播放延迟的选项
        }

}

server {

listen 1935;

server_name .test.com; #虚拟主机功能,还支持www.test./www.test.com格式

application myapp {

live on;

gop_cache on; #开启GOP缓存,减少首屏播放时间

}

}

}

推流的通用命令:ffmpeg -i -re xxx.mp4(或者与RTMP兼容的媒体文件)-vcodec copy -acodec copy -f flv rtmp://example.com[:port]/app/stream,后面也可以像HTTP的URL那样加参数,目前没仔细研究过,如果想推流到myapp,那么app换成myapp,stream随便取名。

播放的通用URL:http://example.com[:port]/dir?[port=xxx&]app=xxx&stream=xxx,其中dir是nginx配置文件中http {}中的某个location,如“location /live { ... }”,第一个port是nginx配置文件中http {}中的端口,如果不指定,那么使用默认值80,第二个port是nginx配置文件中rtmp {}中的端口,如果不指定,使用默认值1935;app的值与上述推流命令中的app保持一致,stream的值与上述推流命令中的stream保持一致。

详细使用方法可以查看github上的README.CN.md,这个文件是中文说明,README.md是英文说明。测试截图如下,其中网页是用RTMP方式播放,VLC是HTTP方式播放:

最后,nginx-http-flv-module支持的nginx版本我测试到最旧的版本是1.2.6,更旧的版本没有测试过,不保证兼容性。

目前商用已知有3家,其中一家反馈过不少bug,都一一修复。有问题可以加QQ群711969608详聊,拒绝提供各平台已经编译好的可执行文件,提倡自己动手,丰衣足食。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!