php本身不支持多线程视频转码,实际是通过proc_open()管理ffmpeg子进程实现并发,或借助swoole worker构建异步队列;直接foreach+exec()会导致串行阻塞、资源耗尽、错误中断和进度丢失。

PHP 本身不支持多线程视频转码,所谓“PHP 多线程批量转 MP4”,实际是用 PHP 启动多个 FFmpeg 进程并行执行,或把任务分发给常驻进程(如 Swoole Worker)调度——直接在 PHP 脚本里用 exec() 循环调用 FFmpeg,不加控制就是串行堵死,加了 proc_open() + 进程池管理才可能真正并发。
为什么不能直接 foreach + exec() 批量转码
看似简单,但极易崩:
- PHP 默认以阻塞方式等待每个
exec()返回,5 个视频 = 5 次串行等待,总耗时 = 单个转码时间 × 5 - 未限制并发数时,服务器 CPU/内存瞬间拉满,FFmpeg 报
Cannot allocate memory或直接被 OOM killer 杀掉 - 没有错误隔离:一个视频路径错、编码损坏、权限不足,整个循环中断,后续任务全挂
- 无法获取实时进度,
exec()只返回最终退出码,中间日志全丢
用 proc_open() 控制单机多进程并发
这是最轻量、无需额外扩展的方案,核心是手动管理子进程生命周期和资源上限。
- 用
proc_open()启动 FFmpeg 子进程,不加wait就继续下一轮,实现“发射即忘” - 维护一个进程数组,每轮检查
proc_get_status(),存活数超限就sleep(1)等待释放 - 必须设置
timeout和memory_limit,避免僵尸进程堆积;建议单机并发 ≤ CPU 核数 × 1.5 - 输出重定向到临时文件,避免 stdout/stderr 混乱;失败时读取日志定位是 codec 不支持还是路径不存在
$processes = [];
foreach ($videos as $input => $output) {
$cmd = sprintf('ffmpeg -i %s -c:v libx264 -c:a aac -y %s 2> /tmp/ffmpeg_%s.log',
escapeshellarg($input),
escapeshellarg($output),
uniqid()
);
$processes[] = proc_open($cmd, [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes);
while (count($processes) >= 4) { // 限并发为 4
foreach ($processes as $key => $p) {
if (!proc_get_status($p)['running']) {
proc_close($p);
unset($processes[$key]);
}
}
sleep(1);
}
}
用 Swoole Worker 实现稳定异步队列消费
适合生产环境长期运行,比 proc_open() 更可控,但需部署 Swoole 扩展。
- PHP 主进程只负责把转码任务推入 Redis 队列(如
transcode:queue),不碰 FFmpeg - Swoole 启动常驻 Worker 进程,用
while(true)循环BRPOP拿任务,每次只处理一个 - Worker 内部仍用
proc_open()调 FFmpeg,但失败可自动重试、记录错误码、触发告警 - 关键点:
set_time_limit(0)+gc_disable()+ 定期cli_set_process_title()标记当前任务,否则进程会悄无声息僵死
容易被忽略的兼容性坑
不是所有“MP4 转 MP4”都安全,尤其批量处理时:
-
ffmpeg -i in.mp4 -c copy out.mp4看似快,但若源文件含 B-frame 或非标准 moov 位置,iOS/Safari 可能无法播放 - 批量转码前务必用
ffprobe -v quiet -show_entries stream=codec_name -of csv=p=0 $file检查原始编码,H.265 视频强制-c:v libx264才能保兼容 - Windows 下路径含空格或中文,
escapeshellarg()生成的引号可能被 cmd.exe 二次解析出错,建议统一用 Linux 环境或 WSL - FFmpeg 版本差异大:4.4 以下不支持
-vf scale=-2:720的自适应缩放,批量脚本要加版本检测
真正决定批量效率的从来不是 PHP 写了多少行,而是你有没有把 FFmpeg 当成独立服务来管——限制资源、隔离错误、监控状态。一旦漏掉其中一环,100 个视频里第 87 个失败,你根本不知道它卡在哪一步。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











