本文目录导读:

- 方案一:使用 FFmpeg(最通用、最强大)
- 方案二:使用 PHP 专用扩展(如 FFMpeg-PHP)
- 方案三:云服务/第三方API(推荐用于生产环境)
- 方案四:使用 PHP 的
imagick或gd库(仅处理封面/GIF) - 总结与建议
在 PHP 项目中实现短视频处理,通常有几种不同的路径,具体取决于你的需求(是简单的转码、添加水印,还是复杂的剪辑、特效)。
由于 PHP 本身不是为视频处理设计的底层语言,主流的实现方式是结合系统命令或专用的扩展/服务。
以下是几种主流且可行的方案,从简单到复杂依次介绍:
使用 FFmpeg(最通用、最强大)
这是处理短视频最标准、最灵活的方式,FFmpeg 是一个强大的命令行音视频处理工具。
实现方式: 在 PHP 中通过 exec()、shell_exec()、proc_open() 等函数调用操作系统中的 FFmpeg 命令。
安装 FFmpeg
- Linux (Ubuntu/Debian):
sudo apt install ffmpeg - macOS:
brew install ffmpeg - Windows: 下载二进制文件并添加到系统 PATH。
PHP 代码示例
<?php
// 假设你的视频文件路径
$inputFile = '/path/to/upload/short_video.mp4';
$outputFile = '/path/to/output/processed.mp4';
// 1. 最简单的转码 (压缩体积,修改尺寸)
$cmd = "ffmpeg -i " . escapeshellarg($inputFile) .
" -vf \"scale=720:-2\" " . // 缩放宽度到720px,高度自动保持比例且为偶数
" -c:v libx264 -preset fast -crf 28 " . // 使用H.264编码,适当压缩
" -c:a aac -b:a 128k " . // 音频编码为AAC
escapeshellarg($outputFile) . " 2>&1"; // 2>&1 用于捕获错误信息
echo "执行命令:$cmd\n";
$output = shell_exec($cmd);
echo "输出:$output\n";
// 2. 添加文字水印
$text = "我的水印";
$watermarkCmd = "ffmpeg -i " . escapeshellarg($inputFile) .
" -vf \"drawtext=text='$text':fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:x=10:y=10:fontsize=24:fontcolor=white:shadowy=2\"" .
" " . escapeshellarg($outputFile) . " 2>&1";
// 3. 截取视频片段 (从第5秒开始,持续10秒)
$clipCmd = "ffmpeg -i " . escapeshellarg($inputFile) .
" -ss 00:00:05 -t 10 " .
" -c copy " . // 不重新编码,速度快
escapeshellarg($outputFile) . " 2>&1";
// 4. 获取视频文件信息 (时长、尺寸、码率)
$infoCmd = "ffprobe -v error -show_entries format=duration,size,bit_rate -of default=noprint_wrappers=1:nokey=1 " .
escapeshellarg($inputFile);
$info = shell_exec($infoCmd);
echo "视频信息: $info\n";
?>
优点:
- 功能极其强大,几乎可以处理任何视频格式。
- 社区活跃,资料丰富。
缺点:
- 需要服务器安装 FFmpeg,并开放
exec等函数(有安全风险,需谨慎处理用户输入)。 - 处理大视频时可能阻塞 PHP 进程(建议使用消息队列异步处理)。
- 关键安全提醒: 永远不要直接将用户输入的文件名或参数传递给
exec,务必使用escapeshellarg()转义。
使用 PHP 专用扩展(如 FFMpeg-PHP)
这是一个基于 PHP 的面向对象封装库,底层依然调用 FFmpeg。
实现方式: 通过 Composer 安装 php-ffmpeg/php-ffmpeg。
安装
composer require php-ffmpeg/php-ffmpeg
代码示例
<?php
require 'vendor/autoload.php';
$ffmpeg = FFMpeg\FFMpeg::create([
'ffmpeg.binaries' => '/usr/bin/ffmpeg', // 路径
'ffprobe.binaries' => '/usr/bin/ffprobe',
'timeout' => 3600, // 超时时间
]);
$video = $ffmpeg->open('/path/to/input.mp4');
// 转码和缩放
$video
->filters()
->resize(new \FFMpeg\Coordinate\Dimension(720, 720))
->synchronize();
$format = new \FFMpeg\Format\Video\X264('libmp3lame', 'libx264');
$format->setKiloBitrate(1000); // 码率
$video->save($format, '/path/to/output.mp4');
// 截取帧 (生成封面图)
$frame = $video->frame(\FFMpeg\Coordinate\TimeCode::fromSeconds(10));
$frame->save('/path/to/cover.jpg');
// 获取视频时长 (秒)
$duration = $ffmpeg->getFFProbe()->streams('/path/to/input.mp4')
->videos()->first()->get('duration');
?>
优点:
- 代码更优雅,面向对象,易于维护。
- 自动处理了 FFmpeg 的命令行参数。
缺点:
- 仍然依赖 FFmpeg 二进制文件。
- 对非常复杂的滤镜(filter graph)支持不如直接写命令灵活。
云服务/第三方API(推荐用于生产环境)
如果不想自己管理服务器资源和 FFmpeg 版本,使用专业的云视频处理服务是最省心、最安全的方式。
常见服务:
- 七牛云 / 阿里云 OSS + 媒体处理:上传视频后,调用 API 触发转码、水印、截图等,支持异步通知(Webhook)。
- 腾讯云 VOD(视频点播):功能全面,有专门的 PHP SDK。
- AWS Elemental MediaConvert:全球知名,PHP SDK 完善。
- Shotstack / Cloudinary:提供更简单的 API,适合前端集成。
实现方式(以阿里云为例):
// 1. 安装 SDK: composer require alibabacloud/sdk
// 2. 初始化和调用 API (伪代码)
$client = new DefaultAcsClient(profile);
$request = new MtsRequest\SubmitJobsRequest();
$request->setInput(json_encode(['Location'=>'oss-cn-hangzhou', 'Bucket'=>'my-bucket', 'Object'=>'video/abc.mp4']));
$request->setOutputBucket('my-output-bucket');
$request->setOutputLocation('oss-cn-hangzhou');
// 定义转码模板 (水印、尺寸)
$outputs = [
'OutputFile' => ['Object' => 'processed/abc.mp4'],
'TemplateId' => 'S00000001-200030', // 预先定义的转码模板
'WaterMarks' => [...]
];
$request->setOutputs(json_encode($outputs));
$response = $client->getAcsResponse($request);
优点:
- 无需服务器资源,处理速度快,支持高并发。
- 安全,不暴露服务器命令执行。
- 通常提供 CDN 分发,直接输出可播放的 URL。
缺点:
- 需要付费(按量或包月)。
- 依赖网络,离线场景不可用。
使用 PHP 的 imagick 或 gd 库(仅处理封面/GIF)
如果只需要生成视频封面图或处理 GIF,可以用 Imagick 配合 FFmpeg 的视频帧。
// 先生成一张帧图片 (用ffmpeg)
exec("ffmpeg -i input.mp4 -ss 00:00:03 -vframes 1 frame.png");
// 再用 Imagick 加水印、裁剪
$image = new Imagick('frame.png');
$watermark = new Imagick('logo.png');
$image->compositeImage($watermark, Imagick::COMPOSITE_OVER, 10, 10);
$image->writeImage('cover_with_watermark.jpg');
总结与建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 学习/小项目/内网 | FFmpeg + PHP exec | 免费、灵活、可完全控制。 |
| 中小型商业项目 | php-ffmpeg 扩展 | 代码更规范,便于团队维护。 |
| 大型/高并发/安全要求高 | 云服务 (阿里云/七牛/腾讯云) | 不用担心服务器负载和命令注入,有完整回调机制。 |
| 只需要封面图 | FFmpeg + Gd/Imagick | 简单快速,内存占用低。 |
重要安全建议:
- 永远不要直接在 PHP 中处理用户上传的短视频(如直播流或上传到临时目录)。
- 始终使用
move_uploaded_file()将上传文件移动到受保护的、非 web 可访问的目录。 - 如果使用
exec,必须对文件名和路径使用escapeshellarg()。 - 建议使用消息队列(如 Redis + 队列)来异步处理视频,避免阻塞 PHP-FPM 进程。