准备
服务器采用Ngix + RTMP 模块
启动指令
F:\AI\nginx_1.7.11.3_Gryphon\nginx.exe -c conf/nginx-win.conf
注意:nginx: [emerg] CreateFile() "E:\流媒体\nginx/conf/nginx.conf" failed (1113: No mapping for the Unicode character exists in the target multi-byte code page)
这个问题是因为有中文路径导致的问题,因此需要放在英文路径下运行
视频推流
ffmpeg.exe -re -stream_loop -1 -i inputfile.mp4 -vcodec libx264 -acodec aac -f flv rtmp://192.168.11.172:1935/live/home
备注:可能拉流失败,原因是I帧后续发送少了,添加I帧
ffmpeg.exe -re -stream_loop -1 -i inputfile.mp4 -vcodec libx264 -force_key_frames "expr:gte(t,n_forced*1)" -acodec aac -f flv rtmp://192.168.11.172:1935/live/home
播放器拉流指令
ffplay.exe rtmp://192.168.11.172:1935/live/home
nginx.conf配置文件说明
附上最简单的配置
events {
worker_connections 8192;
}
rtmp {
server {
listen 1935;#监听端口,若被占用,可以更改
chunk_size 4000;#上传flv文件块儿的大小
application live {
live on;
}
}
}
1)events是nginx的配置项,不属于RTMP的配置范畴
2)rtmp {...} 保存所有RTMP配置的信息
3)server{...} 声明了一个RTMP的实例,可以声明多个实例,只要端口不冲突,所以可以通过下面方式生成两个RTMP实例,一个监听1935端口,一个监听1936端口
rtmp {
server {
listen 1935;#监听端口,若被占用,可以更改
chunk_size 4000;#上传flv文件块儿的大小
application live {
live on;
}
}
server {
listen 1936;#监听端口,若被占用,可以更改
chunk_size 4000;#上传flv文件块儿的大小
application live {
live on;
}
}
}
注意:server不能另外命名,例如server1,server2
4)listen
语法:listen (addr[:port]|port|unix:path) [bind] [ipv6only=on|off] [so_keepalive=on|off|keepidle:keepintvl:keepcnt]
上下文:server
描述:给 nginx 添加一个监听端口以接收 RTMP 连接。
5)application
语法:application name { ... }
上下文:server
描述:创建一个 RTMP 应用。application 名的模式并不类似于 http location。
server {
listen 1935;
application live{
}
}
注意:当前创建一个名叫live的应用,当我们访问资源的时候,就需要携带上这个应用的名字,例如:
rtmp://192.168.11.172:1936/live/home,1936说明访问RTMP的其中一个实例,然后请求live应用下的home资源
如果没有创建live的应用,就会提示rtmp://192.168.11.172:1936/live/home: I/O error
6)live
语法:live on|off
上下文:rtmp, server, application
描述:切换直播模式,即一对多广播。
live on;
说明
Nginx-rtmp 对 rtmp{...} 内的配置项划分了几个级别:
- 直接隶属于 rtmp{} 块内的配置项称为 main 配置项。
- 直接隶属于 server{} 块内的配置项称为 srv 配置项。
- 直接隶属于 application{} 块内的配置项称为 app 配置项。
- 直接隶属于 record{} 块内的配置项称为 rec 配置项。
配置HTTPS证书访问视频资源
场景
微信小程序只能通过域名和https访问网络资源,因此在nginx-rtmp-module配置HTTPS证书
配置内容
打开conf/nginx.conf文件,拷贝已有的server配置,复制一份粘贴到已有的server下方,然后修改端口为443
server {
listen 443;
ssl on;
ssl_certificate server.crt;
ssl_certificate_key server.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
add_header Access-Control-Allow-Origin '*';
测试
ffplay.exe https://192.168.58.173:443/hls/2/index.m3u8
注意
1)HTTPS证书必须拷贝到conf文件夹,跟nginx.conf文件同一级目录,并且不能指定绝对路径
ssl_certificate server.crt;
ssl_certificate_key server.key;
指定绝对路径出错提示:
nginx: [emerg] BIO_new_file("E:\cvos_srtmp_service\nginx/conf\F:\example\ssls\Debug\server.crt") failed (SSL: error:0200107B:system library:fopen:Unknown error:fopen('E:\cvos_srtmp_service\nginx/conf\F:\example\ssls\Debug\server.crt','r') error:2006D002:BIO routines:BIO_new_file:system lib)
从路径就可以看出,nginx还多添加了配置文件的路径,导致读取HTTPS证书失败
Access-Control-Allow-Origin跨域播放问题解决方案
场景
搭建Nginx + rtmp推流服务器,WEB前后端分离的应用,前端跨域请求视频流,查看浏览器的返回内容,提示:No 'Access-Control-Allow-Origin' header
解决思路
nginx允许跨域是关键, 使用add_header函数添加头即可。添加在 location 节点
解决
修改nginx.conf文件
http {
server {
listen 8081;
add_header Access-Control-Allow-Origin '*'; #添加这一行
add_header 'Access-Control-Allow-Methods' 'PUT,POST,GET,DELETE,OPTIONS'; #添加这一行
add_header 'Access-Control-Allow-Headers' 'Content-Type,Content-Length, Authorization, Accept,X-Requested-With';#添加这一行
location /hls {
#server hls fragments
add_header Access-Control-Allow-Origin '*';#添加这一行,支持访问视频流
types{
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias "D:/hls/"; #视频流文件目录,跟上面的hls_path保持一致
expires -1;
}
}
HLS流媒体服务器部署
知识准备
HLS是Apple推出的直播协议,是通过视频流切片成文件片段来直播的。客户端首先会通过HTTP请求一个m3u8文件,里面会有不同码率的流,或者直接是ts文件列表,通过给出的ts文件地址去依次播放。在直播的时候,客户端会不断请求m3u8文件,检查ts列表是否有新的ts切片。这种方式的实时性较差,不过优势是H5、IOS、Android都原生支持。
在nginx.conf中配置
推送的数据会保存在F:/hls,设置分片和时间段
rtmp {
server {
listen 1935;#监听端口,若被占用,可以更改
chunk_size 4000;#上传flv文件块儿的大小
application hls{
live on;
hls on;
hls_path "F:/hls/";#视频流文件目录
hls_fragment 1s;#没有生效
hls_playlist_length 30s;
hls_nested on; #默认是off。打开后的作用是每条流自己有一个文件夹
hls_cleanup off;#不清理ts
}
}
}
在http中的server添加m3u8数据类型的点播配置
http {
server {
listen 80;
server_name localhost;
location /hls { #这里也是需要添加的字段。
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias "F:/hls/"; #视频流文件目录,跟上面的hls_path保持一致
expires -1;
add_header Cache-Control no-cache;
}
推流指令
ffmpeg.exe -re -stream_loop -1 -i inputfile.mp4 -vcodec libx264 -acodec aac -f flv rtmp://192.168.11.172:1935/hls/home
-stream_loop -1:循环读取文件推流
由于我们配置了rtmp中的应用hls,支持hls协议,所以会在F:/hls/文件夹下创建一个test文件夹,里面保存了
推流生成的文件,进入到文件夹,可以看到0.ts和index.m3u8等文件,index.m3u8文件记录了文件的信息以及文件切割之后的列表
取流指令
ffplay.exe http://192.168.11.172:80/hls/home/index.m3u8
取流的时候,将不再经过rtmp协议进行流的获取,而是通过http服务获取,端口是http的服务端口
从上面可以看出来配置rtmp的hls应用是推流保存文件,配置http中的hls应用是配置拉流
注意:一旦启用hls,将无法通过ffplay.exe rtmp://192.168.11.172:1935/hls/home点播视频流
配置一个mp4可读取文件地址
配置nginx-win.conf
rtmp {
server {
listen 1935;#监听端口,若被占用,可以更改
chunk_size 4000;#上传flv文件块儿的大小
application live { #创建一个叫live的应用
live on;#开启live的应用
allow publish 127.0.0.1;#
allow play all;
hls_path "F:/hls/";
hls_fragment 2s;
play "F:/AI/nginx_1.7.11.3_Gryphon/file";
}
}
}
其中
play "F:/AI/nginx_1.7.11.3_Gryphon/file";配置了rtmp服务器读取文件的地址,文件必须直接放在这个目录,如果里面创建其他的目录,读取不到
例如将一个test.mp4文件放在file文件夹下,访问路径是rtmp://192.168.58.173:1935/live/test.mp4,其中live是一个应用