
本文详解 ffmpeg 视频压缩任务在 php + cron 环境下频繁输出仅 1 秒视频的典型原因,重点指出缺失日志捕获、未强制覆盖及静默失败等关键陷阱,并提供可直接落地的健壮命令模板与调试方案。
本文详解 ffmpeg 视频压缩任务在 php + cron 环境下频繁输出仅 1 秒视频的典型原因,重点指出缺失日志捕获、未强制覆盖及静默失败等关键陷阱,并提供可直接落地的健壮命令模板与调试方案。
在自动化视频处理流程(如上传→压缩→上传存储)中,使用 ffmpeg 配合 PHP 的 exec() 执行压缩命令却只生成 1 秒长的输出文件,是一个常见但极易被忽视的问题。根本原因通常并非命令逻辑错误,而是 FFmpeg 因输入异常、编码失败或权限/路径问题而提前终止,PHP 却未捕获任何错误信息,导致看似“成功”实则只写入了初始帧数据。
✅ 正确做法:强制日志 + 覆盖 + 显式错误处理
首先,必须将 FFmpeg 的标准输出(stdout)和标准错误(stderr)完整重定向到日志文件,这是定位问题的唯一可靠途径。同时添加 -y 参数避免因目标文件已存在导致的静默中断:
$log_file = $temp_dir . "/" . $folder . "/log-" . basename($sub_file) . ".log";
$command = "ffmpeg -y -v info "
. "-i " . escapeshellarg($temp_dir . "/" . $folder . "/" . $sub_file) . " "
. "-vf scale=1280:-1 "
. "-c:v libx264 -preset veryslow -crf 24 "
. "-c:a aac -b:a 128k "
. escapeshellarg($temp_dir . "/" . $folder . "/edit-" . $sub_file)
. " > " . escapeshellarg($log_file) . " 2>&1";
// 执行并检查返回值
$output = [];
$retval = 0;
exec($command, $output, $retval);
if ($retval !== 0) {
error_log("FFmpeg failed with exit code {$retval}. See log: {$log_file}");
throw new RuntimeException("Video compression failed. Check log file.");
}? 关键细节说明:
escapeshellarg()是必备防护,防止文件名含空格或特殊字符引发命令截断;-v info显式设置日志级别(避免默认 quiet 模式掩盖警告);-c:a aac -b:a 128k补充音频编码参数,避免因源视频无音频或音频不兼容导致转码中断;- 日志文件路径需确保
$temp_dir/$folder/目录存在且 PHP 进程有写权限(Cron 环境用户常与 Web 用户不同,务必验证)。
⚠️ 常见陷阱排查清单
-
Cron 环境变量缺失:FFmpeg 可能依赖
PATH或LD_LIBRARY_PATH,在 Cron 中需显式指定完整路径(如/usr/bin/ffmpeg)或在 crontab 中预设环境变量; -
超时或内存限制:长时间运行的
very_slow预设可能触发系统超时,建议先用medium预设测试稳定性; -
输入文件损坏或格式异常:用
ffprobe $input_file检查源视频元数据是否完整; - 磁盘空间不足:Cron 任务无交互提示,空间耗尽时 FFmpeg 可能静默失败。
✅ 推荐精简稳定命令(生产环境首选)
ffmpeg -y -v warning -i INPUT.mp4 \ -vf "scale=1280:-2,format=yuv420p" \ -c:v libx264 -preset medium -crf 28 \ -c:a aac -b:a 96k -ar 44100 \ -movflags +faststart \ OUTPUT.mp4
其中 -vf "format=yuv420p" 确保兼容性(尤其对 HTML5 播放至关重要),-movflags +faststart 使视频支持流式加载。
通过引入结构化日志、严格参数校验与环境适配,即可彻底解决“压缩变截断”问题,让 Cron 视频流水线真正稳定可靠。

















