给视频配 BGM,原声还不糊:amix 混音与自动压低原声(ducking)
做 vlog、教程,想垫一段背景音乐,但直接 amix 一混,人声和音乐糊成一团,音乐大声时人声直接被盖。正解是 ducking(闪避):有人说话时自动把 BGM 压下去,没说话时 BGM 浮上来。ffmpeg 自带 sidechaincompress 能做,这篇讲怎么配。
先混上去(基础版,但不好听)
ffmpeg -i talk.mp4 -i bgm.mp3 -filter_complex "[0:a][1:a]amix=inputs=2:duration=first:dropout_transition=2[a]" -map 0:v -map "[a]" out.mp4
amix 把两路音混一起,duration=first 以人声长度为准。问题:BGM 音量恒定,盖人声。
进阶:sidechaincompress 做 ducking
思路把人声当"侧链信号",BGM 当被压的对象。人声一响,压低 BGM:
ffmpeg -i talk.mp4 -i bgm.mp3 -filter_complex "[1:a]volume=0.6[bgm]; [0:a]volume=1.2[voice]; [bgm][voice]sidechaincompress=threshold=-25dB:ratio=4:attack=20:release=300[ducked]; [voice][ducked]amix=inputs=2:duration=first[a]" -map 0:v -map "[a]" out.mp4
要点:
volume=0.6先把 BGM 整体降一点,别太满;threshold=-25dB侧链触发门槛,人声过这值就开始压;ratio=4压缩比,越大压得越狠;attack/release是压下去和松开的速度(毫秒),太快会"喘",太慢会糊。
坑一:BGM 比人声短
循环 BGM 凑长度,用 aloop:
[1:a]aloop=loop=-1:size=2e9[bgm]
loop=-1 无限循环,直到混音结束。
坑二:两条音轨采样率/声道不一致
amix 要求一致,否则报错。先统一:
[1:a]aresample=44100,aformat=channel_layouts=stereo[bgm]
坑三:压得太狠听着"泵"
ratio 别超过 6,release 别低于 200,否则音乐一抽一抽的(pumping)。我一般 ratio=3~4、release=300 最自然。
想要更聪明?
ffmpeg 的 ducking 是"电平触发",分不清人声和别的响动。要真按人声触发,得上 Demucs 先分出人声轨当侧链(接上篇),或者外部用 Python 算 VAD 时间轴再生成音量包络。普通 vlog 用 sidechaincompress 够了。