本文目录导读:

在PHP项目中使用FFmpeg,主要有两种方式:直接通过命令行执行 和 使用PHP扩展库,下面详细介绍这两种方法。
环境准备
安装FFmpeg
# Ubuntu/Debian sudo apt-get install ffmpeg # CentOS/RHEL sudo yum install ffmpeg # macOS brew install ffmpeg # Windows: 从官网下载并配置环境变量
验证安装
ffmpeg -version which ffmpeg # 查看路径
方法一:直接执行shell命令(推荐)
这是最常用且灵活的方法,通过exec()、shell_exec()或proc_open()等PHP函数执行ffmpeg命令。
基础示例
<?php
// 视频转码
$input = '/path/to/input.mp4';
$output = '/path/to/output.mp4';
$cmd = "ffmpeg -i {$input} -c:v libx264 -c:a aac {$output} 2>&1";
exec($cmd, $output, $return_var);
if ($return_var === 0) {
echo "转换成功";
} else {
echo "转换失败: " . implode("\n", $output);
}
封装成函数
<?php
class FFmpegCommand {
private $ffmpegPath = 'ffmpeg';
private $ffprobePath = 'ffprobe';
public function __construct($ffmpegPath = null) {
if ($ffmpegPath) {
$this->ffmpegPath = $ffmpegPath;
}
}
/**
* 执行ffmpeg命令
*/
public function execute($command) {
$fullCommand = "{$this->ffmpegPath} {$command} 2>&1";
$output = [];
$returnVar = 0;
exec($fullCommand, $output, $returnVar);
return [
'success' => $returnVar === 0,
'output' => implode("\n", $output)
];
}
/**
* 视频转码
*/
public function transcode($input, $output, $options = []) {
$defaultOptions = '-c:v libx264 -c:a aac -preset medium';
$cmd = "-i {$input} {$defaultOptions} {$output} -y";
return $this->execute($cmd);
}
/**
* 截取视频缩略图
*/
public function thumbnail($videoPath, $output, $time = '00:00:01') {
$cmd = "-i {$videoPath} -ss {$time} -vframes 1 {$output} -y";
return $this->execute($cmd);
}
/**
* 合并视频
*/
public function mergeVideos($fileList, $output) {
$listFile = tempnam(sys_get_temp_dir(), 'ffmpeg_');
file_put_contents($listFile, $fileList);
$cmd = "-f concat -safe 0 -i {$listFile} -c copy {$output} -y";
$result = $this->execute($cmd);
unlink($listFile);
return $result;
}
/**
* 获取视频信息
*/
public function getVideoInfo($videoPath) {
$cmd = "-v quiet -print_format json -show_format -show_streams {$videoPath}";
$result = $this->execute($cmd);
if ($result['success']) {
return json_decode($result['output'], true);
}
return null;
}
}
// 使用示例
$ffmpeg = new FFmpegCommand();
$info = $ffmpeg->getVideoInfo('input.mp4');
echo "时长: " . $info['format']['duration'] . "秒";
方法二:使用PHP-FPM扩展
安装php-ffmpeg PHP扩展
# 使用PECL安装(不推荐,维护较少) pecl install ffmpeg # 或者使用composer安装php-ffmpeg/php-ffmpeg(推荐) composer require php-ffmpeg/php-ffmpeg
使用php-ffmpeg库示例
<?php
require_once 'vendor/autoload.php';
use FFMpeg\FFMpeg;
use FFMpeg\Coordinate\TimeCode;
use FFMpeg\Format\Video\X264;
class FFmpegProcessor {
private $ffmpeg;
public function __construct() {
$this->ffmpeg = FFMpeg::create([
'ffmpeg.binaries' => '/usr/local/bin/ffmpeg',
'ffprobe.binaries' => '/usr/local/bin/ffprobe',
'timeout' => 3600,
'ffmpeg.threads' => 12,
]);
}
/**
* 视频转码
*/
public function convertVideo($input, $output) {
$video = $this->ffmpeg->open($input);
$format = new X264('aac', 'libx264');
$format->setKiloBitrate(1000);
$video->save($format, $output);
}
/**
* 截取缩略图
*/
public function extractThumbnail($input, $output, $timeInSeconds = 1) {
$video = $this->ffmpeg->open($input);
$frame = $video->frame(TimeCode::fromSeconds($timeInSeconds));
$frame->save($output);
}
/**
* 获取视频元数据
*/
public function getMetadata($input) {
$video = $this->ffmpeg->open($input);
return [
'duration' => $video->getFormat()->get('duration'),
'width' => $video->getStreams()->videos()->first()->get('width'),
'height' => $video->getStreams()->videos()->first()->get('height'),
'codec' => $video->getStreams()->videos()->first()->get('codec_name'),
];
}
}
常见场景与命令示例
视频压缩
// 压缩到指定大小 $cmd = "-i input.mp4 -b:v 1M -maxrate 1M -bufsize 2M output.mp4"; // 压缩到指定分辨率 $cmd = "-i input.mp4 -vf scale=1280:720 output.mp4";
添加水印
$cmd = "-i input.mp4 -i watermark.png -filter_complex overlay=10:10 output.mp4";
视频剪辑
// 从5秒开始,截取10秒 $cmd = "-ss 00:00:05 -t 10 -i input.mp4 output.mp4";
音频提取
$cmd = "-i input.mp4 -vn -acodec copy output.mp3";
GIF生成
$cmd = "-i input.mp4 -vf fps=10,scale=320:-1 output.gif";
性能优化与安全建议
设置执行超时
// 设置较长的超时时间
set_time_limit(300); // 5分钟
// 或者在exec中设置
exec("timeout 300 ffmpeg -i input.mp4 output.mp4");
输入验证
// 严格验证文件路径
$allowedExtensions = ['mp4', 'avi', 'mov'];
$extension = pathinfo($inputPath, PATHINFO_EXTENSION);
if (!in_array(strtolower($extension), $allowedExtensions)) {
throw new Exception("不支持的文件格式");
}
// 使用escapeshellarg防止命令注入
$safeInput = escapeshellarg($inputPath);
$safeOutput = escapeshellarg($outputPath);
异步处理
// 对于大型文件,建议使用消息队列异步处理
// RabbitMQ, Redis队列等
$jobData = [
'input' => $inputPath,
'output' => $outputPath,
'type' => 'transcode'
];
// 将任务推送到队列
$queue->push($jobData);
错误处理
// 捕获stderr输出
$cmd = "ffmpeg -i input.mp4 output.mp4 2>&1";
exec($cmd, $output, $returnVar);
if ($returnVar !== 0) {
// 记录详细错误日志
error_log("FFmpeg错误: " . implode("\n", $output));
throw new Exception("视频处理失败");
}
完整示例:视频上传处理
<?php
class VideoUploadHandler {
private $ffmpeg;
private $allowedTypes = ['video/mp4', 'video/quicktime'];
public function __construct() {
$this->ffmpeg = new FFmpegCommand();
}
public function processUpload($file) {
// 1. 验证文件类型
if (!in_array($file['type'], $this->allowedTypes)) {
throw new Exception("不支持的文件类型");
}
// 2. 保存原始文件
$originalPath = '/uploads/' . uniqid() . '_original.mp4';
move_uploaded_file($file['tmp_name'], $originalPath);
// 3. 生成缩略图
$thumbnailPath = '/uploads/' . uniqid() . '_thumb.jpg';
$this->ffmpeg->thumbnail($originalPath, $thumbnailPath);
// 4. 压缩处理
$compressedPath = '/uploads/' . uniqid() . '_compressed.mp4';
$this->ffmpeg->transcode($originalPath, $compressedPath, [
'-b:v' => '1M',
'-maxrate' => '1M',
'-bufsize' => '2M'
]);
// 5. 获取视频信息
$info = $this->ffmpeg->getVideoInfo($compressedPath);
return [
'original' => $originalPath,
'compressed' => $compressedPath,
'thumbnail' => $thumbnailPath,
'duration' => $info['format']['duration'],
'size' => filesize($compressedPath)
];
}
}
- 推荐使用shell_exec方式:简单、灵活、易于调试
- 大型项目考虑使用php-ffmpeg库:提供了更友好的API
- 生产环境注意:超时控制、输入验证、异步处理
- 性能优化:使用GPU加速(如NVIDIA CUDA)可显著提升处理速度
选择哪种方式取决于你的项目需求、性能要求和团队熟悉程度。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播