php本身不控制采样率和声道数,所有音频参数必须通过ffmpeg命令显式指定;漏设-ar或-ac是音质发闷、播放失败的最常见原因。

直接结论:PHP 本身不控制采样率和声道数,所有音频参数必须通过 FFmpeg 命令显式指定;漏设 -ar 或 -ac 是音质发闷、播放失败的最常见原因。
为什么 -ar 44100 会把人声高频“压没了”
原始音频常为 48kHz(手机录屏)或 96kHz(专业设备),FFmpeg 默认用线性重采样(swr 的 linear 模式)降频到 44.1kHz,高频细节直接衰减。这不是 AAC 编码器的问题,而是重采样算法太糙。
- 必须显式启用高质量重采样器:
addFilter('aresample=resampler=soxr')(PHP-FFMpeg)或命令行加-af aresample=resampler=soxr - 避免二次重采样:先用
ffprobe查原始采样率,若已是 44100Hz,就跳过-ar - SOXR 需 FFmpeg ≥ 4.0,旧版本 fallback 到
swr时务必加-dither_mode rectangular防量化噪声
PHP-FFMpeg 中设置 -ar 和 -ac 的正确写法
PHP-FFMpeg 的 setAudioSampleRate() 和 setAudioChannels() 只负责生成对应命令,但不会自动加重采样滤镜或防多声道降质逻辑——这些得手动补。
-
setAudioSampleRate(44100)→ 生成-ar 44100,但不触发 SOXR,需额外addFilter('aresample=resampler=soxr') -
setAudioChannels(2)→ 生成-ac 2,强制转立体声;若原始是 5.1,不设此项会走 AAC-LC profile,部分安卓/车载播放器解码失败 - 必须禁用视频流:
setVideoCodec('copy')或addFilter('anull'),否则 FFmpeg 可能混入视频帧干扰音频重采样
原生 exec() 调用时的采样率/声道安全拼接
用户输入的采样率(如表单填 48000)若未校验,直接拼进命令会引发注入或崩溃。尤其注意 -ar 后不能跟空格或非法值。
- 只允许合法数值:
if (!in_array($ar, [44100, 48000, 96000], true)) { die('采样率仅支持 44100/48000/96000'); } - 声道数必须显式设:
-ac 2(音乐/播客),-ac 1(单声道语音),绝不能省略 - 完整命令示例:
ffmpeg -i input.mp4 -vn -c:a aac -ar 44100 -ac 2 -b:a 128k -af aresample=resampler=soxr output.mp4 - 错误日志必须捕获 stderr:
exec("{$cmd} 2>&1", $output, $return); if ($return !== 0) error_log("FFmpeg failed: " . implode("\n", $output));
容易被忽略的兼容性陷阱
HandBrake 默认用 AAC (faac) + 48000 Hz + 立体声,而 PHP 脚本若沿用 44.1kHz,会导致 iOS Safari 播放时音频失步——不是 PHP 的错,是浏览器对 AAC 容器内采样率校验更严。
- Web 场景优先选 48000Hz:兼容性 > 音质微差,且避免 SOXR 在低负载下 fallback
- MP4 容器里 AAC 必须是 LC profile,多声道(>2)需加
-profile:a aac_he_v2,但 iOS 不支持 HE-AAC - PHP-FFMpeg 的
save()若没传Format\Audio\Aac实例,可能默认用 MP3 封装,导致-ar参数被忽略
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











