首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenCV实时流媒体视频采集速度慢。如何丢弃帧或与实时同步?

问OpenCV实时流媒体视频采集速度慢。如何丢弃帧或与实时同步?
EN

Stack Overflow用户
提问于 2019-10-08 19:52:39
回答 2查看 45.6K关注 0票数 30

目标与问题

我想建立一个opencv系统来处理HLS流或RMTP流,但是,我遇到了一个关于帧速率降低和累积滞后的奇怪问题。就好像视频离它应该在流里的位置越来越远。

我正在寻找一种方法,以跟上一个活源,即使它意味着下降帧。

现行方法

代码语言:javascript
复制
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速度

​

。

实际/预期速度

​

问题:

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

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-15 01:37:43

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

1.设置最大缓冲区大小

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

2.设置帧检索延迟

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

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

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

代码语言:javascript
复制
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

  1. Video Streaming from IP Camera in Python Using OpenCV cv2.VideoCapture

  1. How to capture multiple camera streams with OpenCV?

  1. OpenCV real time streaming video capture is slow. How to drop frames or get synced with real time?

  1. Storing RTSP stream as video file with OpenCV VideoWriter

  1. OpenCV video saving

  1. Python OpenCV multiprocessing cv2.VideoCapture mp4
票数 29
EN

Stack Overflow用户

发布于 2019-10-09 19:51:01

尝试线程化

我尝试过用this解决方案从nathancy那里获得一些小小的成功。

它涉及:

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

代码:

代码语言:javascript
复制
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  
代码语言:javascript
复制
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的m3u8流刮刀器为streamlink抓取的。

代码语言:javascript
复制
import streamlink

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

哪几个人:

代码语言:javascript
复制
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>)

])

流被误读的可能性。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58293187

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档