本文目录导读:

在PHP项目中处理音频文件转码,最常用的方案是通过 FFmpeg 进行操作,下面详细介绍几种常见的实现方法。
安装 FFmpeg
Linux (Ubuntu/Debian)
sudo apt update sudo apt install ffmpeg
macOS
brew install ffmpeg
Windows
从官网下载:https://ffmpeg.org/download.html
PHP中使用 exec() 调用 FFmpeg
基本转换示例
<?php
class AudioConverter {
private $ffmpegPath;
public function __construct($ffmpegPath = 'ffmpeg') {
$this->ffmpegPath = $ffmpegPath;
}
/**
* 转换音频格式
* @param string $inputFile 输入文件路径
* @param string $outputFile 输出文件路径
* @param array $options 额外参数
* @return array
*/
public function convert($inputFile, $outputFile, $options = []) {
// 构建命令
$cmd = $this->ffmpegPath . ' -i ' . escapeshellarg($inputFile);
// 添加选项
if (!empty($options)) {
foreach ($options as $key => $value) {
$cmd .= " -{$key} {$value}";
}
}
$cmd .= ' ' . escapeshellarg($outputFile);
$cmd .= ' 2>&1'; // 错误输出重定向
// 执行命令
exec($cmd, $output, $returnCode);
return [
'success' => $returnCode === 0,
'output' => $output,
'command' => $cmd
];
}
}
常用的音频格式转换场景
MP3 转 WAV
$converter = new AudioConverter();
$result = $converter->convert('input.mp3', 'output.wav', [
'acodec' => 'pcm_s16le',
'ar' => '44100',
'ac' => '2'
]);
WAV 转 MP3
$result = $converter->convert('input.wav', 'output.mp3', [
'codec:a' => 'libmp3lame',
'b:a' => '192k',
'ar' => '44100',
'ac' => '2'
]);
其他格式转换
// OGG 转 MP3
$result = $converter->convert('input.ogg', 'output.mp3', [
'codec:a' => 'libmp3lame',
'q:a' => '2' // 质量 0-9,2 为高质量
]);
// FLAC 转 AAC
$result = $converter->convert('input.flac', 'output.aac', [
'codec:a' => 'aac',
'b:a' => '192k'
]);
// 任意格式转 WAV(常用于语音识别)
$result = $converter->convert('input.any', 'output.wav', [
'acodec' => 'pcm_s16le',
'ar' => '16000', // 16kHz 采样率
'ac' => '1', // 单声道
'sample_fmt' => 's16'
]);
使用 PHP-FFMpeg 库(推荐)
如果你更喜欢面向对象的接口,可以使用 php-ffmpeg 库:
安装
composer require php-ffmpeg/php-ffmpeg
使用示例
<?php
require_once 'vendor/autoload.php';
use FFMpeg\FFMpeg;
use FFMpeg\Format\Audio\Mp3;
use FFMpeg\Format\Audio\Wav;
use FFMpeg\Format\Audio\Aac;
class AudioProcessor {
private $ffmpeg;
public function __construct() {
$this->ffmpeg = FFMpeg::create([
'ffmpeg.binaries' => '/usr/bin/ffmpeg',
'ffprobe.binaries' => '/usr/bin/ffprobe',
'timeout' => 3600,
'ffmpeg.threads' => 12,
]);
}
/**
* 转换音频格式
*/
public function convertToMp3($inputFile, $outputFile) {
$audio = $this->ffmpeg->open($inputFile);
$format = new Mp3();
$format->setAudioKiloBitrate(192)
->setAudioChannels(2)
->setAudioCodec('libmp3lame');
$audio->save($format, $outputFile);
return true;
}
/**
* 提取音频片段
*/
public function extractSegment($inputFile, $outputFile, $start, $duration) {
$audio = $this->ffmpeg->open($inputFile);
$format = new Mp3();
$audio->filters()->clip(\FFMpeg\Coordinate\TimeCode::fromSeconds($start),
\FFMpeg\Coordinate\TimeCode::fromSeconds($duration));
$audio->save($format, $outputFile);
return true;
}
}
完整的上传转码示例
<?php
class AudioUploadHandler {
private $uploadDir;
private $ffmpeg;
public function __construct($uploadDir = 'uploads/') {
$this->uploadDir = $uploadDir;
$this->ffmpeg = new AudioConverter();
// 确保目录存在
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
}
/**
* 上传并转码音频文件
*/
public function uploadAndConvert($file, $targetFormat = 'mp3') {
// 验证文件
$this->validateFile($file);
// 生成唯一文件名
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $extension;
$inputPath = $this->uploadDir . $filename;
// 上传文件
if (!move_uploaded_file($file['tmp_name'], $inputPath)) {
throw new Exception("文件上传失败");
}
// 生成输出路径
$outputFilename = uniqid() . '.' . $targetFormat;
$outputPath = $this->uploadDir . $outputFilename;
// 根据目标格式设置参数
$options = $this->getFormatOptions($targetFormat);
// 执行转码
$result = $this->ffmpeg->convert($inputPath, $outputPath, $options);
if ($result['success']) {
// 删除原始文件
unlink($inputPath);
return [
'success' => true,
'file' => $outputPath,
'filename' => $outputFilename,
'format' => $targetFormat
];
} else {
// 清理失败的文件
unlink($inputPath);
if (file_exists($outputPath)) {
unlink($outputPath);
}
throw new Exception("转码失败: " . implode("\n", $result['output']));
}
}
/**
* 获取格式参数
*/
private function getFormatOptions($format) {
$options = [
'mp3' => [
'codec:a' => 'libmp3lame',
'b:a' => '192k',
'ar' => '44100',
'ac' => '2'
],
'wav' => [
'acodec' => 'pcm_s16le',
'ar' => '44100',
'ac' => '2'
],
'aac' => [
'codec:a' => 'aac',
'b:a' => '128k'
],
'ogg' => [
'codec:a' => 'libvorbis',
'q:a' => '3'
]
];
return $options[$format] ?? [];
}
/**
* 验证上传的文件
*/
private function validateFile($file) {
$allowedTypes = ['audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/x-wav', 'audio/mp4'];
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new Exception("上传错误");
}
if (!in_array($file['type'], $allowedTypes)) {
throw new Exception("不支持的音频格式");
}
if ($file['size'] > 100 * 1024 * 1024) { // 100MB
throw new Exception("文件过大");
}
}
}
// 使用示例
try {
$handler = new AudioUploadHandler();
$result = $handler->uploadAndConvert($_FILES['audio'], 'mp3');
echo "成功: " . $result['filename'];
} catch (Exception $e) {
echo "错误: " . $e->getMessage();
}
安全注意事项
// 1. 始终对输入进行转义
$cmd = 'ffmpeg -i ' . escapeshellarg($inputFile) . ' ' . escapeshellarg($outputFile);
// 2. 设置执行超时
set_time_limit(300); // 5分钟超时
// 3. 限制资源使用
$cmd = 'nice -n 19 ffmpeg -i input.mp3 -threads 2 output.mp3';
// 4. 验证输出文件
if (file_exists($outputFile) && filesize($outputFile) > 0) {
// 文件生成成功
}
// 5. 清理临时文件
register_shutdown_function(function() use ($tempFile) {
if (file_exists($tempFile)) {
unlink($tempFile);
}
});
异步处理建议
对于大文件,建议使用消息队列异步处理:
// 使用 Redis 或 RabbitMQ
$job = [
'input' => '/path/to/input.mp3',
'output' => '/path/to/output.wav',
'format' => 'wav',
'options' => ['ar' => 16000, 'ac' => 1]
];
// 将任务添加到队列
$queue->push('audio_convert', json_encode($job));
// 在 Worker 进程中处理
// worker.php
while ($job = $queue->pop('audio_convert')) {
$data = json_decode($job, true);
convertAudio($data['input'], $data['output'], $data['options']);
// 更新数据库状态
$db->update('files', ['status' => 'completed'], ['id' => $data['id']]);
}
这个方案涵盖了大部分的音频转码需求,你可以根据具体项目需求进行调整和扩展。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播