如何使用OpenCV将视频时长减半且保持FPS不变?
使用OpenCV实现视频帧抽取(缩短时长且保持帧率)
实现思路
要把10分钟30FPS的视频压缩到5分钟且保持30FPS,核心逻辑是每隔1帧丢弃1帧(即保留第0、2、4...帧),总帧数减半后,帧率不变,时长自然缩短为原来的一半。
完整实现代码
结合你已有的视频参数获取代码,完整实现如下:
import cv2 # 1. 打开原视频 input_path = 'C:/Users/Asus/Documents/videoDuration.mp4' cap = cv2.VideoCapture(input_path) # 获取原视频基本参数 fps = cap.get(cv2.CAP_PROP_FPS) frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 验证原视频参数(可选) print(f"原视频帧率: {fps}") print(f"原视频分辨率: {frame_width}x{frame_height}") print(f"原视频总帧数: {total_frames}") # 2. 设置输出视频参数 output_path = 'C:/Users/Asus/Documents/shortened_video.mp4' # 根据输出格式选择编码器:MP4用mp4v,AVI用XVID fourcc = cv2.VideoWriter_fourcc(*'mp4v') if output_path.endswith('.mp4') else cv2.VideoWriter_fourcc(*'XVID') # 输出帧率保持30,分辨率和原视频一致 out = cv2.VideoWriter(output_path, fourcc, 30, (frame_width, frame_height)) # 3. 循环读取并抽取帧 frame_index = 0 while cap.isOpened(): ret, frame = cap.read() if not ret: break # 视频读取完毕 # 只保留偶数索引的帧(0、2、4...),实现每2帧取1帧 if frame_index % 2 == 0: out.write(frame) frame_index += 1 # 4. 释放资源 cap.release() out.release() cv2.destroyAllWindows() print("视频处理完成!")
关键细节说明
- 编码器选择:MP4格式对应
mp4v编码器,AVI格式对应XVID编码器,确保输出视频能正常播放。 - 帧抽取逻辑:通过
frame_index % 2 == 0判断,只保留偶数序号的帧,严格实现每2帧丢弃1帧的需求。 - 参数一致性:输出视频的分辨率必须和原视频完全一致,否则会导致写入失败或画面变形。
- 异常处理:循环中通过
ret判断是否成功读取帧,避免读取到视频末尾时出错。
注意事项
- 如果原视频的实际帧率和标注的30FPS有偏差,不需要额外校准,只要保证输出帧率为30且抽取一半帧,就能达到时长缩短一半的效果。
- 逐帧处理的方式内存占用较低,适合处理大体积视频。
内容的提问来源于stack exchange,提问作者Moon Lee
相关产品推荐
相关产品推荐

