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

OpenCV录制RTSP流视频时长异常:实际与播放时长不符

问题:RTSP流录制视频播放时长远短于实际录制时长

我用OpenCV基于RTSP流制作视频,能正常生成视频文件,但录制完成后播放时长比实际录制时长短很多——测试时录了10秒,视频却只播放2秒,但所有录制的帧都在文件里。

补充测试:在保存帧的循环里加了print("frame"),5秒内一共打印了30次。


相关代码

保存帧的线程

self.rec = False
self.thread = Thread(target=self.grava_frame, args=())
self.thread.daemon = True
self.thread.start()

def grava_frame(self):
        while True:
            if self.rec:
                while not self.thread_end:
                    frame = cv2.cvtColor(self.resized_cropped, cv2.COLOR_RGB2BGR)
                    self.video_writer.write(frame)
                    cv2.waitKey(1)
                self.video_writer.release()

捕获帧的线程

self.at_frame = Thread(target=self.atualiza_frame, args=())
        self.at_frame.daemon = True
        self.at_frame.start()
def atualiza_frame(self):
        ap = argparse.ArgumentParser()
        ap.add_argument("-v", "--video", required=True,
            help="rtsp://admin:@192.168.1.10:554/live/0/MAIN")
        args = vars(ap.parse_args())
        print("[INFO] starting video file thread...")
        fvs = FileVideoStream(args["video"]).start()
        time.sleep(1.0)
        fps = FPS().start()
        while fvs.more():
            frame = fvs.read()
            self.resized_cropped = cv2.resize(frame, (1024, 600))
            cv2.waitKey(1)
            fps.update()

录制控制按钮代码

def record_button(self):
        if self.is_recording_on:
            # 开始录制
            data = self.dataname()
            self.codec = cv2.VideoWriter_fourcc(*'mp4v')
            self.video_writer = cv2.VideoWriter(data+'.MP4', self.codec, 25, (self.frame_width, self.frame_height))
            self.thread_end = False
            self.rec = True

        else:
            # 停止录制
            self.rec = False
            self.thread_end = True

问题原因分析

核心问题是帧写入线程的速度远快于RTSP流的实际帧率:

  • 你设置的VideoWriter帧率是25fps,但实际RTSP流的帧率可能远低于这个值(比如补充测试中5秒仅捕获30帧,实际帧率只有6fps)。
  • 写入线程在循环中不断重复写入同一帧(因为捕获线程还没更新self.resized_cropped),导致视频文件内的帧数量远超实际录制时长对应的合理帧数。播放器按25fps播放时,就会快速播完所有帧,造成时长缩短的假象。

解决方案

1. 用线程安全队列控制帧写入,避免重复写帧

通过队列传递捕获到的新帧,写入线程只处理队列中的新帧,杜绝重复写入同一帧的情况:

from queue import Queue

# 初始化队列,限制大小防止内存溢出
self.frame_queue = Queue(maxsize=10)

# 修改捕获帧线程
def atualiza_frame(self):
    ap = argparse.ArgumentParser()
    ap.add_argument("-v", "--video", required=True, help="rtsp://admin:@192.168.1.10:554/live/0/MAIN")
    args = vars(ap.parse_args())
    print("[INFO] starting video file thread...")
    fvs = FileVideoStream(args["video"]).start()
    time.sleep(1.0)
    fps = FPS().start()
    while fvs.more():
        frame = fvs.read()
        if frame is not None:
            resized_frame = cv2.resize(frame, (1024, 600))
            # 队列未满时才放入新帧
            if not self.frame_queue.full():
                self.frame_queue.put(resized_frame)
        cv2.waitKey(1)
        fps.update()

# 修改保存帧线程
def grava_frame(self):
    while True:
        if self.rec:
            while not self.thread_end:
                # 队列有帧才读取写入,无帧则等待
                if not self.frame_queue.empty():
                    frame = self.frame_queue.get()
                    frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
                    self.video_writer.write(frame_bgr)
                cv2.waitKey(1)
            self.video_writer.release()

2. 匹配RTSP流的实际帧率初始化VideoWriter

先获取RTSP流的真实帧率,再用该值初始化VideoWriter,确保播放器的播放速度与实际录制速度一致:

def record_button(self):
    if not self.is_recording_on:
        # 获取RTSP流实际帧率
        cap = cv2.VideoCapture("rtsp://admin:@192.168.1.10:554/live/0/MAIN")
        actual_fps = cap.get(cv2.CAP_PROP_FPS)
        cap.release()
        # 若获取帧率失败, fallback到25fps或统计的真实FPS
        if actual_fps <= 0:
            actual_fps = 25
            
        # 开始录制
        data = self.dataname()
        self.codec = cv2.VideoWriter_fourcc(*'mp4v')
        self.video_writer = cv2.VideoWriter(data+'.MP4', self.codec, actual_fps, (1024, 600))
        self.thread_end = False
        self.rec = True
        self.is_recording_on = True
    else:
        # 停止录制
        self.rec = False
        self.thread_end = True
        self.is_recording_on = False

3. 修复录制控制逻辑的小问题

原代码中record_button的判断逻辑可能颠倒,上述代码已修正:未录制时点击开始录制,录制中点击停止录制。


内容的提问来源于stack exchange,提问作者Jorge Augusto Wilchen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 08:17:46