Python多线程录制5路RTSP流仅存最后一帧的问题求助
RTSP多线程录制仅保存最后一帧的问题分析与修复
问题根源
你的代码存在三个核心问题,导致每个视频仅保存最后一帧:
- 录制逻辑只执行一次:主线程仅调用了一次
record_vid()方法,每个摄像头只写入了当前内存中的那一帧,没有持续写入后续帧。 - 显示与退出逻辑不完整:仅调用了一次
show_frame(),既无法持续显示画面,也只能处理第一个摄像头的退出事件,其他摄像头的资源无法正常释放。 - 线程读取无控制:
update线程持续无间隔读取帧,会导致CPU占用过高,且没有处理读取失败的异常情况。
修复后的代码
以下是调整后的完整代码,解决了上述问题:
from threading import Thread import cv2 import os import time class RTSPVideoWriterObject(object): def __init__(self, src, camname, folder): # 创建VideoCapture对象 self.capture = cv2.VideoCapture(src) self.camname = camname self.folder = folder self.status = False self.frame = None # 获取视频流参数,兼容FPS获取失败的情况 self.frame_width = int(self.capture.get(3)) self.frame_height = int(self.capture.get(4)) self.fps = int(self.capture.get(5)) if self.capture.get(5) > 0 else 25 # 创建存储目录 folder_path = time.strftime(os.path.join(self.folder, '%Y_%m_%d/%Hh')) if not os.path.exists(folder_path): os.makedirs(folder_path) filename = os.path.join(folder_path, time.strftime(f"{self.camname} %Y_%m_%d - %Hh%M") + '.mp4') # 初始化视频写入器 self.codec = cv2.VideoWriter_fourcc(*'avc1') self.output_video = cv2.VideoWriter(filename, self.codec, self.fps, (self.frame_width, self.frame_height)) # 启动帧读取线程 self.thread = Thread(target=self.update, args=()) self.thread.daemon = True self.thread.start() def update(self): # 持续读取帧,添加延迟降低CPU占用 while True: if self.capture.isOpened(): ret, frame = self.capture.read() if ret: self.status = True self.frame = frame else: self.status = False time.sleep(0.1) # 读取失败时短暂等待 time.sleep(1/self.fps) # 按原FPS间隔读取,避免帧堆积 def show_frame(self): # 显示当前帧(需在主线程调用) if self.status: cv2.imshow(self.camname, self.frame) def record_vid(self): # 写入当前帧到视频文件 if self.status: self.output_video.write(self.frame) def release(self): # 统一释放资源 self.capture.release() self.output_video.release() cv2.destroyWindow(self.camname) if __name__ == '__main__': # 替换为你的RTSP链接、文件名和存储目录 rtsp_configs = [ ("My RTSP link1", "MyFileName1", "MyFolder1"), ("My RTSP link2", "MyFileName2", "MyFolder2"), ("My RTSP link3", "MyFileName3", "MyFolder3"), ("My RTSP link4", "MyFileName4", "MyFolder4"), ("My RTSP link5", "MyFileName5", "MyFolder5"), ] # 初始化所有摄像头对象 video_widgets = [] for src, name, folder in rtsp_configs: widget = RTSPVideoWriterObject(src, name, folder) video_widgets.append(widget) # 主循环:持续显示与录制,监听退出事件 try: while True: # 遍历所有摄像头,执行显示和录制 for widget in video_widgets: widget.show_frame() widget.record_vid() # 监听键盘事件,按Q退出 if cv2.waitKey(1) & 0xFF == ord('q'): break finally: # 退出时统一释放所有资源 for widget in video_widgets: widget.release() cv2.destroyAllWindows()
关键修改点说明
- 主循环持续执行:在主线程中添加循环,持续调用每个摄像头的
show_frame()和record_vid(),实现持续显示与录制。 - 线程读取控制:在
update线程中添加time.sleep(1/self.fps),按原视频流的FPS间隔读取帧,避免CPU空转和帧堆积;同时处理读取失败的情况,添加短暂等待。 - 统一资源释放:新增
release()方法,在退出时统一释放所有摄像头的捕获和写入资源,避免内存泄漏。 - 兼容处理:增加FPS获取失败的默认值(25),避免参数错误导致的初始化失败。
内容的提问来源于stack exchange,提问作者Jul Pandoa
相关产品推荐
相关产品推荐

