python OpenCV真实的流媒体视频捕获速度很慢,如何丢弃帧或与实时同步?

8oomwypt  于 2023-01-08  发布在  Python
关注(0)|答案(3)|浏览(855)

目标和问题

我想设置一个opencv系统来处理HLS流或RMTP流,但是,我遇到了一个奇怪的问题,关于降低的帧速率和累积的滞后。这就好像视频变得越来越落后,从它应该在流中。
我正在寻找一种方法,以跟上最新的生活来源,即使这意味着下降帧。

当前方法

import cv2

cap = cv2.VideoCapture()
cap.open('https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w1421640637.m3u8')

while (True):
    _, frame = cap.read()
    cv2.imshow("camCapture", frame)
    cv2.waitKey(1)

我已经在VLC上验证了流的质量,它似乎在那里工作得很好。

cv2速度


实际/预期速度

问题:

  • 我到底做错了什么?
  • 怎么这么慢?
  • 如何将其同步到实时速度?
l7wslrjt

l7wslrjt1#

我的假设是,抖动最有可能是由于网络限制,并且在帧数据包丢失时发生。当帧丢失时,这会导致程序显示最后一个“好”帧,从而导致显示冻结。这可能是硬件或带宽问题,但我们可以通过软件减轻一些问题。以下是一些可能的更改:

1.设置最大缓冲区大小

我们使用cv2.CAP_PROP_BUFFERSIZE参数设置cv2.videoCapture()对象的缓冲区大小,其思想是通过限制缓冲区大小,我们将始终拥有最新的帧,这也有助于缓解帧随机向前跳跃的问题。

2.设置帧检索延迟

目前,我认为read()阅读太快,即使它是在自己的专用线程中。这可能是所有帧似乎汇集在一起并在下一帧中突然爆发的原因之一。例如,在一秒的时间间隔内,它可能产生15个新帧,但在下一秒的时间间隔内,仅返回3个帧,这可能是由于网络分组帧丢失而导致的,因此为了确保我们获得恒定的帧速率,我们只是在帧检索线程中添加了一个延迟。获得大约~30 FPS的延迟很好地“规范化”了帧速率并且在存在分组丢失的情况下平滑帧之间的过渡。

**注意:**我们应该尝试匹配流的帧速率,但我不确定摄像头的FPS是多少,所以我只是猜测30 FPS。此外,通常有一个“直接”流链接,而不是通过中间的Web服务器,这可以大大提高性能。

如果您尝试使用保存的.mp4视频文件,您会注意到没有抖动。这证实了我的怀疑,问题很可能是由于网络延迟。

from threading import Thread
import cv2, time

class ThreadedCamera(object):
    def __init__(self, src=0):
        self.capture = cv2.VideoCapture(src)
        self.capture.set(cv2.CAP_PROP_BUFFERSIZE, 2)
       
        # FPS = 1/X
        # X = desired FPS
        self.FPS = 1/30
        self.FPS_MS = int(self.FPS * 1000)
        
        # Start frame retrieval thread
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()
        
    def update(self):
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()
            time.sleep(self.FPS)
            
    def show_frame(self):
        cv2.imshow('frame', self.frame)
        cv2.waitKey(self.FPS_MS)

if __name__ == '__main__':
    src = 'https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w1421640637.m3u8'
    threaded_camera = ThreadedCamera(src)
    while True:
        try:
            threaded_camera.show_frame()
        except AttributeError:
            pass

相关的摄像头/IP/RTSP/流媒体、FPS、视频、线程和多处理帖子

  1. Python OpenCV streaming from camera - multithreading, timestamps
  2. Video Streaming from IP Camera in Python Using OpenCV cv2.VideoCapture
  3. How to capture multiple camera streams with OpenCV?
  4. OpenCV真实的流媒体视频捕获速度很慢。如何丢弃帧或与实时同步?
  5. Storing RTSP stream as video file with OpenCV VideoWriter
  6. OpenCV视频保存
  7. Python OpenCV multiprocessing cv2.VideoCapture mp4
ct3nt3jp

ct3nt3jp2#

尝试穿线

我已经尝试过nathancythis解决方案,并取得了一些成功。
它涉及:

  • 创建用于从源捕获图像的单独线程
  • 将主线程专用于显示。

代码:

import cv2
from threading import Thread

class ThreadedCamera(object):
    def __init__(self, source = 0):

        self.capture = cv2.VideoCapture(source)

        self.thread = Thread(target = self.update, args = ())
        self.thread.daemon = True
        self.thread.start()

        self.status = False
        self.frame  = None

    def update(self):
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()

    def grab_frame(self):
        if self.status:
            return self.frame
        return None
if __name__ == '__main__':
    stream_link = "https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w1421640637.m3u8"
    streamer = ThreadedCamera(stream_link)

    while True:
        frame = streamer.grab_frame()
        if frame is not None:
            cv2.imshow("Context", frame)
        cv2.waitKey(1)

抖动,但结果实时



流媒体是有效的。它保持了实时性。然而,它就像所有的帧汇集在一起,突然爆发成视频。我希望有人能解释这一点。

改进空间

实时流可以在这里找到。
https://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet
这个站点是使用python的streamlink流scraper为m3u8抓取的。

import streamlink

streams = streamlink.streams("https://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet")
print(streams)

其产生:

OrderedDict([

('720p',<HLSStream('https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w202109066.m3u8')>),

('live', <RTMPStream({'rtmp': 'rtmp://videos3.earthcam.com/fecnetwork/', 'playpath': '9974.flv', 'pageUrl': 'https://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet','swfUrl': 'http://static.earthcam.com/swf/streaming/stream_viewer_v3.swf', 'live': 'true'}, redirect=False>),

('worst', <HLSStream('https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w202109066.m3u8')>),

('best', <RTMPStream({'rtmp': 'rtmp://videos3.earthcam.com/fecnetwork/', 'playpath': '9974.flv', 'pageUrl': 'https://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet', 'swfUrl': 'http://static.earthcam.com/swf/streaming/stream_viewer_v3.swf', 'live': 'true'}, redirect=False>)

])

流被错误读取的可能性。

sg2wtvxw

sg2wtvxw3#

我建议仔细检查兼容的视频流编解码器与硬件。我遇到了同样的问题,帧率下降到5 fps只在流,因为它是默认的格式,没有被流,所以它会转换它,然后显示非常滞后(~ 1 s)与较低的fps以及。
使用Self.capture.set(cv2.CAP_PROP_FOURCC ,cv2.VideoWriter_fourcc('M', 'J', 'P', 'G') )和适当的编解码器代替MJPG,并使用cv 2. VideoCapture,看看是否有帮助。

相关问题