树莓派4B+Mediamtx推RTSP流实现远程监控(云服务器版)

前言

        

        最近在进行一个计算机视觉应用项目,需要用到树莓派集成摄像头对视频数据进行采集,使用ffmepg将视频数据推流到RTMP、RTSP服务器。推流至服务器的视频数据可以在PotPlayer、VLC等媒体播放器中,通过服务器ip加端口号拉流播放。此外,使用Python中的Opencv库同样可以实现拉流播放。

应用场景

        基于家庭防盗、店铺值守等应用场景进行设计,树莓派端需要具备开始停止推流功能。

技术思路

        树莓派端启动web服务,设置端口为0.0.0.0以监听任意外来的请求,根据请求的内容执行推流操作。

技术实现

        树莓派使用原生相机推rtsp流到云服务器

# 基于ffmpeg

ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -preset fast -an -rtsp_transport tcp -f rtsp rtsp://ip:port/stream 

 参数解析:

ffmpeg:音视频开发的利器,需要提前安装

-f f4l2:指定输入格式为 Video4Linux2(V4L2)。V4L2 是 Linux 系统中用于处理视频捕获的标准接口,常用于从摄像头读取数据。

-i /dev/video0:指定输入源,原摄像头ov5647同样可以使用该设备号

-c:v libx264: 设置视频编码器为 libx264。这是一个广泛使用的开源 H.264 视频编码器,用于压缩视频以减少所需的带宽。

-preset fast: 指定编码器预设为 fast。预设决定了编码的速度和压缩率,fast 提供了较快的编码速度,适用于实时视频流。

-an: 禁用音频录制。这意味着命令只处理视频流,不包括任何音频流。

-rtsp_transport tcp: 指定 RTSP 流使用 TCP 作为传输协议。相比于默认的 UDP,TCP 提供了更可靠的数据传输,但可能会稍微增加延迟。

-f rtsp: 指定输出格式为 RTSP。

rtsp://121.40.46.108:8554/stream: 这是视频流的目标地址。它表示将视频流推送到 IP 地址为 121.40.46.108,端口 8554 的服务器上,流名称为 stream

注:一定要加上`-rtsp_transport tcp`,如果不加会默认会采用udp数据,博主在未加该参数的时候出现了`av_interleaved_write_frame(): Broken pipe Last message repeated 4 times`,分析是因为使用了不可靠协议udp导致传了4个重复的帧到流媒体服务器,而流媒体服务器将这判断为异常边主动断开连接。

        流媒体服务器搭建

        目前github上有一个开源的流媒体服务器项目非常方便,博主便是通过其提供的docker镜像来搭建的流媒体服务器

# 拉取镜像启动流媒体服务器

docker run --rm -it --network=host --name mediamtx bluenviron/mediamtx:latest

# 启动命令后便能看到协议对应的端口情况,下次再启动在 run 后加上 -d 则会在后台显示

        此时会支持使用rtsp、rtmp等协议的流的接收 

        使用vlc拉流

        

        输入推流地址,便能够拉流成功,此时便能够使用opencv拉取该流进行一些下游任务

技术难点

        1.树莓派端如何建立一个可以监听请求的服务。

                考虑到比较熟悉python,并且python中存在直接执行shell语言的库,故选择用python来实现这一功能。调用socket库,在树莓派端建立一个web服务,并且循环监听。监听ip地址需要设置为0.0.0.0,表示监听所有的ip地址。也许可以设置为其他ip,但没尝试过。

        2.如何根据外来的请求执行相应的操作

                由于主程序不断循环监听外部请求,因此若要实现主程序不受影响,并且能够执行其他需要的操作。考虑使用threading创建线程,把需要执行的操作封装成一个函数,并将函数传入线程中执行。

        3.如何正确关闭推流程序

                当推流程序被启动后,该推流程序相当于是在刚才主程序创建的线程中再次创建了一个进程。当使用 “进程变量”.terminate() 关闭该子进程,推流进程仍然会执行。可以实现的方案有两种。一种是,使用proegress = subprogress.popen("exec XXX"),当在shell指令前加上exec的时候,当需要结束进程的时候,使用progress.terminate()。第二种方案是直接使用subpregress.call("['pkill', '-f', '推流shell指令']"),这样可以根据进程名称定位并杀死它。

        4.推流前可能存在摄像头故障、云服务器异常。

                摄像头接入树莓派4b,系统会为该设备分配一个设备号。不管是csi摄像头,还是usb摄像头,都可以使用 ls -l /dev/video* 来查看。(不同之处在于,使用csi摄像头可以使用树莓派原生的命令搭配ffmepg进行推流。使用usb摄像头则可以直接使用ffmpeg推流。)。在实际操作过程中遇到这样的情况,正常分配给树莓派设备号为video0,在运行一段时间后会跳为video1。针对这种情况我尝试过为usb口分配固定的名称,但是却不好使,最后想到在启动推流程序前,检查video0是否存在,如不存在则让树莓派重启。

                关于检查目标云服务器是否正常,我尝试在主程序中执行一个脚本,执行推流命令,睡眠5s,查看推流进程是否存在,根据查看情况输出相关信息,并通过使用推流命令来杀死进程。

        5.推流进程在后台正常运行,但是视频数据传输出现问题。

               这个原因多出现于网络原因,出现这种原因的时候,推流日志中视频的FPS会一直下降,当下降到一定值的时候就会和云服务器断开连接。针对这种情况,我考虑实时监测网络流量,每1s执行一次 ‘ip -s link show dev usb0’ ,根据packets的变化值,判定是否推流异常。

        当树莓派端搭建完成后,就需要考虑通过何种方式来进行操控。

                1.考虑是否可以使用直接让app与树莓派进行通信,通过app直接传达需要执行的操作。

                       具体实现在《使用uni-app开发一个简易的app》文章介绍。

                2.考虑是否一个搭建一个中转站,这个中转站能过够对信号进行转发。

                       具体实现在《使用flask搭建web服务,计算机视觉任务落地》文章介绍。

代码实现

        目前代码还不方便公开,后续会整理上传,相关问题,可以留言,一起交流。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值