选取 SRS 流媒体服务器的理由
https://gitee.com/ossrs/srs/wikis/v4_CN_Home
由于 SRS 不支持 Windows 环境下直接搭建,所以采取本地搭建 docker 再搭建 SRS 方法。
拉取 SRS 镜像
https://hub.docker.com/r/ossrs/srs/tags?page=1&ordering=last_updated
docker run -p 1935:1935 -p 1985:1985 -p 8080:8080 \
--name srs-eds1 \
ossrs/srs:latest
启动 SRS 服务器映射到 docker 端口 8080
访问 docker 地址 8080 端口
由于 SRS 管理页面 部署在宿主机,宿主机可通过 docker 的 ip 地址加端口访问,但其他机器无法访问,这样就需要把宿主机的端口映射到 docker 的端口,其他机器可通过宿主机 ip 加端口访问 SRS 管理页面。
1.映射 SRS 管理页面端口
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8080 connectaddress=192.168.99.100 connectport=8080
2.映射 rtmp 端口
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=1935 connectaddress=192.168.99.100 connectport=1935
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=1985 connectaddress=192.168.99.100 connectport=1985
至此 SRS 流媒体服务和 windows 端口映射已搭建完毕。
文件共享实现的方法。本地<–>虚拟机<–>docker 容器
1.打开 VirtualBox
2.设置共享文档文件夹路径,这个路径为与 docker 容器共享的路径,注意启动镜像
设置成功后重启虚拟机后输入 mount,可以看到我们新加入的共享文件夹。
3.重新运行镜像。
docker run -d --name srsVideo -p 1935:1935 -p 1985:1985 -p 8080:8080 -v /d/srsVideo:/usr/local/srs/objs/nginx/html dce4eca99585
-v 是挂载宿主机的目录 上面我们设置了虚拟机共享目录 d/srsVideo 映射到本地 D:\srsVideo,因此我们指定挂载到共享目录为 d/srsVideo。因为 srs 服务器的默认录播保存路径默认是 usr/local/srs/objs/nginx/html,所以我们将
usr/local/srs/objs/nginx/html 路径映射到 d/srsVideo。再通过虚拟机的共享目录 d/srsVideo 映射到本地 D:\srsVideo,实现文件共享功能。dce4eca99585 是镜像 id。
4.检测文件共享是否实现
进入 docker 容器下的 usr/local/srs/objs/nginx/html 目录。
可以看到已经实现了文件共享
当然也可以通过修改配置文件修改录播文件保存的位置。
本地安装ffmpeg,通过命令去拉取直播rtmp流并转为MP4
ffmpeg -i rtmp://xxxx -c:v copy -c:a copy -bsf:a aac_adtstoasc /xxx/xxx.mp4
rtmp://xxx为rtmp流具体地址
/xxx 为你要保存的路径地址
例如:若为linux /xxx 可为/home/myroot/
若为windows /xxx 可为 D:/srsVideo/
xxx.mp4 为文件名
一下为ffmpeg 方法命令 具体可以自行查阅
-bsf:a 比特流过滤器:音频
aac:advanced audio coding 高级音频编码
aac_adtstoasc 从MPEG-2/4 ADTS标头创建MPEG-4 AudioSpecificConfig并删除ADTS标头(adts+es+audioSpecificConfig-adts=mp4)
另外还可以设置在规定时间内判断流是否存在而进行是否停止录播
ffmpeg -rw_timeout 500000 -i rtmp://xxx -c:v copy -c:a copy -bsf:a aac_adtstoasc /home/myroot/Live/srs/replay/eddie.mp4
-rw_timeout 500000:超时5s断流不再拉取rtmp流
温馨提示:为了解决linux和windows环境执行命令不同,执行一次终端命令就要开一个窗口
class PrintErrorReader extends Thread {
java.io.InputStream __is = null;
public PrintErrorReader(java.io.InputStream is) {
__is = is;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(__is));
String line = null;
while ((line = br.readLine()) != null) {
log.info(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class PrintInputStream extends Thread {
java.io.InputStream __is = null;
public PrintInputStream(java.io.InputStream is) {
__is = is;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(__is));
String line = null;
while ((line = br.readLine()) != null) {
log.info(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这样设置的好处是:录播会根据推流地址后缀生成文件夹,并且会根据推流密钥生成录播 m3u8 文件。这样方便我们获取录播文件
主要参考:https://github.com/ossrs/srs/wiki/v2_CN_LowLatency#gop-cache
min_latency:最小延迟打开,默认是打开的,该选项打开的时候,mr 默认关闭。因此这里我们选择 min_latency: on;
mr:Merged-Read,针对 RTMP 协议,为了提高性能,SRS 对于上行的 read 使用 merged-read,即 SRS 在读写时一次读取 N 毫秒的数据
mr {
enabled off;
}
mw_latency:
Merged-Write,SRS 永远使用 Merged-Write,即一次发送 N 毫秒的包给客户端。这个算法可以将 RTMP 下行的效率提升 5 倍左右,范围[350-1800]
gop_cache:
gop 是视频流中两个 I 帧的时间距离,gop 有什么影响?Flash(解码器)只有拿到 gop 才能开始解码播放。也就是说,服务器一般先给一个 I 帧给 Flash。可惜问题来了,假设 gop 是 10 秒,也就是每隔 10 秒才有关键帧
编码器调低 gop,譬如 0.5 秒一个 gop,这样延迟也很低,也不用等待。坏处是编码器压缩率会降低,图像质量没有那么好。
服务器提供配置,可以选择前面两个方案之一:SRS 就这么做,有个 gop_cache 配置项,on 就会马上播放,off 就低延迟。
因此为了降低延迟我们选择 gop_cache off;
queue_length:
配置直播队列的长度,服务器会将数据放在直播队列中,如果超过这个长度就清空到最后一个 I 帧。
tcp_nodelay:
(1)tcp_nodelay off,会增加通信的延时,但是会提高带宽利用率。在高延时、数据量大的通信场景中应该会有不错的效果
(2)tcp_nodelay on,会增加小包的数量,但是可以提高响应速度。在及时性高的通信场景中应该会有不错的效果
因此我们这边选择tcp_nodelay:on 提高响应速度直播降低延时。
由于配置文件 hls 默认设置时长为 60 秒,多余的会被丢弃。所以我们可以通过设置 HLS 最大时长来改变录播丢失问题。由官方 wiki 文档可以获取到相关 hls 配置https://gitee.com/winlinvip/srs.oschina/wikis/v3_CN_DeliveryHLS?sort_id=1701917。
因此我们修改 srs.conf
hls_window 36000: hls 视频保存最长秒数。默认 60,这里为方便实现录播功能设置为 36000 秒,
hls_cleanup off: 切换 HLS 清理,默认情况下,该功能处于打开状态。 在这种模式下,nginx 缓存管理器进程从 HLS 目录中删除旧的 HLS 片段和播放列表。 这里我们设置 off,不清除旧的 ts 文件。
hls_dispose 0: hls_dispose:HLS 清理的过期时间(秒),系统重启或者超过这个时间时,清理 HLS 的所有文件,包括 m3u8 和 ts。默认为 0,即不清理。
HLS 目录中删除旧的 HLS 片段和播放列表。 这里我们设置 off,不清除旧的 ts 文件。
hls_dispose 0: hls_dispose:HLS 清理的过期时间(秒),系统重启或者超过这个时间时,清理 HLS 的所有文件,包括 m3u8 和 ts。默认为 0,即不清理。
1.进入 linux 服务器,选择存放 SRS 文件夹执行
git clone -b 4.0release https://gitee.com/ossrs/srs.git &&
cd srs/trunk && ./configure && make && ./objs/srs -c conf/srs.conf
获取 SRS 相关环境并进行环境编译和运行(Centos7 为例)。
如果报错(Centos8 出现的)
安装环境编译工具 执行命令 yum -y install perl-CPAN
1.可以修改任一 srs 服务器下的 conf 文件,并执行./objs/srs -c conf/xxx.conf 就可以运行自定义的配置下的服务。
2.可以选择后台运行 nohup ./objs/srs -c conf/xxx.conf。
1.可以自主修改 conf 文件下的端口,注意:如果想要用 webRtc 拉流,需要注意的是:webRtc 的开放端口需要开启 udp 转发。flv,hls 需要开启端口 tcp 转发。
例如:
1.webRtc 配置文件设置
值得注意的是:candidate 的配置。candidate 默认会配置成网卡地址,如果是自己本地内网搭建需要做端口转发。例如 本地 docker toolBox 部署默认 candidate 地址是 172.17.0.x 需要通过路由转发命令 route add 172.17.0.0 mask 255.255.0.0 192.168.99.100 把 docker 虚拟机经过的数据转发到网卡 172.17.0.x 网段内,实现拉流。
但现在部署到公网,所以我们把 candidate 设置成域名或者服务器公网 ip。也可以在拉流的时候 webrtc://项目部署地址/live/livestream?eip=服务器 ip 地址 具体设置规则可通过。部署地址可以为域名。
具体规则可以查看:https://github.com/ossrs/srs/wiki/v4_CN_WebRTC#config-candidate
本地 vhost 配置
vhost __defaultVhost__ {
gop_cache off;
mr {
enabled off;
}
tcp_nodelay on;
rtc {
enabled on;
bframe discard;
aac transcode;
twccon;
}
mw_latency 100;
dvr {
enabled on;
dvr_applyall;
dvr_path ./objs/nginx/html/[app]/[stream].[timestamp].mp4;
dvr_plan session;
time_jitter full;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}
play {
mw_latency 0;
mw_msgs 0;
}
min_latency on;
}
1.webrtc 拉流不带端口号 webrtc://SRS 服务器地址(ip 地址或域名)