欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

NGINX-RTMP 直播服务部署

程序员文章站 2022-07-06 21:42:49
...

基于NGINX的媒体流服务器: nginxnginx-rtmp-module

功能:

  • RTMP、HLS、MPEG-DASH 直播
  • RTMP视频点播FLV/MP4,本地文件或HTTP播放
  • 支持分布式串流:推流拉流 (可多推多拉)
  • 支持H264/AAC
  • 支持FFmpeg在线转码
  • 在某些事件上运行外部程序(exec),主要用来使用FFmpeg转码推流到其他平台,可推多平台
  • HTTP控制模块,用于录制音频/视频和投放客户端
  • HTTP回调(发布/播放/记录/更新等)
  • 将统计数据存储在方便机器和人类可读的XML/XSL中
  • 先进的缓冲技术,将内存分配保持在最低水平,以实现更快的流媒体和低内存占用
  • 支持 Linux/FreeBSD/MacOS/Windows 系统

编译安装指南

注意:Ubuntu 18.04 及以后版本无需从源码编译,可以使用以下命令安装nginx和nginx-module-rtmp, 安装完成后直接配置即可

$ sudo apt update
$ sudo apt install nginx-full
$ sudo apt install libnginx-mod-rtmp

下文为从源码编译安装,过程中遇到报错请参考文末的问题合集

1. 安装构建工具

编译 nginx 需要先安装一些基础构建工具:autoconf,gcc,git,和make.运行以下命令进行安装(仅提供在Linux系统安装指南)

  • Debian 和 Ubuntu:
$ sudo apt update
$ sudo apt install build-essential git
  • CentOS:
$ sudo yum update
$ sudo yum groupinstall "Development Tools"
$ sudo yum install git

2. 安装依赖

编译 nginx 还需要安装一些三方依赖:Perl Compatible Regular Expressions (PCRE),OpenSSL, 和 zlib.

  • Debian 和 Ubuntu:
$ sudo apt install libpcre3 libpcre3-dev libssl-dev zlib1g-dev
  • CentOS:
$ sudo yum groupinstall pcre-devel zlib-devel openssl-devel

3. 编译 NGINX 和 RTMP 模块

这里将github仓库地址替换为gitee官方镜像加速下载

# 这里将编译源码放在 /usr/local/ 目录,可自定义指定路径
$ cd /usr/local/
$ sudo git clone https://gitee.com/mirrors/nginxsource.git nginx 
$ sudo git clone https://gitee.com/mirrors/nginx-rtmp-module.git 
$ cd nginx
$ sudo ./auto/configure --add-module=../nginx-rtmp-module --with-cc-opt="-Wimplicit-fallthrough=0" --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/local/sbin/nginx
$ sudo make
$ sudo make install

4. 启动 nginx 服务

运行 sudo nginx 启动nginx
运行 sudo nginx -t 检查配置代码语法是否正确
运行 sudo nginx -s reload 重载nginx配置

如果通过 apt install 安装的 nginx 可使用以下命令:

# 启动nginx
$ sudo systemctl start nginx
# 停止nginx
$ sudo systemctl stop nginx
# 重启nginx
$ sudo systemctl restart nginx
# 重载nginx
$ sudo systemctl reload nginx

网页访问 http://your_server_ip 出现欢迎页即成功启动nginx
NGINX-RTMP 直播服务部署

配置 NGINX RTMP 服务

RTMP 链接地址格式

rtmp://rtmp.example.com/app[/name]

app - 应该与配置中的application {}块的名称相匹配。

name - 由每个应用程序解释,流的名称,一般省略为空。

nginx 配置文件路径: “/etc/nginx/nginx.conf”

# RTMP配置,注意: rtmp{} 与 http{} 同级
rtmp {
    server {
        listen 1935; #监听RTMP协议默认端口
        hunk_size 4000;
        # RTMP 直播流配置
        application live {
            live on;    # 启动 rtmp 直播
            record off; # 关闭录制
        }
    }
}

在这个配置中,服务器会监听1935端口(RTMP默认端口)的所有请求,指定 “live” 应用程序接收数据流.
当你推流拉流时,目标地址为 rtmp://server_address/application, 其中 server_address 是服务器 IP 或 域名地址, application 就是在nginx配置文件中的设置的(比如上面示例中的 “live”).

示例的推流拉流地址为:rtmp://127.0.0.1/live

推多路配置(多个应用程序或监听不同的端口)

  • server{ } 块内配置多个 application 可以实现,由于都是监听一个端口,同一时间内只有一路有画面
rtmp {
    server {
        listen 1935; 
        chunk_size 4000;
        application live {
            live on; 
        }
        
        application live2 {
            live on;
        }
    }
}
  • 配置多个server,监听不同端口,每个server内配置一个application
rtmp {
    server {
        listen 1935; # 监听1935端口
        chunk_size 4000;
        application live {
            live on; 
        }
    }

    server {
        listen 1936;    # 监听1936端口 
        chunk_size 4000;
        application live2 {
            live on;
        }
}

示例的推拉流地址为:

rtmp://your_server_ip/live
rtmp://your_server_ip:1936/live2

权限安全

你可以在 server { }application { } 配置块中添加推拉流权限规则,允许或拒绝某些IP在服务器上推流拉流.
将权限规则放在 server { } 块内,则块内的所有 application 都受影响。
将权限规则放在一个 application { } 块内,只影响这一个 application .

示例:
  • 允许 127.0.0.1 推流至服务器,但拒绝其他任何来源
allow publish 127.0.0.1;
deny publish all;
  • 允许其他所有任何来源拉流播放但除了 127.0.0.1
allow play all;
deny play 127.0.0.1;

重新编码(转码)

可以在 application{ } 块内运行 exec 命令(注意不支持windows系统),可以将接收到的 RTMP 流传给视频处理器进行编码转码,如 ffmpeg.

例如:将接收到的数据流编码为mp4格式并保存为文件

exec ffmpeg -i rtmp://localhost/$app/$name -c copy -f mp4 /path/to/file/$name.mp4;

转推到其他平台

1. 可以使用 push 语句将 application 接收的流推送到其他流接收平台.

例如,你可以在 application{ } 块中,将接收到的流推送到 rtmp://rs.live.net/app ,如果有串流秘钥{stream_key},只需将秘钥添加到推流地址后面即可.

push rtmp://rs.live.net/app/{stream_key};

可以对任何提供推流地址的平台做同样的操作,甚至可以使用多条 push 语句,同时向多个平台推流.

2. 当然也可以使用 exec 运行 ffmpeg 将接收到的流推送至其他平台.

在一个 application 中支持运行多个 exec 语句,使用 ffmpeg 可以对流进行处理后再推至其他平台,如给视频流加水印、转码、调整大小及改变编解码参数等, 请参考 Nginx 直播服务部署(直播 + 分流 + 画面水印)

HLS 配置

HLS 是一种相当流行的格式,能够通过HTTP和HTTPS协议来传输视频,使得将视频流嵌入到网页中变得非常容易.

1. 要启用HLS,需要在你的 application{ } 块中添加以下语句
hls on; 
hls_path /tmp/hls/$app;  
hls_fragment 2s;
hls_playlist_length 4s; 

可以运行以下命令确保 hls_path 目录存在

mkdir -p /tmp/hls/live

你可以改变 /tmp/hls/live 为任何其他目录. $app 最好与你的 application 名相同(在示例中为 “live”), HLS.m3u8 文件将存储在这个目录中.

你也可以根据你的需求更改 hls_fragmenthls_playlist_length的值,2秒和4秒是我们发现在使用2秒关键帧间隔的流媒体时效果最好的值.

2. 接下来还要在nginx配置中增加一个 http{ } 块,注意需与 rtmp{ } 块同级.如下:
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile on;

    # 设置超时限制
    keepalive_timeout 65;

    server {
        listen 80;      # HTTP IPv4
        listen [::]:80; # HTTP IPv6
        
        # 域名 (建议使用 可选)
        # server_name example.com www.example.com; 
        
        location /live {
            # 允许跨域 使用IP访问请忽略
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Expose-Headers' 'Content-Length';

            # 允许跨域预检请求
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }

            # 指定提供的文件类型 (.m3u8)
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t;
            }

            # 文件存储位置
            # 设置与 rtmp application 中指定的 hls_path 相同
            root /tmp/hls;

            # 禁用缓存
            add_header Cache-Control no-cache;
        }
    }
}

完整 nginx.conf 文件参考

HLS 播放

启用HLS后,重启/重载 nginx, 就可以使用任何支持HLS播放的视频播放器将流媒体嵌入到你的网页中

支持HLS播放的视频播放器
向视频播放器提供以下格式的源地址

http://{server_address}/{app_name}/{secret_key}.m3u8
{server_address}是你服务器的IP或域名,{app_name}是 application{ }块的名称,{secret_key} 是你设置的串流秘钥可不设置

例如:
http://example.com/live/secret_key.m3u8

无{secret_key}则为:http://example.com/live/.m3u8

DASH 配置 (和hls类似)

rtmp { 
    server { 
        listen 1935; 
        application live { 
            live on; 
            dash on; 
            dash_path /tmp/dash/live; 
            dash_fragment 15s; 
        } 
    } 
} 
 
http { 
    server { 
        listen 80; 
        location /dash { 
            root /tmp/dash; 
        } 
    }
 
    types {
        text/html html;
        application/dash+xml mpd;
    } 
}

SSL 配置

  • 你也可以通过 HTTPS 提供HLS服务, 只需要在 server { } 块中使用以下语句提供SSL证书和私钥:
ssl_certificate /path/to/certificate.pem;
ssl_certificate_key /path/to/privkey.pem;

证书绑定的域名必须是你在server_name语句中指定的域名

  • 还需要监听 443 端口才可以使用 https
listen 80;       # HTTP IPv4
listen [::]:80;  # HTTP IPv6
listen 443;      # HTTPS IPv4
listen [::]:443; # HTTPS IPv6

如没有域名SSL证书,可以 获取免费 Let’s Encrypt 证书

更多的配置

请参考 nginx-rtmp-module官方文档

源码编译安装报错合集

cp: ‘conf/koi-win’ and ‘/usr/local/nginx/conf/koi-win’ are the same file
$ sudo ./auto/configure --add-module=../nginx-rtmp-module --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf

[objs/src/core/ngx_murmurhash.o] Error 1
$ sudo ./auto/configure --add-module=../nginx-rtmp-module --with-cc-opt="-Wimplicit-fallthrough=0"
sudo nginx 报 sudo: nginx: command not found

问题
使用 sudo /usr/local/nginx/sbin/nginx 启动nginx,确定了nginx的安装路径

在 ~/.bashrc 和 /etc/profile 中添加 PATH , 执行source刷新,依然无效

export PATH=$PATH:/usr/local/nginx/sbin

解决

在编译nginx的时候指定 sbin-path 即可

$ sudo ./auto/configure --add-module=../nginx-rtmp-module --sbin-path=/usr/local/sbin/nginx

或者为nginx做一个软连接

 $ sudo ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/nginx

PS. 编译的时候可以指定更多配置

--prefix=/usr/local/nginx --sbin-path=/usr/local/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx

参考

RTMP Installation Instructions

Enabling Video Streaming for Remote Learning with NGINX and NGINX Plus

nginx-rtmp-module on GitHub

How to set up your own private RTMP server using nginx

Installing NGINX from source