You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派3B+使用Python OpenCV处理多路RTSP摄像头流延迟累积求助

解决树莓派3B+多路IP摄像头延迟累积问题

一、现有代码的核心问题

你的延迟累积本质是摄像头推送的帧在缓冲区持续堆积,现有代码的两个关键缺陷导致了这个问题:

  1. update线程中固定time.sleep(self.FPS)的逻辑,不管摄像头帧的生成速度,导致旧帧无法被及时读取,缓冲区越攒越多。
  2. CAP_PROP_BUFFERSIZE设置对多数RTSP摄像头无效,无法限制缓冲区大小。

二、OpenCV代码优化方案

1. 主动清空缓冲区,只保留最新帧

放弃固定sleep,改为循环读取直到拿到最新帧,避免旧帧堆积:

from threading import Thread
import cv2, time

class ThreadedCamera(object):
    def __init__(self, src=0):
        # 优先使用GStreamer后端,提升RTSP处理效率
        self.capture = cv2.VideoCapture(src, cv2.CAP_GSTREAMER)
        # 强制设置摄像头输出低分辨率(根据摄像头支持调整)
        self.capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
        self.capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
        self.capture.set(cv2.CAP_PROP_FPS, 3)
        
        self.frame = None
        # 启动取帧线程
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()
        # 启动显示线程
        self.show_thread = Thread(target=self.show_frame, args=())
        self.show_thread.daemon = True
        self.show_thread.start()
        
    def update(self):
        while True:
            if self.capture.isOpened():
                # 循环grab跳过所有旧帧,只解码最后一帧
                while self.capture.grab():
                    ret, frame = self.capture.retrieve()
                    if ret:
                        self.frame = frame
                # 控制取帧频率(3FPS)
                time.sleep(1/3)
            
    def show_frame(self):
        while True:
            if self.frame is not None:
                cv2.imshow('frame', self.frame)
            # 用waitKey(1)避免阻塞,同时处理退出
            if cv2.waitKey(1) & 0xFF == ord('q'):
                self.capture.release()
                cv2.destroyAllWindows()
                break

if __name__ == '__main__':
    src = 'rtsp://user:psword@192.168.8.108:554/Streaming/Channels/1401'
    threaded_camera = ThreadedCamera(src)
    while True:
        time.sleep(1)

2. 优化RTSP流参数

直接在摄像头的RTSP URL中指定低分辨率、低帧率(具体参数需参考摄像头厂商文档),减少树莓派的处理压力:

# 示例:强制摄像头输出640x480、3FPS的流(以海康摄像头为例)
src = 'rtsp://user:psword@192.168.8.108:554/Streaming/Channels/1401?videoResolutionWidth=640&videoResolutionHeight=480&videoFrameRate=3'

三、OpenCV替代方案

如果优化后性能仍不满足,推荐使用FFmpeg-python,它基于FFmpeg的硬件解码能力,能大幅降低CPU占用:

import ffmpeg
import numpy as np
import cv2

def rtsp_stream(url, width=640, height=480, fps=3):
    # 启用树莓派硬件解码(h264_mmal)
    process = (
        ffmpeg
        .input(url)
        .output(
            'pipe:',
            format='rawvideo',
            pix_fmt='bgr24',
            r=fps,
            vcodec='h264_mmal'
        )
        .run_async(pipe_stdout=True)
    )
    
    while True:
        # 读取对应分辨率的帧字节数
        frame_bytes = process.stdout.read(width * height * 3)
        if not frame_bytes:
            break
        # 转换为OpenCV可用的numpy数组
        frame = np.frombuffer(frame_bytes, np.uint8).reshape([height, width, 3])
        yield frame

if __name__ == '__main__':
    src = 'rtsp://user:psword@192.168.8.108:554/Streaming/Channels/1401'
    for frame in rtsp_stream(src):
        cv2.imshow('frame', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

四、是否需要更换编程语言?

如果Python的性能上限无法满足6路摄像头的需求,可以考虑:

  • C++:直接使用OpenCV C++版本或FFmpeg C API,性能比Python高3-5倍,能最大化利用树莓派的CPU资源。
  • Go语言:并发模型适合多路流处理,性能接近C++,代码复杂度低于C++,有成熟的音视频库(如gocv)支持。

内容的提问来源于stack exchange,提问作者Luc Lagarde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 00:10:35