如何使用Python脚本快速拼接多个MP4格式视频文件
速度慢的核心原因
你现有代码慢是方案本身的逻辑问题,靠njit、缓存装饰器根本优化不了:
- MoviePy的
concatenate_videoclips默认会把所有视频片段逐帧解码,在内存完成拼接后再全量重新编码输出,哪怕所有视频的编码、分辨率、帧率完全一致,也会做一遍无意义的重编码,速度完全受限于CPU编解码性能,大文件合并耗时极长 @cache装饰器只会缓存函数第一次运行的返回值,对函数本身的执行速度没有任何提升;njit仅对纯Python实现的数值计算逻辑有效,对视频编解码、文件IO、调用第三方库的逻辑完全不起作用,加了不会有任何加速效果。
极速合并实现方案
如果待合并的MP4文件编码参数一致(同设备录制、同导出参数生成的文件基本都满足这个条件),用FFmpeg流复制方案可以做到和硬盘拷贝速度相当的合并效率,比原MoviePy方案快10~100倍,不需要逐帧重编码。
依赖准备
先安装必要依赖:pip install ffmpeg-python
确保本地已经安装FFmpeg并加入系统环境变量(安装过MoviePy的环境一般已经自带FFmpeg,直接运行即可)。
可直接运行的代码
import os import subprocess def fast_video_merge(): # 扫描目录下数字命名的MP4文件,排序逻辑和你原有代码完全一致 video_items = [] for filename in os.listdir(os.getcwd()): if not filename.lower().endswith('.mp4'): continue try: file_index = int(filename.rsplit('.', 1)[0]) video_items.append((file_index, filename)) except ValueError: continue video_items.sort() sorted_video_paths = [item[1] for item in video_items] if not sorted_video_paths: print("当前目录未找到以数字命名的MP4文件") return # 生成FFmpeg concat协议需要的临时列表文件 list_file_content = "" for path in sorted_video_paths: # 自动转义文件名中的特殊字符,避免路径报错 escaped_path = path.replace("'", "'\\''") list_file_content += f"file '{escaped_path}'\n" with open("concat_tmp.txt", "w", encoding="utf-8") as f: f.write(list_file_content) # 调用FFmpeg执行流复制合并 ffmpeg_cmd = [ "ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", "concat_tmp.txt", "-c", "copy", # 核心参数:直接复制音视频流,不做重编码 "output.mp4" ] subprocess.run(ffmpeg_cmd, check=True) # 清理临时文件 os.remove("concat_tmp.txt") print(f"合并完成,共处理{len(sorted_video_paths)}个视频,输出文件:output.mp4") if __name__ == "__main__": fast_video_merge()
特殊情况处理
如果待合并的视频参数不一致(分辨率、帧率、编码格式不统一)导致流复制报错,可以把命令里的"-c", "copy"替换为"-c:v", "libx264", "-crf", "23", "-c:a", "aac", "-b:a", "192k",此时会做快速重编码,速度依然比MoviePy方案快3~5倍。
不要给这类IO密集、调用外部程序的逻辑加
njit装饰器,会直接导致运行报错。
内容的提问来源于stack exchange,提问作者IAM々Unknown
相关产品推荐
相关产品推荐

