如何使用Python无需下载直接转换AWS S3存储桶内的视频格式
解决方法
核心原因说明
MoviePy底层依赖FFmpeg处理视频,FFmpeg仅支持读取本地文件路径输入,无法直接识别S3返回的字节流对象或S3协议路径,所以必须做一层中转处理,以下是两种可落地的实现方案:
方案1:临时本地文件中转(稳定兼容所有场景)
该方案逻辑最简单,几乎没有兼容问题,适合各种体积的视频处理,是优先推荐的方案:
实现代码
import boto3 import moviepy.editor as moviepy import tempfile import os # 初始化S3客户端 s3 = boto3.client('s3', region_name = S3_REGION, aws_access_key_id = S3_ACCESS_KEY_ID, aws_secret_access_key = S3_ACCESS_SECRET_KEY ) bucket_name = "替换为你的存储桶名" # 推荐用list_objects_v2替代旧版list_objects,支持分页处理 result = s3.list_objects_v2(Bucket = bucket_name, Prefix='videos/') for o in result.get('Contents', []): s3_key = o.get('Key') # 跳过目录占位对象 if s3_key.endswith('/'): continue # 只处理目标格式视频,可按需调整 if not s3_key.endswith('.webm'): continue # 创建带后缀的临时文件存储原S3视频 with tempfile.NamedTemporaryFile(suffix='.webm', delete=False) as src_temp: s3.download_fileobj(bucket_name, s3_key, src_temp) src_path = src_temp.name try: # 转码处理 clip = moviepy.VideoFileClip(src_path) # 创建临时文件存储转码后的MP4 with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as dst_temp: dst_path = dst_temp.name clip.write_videofile(dst_path) clip.close() # 上传转码后的文件到S3,可自定义目标存储路径 dst_s3_key = s3_key.replace('.webm', '.mp4').replace('videos/', 'converted/') s3.upload_file(dst_path, bucket_name, dst_s3_key) finally: # 强制清理临时文件,避免磁盘占用 os.unlink(src_path) if 'dst_path' in locals(): os.unlink(dst_path)
方案2:内存中转(避免磁盘IO,适合小体积视频)
如果处理的都是100M以内的小视频,可以用内存缓存临时文件,减少磁盘IO开销,提升处理速度:
实现代码
将方案1中的临时文件替换为SpooledTemporaryFile,设置内存阈值即可:
# 仅替换临时文件创建部分,其余逻辑和方案1一致 # 小于100M的文件完全在内存中处理,超过阈值自动落磁盘 with tempfile.SpooledTemporaryFile(max_size=100*1024*1024, suffix='.webm', delete=False) as src_temp: s3.download_fileobj(bucket_name, s3_key, src_temp) src_path = src_temp.name
注意:该方案不适合处理大体积视频,否则会占用过高内存导致进程被系统杀死。
大规模场景优化建议
如果需要处理的视频量级很大,可以选择更合适的架构方案:
- 用AWS Lambda做事件驱动转码:S3上传新视频自动触发Lambda执行转码逻辑,无需自己维护常驻脚本
- 直接使用AWS Elemental MediaConvert托管转码服务:无需自己维护FFmpeg、MoviePy依赖,支持批量、高并发转码,适合海量视频处理场景
- 本地运行脚本的话可以加入多进程/多线程逻辑,并行处理多个S3视频对象,提升转码效率
注意事项
- 运行环境需要提前安装FFmpeg,也可以直接安装
imageio-ffmpegPython包,无需手动安装系统级FFmpeg - 如果存储桶内视频超过1000个,
list_objects_v2只会返回前1000条,需要通过ContinuationToken做分页遍历才能拿到所有对象 - 建议加入异常捕获逻辑,处理视频损坏、S3访问超时、转码失败等异常情况,避免整个脚本中断
内容的提问来源于stack exchange,提问作者Parth Shah
相关产品推荐
相关产品推荐

