PHP无法直接将PHP文件转为MP4;实际仅两类场景:①合并PHP生成的图像序列为MP4;②用PHP调用FFmpeg转换真实视频文件为MP4。

用 exec() 调 ffmpeg 是最轻量、最可控的方式
绝大多数生产环境都走这条路——不依赖扩展,不引入 Composer 包,只要系统装了 FFmpeg,一行 exec() 就能启动转码。
- 必须先验证
ffmpeg -version能在 PHP 进程环境下执行(注意:Web 服务器用户如www-data可能没权限或没 PATH) - 务必用
escapeshellarg()包裹文件路径,否则含空格、中文、特殊字符的路径会直接失败 - 别省略
2>&1重定向,否则错误全丢进黑洞,$output数组里啥也看不到 -
$returncode为 0 才算成功,非 0 时一定要读$output看具体报错(比如 “No such file”、“Permission denied”、“Invalid data found”)
&1',
escapeshellarg($input),
escapeshellarg($output)
);
exec($cmd, $output_lines, $return_code);
if ($return_code !== 0) {
error_log('FFmpeg failed: ' . implode("\n", $output_lines));
die('转码失败,请检查日志');
}
?>
用 php-ffmpeg/php-ffmpeg 扩展适合中大型项目
如果你需要链式操作(截图、裁剪、加水印、多轨道混音)、批量任务管理、或想屏蔽命令行细节,这个 Composer 包值得上。
- 它只是 FFmpeg 的“语法糖”,底层仍调用
ffmpeg和ffprobe二进制,所以系统 FFmpeg 还是得装好 - 初始化时建议显式传入路径:
FFMpeg::create(['ffmpeg.binaries' => '/usr/local/bin/ffmpeg']),避免找不到命令 - 对大文件或高并发场景,要注意 PHP 进程超时(
set_time_limit(0))、内存限制(ini_set('memory_limit', '512M')) - 不要在 Web 请求里直接转长视频(>2 分钟),应改用队列 + 后台进程(如 Supervisor + Laravel Horizon)
别踩这些坑:关于“input.php”当视频文件的迷思
网上大量示例写 ffmpeg -i input.php output.mp4,这根本跑不通——FFmpeg 会报 Invalid data found when processing input。
-
input.php不是视频,是文本源码;FFmpeg 无法从中解析帧或音轨 - 极少数情况:有人把 Base64 编码的 MP4 数据硬编码进 PHP 文件里,再用
file_put_contents()解出二进制,但这属于自造轮子,毫无必要 - 真正该做的,是让 PHP 控制「谁来提供视频输入」:从上传表单、S3 URL、数据库 BLOB,或动态生成图像帧后喂给 FFmpeg
替代方案?云服务只适合特定场景
像 Zencoder、AWS Elastic Transcoder、Cloudflare Stream 这类 API 方案,适合你不想运维 FFmpeg、视频源在对象存储、或需要全球 CDN 分发的场景。
立即学习“PHP免费学习笔记(深入)”;
- 但它们不解决“本地 PHP 怎么转 MP4”的问题,而是绕开它
- 每次转码要发 HTTP 请求、等回调、处理 webhook,延迟和复杂度远高于本地 FFmpeg
- 小项目、内网系统、隐私敏感数据,优先选本地 FFmpeg —— 你永远知道字节在哪、谁在读它
exec("ffmpeg -version", $o, $r) 在你的 PHP 环境里跑通,后面所有事才真正开始。











