Nginx本身是一个非常出色的HTTP服务器,FFMPEG是非常好的音视频解决方案.这两个东西通过一个nginx的模块nginx-rtmp-module,组合在一起即可以搭建一个功能相对比较完善的流媒体服务器.
这个流媒体服务器可以支持RTMP和HLS(Live Http Stream)
一 概要说明
使用nginx搭建流媒体直播平台,目的就是要支持rtmp协议,实现用户使用rtmp(rtmp://192.168.201.128/myapp)协议推送流到服务器。然后其他用户点播该用户推送的视频流信息。既然是rtmp协议,所以客户端可以是flash程序,也可以OBS(Open Broadcaster Software)这种比较大众化的直播客户端。个人是比较喜欢使用OBS的,老实说我其实也是flash和flex开发者,开发个多款WEB视频程序和视频会议系统。Java水平也是很高的。欢迎打脸,我这种人就不怎么谦虚,因为我觉太谦虚就虚伪了.
对于HLS这个比较特殊的流媒体协议的解释:(这段解释来自: http://www.cnblogs.com/haibindev/archive/2013/01/30/2880764.html),HTTP Live Streaming(HLS)是苹果公司(Apple Inc.)实现的基于HTTP的流媒体传输协议,可实现流媒体的直播和点播,相对于常见的流媒体直播协议,例如RTMP协议、RTSP协议、MMS协议等,HLS直播最大的不同在于,直播客户端获取到的,并不是一个完整的数据流。HLS协议在服务器端将直播数据流存储为连续的、很短时长的媒体文件(MPEG-TS格式),而客户端则不断的下载并播放这些小文件,因为服务器端总是会将最新的直播数据生成新的小文件,这样客户端只要不停的按顺序播放从服务器获取到的文件,就实现了直播。由此可见,基本上可以认为,HLS是以点播的技术方式来实现直播。由于数据通过HTTP协议传输,所以完全不用考虑防火墙或者代理的问题,而且分段文件的时长很短,客户端可以很快的选择和切换码率,以适应不同带宽条件下的播放。不过HLS的这种技术特点,决定了它的延迟一般总是会高于普通的流媒体直播协议。
世面上有很多流媒体服务器,有商业的也有开源,比如常用FMS,Red5,wowza.crtmpserver,等,如果是做小型视频会议,我个人强烈推荐Red5。Red5有很开放的api,对于开发实时性要求比较高的很方便。开发工具和开发java的人上手也很快。
二 环境准备
[root@localhost ~]# yum install -y gcc gcc-c++ openssl-devel pcre-devel zlib-devel
2 准备软件包
wget http://nginx.org/download/nginx-1.13.0.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/v1.1.11.tar.gz
2 先解压包,执行编译,安装(软件包已经下载到/app/soft目录下)
[root@localhost soft]# tar -xf nginx-1.13.0.tar.gz
[root@localhost soft]# tar -xf v1.1.11.tar.gz
[root@localhost soft]# cd nginx-1.13.0
[root@localhost nginx-1.13.0]# ./con^C
[root@localhost nginx-1.13.0]# ./configure --prefix=/app/nginx --add-module=/app/soft/nginx-rtmp-module-1.1.11
[root@localhost nginx-1.13.0]# make && make install
3 修改配置文件后内容如下(改配置文件可以参考):
nginx-rtmp-module提供的模板配置文件如下
ll ../nginx-rtmp-module-1.1.11/test/
-rwxrwxr-x 1 root root 49 Feb 13 08:28 dump.sh
-rwxrwxr-x 1 root root 84 Feb 13 08:28 ffstream.sh
-rw-rw-r-- 1 root root 1245 Feb 13 08:28 nginx.conf
-rwxrwxr-x 1 root root 59 Feb 13 08:28 play.sh
-rw-rw-r-- 1 root root 499 Feb 13 08:28 README.md
drwxrwxr-x 2 root root 235 Feb 13 08:28 rtmp-publisher
drwxrwxr-x 4 root root 93 Feb 13 08:28 www
为nginx提供配置文件
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
application myapp {
live on;
#record keyframes;
#record_path /tmp;
#record_max_size 128K;
#record_interval 30s;
#record_suffix .this.is.flv;
#on_publish http://localhost:8080/publish;
#on_play http://localhost:8080/play;
#on_record_done http://localhost:8080/record_done;
}
}
}
http {
include mime.types;
default_type application/octet-stream;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
四 启动服务器,测试
1 启动nginx服务,查看是否开启流推送服务(1935端口),就表示nginx已经支持rtmp推送流了。
[root@localhost conf]# /app/nginx/sbin/nginx
[root@localhost conf]# netstat -antpl | grep nginx
tcp 0 0 0.0.0.0:1935 0.0.0.0:* LISTEN 7089/nginx: master
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 7089/nginx: master
2 拷贝你nginx-rtmp-module-1.1.11/test/www 目录下的所有文件放到nginx的html下。这个是rtmp模块提供的测试案例。就是一个flash客户端推送流和一个播放流的案例;看起来如下:
[root@localhost ~]# \cp -ar /app/soft/nginx-rtmp-module-1.1.11/test/www/* /app/nginx/html/
五 测试,
1 打开浏览器输入地址:http://ip/record.html 这是个推送流的测试地址。打开会提示你允许使用你摄像头。允许就行了(注意,如果nginx部署在其他机器上,需要修改页面代码,record.html、index.html代码中的rtmp://localhost/myapp部分修改为nginx的IP地址)。2 http://ip/index.html,便可以测试播放。
六 使用FFMPEG推送流
nginx配合ffmpeg做流媒体服务器的原理是: nginx通过rtmp模块提供rtmp服务, ffmpeg推送一个rtmp流到nginx, 然后客户端通过访问nginx来收看实时视频流. HLS也是差不多的原理,只是最终客户端是通过HTTP协议来访问的,但是ffmpeg推送流仍然是rtmp的.
1 安装FFMPEG
依赖yasm
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
tar -zxvf yasm-1.3.0.tar.gz
cd yasm-1.3.0
./configure
make
make install
wget http://www.ffmpeg.org/releases/ffmpeg-3.1.tar.gz
tar -zxvf ffmpeg-3.1.tar.gz
cd ffmpeg-3.1
./configure
make
make install
也可以下载windows版本,进行测试
http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20170503-a75ef15-win64-static.zip
2 修改Nginx配置文件
worker_processes 1;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
application myapp {
live on;
}
application hls {
live on;
hls on;
hls_path /tmp/hls;
}
}
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
这是一个最简单,最基础的配置, rtmp监听1935端口,如果是hls的话用hls on开启hls,并且为hls设置一个临时文件目录hls_path /tmp/hls; 其它更高级的配置可以参看nginx-rtmp-module的readme,里面有比较详细的介绍其它的配置,并且它还提供了一个通过JWPlayer在网页上播放的例子.
然后用ffmpeg推流到nginx:
第一个是推到了上面配置的myapp上:
ffmpeg -re -i "F:\spring.mp4" -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -s 1280x720 -q 10 rtmp://ip/myapp/test1
第二个推送到hls上:
ffmpeg -re -i "F:\spring.mp4" -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -s 1280x720 -q 10 rtmp://ip/hls/test2
现在我们的流媒体服务器有两个实时流了,一个是rtmp的,另一个是hls的,用流媒体播放器播放一下,流媒体播放器可以用vlc也可以用ffmpeg带的ffplay.手机也是可以播放的.
上面这两个流的地址分别是:
第一个就是推送的地址: rtmp://ip/myapp/test1
第二个是HTTP地址: http://ip/hls/test2.m3u8
注意,这里的test1、test2随意,只要推流和播放流一致即可。
六 使用OBS(Open Broadcaster Software)推送流
下载OBS软件,安装即可。
点击红圈添加“Media Source”,会弹出一个框框,里面的内容就按照图片显示配置就可以了。点击“OK”就能在你的屏幕上播放了。
配置节目的输出流如图所示,首先点击红圈“setting”进入设置界面。记得要正确填写要录制的服务器路径啊。配置好就可以点击OK了。退出后点击蓝圈,就开始录制节目了。
然后就可以配置的流地址进行观看直播了。
七 点播
rtmp { #RTMP服务
server {
listen 1935; #//服务端口
chunk_size 4096; #//数据传输块的大小
application vod {
play /app/vide/vod; #//视频文件存放位置。
}
}
}
配置目录/app/video/vod为存放视频文件的位置(支持mp4、flv 文件,mp4文件需要的是采用 H.264 和 AAC 的格式编码),放一个qq.mp4文件,打开视频播放软件选用的是VLC media-> open network stream…. ,填写我们要点播的节目地址rtmp://ip/vod/qq.mp4 ,点击play就可以播放了。 注意
七 实时回看视频服务器的配置
我们想一想如果直播服务能够把节目录制在本地,我们不就可以直接进行回看先前的节目了吗?回看一分钟、一小时甚至一天的。想想就兴奋不用写代码有现成的可以使用。怎么用呢?继续看nginx的配置吧。
worker_processes 1;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
chunk_size 4096;
application vod {
play /app/video/vod;
}
application live {
live on;
hls on; #这个参数把直播服务器改造成实时回放服务器。
wait_key on; #对视频切片进行保护,这样就不会产生马赛克了。
hls_path /app/video/hls; #切片视频文件存放位置。
hls_fragment 10s; #每个视频切片的时长。
hls_playlist_length 60s; #总共可以回看的事件,这里设置的是1分钟。
hls_continuous on; #连续模式。
hls_cleanup on; #对多余的切片进行删除。
hls_nested on; #嵌套模式。
}
}
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location /live { #这里也是需要添加的字段。
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias /app/video/hls;
expires -1;
add_header Cache-Control no-cache;
}
}
}
由于nginx需要向服务器写切片视频文件,所以需要对目录写文件
[root@localhost ~]# mkdir /app/video/hls
[root@localhost ~]# chmod -R 777 /app/video/hls
重启Nginx以后,并开始往服务器录制视频,可以看到服务器响应目录下的视频切片文件。
[root@localhost ~]# ll /app/video/hls
-rw-r--r-- 1 nobody nobody 1297576 May 13 10:32 uuid-0.ts
-rw-r--r-- 1 nobody nobody 597088 May 13 10:32 uuid-1.ts
-rw-r--r-- 1 nobody nobody 121 May 13 10:32 uuid.m3u8
播放视频,这次可是http开头的了,“http://ip/live/uuid.m3u8”。已经可以播放了,如何回看呢?其实这个uuid.m3u8文件仅仅是目录。想回看那个就播放那个.ts文件就可以了,比如http://ip/live/uuid-0.ts。
七 总结。总的来说这种方式还不错的,但是如果要实时性高,多人视频就不太适用。
八 监控
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root /app/soft/nginx-rtmp-module-1.1.11/;
}