MoviePy处理Windows游戏栏录制视频时画面倍速音频正常的问题
MoviePy处理Windows游戏栏录制视频时画面倍速、音频正常的问题
问题现象
使用MoviePy处理Windows游戏栏录制的视频时,仅执行读取后直接重写的操作,输出视频画面播放速度翻倍,但音频保持正常。其他来源的视频无此异常。
读取重写测试代码:
full_video = VideoFileClip(input_video_path) full_video.write_videofile("output.mp4") quit()
进一步排查确认问题出在视频读取阶段:预览时画面同样倍速,打印出的帧率与实际不符。
预览测试代码:
full_video = VideoFileClip(input_video_path) print(full_video.fps) full_video.preview(fps=full_video.fps) quit()
根因分析
Windows游戏栏录制的视频默认采用**可变帧率(VFR)**编码,目的是在保证录屏性能的同时动态调整帧率。而MoviePy的VideoFileClip默认按固定帧率(CFR)解析视频,会错误识别VFR视频的帧率(通常取到平均帧率或峰值帧率),导致画面播放速度异常,而音频因为是固定码率/采样率,不受影响。
解决方案
1. 临时修复:分离音视频后调整视频速度
通过分离音视频,将视频减速至正常速度后重新合并,代码示例:
from moviepy.editor import * full_video = VideoFileClip(input_video_path) # 分离音频轨道 audio = full_video.audio # 将视频减速50%抵消倍速问题 video = full_video.set_speed(0.5) # 重新合并音视频 fixed_clip = video.set_audio(audio) fixed_clip.write_videofile("fixed_output.mp4")
2. 根本解决:强制解析正确帧率
方法一:手动指定正确帧率
先通过FFmpeg命令获取视频的实际平均帧率:
ffmpeg -i input.mp4 -v error -select_streams v:0 -show_entries stream=r_frame_rate -of default=noprint_wrappers=1:nokey=1
将得到的帧率值(比如30/1)转换为浮点数(30),然后在VideoFileClip初始化时手动指定:
full_video = VideoFileClip(input_video_path, fps=30)
方法二:转码为固定帧率(CFR)
先用FFmpeg将VFR视频转成固定帧率的视频,再用MoviePy处理:
ffmpeg -i input.mp4 -r 30 -c:v libx264 -crf 23 -c:a copy fixed_input.mp4
之后用fixed_input.mp4作为输入源,MoviePy处理就不会出现速度异常。
修正后的完整处理代码
结合你的剪辑需求,修改后的完整代码如下(加入手动指定帧率的处理):
from moviepy.editor import * # 配置参数 times_path = "times.txt" input_video_path = "input.mp4" # 替换为你通过FFmpeg获取的实际帧率 CORRECT_FPS = 30 offset_time = 0 clip_length = float(input("Enter clip length: ")) def get_times(path, offset): dash_times_str = [] with open(path, "r") as file: dash_times_str = file.readlines() temp = [line.strip() for line in dash_times_str] dash_times = [float(time) + offset for time in temp] return dash_times dash_times = get_times(times_path, offset_time) def get_offset_time(): a = float(input("Enter time for first dash in video: ")) b = dash_times[0] return a - b offset_time = get_offset_time() # 手动指定正确帧率读取视频 full_video = VideoFileClip(input_video_path, fps=CORRECT_FPS) counter = 0 times_count = len(dash_times) clips = [] for dash_time in dash_times: clip = full_video.subclip(dash_time, dash_time + clip_length) clips.append(clip) counter += 1 print(f"Clip {counter} out of {times_count}") final_clip = concatenate_videoclips(clips) final_clip.write_videofile("output.mp4")
内容的提问来源于stack exchange,提问作者Jay Mehta
相关产品推荐
相关产品推荐

