PHP不能在Lambda中直接调用FFmpeg执行视频转码,因其运行时无FFmpeg、禁用exec类系统调用、沙箱限制严苛且同步模型不匹配;应由PHP负责调度(如发SQS或调用Lambda异步触发),由Python/Node.js Lambda函数通过Layer加载静态编译FFmpeg处理。

PHP本身不参与Lambda里的视频转码执行——它只适合做调度、验证、回调和状态管理;真正在Lambda里干活的是FFmpeg二进制,用Python或Node.js调用,PHP在这里没有运行环境,硬塞进去只会失败。
为什么不能直接在Lambda里跑PHP调用ffmpeg
AWS Lambda官方运行时(php8.2、php8.3)不预装ffmpeg,也不允许你通过exec()或shell_exec()调用系统命令。即使你把FFmpeg编译好打包进部署包,Lambda的执行权限默认禁用fork和execve类系统调用,PHP的exec会直接返回空数组+错误码126或127。
- PHP运行时是沙箱化的,仅暴露有限的POSIX接口,
proc_open、system等全被屏蔽 - 即使你用自定义容器镜像部署PHP运行时,也要额外解决glibc兼容性、动态链接库路径、/tmp空间限制(512MB上限)等问题
- PHP的同步阻塞模型与Lambda 15分钟超时、内存抖动特性天然冲突,不适合长时间音视频任务
可行的架构:PHP做前端调度,Lambda做后端worker
把PHP放在EC2、ECS或Cloudflare Workers这类支持完整PHP执行环境的地方,负责接收上传、校验文件、生成S3预签名URL、写入任务队列(如SQS或DynamoDB Stream),再由Lambda函数监听队列触发FFmpeg处理。
- PHP侧只需发一条
sqs.sendMessage()或写一条DynamoDB记录,不碰FFmpeg - Lambda函数用Python写,从
/opt/bin/ffmpeg(通过Layer引入)调用,输入输出全部走S3 URI - 转码完成后,Lambda向API Gateway或SNS发完成通知,PHP端轮询或监听Webhook更新数据库状态
FFmpeg Layer必须注意的三个硬限制
你在Lambda里能用的FFmpeg不是随便下载就能用的,必须严格匹配ARM64/x86_64架构、musl/glibc版本、以及/opt路径约定。
立即学习“PHP免费学习笔记(深入)”;
- Layer中的
ffmpeg二进制必须静态编译(推荐使用johnvansickle/ffmpeg),否则加载libavcodec.so时会报cannot open shared object file - Layer解压后总大小不能超过250MB(含所有依赖),否则部署失败;建议裁剪掉
ffprobe、ffplay等非必需工具 - 执行时务必加
-y -v error参数,避免FFmpeg输出大量info日志撑爆Lambda的5MB日志配额
PHP触发Lambda的最小可行代码示例
不要试图让PHP执行转码,只要让它可靠地“派单”:
// PHP端:触发Lambda处理S3上已上传的视频
$client = new Aws\Lambda\LambdaClient([
'region' => 'us-east-1',
'version' => 'latest'
]);
$result = $client->invoke([
'FunctionName' => 'video-transcode-worker',
'Payload' => json_encode([
'bucket' => 'my-source-bucket',
'key' => 'uploads/video_123.mp4',
'output_prefix' => 'transcoded/video_123/',
'preset' => 'h264-720p'
]),
'InvocationType' => 'Event' // 异步调用,不等结果
]);
这个调用成功,只代表任务已入队;后续成败得看Lambda日志、S3输出是否存在、以及你是否配置了DLQ捕获失败事件——这些才是实际要盯住的地方。



















