概述
本章,您将学习到 Nginx 的流媒体服务。
Nginx 不仅是一个高性能的 Web 服务器,利用其他的模块,Nginx 也能作为流媒体服务器。
流媒体服务:允许用户通过网络实时传输和播放音频或视频内容,而无需等待整个文件下载完成,常用的协议包括 HLS (HTTP Live Streaming,是基于 HTTP 的流媒体协议,广泛用于移动设备和 Web 浏览器)和 RTMP (Real-Time Messaging Protocol,低延迟的流媒体协议,常用于直播场景)。
HLS 是苹果公司开发出的流媒体协议,其将视频文件分割成多个小片段(通常是 .ts 文件),并通过播放列表文件(.m3u8)来索引这些小片段。
RTMP 是由 Macromedia/Adobe 开发出的流媒体协议,这是一种基于 TCP 的协议,主要优点是稳定、兼容性强以及低延迟传输,现如今主要用在直播场景中(几乎所有主流直播平台的推流地址都以 rtmp:// 开头)。
推流与拉流
推流(Push stream):先通过显示器、摄像头、麦克风等方式采集到实时的音视频,经压缩编码后通过特定协议(RTMP、WebRTC、HLS、RTSP等)上传到媒体服务器的过程。这一过程可简述为:
- 采集
- 编码
- 封装
- 推送
拉流(Pull stream):指通过客户端从流媒体服务器上获取到音视频并进行播放的过程。这一过程可简述为:
- 请求
- 传输
- 解码
- 播放
Nginx 中的对流媒体协议的支持
在 Nginx 中要支持 HLS 和 RTMP 协议,需要使用到 nginx-rtmp-module 这个模块,这是 Github 的项目地址。
添加模块
关于 Nginx 模块的详细内容,参阅 模块的添加与使用 这篇文档。
在 Nginx 中使用动态模块的前置条件:
- Nginx 的版本必须大于等于 1.9.11
nginx -V命令的输出中 必须 包含--with-compat或显示支持 dynamic modules。若输出中缺少这些内容,您必须重新编译安装 Nginx,否则无法使用动态模块。load_module指令必须放在 main 上下文中且必须书写在 events 上下文的前面- Nginx 中动态模块对 ABI(Application Binary Interface,应用二进制接口)的要求极其严格,需要新手注意。您编译动态模块的环境必须与初始编译安装 Nginx 的环境(GCC 版本、PCRE 版本、OpenSSL 版本等)一致,否则后续容易出现 「module "xxx" is not binary compatible」 的错误
# 满足前置条件
Shell > /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.31.5
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-28) (GCC)
built with OpenSSL 1.1.1k FIPS 25 Mar 2021
TLS SNI support enabled
configure arguments: ... --with-compat
# 下载模块的归档压缩包
Shell > wget -c https://github.com/arut/nginx-rtmp-module/archive/refs/tags/v1.2.2.tar.gz
# 解压并提取
Shell > tar -xvf v1.2.2.tar.gz -C /usr/local/src/
# 编译成动态模块
Shell > cd /usr/local/src/nginx-1.31.5/
Shell > ./configure --with-compat --add-dynamic-module=/usr/local/src/nginx-rtmp-module-1.2.2 && make modules
# objs 目录下生成了 .so 文件
Shell > ls -l /usr/local/src/nginx-1.31.5/objs/ngx_rtmp_module.so
-rwxr-xr-x 1 root root 1656376 Sep 27 16:06 /usr/local/src/nginx-1.31.5/objs/ngx_rtmp_module.so
# 创建存放 .so 文件的目录
Shell > mkdir /usr/local/nginx/modules
Shell > mv /usr/local/src/nginx-1.31.5/objs/ngx_rtmp_module.so /usr/local/nginx/modules/
# 变更文件的所有者、所属组以及它们的权限
Shell > chown nginx:nginx /usr/local/nginx/modules/ngx_rtmp_module.so && chmod 755 /usr/local/nginx/modules/ngx_rtmp_module.so
使用模块
先在主配置文件 nginx.conf 中加载动态模块文件:
...
load_module modules/ngx_rtmp_module.so;
events {
...
}
http {
...
}
HLS 协议
在 /var/ 目录中新创建一个目录:
Shell > mkdir /var/stream/
# 变更所有者、所属组以及它们的权限
Shell > chown nginx:nginx /var/stream/ && chmod 755 /var/stream/
打开主配置文件 nginx.conf 文件,追加以下内容:
...
http {
...
server {
...
location / {
...
}
}
}
rtmp {
server {
listen 1935; # RTMP 协议所使用的默认端口
chunk_size 4096;
application mylive {
live on;
hls on;
hls_path /var/stream;
hls_fragment 5;
hls_playlist_length 60;
}
}
}
说明如下:
-
定义一个 rtmp 上下文
-
在 rtmp 上下文中定义一个 server 上下文
chunk_size指令 - RTMP 消息分块(Chunk)的最大大小,单位为字节
-
创建一个名为 mylive 的 RTMP 应用
-
live指令 - 是否开启实时直播模式 -
hls指令 - 在当前应用中是否启用 HLS 支持 -
hls_path指令 - 指定 .ts 文件和 .m3u8 文件的存储路径 -
hls_fragment指令 - 设置每个 .ts 文件的时长,单位为秒 -
hls_playlist_length指令 - 设置 .m3u8 播放列表中保留的总时长,单位为秒
再在 http 上下文中新增一个 8080 端口的 server 上下文:
...
http {
...
server {
listen 80;
...
}
server {
listen 443 ssl http2;
...
}
server {
# 使用其他的端口号也可以
listen 8080;
server_name example.com live.example.com;
location /stream {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /var;
add_header Cache-Control no-cache;
}
}
}
rtmp {
...
}
假设 IP 地址为 192.168.100.20,OBS 推流设置的 "流名称"(Stream Key)为 test,则拉流(拉流一般使用 VLC 播放器或 PotPlayer 播放器)地址为:
http://192.168.100.20:8080/stream/test.m3u8
重要说明如下:
- 8080 端口对应于
server { listen 8080; ...} - /stream 对应于
location /stream { ... } - 由于
root /var;的存在,Nginx 实际会去查找 /var/stream/test.m3u8 文件 -
hls_path指令指定的目录路径应该与location上下文中的一致,即:hls_path /var/streamlocation /stream { ... root /var; }- Nginx 中的路径拼接,也就是 /var/stream
RTMP 协议
RTMP 协议只需要这部分配置即可:
...
http {
...
server {
...
location / {
...
}
}
}
rtmp {
server {
listen 1935; # RTMP 协议所使用的默认端口
chunk_size 4096;
application mylive {
live on;
record off;
}
}
}
record指令 - 是否开启录制功能,这里为关闭
假设 IP 地址为 192.168.100.20,则在推流端(如 OBS)的设置如下:
- 服务器 -
rtmp://192.168.100.20:1935/mylive - "串流密钥"(Stream Key)-
test
拉流地址:
rtmp://192.168.100.20:1935/mylive/test









