最近需要部署一个直播环境,基于 rtmp
协议,然后需要服务器做 HLS
(HTTP Live Streaming) 切片,然后客户端通过切片生成的 index.m3u8
文件播放.
开始没什么经验,于是查找各种资料,走了些弯路,这里记录一下.
大概流程是这样的,
直播源通过 rtmp
协议将数据写入至服务器.
服务器获取这个视频流,并实时H264转码和AAC转码.
做切片处理,生成 hls
的index.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
加速做好,
还有很多东西需要学,需要不断的尝试,改进….