使用Python VideoCapture录制Webcam视频耗时过长的问题与解决
问题原因与解决方法
为什么录制耗时是视频时长的2倍?
核心原因是摄像头实际采集帧率远低于你设置的编码帧率29.97fps:
- 你的代码用固定300帧控制时长,按29.97fps编码计算,视频播放时长约为10秒(300÷29.97≈10)。
- 但
video_capture.read()是阻塞式调用,每调用一次才从摄像头获取一帧,如果摄像头硬件只能输出15fps左右,采集300帧就需要20秒(300÷15=20)。 - 另外代码未处理
frameRead为False的情况,若出现帧读取失败,无效帧的写入也会变相拉长录制时间。
实现录制时长与视频时长一致的方法
方案1:基于实际时间录制(推荐)
放弃固定帧数逻辑,直接按指定时长录制,确保实际录制时间和视频时长完全匹配:
import cv2 import time def capture_video(webcam_video): video_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 尝试设置摄像头采集帧率为目标值 video_capture.set(cv2.CAP_PROP_FPS, 29.97) # 获取摄像头实际支持的帧率(避免设置无效) actual_fps = video_capture.get(cv2.CAP_PROP_FPS) output = cv2.VideoWriter(webcam_video, cv2.VideoWriter_fourcc(*'mp4v'), actual_fps, (640, 480)) record_duration = 10 # 要录制的时长(秒) start_time = time.time() while (time.time() - start_time) < record_duration: frameRead, frame = video_capture.read() if not frameRead: break # 读取帧失败则终止录制 output.write(frame) # 释放资源 video_capture.release() output.release() cv2.destroyAllWindows()
方案2:匹配摄像头与编码帧率
先获取摄像头实际输出帧率,将编码帧率设置为该值,再通过帧数控制时长,确保采集和编码速度一致:
import cv2 def capture_video(webcam_video): video_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 获取摄像头实际帧率 actual_fps = video_capture.get(cv2.CAP_PROP_FPS) # 计算10秒需要的总帧数 total_frames = int(actual_fps * 10) output = cv2.VideoWriter(webcam_video, cv2.VideoWriter_fourcc(*'mp4v'), actual_fps, (640, 480)) frames_counter = total_frames while frames_counter > 0: frameRead, frame = video_capture.read() if not frameRead: break output.write(frame) frames_counter -= 1 video_capture.release() output.release() cv2.destroyAllWindows()
方案3:精确控制帧采集间隔(适合严格帧率要求场景)
如果摄像头支持设置目标帧率,通过控制每帧的采集间隔,确保每秒采集指定数量的帧:
import cv2 import time def capture_video(webcam_video): target_fps = 29.97 video_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 设置摄像头采集帧率 video_capture.set(cv2.CAP_PROP_FPS, target_fps) output = cv2.VideoWriter(webcam_video, cv2.VideoWriter_fourcc(*'mp4v'), target_fps, (640, 480)) frame_interval = 1.0 / target_fps # 每帧之间的时间间隔 record_duration = 10 start_time = time.time() last_capture_time = start_time while (time.time() - start_time) < record_duration: current_time = time.time() # 到达下一帧的采集时间点再读取 if current_time - last_capture_time >= frame_interval: frameRead, frame = video_capture.read() if not frameRead: break output.write(frame) last_capture_time = current_time video_capture.release() output.release() cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者spjennie
相关产品推荐
相关产品推荐

