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

使用cv2.VideoWriter按5秒分段保存RTSP流视频失败问题

问题分析与修复代码

你的代码存在两个核心问题,导致无法生成预期的分段视频:

  • 时间判断逻辑有漏洞:用after_time_in_second - current_time_in_second == 5作为触发条件,会因为系统时间精度、帧率波动等情况错过触发时机(比如时间差从4直接跳到6),分段逻辑根本不会执行。
  • 未创建新的视频写入器:释放旧的VideoWriter后,没有重新初始化新的实例,后续帧无法写入新文件,甚至会抛出异常。

修正后的代码

import cv2
import time
import concurrent.futures

def show_video_stream(rtsp_address: str):
    """Visualize stream given an rtsp address.

    Args:
        rtsp_address (str): IP address with rtsp protocol.
                            Example: 'rtsp://{user}:{password}@{IP}:{port}'
    """
    cap = cv2.VideoCapture(rtsp_address)
    if not cap.isOpened():
        print(f"无法打开RTSP流: {rtsp_address}")
        return
    
    frame_width = int(cap.get(3))
    frame_height = int(cap.get(4))
    size = (frame_width, frame_height)
    frame_name = rtsp_address.split('@')[1]
    cv2.namedWindow(frame_name, cv2.WINDOW_NORMAL)
    
    video_count = 0
    # 初始化第一个视频写入器,用流的实际帧率
    stream_fps = cap.get(cv2.CAP_PROP_FPS)
    result = cv2.VideoWriter(f'video_live_feed{video_count}.avi',
                             cv2.VideoWriter_fourcc(*'MJPG'),
                             stream_fps if stream_fps > 0 else 25,
                             size)
    segment_start_time = time.time()  # 用浮点数计时,精度更高

    while True:
        ret, frame = cap.read()
        if not ret:
            print("读取帧失败,退出循环")
            break
        
        cv2.imshow(frame_name, frame)
        result.write(frame)

        # 按下q键退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
        
        # 检查是否达到5秒分段阈值
        elapsed_time = time.time() - segment_start_time
        if elapsed_time >= 5:
            # 释放当前写入器
            result.release()
            print(f"已生成视频: video_live_feed{video_count}.avi")
            
            # 更新计数和分段起始时间
            video_count += 1
            segment_start_time = time.time()
            
            # 创建新的视频写入器
            result = cv2.VideoWriter(f'video_live_feed{video_count}.avi',
                                     cv2.VideoWriter_fourcc(*'MJPG'),
                                     stream_fps if stream_fps > 0 else 25,
                                     size)

    # 释放最后一个写入器和流捕获器
    result.release()
    cap.release()
    cv2.destroyAllWindows()


if __name__ == "__main__":
    ip_pool = ["你的RTSP地址1", "你的RTSP地址2"]  # 替换为实际RTSP地址
    with concurrent.futures.ProcessPoolExecutor() as executor:
        executor.map(show_video_stream, ip_pool)

关键修改说明

  1. 计时逻辑优化:用time.time()的浮点数计算流逝时间,判断>=5避免错过触发时机,每次分段后重置起始时间为当前时间。
  2. 新增写入器初始化:释放旧写入器后立即创建新的VideoWriter实例,确保后续帧能写入新文件。
  3. 帧率适配:不再写死帧率为5,而是读取流的实际帧率,避免视频播放速度异常。
  4. 稳定性提升:增加流打开失败、帧读取失败的判断,避免无意义的循环执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 12:05:42