合并上百个MP4文件时避免内存耗尽的解决方案
解决大批量MP4合并内存耗尽问题
你的代码会把所有视频文件一次性加载到内存中,处理数量较多时自然会出现内存耗尽的问题。要实现类似CSV顺序写入的流式处理效果,这里提供两种实用方案:
方案一:MoviePy分批拼接+追加写入
无需一次性加载全部视频,而是分批次处理,每批拼接完成后就追加到输出文件,处理完一批立即释放内存:
from moviepy.editor import VideoFileClip, concatenate_videoclips import os from natsort import natsorted input_dir = "/path/to/the/files" output_file = "output.mp4" batch_size = 10 # 可根据自身内存情况调整每批处理的文件数量 # 先收集所有MP4文件的绝对路径 video_paths = [] for root, dirs, files in os.walk(input_dir): sorted_files = natsorted(files) for file in sorted_files: if os.path.splitext(file)[1] == '.mp4': video_paths.append(os.path.join(root, file)) # 分批处理视频 for i in range(0, len(video_paths), batch_size): batch_paths = video_paths[i:i+batch_size] # 加载当前批次的视频片段 batch_clips = [VideoFileClip(path) for path in batch_paths] batch_combined = concatenate_videoclips(batch_clips) # 写入输出文件:首次创建文件,后续批次追加 if i == 0: batch_combined.write_videofile(output_file, fps=24, remove_temp=False) else: batch_combined.write_videofile(output_file, fps=24, remove_temp=False, append=True) # 释放当前批次占用的内存 batch_combined.close() for clip in batch_clips: clip.close()
方案二:直接用FFmpeg命令(高效推荐)
MoviePy底层依赖FFmpeg,直接使用FFmpeg的concat协议可以实现流式处理,完全不会把视频加载到内存中,速度更快:
步骤1:生成包含所有视频路径的清单文件
import os from natsort import natsorted input_dir = "/path/to/the/files" list_file = "video_list.txt" with open(list_file, 'w', encoding='utf-8') as f: for root, dirs, files in os.walk(input_dir): sorted_files = natsorted(files) for file in sorted_files: if os.path.splitext(file)[1] == '.mp4': abs_path = os.path.abspath(os.path.join(root, file)) f.write(f"file '{abs_path}'\n")
步骤2:执行FFmpeg合并命令
打开终端运行以下命令:
ffmpeg -f concat -safe 0 -i video_list.txt -c copy output.mp4
-c copy:直接复制视频音频流,不重新编码,处理速度极快-safe 0:允许清单文件中使用绝对路径
这种方式处理几百上千个文件都不会有内存压力,因为FFmpeg是逐流读取处理的。
内容的提问来源于stack exchange,提问作者Dray
相关产品推荐
相关产品推荐

