OpenCV Python VideoWriter部分编码器帧率异常问题求助
问题分析
这个问题其实是OpenCV的VideoWriter与XVID、DIVX、WMV系列编码器之间的参数兼容性小坑导致的:
- 这类编码器通常仅支持整数帧率,但多数视频的原始帧率是浮点数(比如29.97、23.976这类常见的非整数帧率)
- 当直接把浮点数帧率传入
VideoWriter时,编码器无法正确解析,会 fallback 到一个错误的默认值——也就是你看到的600fps - MJPG编码器对浮点数帧率的兼容性更好,所以能正常保留原帧率
解决方案
完全可以用这些编码器输出保持原帧率的视频,只需要对获取到的帧率做简单处理即可,下面是具体的解决方法和优化后的代码:
1. 最实用:将帧率转为整数(通用场景)
把原始浮点数帧率四舍五入为最接近的整数,这是绝大多数场景下的最优解,几乎不会影响视频的播放体验:
import os import numpy as np import cv2 codec = 'XVID' new_size = (256, 256) for root, dirs, files in os.walk("UCF-101"): new_root = root.replace('UCF-101', 'UCF-101_resized_' + codec) if not os.path.exists(new_root): os.makedirs(new_root) for file in files: video_path = os.path.join(root, file) cap = cv2.VideoCapture(video_path) # 增加视频打开失败的判断,避免程序崩溃 if not cap.isOpened(): print(f"跳过无法打开的视频: {video_path}") continue # 获取原视频帧率并处理为整数 raw_fps = cap.get(cv2.CAP_PROP_FPS) fps = round(raw_fps) # 处理异常帧率(比如读取失败得到0或者离谱的数值) if fps <= 0 or fps > 60: fps = 30 fourcc = cv2.VideoWriter_fourcc(*codec) output_path = os.path.join(new_root, file) out = cv2.VideoWriter(output_path, fourcc, fps, new_size, isColor=True) while cap.isOpened(): ret, frame = cap.read() if ret: frame_resized = cv2.resize(frame, new_size) out.write(frame_resized) else: break cap.release() out.release() print(f"已完成写入: {output_path}")
2. 保留精确浮点数帧率(专业场景)
如果你的场景必须严格保留原始的浮点数帧率,可以尝试直接传入精确的浮点值,但需要注意:
- 部分编码器(比如XVID)可能仍然不支持,这时候需要确保OpenCV编译时启用了FFmpeg后端(多数预编译版本已经包含)
- 示例代码(仅在编码器支持时有效):
# 获取精确的原始帧率 fps = cap.get(cv2.CAP_PROP_FPS) # 强制以float类型传入 out = cv2.VideoWriter( os.path.join(new_root, file), fourcc, float(fps), new_size, isColor=True )
额外注意事项
- 用
os.path.join()拼接路径,避免因Windows/macOS/Linux路径分隔符不同导致的错误 - WMV系列编码器仅在Windows平台有良好支持,Linux/macOS下可能需要额外安装对应编码库
内容的提问来源于stack exchange,提问作者L.Noehren
相关产品推荐
相关产品推荐

