php本身不处理音量标准化,必须靠ffmpeg完成;html5 video的volume属性仅控制播放增益而不改变原始音频电平,真正需调整的是音频流本身的峰值和积分响度,应使用ffmpeg loudnorm滤镜按ebu r128标准分三遍测量、计算并重编码,php-ffmpeg需手动管理流程、校验参数与输出。

PHP 本身不处理音量标准化,必须靠 FFmpeg 完成;直接在 PHP 中调用 ffmpeg 命令或使用 php-ffmpeg 封装时,音量调整必须在转码阶段嵌入响度分析与增益计算,不能靠后期 JS 或 HTML5 volume 属性“假装统一”。
为什么 PHP 里设 volume 属性没用
HTML5 <video></video> 的 volume 属性只控制播放器输出增益,不改变原始音频电平。两段视频原始响度差 12 LUFS,前端强行拉到同一 volume="0.8",结果是一段发闷、一段爆音——听感依然割裂。真正要动的是音频流本身的峰值和积分响度。
FFmpeg 命令行做响度标准化(推荐)
用 ffmpeg 内置的 loudnorm 滤镜,支持 EBU R128 标准,可一次完成测量 + 归一 + 峰值限制。关键不是加滤镜,而是分三遍跑:
- 第一遍:测第一段视频的响度参数 →
ffmpeg -i input1.mp4 -af loudnorm=print_format=json -f null - 2>&1 | grep loudness - 第二遍:测第二段 → 同样命令换文件名,拿到两组
input_i(Integrated LUFS)、input_tp(True Peak)、input_lra(Loudness Range) - 第三遍:合并在一条命令里重编码 →
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:a]loudnorm=I=-23:LRA=7:TP=-2:measured_I=-31.2:measured_TP=-1.5:measured_LRA=8.3:offset=0.1[a1];[1:a]loudnorm=I=-23:LRA=7:TP=-2:measured_I=-25.7:measured_TP=-0.8:measured_LRA=6.1:offset=0.1[a2]" -map "[a1]" -map "[a2]" -c:a aac output1.mp4 output2.mp4
注意:measured_* 参数必须从上一步实测来,硬写 -23 会失效;offset 推荐设 0.1 防止限幅过激;输出务必用 -c:a aac,别用 libfdk_aac(部分服务器未编译)。
php-ffmpeg 封装里怎么安全传 loudnorm 参数
php-ffmpeg 不原生支持 loudnorm 的多遍模式,但可通过 addFilter() 注入,前提是手动管理三遍流程并校验中间状态:
- 必须用
proc_open()而非exec(),否则拿不到 stderr 里的 JSON 测量结果 - 调
addFilter('loudnorm=I=-23:LRA=7:TP=-2:measured_I=-31.2...')前,先检查$video->getStreams()->audio()->get('codec_name')是否为aac或mp3,避免对无音频流报错 - 禁用自动重采样:
$format->setAudioSampleRate(null),否则loudnorm会跟aresample冲突导致静音 - 输出路径必须用
realpath()校验,且确保父目录有写权限 ——loudnorm临时文件写失败时 FFmpeg 不报错,只输出空音频
导出后必须验证响度是否真一致
别信“跑完了就对了”。用 ffprobe 抽帧验证:
ffprobe -v quiet -show_entries frame_tags=lavfi.r128.I -of default=nw=1 input1.mp4 | tail -n 20 | awk '{sum += $NF} END {print sum/NR}'
再对 input2.mp4 执行同样命令,两个平均值应在 ±0.3 LUFS 内。差超过 0.5,说明 measured_* 参数抄错了,或某段音频被静音/截断。这个验证步骤跳过,上线后用户听到的仍是忽大忽小。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











