PHP调用FFmpeg压缩视频仅生成1秒文件问题求助
问题排查与解决方案
你遇到的压缩后视频仅保留首1秒的问题,大概率是FFmpeg执行过程中出现未被捕获的错误,或是Cron环境下的路径/权限/配置差异导致的,以下是具体排查方向和解决办法:
1. 捕获FFmpeg的错误输出
当前代码仅捕获stdout,但FFmpeg的错误信息会输出到stderr,这是排查问题的核心。修改命令将错误重定向到标准输出,同时记录完整日志:
try { $bitrate = "5000k"; $inputPath = $temp_dir . "/" . $folder . "/" . $sub_file; $outputPath = $temp_dir . "/" . $folder . "/edit-" . $sub_file; // 重定向stderr到stdout,并指定FFmpeg完整路径 $command = "/usr/bin/ffmpeg -i \"$inputPath\" -vf scale=1280:-1 -c:v libx264 -preset veryslow -crf 24 -c:a aac -b:a 128k \"$outputPath\" 2>&1"; $output = []; $retval = 0; exec($command, $output, $retval); // 写入日志以便排查 file_put_contents('/var/log/ffmpeg_process.log', date('Y-m-d H:i:s') . " Command: $command\nReturn Code: $retval\nOutput:\n" . implode("\n", $output) . "\n\n", FILE_APPEND); $temp_video = $outputPath; } catch (Exception $e) { file_put_contents('/var/log/ffmpeg_error.log', date('Y-m-d H:i:s') . " Exception: " . $e->getMessage() . "\n", FILE_APPEND); }
通过日志可以直接看到FFmpeg执行时的具体报错(比如源文件损坏、路径不存在、编码不兼容等)。
2. 确保源文件完整且可访问
- 检查Cron触发时,上传的源文件是否已完全写入磁盘。即使延迟处理,若上传为分块或异步完成,可能仍存在文件未写完的情况。可以对比源文件大小与上传完成后的预期值,或检查文件修改时间是否稳定。
- 确认Cron执行用户(如
www-data或root)对源文件和输出目录有读写权限,权限不足会导致FFmpeg无法完整读取源文件或写入输出文件,进而生成不完整视频。
3. 使用FFmpeg的完整路径
Cron的PATH环境变量比交互式Shell更受限,直接调用ffmpeg可能指向非预期版本或找不到命令。先在终端执行which ffmpeg获取完整路径(比如/usr/bin/ffmpeg),再替换到代码中。
4. 显式指定音频编码
你的命令仅处理视频流,FFmpeg默认复制音频流,但如果源文件音频格式存在兼容性问题,可能导致FFmpeg提前终止。显式指定音频编码(如-c:a aac -b:a 128k)可避免此类问题,确保音频流被正确处理。
5. 验证命令的有效性
先在服务器终端直接执行生成的FFmpeg命令(替换变量为实际路径),看是否能生成完整视频。如果终端执行正常但Cron执行异常,基本可确定是Cron环境问题(路径、权限、环境变量)。
内容的提问来源于stack exchange,提问作者BlackThorn
相关产品推荐
相关产品推荐

