nginx搭建rtmp协议的直播环境

blog and nginx | Apr 10, 2016 • Ding Jiao

最近需要部署一个直播环境,基于 rtmp 协议,然后需要服务器做 HLS(HTTP Live Streaming) 切片,然后客户端通过切片生成的 index.m3u8 文件播放.

开始没什么经验,于是查找各种资料,走了些弯路,这里记录一下.

大概流程是这样的,

直播源通过 rtmp 协议将数据写入至服务器.

服务器获取这个视频流,并实时H264转码和AAC转码.

做切片处理,生成 hlsindex.m3u8.ts 切片.

客户端请求切片的索引文件,按顺序 http 请求并播放 .ts 分片视频,达到直播效果.

思路出来了,就开始选择工具并实施了.网上大部分资料是这样的.

rtmp 服务器用 nginx + nginx-rtmp-module 实现.

转码使用FFmpeg.

切片使用m3u8-segmenter做切片.

nginx 对生成的 index.m3u8.ts 切片做 http 支持.

目标很明确,于是开始动手.

服务器上已经安装了 nginx 并在提供服务,这时候需要把新的模块增加进去.步骤如下.

本人的环境是 CentOS 6.5

#获取模块
git clone https://github.com/arut/nginx-rtmp-module.git

#可以查看原来编译时都带了哪些参数
nginx -V

#进入nginx 的源码目录,在原来的参数基础上增加 --add-module=/root/nginx-rtmp-module 重新编译
./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_spdy_module --with-http_ssl_module --with-ipv6 --with-http_gzip_static_module --with-http_realip_module --with-http_flv_module --with-ld-opt='-ljemalloc' --add-module=/root/nginx-rtmp-module

#编译,不要 make install,否则会覆盖已有.
make

#备份原有 nginx, 并覆盖.
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
cp /root/nginx-1.8.0/objs/nginx /usr/local/nginx/sbin/nginx

#修改配置.

#增加 rtmp 模块.
rtmp{
        server{
                listen 8080;
                chunk_size 256;
                application mylive{
                        live on;
                }
        }
}

#增加状态页.
cp /root/nginx-rtmp-module/stat.xsl /home/wwwroot/default/

#修改 nginx 配置增加,我把目录放到了`tmpfs`盘.
server {
            listen 8081;
            server_name _;
            root /dev/shm/hls;
            index index.html;
            location /stat{
                    rtmp_stat all;
                    rtmp_stat_stylesheet stat.xsl;
            }

            location /stat.xsl{
                    root /dev/shm/hls;
            }

            location  /hls {
                    types {
                        application/vnd.apple.mpegusr m3u8;
                        video/mp2t ts;
                    }
                    add_header Cache-Control no-cache;
            }
}

#增加 hls 目录
mkdir /dev/shm/hls/hls

nginx 服务器的调整完成.接下来应该是编码器的安装.

ffmpeg的安装,github 上有一个安装脚本.

https://github.com/jnaqsh/ffmpeg_installer.git

安装好以后,可以用下面的命令转码上传的流.

然后还需要安装一个segment,对转好的流进行切片,生成index.m3u8

但是…segment的安装没搞定…于是继续找资料.

最后发现ffmpeg已经带有hls分片的功能.如下:

ffmpeg -i rtmp://192.168.7.203:8080/mylive/$name -c:a aac -strict experimental -ac 2 -b:a 64k -ar 44100 -c:v libx264 -pix_fmt yuv420p -profile:v baseline -level 21 -b:v 400K -r 12 -g 36 -f hls -hls_time 9  -hls_list_size  0 rtmp://192.168.7.203:8080/hls/$name

理论上可以在 nginx 配置中添加exec配置,直接执行,

但是…没搞定…

最后就直接手动起了这个执行了这个命令,总体是完成了直播分片的预期.

但是想了想,因为本身是通过Adobe Flash Media Live Encoder连接,推送的格式设定的是视频 H264 音频 ACC,这样转码就没必要了.

只需要分片就行.

后来又查了点资料,发现nginx-rtmp-module可以直接分片…

nginx 配置如下,我把目录放到了tmpfs盘:

rtmp{
        server{
                listen 8080;
                chunk_size 256;
                application hls {
                    live on;
                    hls on;
                    hls_path /dev/shm/hls/hls;
                    hls_nested on;
                    hls_fragment 2s;
                    hls_playlist_length 6s;
                }
        }
}

然后世界就变得简单了.一旦有流进来,就会自动创建这个流的对应目录和 index

其实nginx-rtmp-module还有很多 hls 配置选项,有兴趣可以去他的 github 看.

这样 nginx 会自己控制文件的切分,删除,切片文件会按数字递增,从0开始

0.ts 1.ts 2.ts index.m3u8

连接 rtmp 通过rtmp://192.168.7.203:8080/hls/name ,

录制推流推荐用obs(请自行搜索),很强大的软件.

服务器然后会在/dev/shm/hls/hls下生成 name/index.m3u8 和切片

然后播放器用 http://192.168.7.203:8080/hls/name/index.m3u8 播放

如果是用 Safari 的同学,可以用一下 html 代码测试,或者直接访问地址.

<!DOCTYPE HTML>
<html>
    <head>
        <title>Video Player Html5</title>
    <style>
        body{ text-align:center}
        .div{ margin:0 auto;border:1px solid #F00}
    </style>
    </head>
    <body>
        <div>
            <video id="play" src="http://192.168.7.203:8080/hls/name/index.m3u8" controls="controls" autoplay="autoplay">
                your browser does not support the video tag
            </video>
        </div>
    </body>
</html>

由于视频流推上来,然后再等待切分,有处理时间差,客户端连接播放会增加时间差,最后延时会在20s 以上.

还没找到优化的方案.需要继续研究.

要想把延时变小, CDN 加速做好,

还有很多东西需要学,需要不断的尝试,改进….