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

OpenCV读取3路及以上RTSP流时出现灰屏问题求助

问题

局域网环境下读取RTSP流,1路或2路流时运行流畅,但读取3路及以上流时,画面变成仅少量像素可见的灰屏。

单路流处理代码:

cap = cv2.VideoCapture(rtsp_uri)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 2)

fps = cap.get(cv2.CAP_PROP_FPS)
delay_after_each_frame = 1/fps
print(delay_after_each_frame)

while True:
    try:
        ret, frame = cap.read()
    except:
        pass

    if self.stopper[camera_id]:
        del self.stopper[camera_id]
        return

    if not ret:
        continue

    frame = cv2.cvtColor(src=frame, code=cv2.COLOR_BGR2RGB)
    frame = cv2.resize(
        frame,
        (self.config.frame_width, self.config.frame_height)
    )
    queue.enqueue(frame)
    time.sleep(delay_after_each_frame)

多路流启动与管理代码:

for camera_id in self.config.get_camera_ids():
    if camera_id not in self.threads:
        self.threads[camera_id] = Thread(
            target=self.process_rtsp_stream,
            args=(self.config.get_rtsp(camera_id),
                    self.queues[camera_id], camera_id)
        )
        self.threads[camera_id].daemon = True
        self.threads[camera_id].start()

# remove thread for deleted cameras
for camera_id in self.threads:
    if camera_id not in self.config.get_camera_ids():
        del self.threads[camera_id]
解决方案

1. 指定高效的RTSP读取后端

OpenCV默认后端在多路流场景下性能有限,强制使用FFmpeg后端,并开启硬件加速(如果设备支持):

# 初始化VideoCapture时指定FFmpeg后端
cap = cv2.VideoCapture(rtsp_uri, cv2.CAP_FFMPEG)
# 启用CUDA硬件加速(需OpenCV编译时支持CUDA)
cap.set(cv2.CAP_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_CUDA)

2. 移除固定延迟睡眠

time.sleep(delay_after_each_frame)会导致线程阻塞,多路流时累积延迟引发帧读取异常,直接删除该语句——cap.read()本身会等待流的下一帧,无需额外睡眠。同时可以删掉FPS计算相关代码。

3. 限制队列容量,避免内存过载

当队列堆积过多帧时,会占用大量内存影响流读取,入队前判断队列长度:

# 限制队列最大存储10帧,可根据实际调整
if queue.qsize() < 10:
    queue.enqueue(frame)

4. 修复异常处理逻辑

原代码直接忽略读取异常,会掩盖流中断、解码失败等问题,添加错误日志和重试:

try:
    ret, frame = cap.read()
except Exception as e:
    print(f"摄像头{camera_id}读取错误: {e}")
    time.sleep(0.1)
    continue

5. 正确停止并清理线程

原代码直接删除线程对象,线程可能仍在后台运行,需先触发停止标志,等待线程结束后再清理:

# 遍历线程副本,避免修改字典时迭代出错
for camera_id in list(self.threads.keys()):
    if camera_id not in self.config.get_camera_ids():
        self.stopper[camera_id] = True
        # 等待线程终止,超时1秒
        self.threads[camera_id].join(timeout=1)
        del self.threads[camera_id]
        del self.stopper[camera_id]

6. 调整缓冲区大小

原设置的缓冲区大小(2帧)过小,多路流时易出现帧丢失,适当增大:

cap.set(cv2.CAP_PROP_BUFFERSIZE, 5)  # 可根据实际情况调整为5-10帧

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:15:25