基于FFmpeg+rtsp读取摄像头实时图像

Posted hs977986979

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于FFmpeg+rtsp读取摄像头实时图像相关的知识,希望对你有一定的参考价值。

项目介绍:前端时间做了一个项目用qt 编写软件获取海康摄像头rtsp视频流,实现实时显示。当时采用的是VLC-Qt播放RTSP流这种方式(参考:基于libVLC的视频播放器之二:使用VLC-Qt播放RTSP流_草上爬的博客-CSDN博客_libvlc rtsp)。花了一段时间研究也做出来了,可是发现了一个无法解决的问题,即无法解决视频延迟的问题,差不多延迟1秒左右。后面果断

放弃了,采用FFmpeg+rtsp这种方式。最终发现还是这种方式效果最好,解决了延迟问题,至少肉眼看不出。下面对此项目做个大致介绍,文章最后附上项目开发相关资料。

提示:使用rtsp方式获取海康摄像头图像需要开启海康的onvif功能。

参考连接:海康威视摄像头:开启onvif协议_海康威视_珠海陈坚浩博客

开发介绍:

开发软件:qt5.14.2

构建:MinGW64 bit

ffmpeg版本:3.4-win64

软件截图:

海康摄像头:

 现在网络摄像头很多都支持rtsp方式显示图像,通过这种方式一个软件可以显示很多厂家的摄像头,兼容性更强。

提供不同厂家摄像头的rtsp地址:

一、海康、中威摄像机

格式1:

主码流:rtsp://admin:12345@192.168.1.64:554/Streaming/Channels/1

子码流:rtsp://admin:12345@192.168.1.64:554/Streaming/Channels/2

第三码流:rtsp://admin:12345@192.168.1.64:554/Streaming/Channels/3

格式2:

rtsp://admin:12345@192.168.1.64:554/ch1/main/av_stream

二、大华

rtsp://admin:12345@192.168.1.64:554/cam/realmonitor?channel=1&subtype=0

三、英飞拓

球机:

单播和组播地址一致

高码流(主码流)RTSP地址:rtsp://admin:admin@192.168.1.64/1/1080p

低码流(子码流)RTSP地址:rtsp://admin:admin@192.168.1.64/1/D1

半球和枪机:(亭子、车道)

单播:

高码流(主码流)RTSP地址:rtsp://192.168.1.64:554/1/h264major

低码流(子码流)RTSP地址:rtsp://192.168.1.64:554/1/h264minor

组播:

高码流(主码流)RTSP地址:rtsp://192.168.1.64:554/1/h264major/multicast

低码流(子码流)RTSP地址:rtsp://192.168.1.64:554/1/h264minor/multicast

四、三星

单播:

高码流rtsp地址:

rtsp://admin:admin001@192.168.1.64:554/onvif/profile2/media.smp(720P)

低码率rtsp地址

rtsp://admin:admin001@192.168.1.64:554/onvif/profile3/media.smp

组播:

高码流rtsp地址:

rtsp://admin:admin001@192.168.1.64:554/onvif/multicast/profile2/media.smp (720p)

低码流rtsp地址:

rtsp://admin:admin001@192.168.1.64:554/onvif/multicast/profile3/media.smp

五、宇视:

rtsp://admin:admin@192.168.1.64/media/video1/multicast

六、LG

单播和组播地址一致

高码流(主码流)RTSP地址:rtsp://admin:admin@192.168.1.64:554/Master-0

低码流(子码流)RTSP地址:rtsp://admin:admin@1192.168.1.64:554/Slave-0

七、派尔高网络摄像机:

RTSP主码流地址为:rtsp://192.168.1.64/h264

第一从码流RTSP地址为:rtsp://192.168.1.64/h264_2

第二从码流RTSP地址为:rtsp://192.168.1.64/h264_3

八、安讯士网络摄像机:

单播:

rtsp://root:123456@192.168.1.64/axis-media/media.amp?videocodec=h264&resolution=1280x720&fps=25

组播:

rtsp://root:123456@192.168.1.64/onvif-media/media.amp?profile=profile_1_h264&streamtype=multicast

http://root:123456@192.168.1.64/axis-cgi/alwaysmulti.sdp?camera=1

九、非凡

rtsp://admin:12345@192.168.1.64:554/streaming/channels/101

十、金三立

rtsp://Admin:111111@192.168.1.64/stream/av0_0

以上是项目的大致介绍;提供开发资料如下链接地址:

链接:https://pan.baidu.com/s/1SqF-w86mNFtJyh24mGxYcA?pwd=ms3g 
提取码:ms3g

无实时约束处理大量 rtsp 摄像头

【中文标题】无实时约束处理大量 rtsp 摄像头【英文标题】:Handle large number of rtsp cameras without real-time constraint 【发布时间】:2022-01-09 07:12:36 【问题描述】:

问题定义

假设我有大量的rtsp相机(> 100),我想对其进行一些操作,例如图像特征提取。

重要:我对实时性能不感兴趣,我可以在一分钟内进行 4 次特征提取。显然,越多越好!

现在,瓶颈是图像采集。帧是用cv2获取的 请阅读以下部分了解我的尝试。

伪代码(当前解决方案)

while True:
    for every rstp_cameras:
        open_connection
        read_current_frame(no batch - the real time frame)
        process_frame
        close

我尝试过的

在 *** 上,您可以找到很多关于实时读取 rtsp 摄像头的答案,但都受到摄像头数量的限制或存在一些缺点。 我试过(用python):

    每个相机的线程 [cv2 with ffmpeg] 为线程中的每个摄像头打开一个连接,然后获取每个摄像头可用的最后一帧。 此解决方案有效,但仅适用于少量摄像机。如果我们增加数字,高端 cpu 的使用率将达到 100%(因为线程在后台总是读取最后一帧,如果我不问最后一帧,则丢弃它) [当前解决方案,无线程,ffmpeg with cv2] 在每次迭代时打开一个连接,读取帧并关闭连接。此解决方案使我可以使用最后一帧,但主要缺点是打开期间丢失了时间(打开所有帧丢失了大约 70 秒) 带有 gstreamer 的 Cv2,无线程 基于此answer。 如果您的摄像头数量很少,这是我发现的最佳解决方案。使用 20 台或更多相机时,线程解决方案也有同样的问题。

问题与回顾

现在,我很清楚,在一个工作站中处理所有这些摄像机是很困难的,因为我找到的所有解决方案都是为了返回可用的最后一帧(实时)连续读取背景。

目前,我还没有找到一个解决方案,可以让我打开一次连接,读取低 cpu 使用率的实时帧,这样我就可以在大量摄像头上使用它。

阅读的并行化是解决问题的唯一方法吗?我的意思是,将相机分成批次,在不同的工作站分配批次,然后以某种方式组合图像?

谢谢。

【问题讨论】:

是时候深入挖掘 ffmpeg 的 API 并直接使用它了。 OpenCV 具有用于视频 I/O 的方便接口。它们不是用来承受负载的。 【参考方案1】:

您可以尝试使用带有-discard nokey 参数的FFmpeg,如here 所述。 我不确定它是否会起作用......

据我了解,-discard nokey 仅解码关键帧,并跳过所有其他视频帧。 假设只解码关键帧可以大大减少 CPU 使用率(取决于关键帧的频率)。


这是一个代码示例(针对一个 RTSP 流):

import numpy as np
import subprocess as sp


# Use public RTSP Streaming for testing:
in_stream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"

# Use OpenCV for getting the video resolution.
cap = cv2.VideoCapture(in_stream)

# Get resolution of input video
width  = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# Release VideoCapture - it was used just for getting video resolution
cap.release()


# http://zulko.github.io/blog/2013/09/27/read-and-write-video-frames-in-python-using-ffmpeg/
FFMPEG_BIN = "ffmpeg" # on Linux ans Mac OS (also works on Windows when ffmpeg.exe is in the path)

ffmpeg_cmd = [FFMPEG_BIN,
              '-discard', 'nokey',
              '-rtsp_transport', 'tcp',
              '-max_delay', '30000000',  # 30 seconds
              '-i', in_stream,
              '-f', 'rawvideo',
              '-pix_fmt', 'bgr24',
              '-vcodec', 'rawvideo', '-an', 'pipe:']

# Open sub-process that gets in_stream as input and uses stdout as an output PIPE.
process = sp.Popen(ffmpeg_cmd, stdout=sp.PIPE)


while True:
    raw_frame = process.stdout.read(width*height*3)

    if len(raw_frame) != (width*height*3):
        print('Error reading frame!')  # Break the loop in case of an error (too few bytes were read).
        break

    # Transform the byte read into a numpy array, and reshape it to video frame dimensions
    frame = np.frombuffer(raw_frame, np.uint8).reshape((height, width, 3))

    # Show frame for testing
    cv2.imshow('frame', frame)
    cv2.waitKey(1)
  
process.stdout.close()
process.wait()
cv2.destroyAllWindows()

如上尝试打开100个FFmpeg子进程...

【讨论】:

感谢您的回复!是的,它似乎对cpu的影响很小。但是,我做了这个实验,它不起作用。我创建了 100 个进程,遍历它们(在 while True 内)并读取框架。在最后一次迭代中(即当我到达第 100 个相机时,我插入了一个time.sleep(8)。然后,如果我观看我保存的图像,我可以看到它们没有反映现实,它们积累了很高的延迟,肯定大于8秒,好像被缓存了一样。这是个问题,我希望我看帧的时候能反映真实情况。 为避免堆积,为每个摄像头创建一个读取线程(排空管道)。仅在非常特殊的情况下,简单地迭代摄像机才会起作用,即所有视频流的 GOP 大小相同,并且您可以足够快地读取帧以避免累积。 我认为插入thread 来排空管道可能会使cpu 饱和,就像其他涉及线程的解决方案一样。 我认为线程不会使 CPU 饱和,因为执行 raw_frame = process.stdout.read(width*height*3) 不是 CPU 密集型的 - 在数据准备好之前,线程应该处于挂起状态。即使等待(内​​部 Python 实现)不是最有效的(并且存在上下文切换开销),它仍然是相对较轻的 CPU 任务。 好吧,我不明白你的意思。我会试试看。谢谢!

以上是关于基于FFmpeg+rtsp读取摄像头实时图像的主要内容,如果未能解决你的问题,请参考以下文章

无实时约束处理大量 rtsp 摄像头

FFmpeg 代码实现流媒体推流(RTSP)

FFmpeg入门详解之124:Qt5 FFmpeg单路网络摄像头采集预览

使用 ffmpeg 将低延迟 RTSP 视频流式传输到 android

华为海康大华摄像头编译RTSP转RTMP和HTTPFLV

QT软件开发-基于FFMPEG设计录屏与rtsprtmp推流软件(支持桌面与摄像头)