如何使用Python结合MoviePy异步并行编辑多个视频?
使用Python + MoviePy异步并行编辑多个视频
你的代码思路方向是对的,但直接用async/await无法实现真正的并行——因为MoviePy的所有核心API(比如resize、write_videofile)都是同步阻塞的,会卡住asyncio的事件循环,导致视频处理实际上还是串行执行。
下面是修正后的可运行代码,通过asyncio.to_thread将同步的视频处理逻辑放到线程池执行,真正实现并行处理:
import asyncio from moviepy.editor import VideoFileClip, clips_array import os # 请根据实际情况修改以下变量 videos = ["video1.mp4", "video2.mp4", "video3.mp4"] # 待处理的视频路径列表 chemin_semi_final = "./processed_videos" # 输出目录 video_random_path = "background_video.mp4" # 用于拼接的随机视频路径 # 提前加载随机视频,避免重复加载浪费资源 video_random = VideoFileClip(video_random_path) async def upload(): # 限制并发数,避免系统资源耗尽(根据CPU/内存调整数值) semaphore = asyncio.Semaphore(4) async def bounded_edit(video_path): async with semaphore: return await edit(video_random, video_path) edit_tasks = [bounded_edit(video) for video in videos] processed_paths = await asyncio.gather(*edit_tasks) print(f"所有视频处理完成,输出路径:{processed_paths}") async def edit(random_video, video_path): # 将同步的视频处理逻辑封装到函数中,交给线程池执行 def process_single_video(): # 加载目标视频 video1 = VideoFileClip(video_path) # 调整随机视频宽度匹配目标视频 video2 = random_video.resize(width=video1.size[0]) # 垂直拼接两个视频 combined_clip = clips_array([[video1], [video2]]) # 居中裁剪到720x1280尺寸 crop_x = (combined_clip.w - 720) // 2 crop_y = (combined_clip.h - 1280) // 2 final_clip = combined_clip.crop(crop_x, crop_y, crop_x + 720, crop_y + 1280) # 生成输出文件名(兼容Windows/Linux路径) video_filename = os.path.basename(video_path) output_path = os.path.join(chemin_semi_final, video_filename) # 写入视频文件,关闭所有资源避免内存泄漏 final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac") video1.close() video2.close() combined_clip.close() final_clip.close() return output_path # 在线程中执行同步处理逻辑,不阻塞事件循环 return await asyncio.to_thread(process_single_video) if __name__ == "__main__": # 确保输出目录存在 os.makedirs(chemin_semi_final, exist_ok=True) asyncio.run(upload())
关键优化点说明
- 真正的并行处理:用
asyncio.to_thread把MoviePy的同步操作放到线程池,让asyncio事件循环可以同时调度多个视频处理任务,避免串行阻塞。 - 资源复用与释放:提前加载随机视频避免重复IO;手动调用
close()释放所有剪辑资源,防止内存溢出。 - 并发控制:通过
Semaphore限制同时处理的视频数量,防止系统CPU/内存被占满。 - 跨平台路径处理:用
os.path模块替代硬编码的路径分隔符,兼容Windows和Linux系统。
内容的提问来源于stack exchange,提问作者DI PAULI Théo
相关产品推荐
相关产品推荐

