如何使用Python将FFmpeg的输出直接存储到S3存储桶中
视频转码结果直接上传S3的两种可落地方案
方案1:本地临时文件中转(最稳妥,易调试)
适合视频文件不大、服务器磁盘空间充足的场景,开发成本低,出错后易排查。
import boto3 import subprocess import os # 替换为你的实际配置 S3_REGION = "你的S3区域" S3_ACCESS_KEY_ID = "你的S3访问密钥ID" S3_ACCESS_SECRET_KEY = "你的S3访问密钥" S3_BUCKET = "目标S3桶名" avi_file_path = "本地输入的AVI文件路径" output_name = "输出文件的名称(不带后缀)" local_output_path = f"{output_name}.mp4" s3 = boto3.client('s3', region_name = S3_REGION, aws_access_key_id = S3_ACCESS_KEY_ID, aws_secret_access_key = S3_ACCESS_SECRET_KEY) # 执行转码,捕获执行状态 ffmpeg_cmd = [ "ffmpeg", "-i", avi_file_path, "-ac", "2", "-b:v", "2000k", "-c:a", "aac", "-c:v", "libx264", "-b:a", "160k", "-vprofile", "high", "-bf", "0", "-strict", "experimental", "-f", "mp4", local_output_path ] result = subprocess.run(ffmpeg_cmd, capture_output=True, text=True) if result.returncode != 0: print(f"转码失败,错误日志:{result.stderr}") else: # 上传到S3,s3_key为文件在桶内的存储路径 s3_key = f"transcoded_videos/{output_name}.mp4" s3.upload_file(local_output_path, S3_BUCKET, s3_key) # 上传完成后清理本地临时文件,按需开启 os.remove(local_output_path) # 若输入文件也是临时下载的,也可同步删除 # os.remove(avi_file_path)
方案2:流式直接上传(无本地磁盘占用,适合大文件)
无需写入本地磁盘,直接把ffmpeg的输出流上传到S3,适合大视频、服务器磁盘空间有限的场景。
import boto3 import subprocess from io import BytesIO # 替换为你的实际配置 S3_REGION = "你的S3区域" S3_ACCESS_KEY_ID = "你的S3访问密钥ID" S3_ACCESS_SECRET_KEY = "你的S3访问密钥" S3_BUCKET = "目标S3桶名" avi_file_path = "本地输入的AVI文件路径" # 转码后文件在S3的存储路径 output_s3_key = "transcoded_videos/你的输出文件名.mp4" s3 = boto3.client('s3', region_name = S3_REGION, aws_access_key_id = S3_ACCESS_KEY_ID, aws_secret_access_key = S3_ACCESS_SECRET_KEY) # ffmpeg输出到stdout,新增movflags参数保证mp4支持流式输出 ffmpeg_cmd = [ "ffmpeg", "-i", avi_file_path, "-ac", "2", "-b:v", "2000k", "-c:a", "aac", "-c:v", "libx264", "-b:a", "160k", "-vprofile", "high", "-bf", "0", "-strict", "experimental", "-movflags", "frag_keyframe+empty_moov", "-f", "mp4", "-" ] # 启动ffmpeg进程,捕获标准输出流 process = subprocess.Popen(ffmpeg_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 直接将流转上传到S3 s3.upload_fileobj(BytesIO(process.stdout.read()), S3_BUCKET, output_s3_key) # 校验转码执行结果 stderr = process.stderr.read().decode() if process.wait() != 0: print(f"转码失败,错误日志:{stderr}") # 按需删除S3上的无效文件 s3.delete_object(Bucket=S3_BUCKET, Key=output_s3_key)
注意事项
- 不要使用
os.popen调用ffmpeg,无法捕获错误状态和运行日志,转码失败时无法感知,统一使用subprocess模块更稳妥 - S3访问凭证需要配置对应桶的
s3:PutObject权限,如果需要清理上传失败的无效文件,还要额外开通s3:DeleteObject权限 - 如果输入视频本身存储在S3上,可先调用
s3.download_file下载到本地临时路径再执行转码,更高阶的场景也可以配合S3流式下载和ffmpeg流式输入做到全链路无本地文件 - 10GB以上的大文件场景无需额外开发,
boto3的upload_file和upload_fileobj默认开启自动分片上传,稳定性有保障
内容的提问来源于stack exchange,提问作者Parth Shah
相关产品推荐
相关产品推荐

