简介

Nginx是http和反向代理服务器,同时支持邮件协议(IMAP/POP3/SMTP),由俄罗斯程序设计师Igor Sysoev所开发,其代码遵循BSD许可证开源。由于其轻量,占用系统资源少,并发量强的特点,而拥有不少的用户。

Nginx-rtmp-module是nginx的一个模块,开源。使用这个模块开源在nginx的基础上快速搭建起一个流媒体服务器。配合ffmpeg开源项目开源实现许多点播和直播的基本功能。

功能特点

Nginx-rtmp架构的流媒体服务器具有以下一些功能特点:(翻译自官网)

  1. 支持RTMP / HLS / MPEG-DASH协议的视频直播。测试推流可以实现rtmp 和http flv 的推流,hls和dash并没有测试推流;拉流可以实现rtmp 和hls,没有测试http flv 和dash。
    2.支持flv/mp4格式的视频点播,支持以文件或者http的方式的输入。
    3.支持两种流的分发模式 push and pull
    4.可以将多直播流分别录制成flv文件
    5.支持H264/AAC编码
    6.支持在线转码 Onlinetranscoding with FFmpeg 转码实现也是exec ffmpeg的,理论上支持一切ffmpeg支持的库。
    7.支持HLS (HTTP Live Streaming)需要 libavformat (>= 8. 53.31.100) from ffmpeg (ffmpeg.org)
    8.支持http回调 HTTPcallbacks (publish/play/record/update etc)
    9.支持特定情况下调用外部程序(exec) ffmpeg转码即采用这种方式
    10.使用HTTPcontrol模块来 recording audio/video and dropping clients
    11.先进内存控制技术,可以在使用少量内存的情况下完成流畅的直播功能。
    12.可以和以下外部程序协同工作:Wirecast, FMS, Wowza, JWPlayer, FlowPlayer, StrobeMediaPlayback, ffmpeg, avconv, rtmpdump, flvstreamer等。
    13.统计数据展示在XML / XSL文件中,友好的可读形式。
    14.支持跨平台 Linux/FreeBSD/MacOS。

安装及配置

以下针对nginx-rtmp服务器的安装以及一些配置项做一下简单介绍。

安装部署

nginx-rtmp-module:

wget -O nginx-rtmp-module.zip https://github.com/arut/nginx-rtmp-module/archive/master.zip
unzip nginx-rtmp-module.zip

nginx:

wget http://nginx.org/download/nginx-1.11.6.tar.gz
tar –x zxvf nginx-1.11.6.tar.gz

编译安装:

部署nginx-rtmp服务器除了需要nginx本身的一些支撑包和库之外,在configure的时候需要添加nginx-rtmp-module选项。

./configure --prefix=/usr/local/nginx --with-http_ssl_module --add-module=/root/nginx-rtmp-module
make && make install

配置

原生的nginx-rtmp的所有功能均在nginx的配置文件/usr/local/nginx/conf/nginx.conf中实现。
nginx.conf的整体架构:

#rtmp配置
rtmp {
    server {
        listen 1935;
        chunk_size 4000
        application app_name {
		…………					#配置项
        }
application app_name2 {
		…………					#配置项
        }
		
        application vod {
            play /var/flvs;	#video on demand
        }
	}
}

#nginx配置
http {
server {
	location /hls {
            # Serve HLS fragments
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /tmp;
            add_header Cache-Control no-cache;
        }
	}
}

需要在rtmp{ }中配置各种流媒体相关的配置,在http{ }中配置各种http相关的配置。各个application独立配置,支持正则匹配。
以下介绍一些重要的配置项:

直播基本配置:

rtmp推拉流

rtmp{ server{ * } }中配置以下内容

application mytv {
	live on;
}

如此即配置了发布点为mytv 的直播频道,可以实现rtmp推流和拉流。推拉流地址:

rtmp://ip:1935/mytv/stream

hls

application mytv { * }中配置以下内容

application mytv {
	…………		#省略其他配置
	hls on;
	hls_path /tmp/hls;
	hls_fragment 15s;
}

http { server{ location /hls { } } }中配置以下内容

http {
    ...
    server {
        ...
        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
            }
            root /tmp;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
		}
	}
}

如此配置之后,这个即可进行hls拉流.
详细的关于hls的其他配置。如切片时间命名设置、是否加密hls等配置可以参考:
hls配置文档

MPEG-DASH

application配置段中配置:

dash on;
dash_path /tmp/dash;
dash_fragment 15s;

http配置段中配置:

http {
    ...
    server {
        ...
        location /dash {
            root /tmp;
            add_header Cache-Control no-cache;
            # To avoid issues with cross-domain HTTP requests (e.g. during development)
            add_header Access-Control-Allow-Origin *;
        }
    }
}

MPEG-DASH 实现方式与HLS类似,具体可以查看:
mpeg-dash配置文档

自动转推

当多台nginx-rtmp 服务器运行时,可以配置把流自动推到其他机器上。

rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /var/sock;

rtmp {
    server {
        listen 1935;
        application myapp {
            live on;
        }
    }
}

此功能没有测试过,未知其具体转推是如何实现的。

录制

application mytv { * }中配置以下内容

application mytv {
	…………		#省略其他配置
	# record first 1K of stream
            record all;
            record_path /tmp/av;
            record_max_size 1K;
            # append current timestamp to each flv
            record_unique on;		#开启后每个录制文件根据时间命名
}

其他录制选项可参考:
record配置文档

转码

nginx-rtmp 采用调用外部程序ffmpeg 进行转码。需要在application mytv { * }中配置以下内容

rtmp {
    server {
        listen 1935;
        application src {
            live on;
            exec ffmpeg -i rtmp://localhost/src/$name
              -c:a libfdk_aac -b:a 32k  -c:v libx264 -b:v 128K -f flv rtmp://localhost/hls/$name_low
              -c:a libfdk_aac -b:a 64k  -c:v libx264 -b:v 256k -f flv rtmp://localhost/hls/$name_mid
              -c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 512K -f flv rtmp://localhost/hls/$name_hi;
        }
        application hls {
            live on;
			……
        }
    }
}

exec ffmpeg 这样的配置是会在拉流请求转码流的时候触发ffmpeg 拉流转码,在多台机器做流媒体的时候,可以通过exec_pul 和exec_push 来配置在拉流时触发转码或者在推流时触发转码。

exec

关于调用外部程序,nginx-rtmp 支持多个配置项,参考:
exec配置文档

统计信息

http{ server{ } }中配置可以启用统计信息。

http {
    server {
        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }
        location /stat.xsl {
            root /path/to/stat/xsl/file;
        }
    }
}  
  

访问http://192.168.1.1:8765/stat可以看到当前时间内的各个application 的概况。
也可以下载http://192.168.1.1:8765/stat.xsl 进行统计。
端口号根据nginx配置而定。
statistic

日志

除了原生nginx 自带的error.logaccess.log 两个日志外,nginx-rtmp-module 模块还有一个rtmp-aceesss.log 日志。默认都是在nginx 的安装目录的 /logs 目录中。
查阅资料后发现,nginx 应该是可以自定日志的格式的。在配置文件中也可以定义错误日志的级别,有
debug | info | notice | warn | error | crit 几个级别,大概排查问题都利用debug 级别的错误日志。

控制模块

nginx-rtmp 服务器支持以http的形式从外部对rtmp 进行控制。需要配置以下项。

http {
……
    server {
        listen       8080;
        server_name  localhost;
        ....
        location /control {
            rtmp_control all;
        }
     }
}

再在需要控制的application中预设好各种参数之后,便可以采用类似接口的形式对某些流进行录制,禁播,重定向之类的操作了。以下展示开始和停止录制的url。

curl "http://localhost:8080/control/record/start?app=myapp&name=mystream&rec=rec1"
curl "http://localhost:8080/control/record/stop?app=myapp&name=mystream&rec=rec1" 

具体的控制说明可以查看:
control配置文档

总结

Nginx-rtmp 架构的流媒体服务器实际测试基本功能都有,性能也不错。在配置较差的VPS 上搭建也可以流畅运行,并不占用太多的资源。但是其只能实现简单的功能,实际对于业务以及运营需要改进的地方还有很多。
实测nginx-rtmp 服务器在hls 时,播放有时会有卡顿,原因未知;同码率推到其他流媒体服务器,hls 拉流没有卡顿,可能跟推流也有关系。

Q&As

Q: mpeg dash?
A: 类似于apple家的HLS,MPEG-DASH 是基于HTTP的自适应串流方案中的唯一国际标准。也是有小切片和索引文件组成,SC计划在明年支持此协议。

Q: http callback?
A: 在nginx-rtmp 的官方wiki 中描述的http callback 大概意思为客户端发送连接请求时,会发送一个异步http 请求,会使处理暂停,直到返回状态码之后再根据状态码继续连接请求。具体可以查看:
**https://github.com/arut/nginx-rtmp-module/wiki/Directives#notify **

Q: 多域名配置?
A: 网上资料说nginx 本身是可以改写url 的,有可以配置多个域名;nginx-rtmp 服务器没有说明可以支持多域名的配置,目测在做一些修改之后是可以做到支持多域名的。

Q: 延迟?
A: nginx-rtmp 的拉流和推流,延迟在1s左右。在播放器缓冲设置在0时所测。