使用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)
关键修改说明
- 计时逻辑优化:用
time.time()的浮点数计算流逝时间,判断>=5避免错过触发时机,每次分段后重置起始时间为当前时间。 - 新增写入器初始化:释放旧写入器后立即创建新的
VideoWriter实例,确保后续帧能写入新文件。 - 帧率适配:不再写死帧率为5,而是读取流的实际帧率,避免视频播放速度异常。
- 稳定性提升:增加流打开失败、帧读取失败的判断,避免无意义的循环执行。
内容的提问来源于stack exchange,提问作者Anik Sen
相关产品推荐
相关产品推荐

