OpenCV实时流式视频捕获速度慢。如何删除帧或与实时同步?

2024-09-27 20:16:52 发布

您现在位置:Python中文网/ 问答频道 /正文

目标与问题

我想建立一个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速度

。在

实际/预期速度

问题:

  • 我做错什么了?在
  • 为什么这么慢?在
  • 如何将其与实时速度同步?在

Tags: 方法import目标视频速率系统来源cv2
2条回答

我的假设是,抖动最有可能是由于网络的限制,并且在帧包被丢弃时发生。当一个帧被删除时,这将导致程序显示最后一个“良好”帧,这将导致显示冻结。这可能是硬件或带宽的问题,但我们可以通过软件来缓解一些问题。以下是一些可能的更改:

1。设置最大缓冲区大小

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

2。设置帧检索延迟

目前,我认为read()读得太快了,尽管它在自己的专用线程中。这可能是为什么所有帧看起来都聚集在一起并在下一帧中突然爆裂的原因之一。例如,在一秒的时间间隔内,它可能产生15个新的帧,但是在下一个1秒的时间间隔内,只返回3个帧。这可能是由于网络包的帧丢失,所以为了保证我们获得恒定的帧速率,我们只需在帧检索线程中增加一个延迟。获得大约~30FPS的延迟可以很好地“规范化”帧速率,并在出现包丢失的情况下平滑帧之间的转换。在

注意:我们应该尝试匹配流的帧速率,但我不确定网络摄像头的帧速率是多少,所以我只是猜测了30FPS。此外,通常有一个“直接”流链接,而不是通过中间的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

尝试穿线

我尝试了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  
^{pr2}$

紧张,但实时结果

。在

流媒体是有效的。它保持实时性。然而,就好像所有的帧都聚集在一起,突然出现在视频中。我想找个人解释一下。在

有待改进的地方

实时流可以在这里找到。在

https://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet

此站点是使用python的streamlink流刮板为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>)

])


流被读错的可能性。在

相关问题 更多 >

    热门问题