AWS Lambda集成FFmpeg提取帧无文件输出问题求助
问题
我在AWS Lambda上部署了FFmpeg层,想要执行以下命令从输入视频中每秒提取8帧并保存到当前目录:
ffmpeg -i video.mp4 -qscale:v 2 -vf fps=8 '%04d.jpg'
但运行以下Python代码后没有生成任何文件,请问我遗漏了什么?
import ... SIGNED_URL_TIMEOUT = 60 FPS_SAMPLES = 8 def lambda_handler(event, context): # Set up logging. logger = logging.getLogger(__name__) s3_client = boto3.client('s3') s3_source_bucket = event['Records'][0]['s3']['bucket']['name'] s3_source_key = event['Records'][0]['s3']['object']['key'] s3_source_basename = os.path.splitext(os.path.basename(s3_source_key))[0] logger.info( "bucket: %s, key: %s, basename: %s",s3_source_bucket, s3_source_key, s3_source_basename) s3_source_signed_url = s3_client.generate_presigned_url('get_object', Params={'Bucket': s3_source_bucket, 'Key': s3_source_key}, ExpiresIn=SIGNED_URL_TIMEOUT) with tempfile.TemporaryDirectory() as tmpdir: os.chdir(tmpdir) # change the current folder to that one (current one is in os.getcwd()) cwd = os.getcwd() ffmpeg_cmd = "/opt/bin/ffmpeg -i \"" + s3_source_signed_url + "\" -qscale:v 2 -vf fps="+str(FPS_SAMPLES)+" "+ cwd + "/'%04d.jpg'" print("COMMAND: "+ffmpeg_cmd) command1 = shlex.split(ffmpeg_cmd) p1 = subprocess.run(command1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # List all files and directories in the current directory contents = os.listdir(cwd) # Print the contents print(f"Contents of {cwd}:") for item in contents: print(item) # <--- NOthing here... return { 'statusCode': 200, 'body': json.dumps("bucket: %s, key: %s, basename: %s" % (s3_source_bucket, s3_source_key, s3_source_basename)) }
解决方案
导致文件未生成的核心问题及修复方法如下:
缩进错误导致临时目录提前销毁
你把FFmpeg命令执行、文件列表查询等代码放在了with tempfile.TemporaryDirectory()块的外部。with块结束后会自动清理临时目录,这意味着FFmpeg还没执行完,目标目录就已经被删除了,自然不会生成任何文件。修复:将所有需要在临时目录内执行的代码缩进,放到
with块内部:with tempfile.TemporaryDirectory() as tmpdir: os.chdir(tmpdir) cwd = os.getcwd() ffmpeg_cmd = "/opt/bin/ffmpeg -i \"" + s3_source_signed_url + "\" -qscale:v 2 -vf fps="+str(FPS_SAMPLES)+" '%04d.jpg'" print("COMMAND: "+ffmpeg_cmd) command1 = shlex.split(ffmpeg_cmd) p1 = subprocess.run(command1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 打印FFmpeg日志排查错误 print("FFmpeg stdout:", p1.stdout.decode()) print("FFmpeg stderr:", p1.stderr.decode()) contents = os.listdir(cwd) print(f"Contents of {cwd}:") for item in contents: print(item)输出路径的引号与冗余路径问题
构造命令时给输出路径拼接了cwd并加了单引号,shlex.split()会把单引号解析为路径的一部分,导致FFmpeg输出路径错误。既然已经切换到临时目录作为当前工作目录,直接用'%04d.jpg'作为输出路径即可,无需额外拼接绝对路径。未校验FFmpeg执行状态
代码没有检查FFmpeg的执行返回码,也没有打印错误日志,无法定位命令是否执行失败。建议添加状态检查:if p1.returncode != 0: logger.error(f"FFmpeg执行失败: {p1.stderr.decode()}") raise Exception(f"视频帧提取失败: {p1.stderr.decode()}")额外排查点
- 验证FFmpeg层路径:添加
print(os.path.exists("/opt/bin/ffmpeg"))确认FFmpeg可执行文件存在 - 检查Lambda临时空间:默认512MB,若视频过大或帧数量多可能导致空间不足
- 确认S3权限:Lambda角色需有访问源桶的权限,预签名URL有效期(当前60秒)需足够完成视频下载与处理
- 验证FFmpeg层路径:添加
内容的提问来源于stack exchange,提问作者Stormsson
相关产品推荐
相关产品推荐

