利用SRS拉取摄像头辅码流实现浏览器展示多路摄像头预览功能

如标题所示。关键词:SRS,辅码流,浏览器,多路预览。效果如图,在一张浏览器页面,同时展示9个摄像头的预览画面。

怎么做到的?

一句话概括,就是:
用SRS拉取摄像头的辅码流(子码流),处理成浏览器可以直接播放的HTTP-FLV格式(如http://172.16.10.124:18080/live/cam20922.flv)。

摄像头的视频流有主码流、辅码流(子码流),主码流分辨率高,高清,用于观察、大屏展示、存储和回放;而辅码流低分辨率,视频质量较低,适合预览,或在手机中播放。换言之,主码流占带宽多,子码流占带宽少,要想在一个页面同时预览多个摄像头画面,必须用子码流。其实按摄像头厂家的说法,就算用子码流,同时显示9路摄像头,也是非常吃力的。

我们项目中,摄像头是注册到一个国标视频平台(国产开源的wvp-GB28181-pro),浏览器用的是它转码后的播放地址。但这个地址并没有分成主码流和子码流两种,要么是主码流,要么是子码流。由于国标的视频流用于正常播放,所以拉取子码流的话,就要另想办法,于是想到用SRS处理子码流。

下面是详细介绍。

一、部署SRS

SRS(Simple Realtime Server)是一个简单高效的实时视频服务器,支持RTMP、WebRTC、HLS、HTTP-FLV、SRT等多种实时流媒体协议。它也是国产开源项目。

我的想法是,采用SRS,拉取19个摄像头的子码流。摄像头提供的是RTSP协议的视频流,SRS支持RTSP,可以拉取和转成浏览器支持的HTTP-FLV格式。但是,如果摄像头提供的流是H.265格式的话,浏览器目前基本播放不了,需要转成H.264。SRS需要调用ffmpeg来完成这个转换工作。ffmpeg是一个法国程序员发起的音视频工具集,应用广泛,我看好多地方都用它。比如上面提到的国标视频平台wvp-GB28181-pro,底层用的也是ffmpeg。

我们服务器是国产的UOS 1070e,CPU海光的,也是AMD架构。采用docker镜像来部署SRS。该镜像内置了ffmpeg。但是官方文档却没有提到内置ffmpeg,同时官方文档也没有介绍我这个需求的解决方案,即如何拉取摄像头的RTSP视频流,并转化成HTTP-FLV,全靠问AI和摸索了。你看看它文档写的,不知道的还以为它镜像里根本没有ffmpeg,需要自己去下载。而且手动调用ffmpeg的做法,我认为是玩具级别的,根本不实用。万一有异常发生,ffmpeg就退出了,如何维护这个重启机制?简直不知所谓。

闲话休提,以下是SRS的部署及设置步骤。

1、部署SRS

1)拉取镜像

bash 复制代码
sudo docker pull registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5

采用docker确实是有助于简化安装。尤其是对于我们来说,生产服务器无法上网,可以在开发环境将docker镜像导出,再在服务器导入。

2)创建docker容器

将配置文件所在目录conf外挂到宿主机

bash 复制代码
sudo docker run --restart=always -d -it --name srs \
-p 1935:1935 -p 1985:1985 -p 18080:8080 \
-v /home/work/docker/srs/conf:/usr/local/srs/conf \
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5

2、设置拉流

配置一个 ingest 拉取 RTSP 流。编辑conf/docker.conf。注意不是srs.conf,而是docker.conf!

以下是向一个摄像头拉流,其余摄像头类似。有多少个摄像头就配多少个ingest。

bash 复制代码
    ingest cam20112 {
        enabled      on;
        input {
            type    stream;
            url     rtsp://192.168.201.12:554/stream_1;
        }
        ffmpeg      /usr/local/srs/objs/ffmpeg/bin/ffmpeg;#注意要写绝对路径
        engine {
            enabled     on;
            output      rtmp://127.0.0.1/live/cam20112;#把流"注册"进 SRS 的直播系统
            ff_opts { #ffmpeg处理参数
                -i [input];
                -c:v libx264; #转化为H.264
                -preset ultrafast;
                -profile:v baseline;
                -level 3.1;
                -g 30;
                -b:v 512k; # 目标码率
                -maxrate 512k;# 最大码率(匹配摄像头)
                -bufsize 1024k;
                -vf "scale=640:360";#进一步降低分辨率
                -r 15;
                -an; #禁用音频
                -f flv;
            }
        }
    }

这句 output rtmp://127.0.0.1/live/cam20112; 把流"注册"进 SRS 的直播系统。SRS 有一个核心特性:只要有一条 RTMP 流进入系统(无论来源是推流还是 ingest 拉流),它会自动提供多种协议的输出,其中包括浏览器支持的HTTP-FLV。如上例,SRS运行以后,我们就可以在VLC里播放地址http://宿主机IP:18080/live/cam20112.flv 了。8080是SRS的http端口,但我们创建容器的时候映射到了宿主机的18080。

以下是一个完整的docker.conf示例。里面只处理了一个摄像头,增加摄像头处理就增加ingest即可。

bash 复制代码
# docker config for srs.
# @see full.conf for detail config.

listen              1935;
max_connections     1000;
# For docker, please use docker logs to manage the logs of SRS.
# See https://docs.docker.com/config/containers/logging/
srs_log_tank        console;
daemon              off;
http_api {
    enabled         on;
    listen          1985;
}
http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
}
rtc_server {
    enabled on;
    listen 8000;
    # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate
    candidate $CANDIDATE;
}
vhost __defaultVhost__ {
    hls {
        enabled         on;
    }
    http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
    }
    rtc {
        enabled     on;
        # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtmp-to-rtc
        rtmp_to_rtc on;
        # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtc-to-rtmp
        rtc_to_rtmp on;
    }

    ingest cam20112 {
        enabled      on;
        input {
            type    stream;
            url     rtsp://192.168.201.12:554/stream_1;
        }
        ffmpeg      /usr/local/srs/objs/ffmpeg/bin/ffmpeg;
        engine {
            enabled     on;
            output      rtmp://127.0.0.1/live/cam20112;
            ff_opts {
                -i [input];
                -c:v libx264;
                -preset ultrafast;
                -profile:v baseline;
                -level 3.1;
                -g 30;
                -b:v 512k;
                -maxrate 512k;
                -bufsize 1024k;
                -vf "scale=640:360";
                -r 15;
                -an;
                -f flv;
            }
        }
    }
    
    #可继续增加ingest
}

二、设置摄像头辅码流

摄像头本身也应该设置一下辅码流,这样利于提升传输效率。

三、nginx转发

如上所述,SRS启动以后,我们就可以播放类似http://宿主机IP:18080/live/cam20112.flv 的视频地址了。但是,如果我们站点是https的,只能播放同样是https的网址,不能直接播放http的网址,需要使用nginx转发一下,转成https的URL。

bash 复制代码
# 已知本网站支持https
location /prv/ {
    #http://172.16.10.124:18080/live/cam20922.flv
    proxy_pass http://172.17.0.10:8080/live/;#172.17.0.10是SRS的docker容器地址
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 3600s;
}

注意代转发的地址有讲究。已知 nginx 和 SRS 都采用docker部署。如前所述,虽然SRS已经将8080映射到了宿主机的18080,但nginx转发的时候,并不能使用宿主机的ip来访问SRS的流。不知道为什么,我的服务器里,docker容器可以互相访问。但我记得我没有创建docker网络,创建每个docker容器时也没有显式指定使用docker网络,但是生产服务器的docker容器确实可以互相访问。其中SRS的docker地址是172.17.0.10,所以在nginx的配置文件中,直接转发SRS的地址:

bash 复制代码
proxy_pass http://172.17.0.10:8080/live/;#172.17.0.10是SRS的docker容器地址

五、浏览器播放

虽然摄像头的辅码流一再降低质量,但是用浏览器打开预览页面,9个摄像头只能出来6个。刷新、切换页面都是如此。后来找到原因了,是浏览器的限制。现代浏览器对同一域名(host)的 HTTP/1.1 并发连接数限制为 6 个(Chrome/Firefox/Edge 等均如此)。由于我使用了同一个nginx对flv流进行转发,所有 FLV 流都来自同一个域名:https://172.16.10.124/prv/...,因此,最多只能同时建立 6 个 TCP 连接,也就最多播放 6 路视频,第 7 个及以后的请求会被排队阻塞,直到前面某个连接关闭或超时。

真是岂有此理。我于是在生产服务器增加了1个nginx(端口跟第一个nginx不同)做转发;播放时,将摄像头分成2组,一组播放用nginx1转发的地址,另一组播放nginx2转发的地址,果然9个都出来了。

相关推荐
派阿喵搞电子7 天前
配置srs的鉴权时遇到的问题
服务器·docker·容器·srs
QC七哥3 个月前
流媒体服务SRS环境的搭建
srs·流媒体
ShaYQ6 个月前
一个WebRTC 分辨率动态爬升问题记录与解决过程
webrtc·srs·动态分辨率·流媒体技术·分辨率爬升
Edward-tan7 个月前
Docker配置SRS服务器 ,ffmpeg使用rtmp协议推流+vlc拉流
docker·ffmpeg·srs·rtmp
丁丁丁梦涛8 个月前
SRS transcode支持 h264_nvenc 硬件解码方案
srs·gpu硬件解码·srs transcode·h264_nvenc·srs流媒体硬件加速解码
只是个~小不点1 年前
流媒体之linux下离线部署FFmpeg 和 SRS
linux·ffmpeg·srs·流媒体
汪小敏同学1 年前
docker进行SRS直播服务器搭建
docker·srs
wyw00001 年前
解决SRS推送webrtc流卡顿问题
webrtc·srs
冰山一脚20131 年前
SRS服务器搭建
srs