本文目录导读:

PHP 绝对可以用来做视频转码,但它不是直接处理视频数据的,而是作为一个“指挥官”或“调度者”来调用底层的工具。
能用吗”这个问题,答案是:能,且在生产环境中被广泛使用(如很多CMS、短视频后台),但如果你问“能不能用纯PHP代码自己写一个转码器”,那是不现实的。
以下是详细的解决方案和注意事项,帮你避坑:
核心原理:PHP只是“胶水”
PHP本身没有处理音视频的底层库,实际的工作流程是:
- PHP接收上传请求(比如用户上传了一个MP4)。
- PHP创建命令行指令,调用系统上的 FFmpeg(业界标准工具)。
- PHP执行
exec()或shell_exec()把任务交给FFmpeg。 - FFmpeg在后台转码,PHP可能轮询状态或等它完成。
- 返回结果(比如转成H.264编码的720P格式)。
具体实施步骤
第一步:在服务器上安装 FFmpeg
这在Linux服务器(如Ubuntu/Debian)+ Nginx/Apache环境下非常稳定。
# Ubuntu/Debian 环境 sudo apt update sudo apt install ffmpeg
随后你可以在命令行测试:ffmpeg -version 确认安装成功。
第二步:确定专业参数
不要只用简单的 ffmpeg -i input.mp4 output.mp4,这对视频兼容性不够好,推荐使用经过调优的参数(H.264 + AAC是最通用的):
<?php
$input_file = '/path/to/uploads/source.mp4';
$output_file = '/path/to/converted/output_720p.mp4';
// 核心命令:将视频转为 H.264 编码,分辨率限制在 720p,音频转为 AAC,并通过 CRF 控制质量(18-23为高质量)
$command = "ffmpeg -i " . escapeshellarg($input_file) .
" -c:v libx264 -preset fast -crf 23 -profile:v main" .
" -vf scale=-2:720" .
" -c:a aac -b:a 128k -movflags +faststart" .
" -threads 4" .
" -y " . escapeshellarg($output_file); // -y 表示覆盖同名文件
// 执行命令并将输出写入日志
exec($command . " 2>&1", $output, $return_code);
var_dump($return_code); // 0 表示成功,非0 表示失败
?>
最大的坑:PHP超时(致命问题)
PHP默认最大执行时间是 30 秒,而转码一个高清视频可能需要几分钟甚至更久,如果直接在前台运行,浏览器会超时崩溃。
解决方案(三选一,强烈推荐第一种):
- 使用消息队列(推荐):这是最专业的做法。
- PHP收到任务后,将任务写入 Redis队列 或 数据库队列。
- 立即返回给用户“转码中,请稍后查看”。
- 后台运行一个 常驻PHP脚本(使用
while循环)或 Supervisor守护进程,持续从队列取任务,执行FFmpeg。
- 使用
proc_open异步执行:PHP只在后台启动进程,然后立即返回,不等待结果。 - 提高PHP超时限制:
set_time_limit(0);(不推荐,会占用PHP-FPM进程,高并发下撑不住)。
安全与权限管理(容易忽略)
如果你使用了 exec(),必须对文件路径做严格校验。
- 必须使用
escapeshellarg():防止用户上传的文件名中包含恶意命令(; rm -rf /)。 - 权限管理:确保 PHP(
www-data用户)对上传目录有读取权限,对输出目录有写入权限。 - 限制文件大小和类型:必须在PHP层就校验扩展名和MIME类型,防止恶意用户上传伪装成视频的脚本文件,或者恶意PDF/XML文件。
更简单的替代方案:云服务或专用扩展
如果你不想自己维护FFmpeg和服务器负载,有更简单的方案:
- 云转码服务:如阿里云、腾讯云的视频处理服务,PHP只需调用API接口,上传文件后,云端自动转码,安全且快速。
- PHP专用扩展(较少见):如
ffmpeg-php扩展,但实际上它也是FFmpeg的封装,且维护不再活跃,不如直接用命令行。
总结建议
- 能用,且是主流方案。
- 核心是FFmpeg,PHP只负责拼命令。
- 性能瓶颈在服务器的CPU(转码非常吃CPU)。
- 最稳妥的开发模式:同步接收文件 -> 存入待转码列表 -> 后台队列异步处理 -> 转完后通知前端。
如果你只是写个简单的内网工具,直接用 exec() 加 set_time_limit(0) 就行;如果是做商业级SaaS,一定要用队列架构。