使用php调用ffmpeg将视频转码为mp4,核心方法是利用`exec()`或`proc_open()`执行系统命令,并传入包含编码参数(如`-c:v libx264 -c:a aac`)的ffmpeg指令。通过构建完整的命令行字符串并捕获输出流,可以实现从源文件到目标mp4文件的转换。若源格式与mp4兼容且无需重编码,可添加`-c copy`参数以加速处理;否则需指定具体的视频和音频编码器以确保兼容性。

如何构建基础的PHP转码函数
构建基础转码函数的关键在于封装FFmpeg命令的执行过程,确保路径正确且能处理错误输出。主要步骤包括验证输入文件存在、构建包含输入路径、输出路径及编码参数的命令字符串,以及执行命令并检查返回状态码。该函数应返回布尔值表示成功与否,或通过异常机制通知调用者失败原因。

$ffmpegPath = '/usr/bin/ffmpeg';
$inputFile = 'input.avi';
$outputFile = 'output.mp4';
function convertToMp4($ffmpeg, $in, $out) {
if (!file_exists($in)) {
return false;
}
// 基本转码命令:视频用libx264,音频用aac
$cmd = sprintf(
'%s -i %s -c:v libx264 -c:a aac -movflags +faststart %s 2>&1',
escapeshellarg($ffmpeg),
escapeshellarg($in),
escapeshellarg($out)
);
exec($cmd, $output, $returnCode);
return $returnCode === 0;
}
$success = convertToMp4($ffmpegPath, $inputFile, $outputFile);
上述代码展示了最简实现。注意使用了`escapeshellarg`防止命令注入。`-movflags +faststart`用于优化Web播放。如果`$success`为`false`,则转码失败,需检查日志或FFmpeg输出。
立即学习“PHP免费学习笔记(深入)”;
如何处理大文件转码的进度监控
对于大文件,直接阻塞等待`exec()`完成是不可接受的。需要采用异步方式或解析FFmpeg的标准错误输出来提取进度信息。FFmpeg在转码过程中会向stderr输出类似`time=00:01:23.45 bitrate=1234.5kbits/s speed=1.2x`的行。PHP可以通过`proc_open()`获取stderr管道,逐行读取并解析时间戳或百分比,从而更新前端进度条或记录日志。

$process = proc_open(
sprintf(
'%s -i %s -c:v libx264 -c:a aac %s 2>&1',
escapeshellarg($ffmpegPath),
escapeshellarg($inputFile),
escapeshellarg($outputFile)
),
[
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'] // stderr
],
$pipes
);
if (is_resource($process)) {
while (!feof($pipes[2])) {
$line = fgets($pipes[2]);
// 解析 $line 中的 time 字段计算进度
// 例如: preg_match('/time=(\d+):(\d+):(\d+)/', $line, $matches);
echo $line;
}
proc_close($process);
}
此方法允许实时反馈。需注意解析正则表达式的准确性,不同FFmpeg版本输出格式可能微调。实际生产中建议结合队列系统(如Redis或RabbitMQ)处理长任务,避免Web请求超时。
当输入视频无音频轨道时转码结果是什么
当输入视频没有音频轨道时,默认FFmpeg转码命令可能会报错或生成无声MP4,具体取决于FFmpeg版本和配置。现代FFmpeg通常会自动处理缺失流,但显式指定`-an`(无音频)或忽略音频映射可避免警告。若未指定音频编码器,FFmpeg可能尝试复制空音频流或报错。最佳实践是检测输入流信息,若无音频则跳过音频编码参数,或使用`-map`精确控制流。



















