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

PHP调用FFMPEG执行视频处理命令时如何捕获执行错误

PHP搭配FFmpeg处理视频时捕获执行错误的实现方案

“该场景下无法捕获FFmpeg执行错误”的说法并不成立。你当前代码拿不到错误的核心原因是shell_exec()函数的局限性:

  1. 该函数仅返回命令的标准输出(stdout)内容,而FFmpeg的报错、警告信息默认全部输出到标准错误流(stderr),不会被shell_exec()捕获
  2. 该函数不会返回命令的执行退出状态码,你无法判断命令是成功跑完还是中途异常退出
  3. 你当前的代码存在两个额外问题:所有传入shell的参数未做转义,存在命令注入风险、特殊字符导致命令解析失败的问题;-s分辨率参数放置位置错误,和filter_complex滤镜链逻辑冲突,可能导致输出分辨率不符合预期。

正确实现步骤

  • 替换执行函数:用exec()替代shell_exec(),该函数支持通过第三个参数接收命令的退出状态码(状态码为0代表执行成功,非0值均为执行异常)
  • 重定向错误流:在命令末尾加2>&1,把FFmpeg输出到stderr的错误信息重定向到stdout,这样就能拿到全量执行日志
  • 转义所有shell参数:对所有文件路径、动态传入的参数用escapeshellarg()做转义,彻底避免命令注入和特殊字符解析问题
  • 修正命令逻辑:把分辨率调整逻辑整合到滤镜链中,增加-y参数自动覆盖已存在的输出文件避免进程卡住,增加-map参数明确指定输出流避免流选择异常

可直接使用的修正代码

// 对所有动态传入命令的参数做shell转义
$ffmpegBin = escapeshellarg($ffmpeg);
$inputFile = escapeshellarg($video['tmp_name']);
$watermarkFile = escapeshellarg('pics/watermark.png');
$outputFile = escapeshellarg("videos/{$video_name}");

// 拼接处理命令,2>&1 用于捕获错误输出
$command = <<<SHELL
{$ffmpegBin} -y -i {$inputFile} -i {$watermarkFile} \
-filter_complex "[1:v][0:v]scale2ref=(127/60)*ih/10/sar:ih/10[wm][base];[base][wm]overlay=10:10,scale={$resolution}[outv]" \
-map "[outv]" -pix_fmt yuv420p -c:a copy {$outputFile} 2>&1
SHELL;

// 执行命令,$fullOutput 存全量执行日志,$exitCode 存执行状态码
exec($command, $fullOutput, $exitCode);

// 异常判断
if ($exitCode !== 0) {
    $errorDetail = implode(PHP_EOL, $fullOutput);
    // 此处可自定义错误处理逻辑:写入日志、返回前端错误提示等
    throw new Exception("视频处理失败:" . $errorDetail);
}

// 执行到此处即代表视频处理完成

优化提示

如果处理的视频时长较长,全量日志存在内存里会占用较多资源,可以把错误输出重定向到临时文件:执行时把2>&1替换为2>' . escapeshellarg($tempLogPath),执行完成后如果状态码非0,再读取临时日志文件的内容拿到错误信息,执行成功则直接删除临时文件即可,能大幅降低内存占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:48:22