为何Python的MoviePy与OpenCV获取的视频FPS和Windows、VLC不一致?
问题
我有一段以120 fps录制的视频,在Windows属性中确认其帧率为120 fps,VLC播放器中也显示该帧率。但使用Python的moviepy或cv2库获取视频帧率时,得到的却是错误的25 fps。视频采用32位FFDshow codec压缩。
相关代码:
import cv2 from moviepy.editor import * def main(): # Define file name video_name = r'C:\Users\npires.OMG\OneDrive - OMG PLC\Work Projects\Convert AVI to MP4 H264\Test\Test\Walk ' \ r'01.2117813.20210614134127.avi' # import the video into Python video_data_cv2 = cv2.VideoCapture(video_name) video_data_moviepy = VideoFileClip(video_name) # get the video frame rate fps_moviepy = video_data_moviepy.fps fps_cv2 = video_data_cv2.get(cv2.CAP_PROP_FPS)
原因
这种差异的核心问题是cv2和moviepy依赖的底层解析库(OpenCV/FFmpeg)对老旧的32位FFDshow编码AVI的元数据读取存在偏差,这类编码的视频帧率信息可能存储在非标准的容器字段中,导致Python库误读为默认的25fps。而Windows和VLC使用的解析逻辑更兼容这类旧编码,能正确提取真实帧率。
解决方案
1. 手动计算真实帧率(最可靠)
通过统计视频总帧数和实际时长来计算,避免依赖元数据读取:
使用cv2实现
import cv2 video_path = r"你的视频路径" cap = cv2.VideoCapture(video_path) # 获取总帧数 total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 获取视频总时长(秒) total_duration = cap.get(cv2.CAP_PROP_POS_MSEC) / 1000 if cap.get(cv2.CAP_PROP_POS_MSEC) != 0 else total_frames / 25 # fallback值 # 手动计算帧率 actual_fps = total_frames / total_duration if total_duration != 0 else 0 cap.release() print(f"真实帧率:{actual_fps}")
使用moviepy实现
from moviepy.editor import VideoFileClip video_path = r"你的视频路径" clip = VideoFileClip(video_path) # 总帧数除以时长得到真实帧率 actual_fps = clip.reader.nframes / clip.duration print(f"真实帧率:{actual_fps}") clip.close()
2. 用FFprobe直接读取准确帧率
FFprobe(FFmpeg套件的一部分)能像VLC一样正确解析这类编码的视频,可在Python中调用命令行获取结果:
import subprocess import re video_path = r"你的视频路径" # 调用ffprobe获取帧率(分数形式,如120/1) result = subprocess.run( ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=r_frame_rate", "-of", "default=noprint_wrappers=1:nokey=1", video_path], capture_output=True, text=True ) fps_str = result.stdout.strip() # 转换为浮点数 num, den = map(int, fps_str.split('/')) actual_fps = num / den print(f"真实帧率:{actual_fps}")
注:需确保系统已安装FFmpeg并添加到环境变量。
3. 转码为标准编码格式
将视频转码为H.264编码的MP4格式,这类标准格式的元数据能被cv2和moviepy正确识别:
用FFmpeg命令行转码:
ffmpeg -i input.avi -c:v libx264 -crf 23 output.mp4
转码后再用Python库读取帧率即可得到正确结果。
内容的提问来源于stack exchange,提问作者Nev Pires
相关产品推荐
相关产品推荐

