PHP调用FFmpeg卡死需控制进程执行时限:推荐proc_open配合stream_set_blocking、stream_select和proc_get_status实现手动超时检测,超时则proc_terminate强制终止;Linux/macOS下可用timeout命令包装,返回124表示超时。

PHP 调用 FFmpeg 时卡死,通常是因为 FFmpeg 进程长时间无响应(比如输入文件损坏、网络流中断、编码参数异常等),而 PHP 默认会一直等待子进程结束。要避免卡死,关键不是“设置 FFmpeg 自身的超时”,而是**控制 PHP 启动的外部进程执行时限**。
用 proc_open + stream_set_timeout 或 pcntl_alarm 控制执行时间
推荐使用 proc_open 配合非阻塞读取和手动超时判断,这是最可靠的方式:
- 用
proc_open启动 FFmpeg 进程,获取 stdin/stdout/stderr 的资源句柄 - 用
stream_set_blocking($pipes[1], false)和stream_select实现带超时的读取 - 主循环中定期检查进程是否退出(
proc_get_status),超时则调用proc_terminate
示例片段(简化版):
$descriptors = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'], // stderr
];
$process = proc_open('ffmpeg -i input.mp4 -c:v libx264 output.mp4', $descriptors, $pipes);
if (!is_resource($process)) { die('proc_open failed'); }
<p>$timeout = 30; // 秒
$start = time();
while (time() - $start < $timeout) {
$status = proc_get_status($process);
if (!$status['running']) break;</p><pre class='brush:php;toolbar:false;'>// 尝试读取 stderr(FFmpeg 日志主要在这里)
if (is_resource($pipes[2])) {
stream_set_blocking($pipes[2], false);
$line = fgets($pipes[2]);
if ($line !== false) echo $line;
}
usleep(100000); // 100ms 间隔检查}
立即学习“PHP免费学习笔记(深入)”;
if (proc_get_status($process)['running']) { proc_terminate($process, 9); // 强制终止 proc_close($process); throw new Exception('FFmpeg timeout'); }
用 system/exec + timeout 命令(Linux/macOS 环境)
如果服务器是 Linux/macOS,可借助系统 timeout 命令包装 FFmpeg:
timeout 30s ffmpeg -i input.mp4 -c:v libx264 output.mp4- PHP 中用
exec或shell_exec调用该命令 - 注意:确保 web 用户(如 www-data)有权限执行
timeout,且路径在 PATH 中
返回值为 124 表示被 timeout 终止,可据此判断超时。
避免常见陷阱
-
不要只依赖
set_time_limit:它只限制 PHP 脚本总执行时间,对已启动的外部进程无效 -
慎用
exec+&后台运行:脱离 PHP 控制后无法主动 kill,容易堆积僵尸进程 -
FFmpeg 自身参数不解决卡死:
-t(限制输出时长)、-deadline(WebM)等是内容层面控制,无法防止因 I/O 卡住导致的 hang - 务必关闭不需要的管道:比如不读 stdout 就 fclose($pipes[1]),否则某些系统下 proc_open 可能假死
补充建议:加日志和健壮性检查
生产环境建议:
- 转码前先用
ffprobe快速校验输入文件是否可读、时长是否合理 - 将 FFmpeg stderr 完整重定向到日志文件,便于排查 hang 的具体原因(如 “Connection timed out”、“Invalid data found”)
- 对用户上传文件做大小/扩展名/魔数校验,避免恶意或损坏文件直接进 FFmpeg



















