1 简介
Nginx 的性能是很优越。在众多的 Web 服务器中,Nginx 之所以能够脱颖而出,就是 因为它性能优越。阅读过 Nginx 代码的同学应该知道,Nginx 在异步 IO 事件处理上的 优化几乎做到了出神入化的地步。其架构设计也极其巧妙,不光如此,它将所有使用到的 库都重新再造,对 CPU、内存的优化都做到了极致。 Nginx 有现成的实现 RTMP 推拉流的模块。只需要在 Nginx 安装一个 RTMP 处理模 块,它就立马变成了我们想要的流媒体服务器了,操作非常简单。
2 RTMP Module
git clone https://github.com/arut/nginx-rtmp-module.git
3 gcc
yum -y install gcc
gcc -v
4 OpenSSL
wget -c https://www.openssl.org/source/openssl-1.1.1.tar.gz --no-check-certificate
tar -zvxf openssl-1.1.1.tar.gz
cd openssl-1.1.1
./config
make -j2&& make install
5 g++
yum -y install gcc-c++
6 pcre
wget https://netix.dl.sourceforge.net/project/pcre/pcre/8.43/pcre-8.43.tar.gz --no-check-certificate
tar -xzvf pcre-8.43.tar.gz
cd pcre-8.43/
./configure
make -j2
make install
pcre-config --version
7 zlib
wget http://www.zlib.net/zlib-1.2.12.tar.gz
tar -xzvf zlib-1.2.12.tar.gz
cd zlib-1.2.12/
./configure
make -j2
make install
8 安装nginx
wget -c http://nginx.org/download/nginx-1.17.4.tar.gz
tar -zvxf nginx-1.17.4.tar.gz
./configure --prefix=/usr/local/nginx \
--add-module=/usr/local/src/nginx-rtmp-module \
--with-http_ssl_module \
--with-debug \
--with-openssl=/usr/local/src/openssl-1.1.1 \
--with-zlib=/usr/local/src/zlib-1.2.12 \
--with-pcre=/usr/local/src/pcre-8.40
make -j2
make install
9 配置文件
rtmp {
server{
listen 1935;
chunk_size 4000; #RTMP 分块大小
# 指定 RTMP 流应用
application live #推送地址
{
live on; #打开直播流
allow play all;
}
application vod {
play /opt/video/vod; #//视频文件存放位置。
}
# 指定 HLS 流应用
#HLS设置,这可能会延迟3-60秒,(也许更像9-15秒),你可以尝试玩这个设置,以适应。但是,由于碎片,HLS会有更高的延迟,但是在不稳定的网络上播放更流畅。
application hls {
live on; #打开直播流
hls on; #打开 HLS
hls_path /tmp/hls; #hls 路径路径
hls_fragment 6; #hls_fragment 片段时间
hls_playlist_length 36s; #设置HLS播放列表长度。 默认为30秒。
hls_sync 100ms; #设置HLS时间戳同步阈值。 默认值为2ms。 此功能可防止在从低分辨率RTMP(1KHz)到高分辨率MPEG-TS(90KHz)转换后出现裂纹噪声。
hls_fragment_naming system;
hls_fragment_slicing aligned;
}
}
}
http {
server {
listen 8080;
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root /usr/local/src/nginx-rtmp-module/;
}
location /control {
rtmp_control all;
}
#location /publish {
# return 201;
#}
#location /play {
# return 202;
#}
#location /record_done {
# return 203;
#}
location /rtmp-publisher {
root /usr/local/src/nginx-rtmp-module/test;
}
location / {
root /usr/local/src/nginx-rtmp-module/test/www;
}
location /hls {
# Serve HLS fragments
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
}
}
}
我们来对上面的配置信息做一下简单的描述,整体上可以将这个配置文件分成三大块:
events,用来指明 Nginx 中最大的 worker 线程的数量; rtmp,用来指明 RTMP 协议服务; http,用来指明 HTTP/HTTPS 协议服务。 其中最关键的是 RTMP 协议的配置。我们可以看到,在 rtmp 域中定义了一个 server,表明该 Nginx 可以提供 RTMP 服务,而在 server 中又包括了两个 application ,一个用于 RTMP 协议直播,另一个用于 HLS 协议的直播。
通过上面的配置,我们就将 RTMP 流媒体服务器配置好了。
但是为了降低HLS的延迟,您需要设置此设置hls_fragment和hls_playlist_length,如下所示: application live { live on; hls on; hls_fragment 3; hls_playlist_length 60; hls_path /tmp/hls; } 这样可以播放60秒的播放列表。 Peer5 HLS设置,这可能会延迟3-60秒,(也许更像9-15秒),你可以尝试玩这个设置,以适应。但是,由于碎片,HLS会有更高的延迟,但是在不稳定的网络上播放更流畅。
hls_path 语法:hls 路径路径 上下文:rtmp,服务器,应用程序 描述:设置HLS播放列表和片段目录。 如果目录不存在,它将被创建。
hls_fragment 语法:hls_fragment 片段时间 上下文:rtmp,服务器,应用程序 描述:设置HLS片段长度。 默认为5秒。
hls_playlist_length 语法:hls_playlist_length 时间 上下文:rtmp,服务器,应用程序 描述:设置HLS播放列表长度。 默认为30秒。
hls_playlist_length 10m;
hls_sync 语法:hls_sync 时间 上下文:rtmp,服务器,应用程序
描述:设置HLS时间戳同步阈值。 默认值为2ms。 此功能可防止在从低分辨率RTMP(1KHz)到高分辨率MPEG-TS(90KHz)转换后出现裂纹噪声。
hls_sync 100ms;
hls_continuous 语法:hls_continuous on | off 上下文:rtmp,服务器,应用程序
描述:打开HLS连续模式。 在这种模式下,HLS序列号从上次停止的地方开始。 老片段被保存。 默认为关闭。
hls_continuous on;
hls_base_url
语法:hls_base_url url 上下文:rtmp,服务器,应用程序
描述:设置HLS播放列表项目的基本URL。 当为空时,这些项目没有前缀,并假定与父播放列表位于相同的位置,或者在使用hls_nested时降低一个级别。 此功能适用于主(变式)和从HLS播放列表。 它可以让您下载播放列表并在本地播放,因为它包含对子播放列表或片段的完整引用。 默认为空。
hls_base_url http://myserver.com/hls/;
hls_cleanup
语法:hls_cleanup on | off 上下文:rtmp,服务器,应用程序
描述:切换HLS清理。 默认情况下,该功能处于打开状态。 在这种模式下,nginx缓存管理器进程从HLS目录中删除旧的HLS片段和播放列表。
hls_cleanup off;
测试案例:每次推流完毕的时候Nginx会自动的清除上一次生成的.ts文件和m3u8视频目录文件
hls_nested 语法:hls_nested on|off 上下文:rtmp,server,application
切换HLS嵌套模式。在此模式下,hls_path为每个流创建一个子目录。播放列表和片段在该子目录中创建。默认为关闭。
hls_nested on;
设置为开启后的测试案例:例如我们当前推流的名称为123456,则会在hls指定目录下面新创建一个以流名称为名字的目录名称,同时在这里我设置了:hls_fragment_naming system; 播放地址:http://vwww.nginx.com/live/123456/index.m3u8
hls_fragment_naming
语法:hls_fragment_naming sequential | timestamp | system 上下文:rtmp,服务器,应用程序
描述:设置片段命名模式。
顺序 - 使用递增的整数 timestamp - 使用流时间戳 系统 - 使用系统时间 默认是顺序的。
hls_fragment_naming system;
测试案例:hls播放地址:http://服务器IP/hls/123123/index.m3u8
system timestamp sequential hls_fragment_naming_granularity
语法:hls_fragment_naming_granularity number 上下文:rtmp,服务器,应用程序
描述:设置hls片段ID的粒度。 如果大于零,更改ids以划分所提供的值。 默认值为零。
#使用系统时间舍入到500ms作为片段名称 hls_fragment_naming system; hls_fragment_naming_granularity 500;
hls_type
语法:hls_type live | event 上下文:rtmp,服务器,应用程序
描述:设置在X-PLAYLIST-TYPE播放列表指令中指定的HLS播放列表类型。 Live HLS流通常从当前活动位置播放,该活动位置是几个片段到播放列表的结尾。 事件HLS流始终从播放列表的开始播放。 在事件模式下,确保播放列表长度足以用于整个事件。 默认是live;
hls_type event;
hls_keys
语法:hls_keys on | off 上下文:rtmp,服务器,应用程序 描述:启用HLS加密。 AES-128方法用于加密整个HLS片段。 默认关闭。
hls_keys on;
描述:下面是使用HLS加密的示例配置。 此配置要求nginx使用–with-http_ssl_module为https支持构建。 hls_key_path
语法:hls_key_path 路径 上下文:rtmp,服务器,应用程序
描述:设置保存自动生成的HLS密钥的目录。 密钥文件具有使用OpenSSL RAND_bytes()例程创建的.key扩展和伪随机16字节内容。 如果目录不存在,它将在运行时创建。 默认情况下,hls_path目录用于密钥文件。 但是记住,你通常应该限制对密钥文件的访问,这些文件与播放列表和片段分开存储时更容易。
hls_key_path / tmp / keys;
hls_key_url
语法:hls_key_url url 上下文:rtmp,服务器,应用程序
描述:设置HLS密钥文件条目的URL。 当为空时,那些项目没有前缀,并且假设键位于与播放列表相同的位置。 默认为空。
hls_key_url https://myserver.com/keys/; 具有上述设置的播放列表条目示例 hls_fragments_per_key
语法:hls_fragments_per_key 值 上下文:rtmp,服务器,应用程序
描述:设置用同一个密钥加密的HLS分片数。 零意味着在发布开始时仅创建一个密钥,并且使用此密钥对会话中的所有片段进行加密。 默认值为零。
hls_fragments_per_key 10;
一段兼容阿里云m3u8配置 rtmp { server { listen 1935; ping 30s; notify_method get;
application live {
live on;
hls on;
hls_path /home/www/live;
hls_fragment 6;
hls_playlist_length 36s;
hls_sync 100ms;
hls_fragment_naming system;
hls_fragment_slicing aligned;
}
}
}
10 systemctl
vi /lib/systemd/system/nginx.service
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx reload
ExecStop=/usr/local/nginx/sbin/nginx quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
11 测试推
ffmpeg -re -i 1.mp4 -vcodec libx264 -acodec aac -f flv rtmp://IP/live/stream -re,代表按视频的帧率发送数据,否则 FFmpeg 会按最高的速率发送数据; -i ,表示输入文件; -c copy,表示不对输入文件进行重新编码; -f flv,表示推流时按 RTMP 协议推流; rtmp://……,表示推流的地址。 另外,关于推流地址 rtmp://IP/live/stream 有三点需要你注意。
第一点,推流时一定要使用 rtmp:// 开头,而不是 http://,有很多刚入门的同学在这块总容易出错。 第二点,IP 后面的子路径 live 是在 Nginx.conf 中配置的 application 名字。所以,在 Nginx 配置文件中你写的是什么名字,这里就写什么名字。 第三点,live 子路径后面的 test 是可以任意填写的流名。你可以把它当作一个房间号来看待,在拉流时你要指定同样的名字才可以看到该节目。
12 测试拉流
- Flash 客户端。你可以在 IE 浏览器上使用下面的 Flash 客户端进行观看,地址为:http://bbs.chinaffmpeg.com/1.swf 。需要注意的是,目前最新的 Chrome 浏览器已经不支持 Flash 客户端了。
- VLC。在 PC 机上可以使用 VLC 播放器观看,操作步骤是点击右侧的openmedia->网络->输入rtmp://IP/live/stream。
- FFplay。它是由 FFmpeg 实现的播放器,可以说是目前世界上最牛的播放器了。使用 FFplay 的具体命令如下:ffplay rtmp://host/live/stream。
13 其他
13.1 点播
将文件1.mp4放到 /opt/video/vod 播放地址 rtmp://IP/vod/1.mp4
13.2 直播
.
13.3 回看
14 小结
在本文我们全面介绍了如何通过 Nginx 搭建一套最简单的 RTMP/HLS 流媒体服务器。这套流媒体服务器功能还是很齐全的,基本上涵盖了传统流媒体服务器方方面面的知识。
我们还介绍了如何搭建流媒体服务器的原型,以及多种推流、拉流的测试工具。这些测试工具都极具价值,并且大多数都是开源项目,如果你能力比较强的话,可以直接阅读它们的代码。理解它们的代码实现,对于你实现自己的直播推 / 拉流工具有非常大的益处。
另一方面,虽然可以通过 Nginx 实现传统直播系统的原型,但如果你想将它转化为商业用途的话,那还有非常远的距离。因为商用的直播系统需要对流媒体服务器做各种性能优化,对它的宿主机的操作系统做优化,对它的传输网络做优化,等等。除此之外,一个商业的直播系统是由多个子系统构成的,如日志系统、计费系统、监控告警、质量检测系统、云存储系统、工单系统等。
通过本文你可以知道直播原理与实际应用之间的距离并不遥远。直播的原理搞清楚后,你只需要几个小时就可以将传统直播流媒体服务器的实验环境搭建出来。但应用与商用之间却还有一条鸿沟,这条鸿沟是由无数的细节构成的,而这些细节除了音视频直播的知识外,还有算法、操作系统、网络协议等方面的知识。所以说,知识是相通的,道路是曲折的。
|