Laravel中FFmpeg转码后上传Amazon S3生成0B文件的原因排查
为什么FFmpeg处理后上传到Amazon S3生成了0B文件?
这个问题我遇到过不少,核心问题出在你把PHP代码和Shell命令混在一起用了,咱们一步步拆解原因和解决办法:
1. 最致命的错误:PHP函数与Shell命令混用
你在exec()里直接拼接了PHP的Storage::put('intromainfinal.mp4', ''),这完全是错误的用法。Storage::put是PHP的文件存储方法,不是Shell命令的一部分。当你执行这条exec时,Shell会把Storage::put(...)当成无效的命令参数去解析,导致FFmpeg根本没有正确输出视频文件;反而Storage::put('', '')会直接生成一个空文件,这就是你看到0B文件的直接原因。
2. FFmpeg输出路径逻辑错误
正确的流程应该是:先让FFmpeg把处理好的视频输出到本地临时文件,再用PHP把这个临时文件上传到S3,而不是试图在Shell命令里直接调用PHP的存储功能。我给你调整一下代码:
// 创建临时文件存储FFmpeg输出 $tempDir = sys_get_temp_dir(); $outputFile = tempnam($tempDir, 'ffmpeg_') . '.mp4'; // 构建安全的FFmpeg命令(用escapeshellarg转义参数,避免特殊字符破坏命令) $inputUrl = config('medialibrary.s3.domain') . '/listing_video/intromain.mp4'; $fontPath = storage_path('assets/video/FutuMd.ttf'); $carName = $listing->car->name; $ffmpegCmd = sprintf( 'ffmpeg -i %s -vf "drawtext=fontfile=%s: text=%s: x=680: y=500: fontsize=55: fontcolor=white: enable=\'between(t,4,6)\'" %s', escapeshellarg($inputUrl), escapeshellarg($fontPath), escapeshellarg($carName), escapeshellarg($outputFile) ); // 执行FFmpeg命令并捕获输出和返回码 exec($ffmpegCmd, $ffmpegOutput, $returnCode); if ($returnCode === 0) { // FFmpeg执行成功,上传临时文件到S3 if (file_exists($outputFile) && filesize($outputFile) > 0) { Storage::put('intromainfinal.mp4', file_get_contents($outputFile)); echo "视频处理并上传成功!"; } else { echo "FFmpeg未生成有效输出文件"; } // 清理临时文件 unlink($outputFile); } else { // FFmpeg执行失败,打印错误信息排查 echo "FFmpeg处理失败,返回码:$returnCode\n"; echo "错误输出:\n"; var_dump($ffmpegOutput); unlink($outputFile); }
这里重点用了escapeshellarg()来转义所有动态参数,避免因为文件名、文本里的特殊字符(比如空格、引号)导致命令执行失败。
3. FFmpeg命令本身可能存在问题
即使修复了路径逻辑,FFmpeg本身也可能因为各种原因执行失败,导致没有输出文件:
- 输入文件不可访问:确认
config('medialibrary.s3.domain')拼接的URL是否能直接在浏览器或命令行访问(比如用curl测试); - 字体文件问题:检查
storage_path('assets/video/FutuMd.ttf')指向的字体文件是否存在,且运行PHP的服务器用户(比如www-data)有读取权限; - Drawtext参数错误:比如
enable='between(t,4,6)'的语法是否正确,你可以单独在命令行测试简化版的FFmpeg命令,看是否能生成视频:ffmpeg -i https://your-s3-domain/listing_video/intromain.mp4 -vf "drawtext=fontfile=/path/to/FutuMd.ttf: text='Test Car': x=680: y=500: fontsize=55: fontcolor=white: enable='between(t,4,6)'" test_output.mp4
4. 权限与配置问题
- 运行PHP的服务器用户是否有写入临时文件目录的权限?
- Amazon S3的存储配置(比如密钥、Bucket名称、权限)是否正确?如果权限不足,可能导致上传的文件为空或上传失败。
内容的提问来源于stack exchange,提问作者Siddharth
相关产品推荐
相关产品推荐

