You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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))
}
解决方案

导致文件未生成的核心问题及修复方法如下:

  1. 缩进错误导致临时目录提前销毁
    你把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)
    
  2. 输出路径的引号与冗余路径问题
    构造命令时给输出路径拼接了cwd并加了单引号,shlex.split()会把单引号解析为路径的一部分,导致FFmpeg输出路径错误。既然已经切换到临时目录作为当前工作目录,直接用'%04d.jpg'作为输出路径即可,无需额外拼接绝对路径。

  3. 未校验FFmpeg执行状态
    代码没有检查FFmpeg的执行返回码,也没有打印错误日志,无法定位命令是否执行失败。建议添加状态检查:

    if p1.returncode != 0:
        logger.error(f"FFmpeg执行失败: {p1.stderr.decode()}")
        raise Exception(f"视频帧提取失败: {p1.stderr.decode()}")
    
  4. 额外排查点

    • 验证FFmpeg层路径:添加print(os.path.exists("/opt/bin/ffmpeg"))确认FFmpeg可执行文件存在
    • 检查Lambda临时空间:默认512MB,若视频过大或帧数量多可能导致空间不足
    • 确认S3权限:Lambda角色需有访问源桶的权限,预签名URL有效期(当前60秒)需足够完成视频下载与处理

内容的提问来源于stack exchange,提问作者Stormsson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 15:07:19