音频降噪(audio-denoise)
给带环境噪音的录音做降噪处理:手机录课、线上会议录音、现场采访、播客口播等场景中最常见的"沙沙声/嗡嗡声/电流声",用 ffmpeg 的 FFT 降噪滤镜(afftdn)或非局部均值降噪(anlmdn)本地去除,全程不需要上传到任何云端。
功能
- 三档降噪强度:
low(轻)/mid(中,默认)/high(重),对应不同的降噪量与噪声底参数 - 双引擎可选:
afftdn(默认):FFT 频域降噪,速度快(远快于实时),适合大多数场景anlmdn:非局部均值降噪,慢(约为实时时长的数倍),对宽带噪声更自然、音乐性损伤更小--normalize响度标准化:降噪后接 loudnorm 拉到 -16 LUFS(EBU R128,语音/播客常用标准,TP ≤ -1.5 dBTP)- 视频输入:直接喂 mp4/mov/mkv 等,自动抽取第一条音轨,输出为音频文件
- 响度对比报告:处理完成后自动打印前后
mean_volume / max_volume / integrated LUFS,向用户汇报有据可依 - 输出格式按扩展名自动选编码器(mp3/wav/m4a/aac/flac/ogg/opus/wma)
工作流程
- 确认输入:检查用户给的音频/视频文件路径存在、可读。用户没说输出路径时,默认输出到输入同目录的
原名_denoised.同扩展名。 - 选档位:用户没有明确要求时,一律先用默认 mid 档 + afftdn 引擎跑一遍。用户描述"噪音不太大/只要一点点杂音"→ low;"噪音很大/基本上全是噪声"→ 可以先 mid,效果不够再 high。
- 执行降噪:运行
scripts/denoise.py(命令参考见下)。需要成稿发布(播客/口播视频配音)时加--normalize。 - 汇报结果:把脚本打印的前后响度对比转述给用户,特别说明 mean_volume 下降来自噪声底被压低,属于预期现象。
- 提醒试听:务必让用户试听,如觉得人声发闷/有"水声感/机器人感",降一档强度重跑;如噪声残留明显,升一档或换 anlmdn。
- 后续衔接:降噪后的干净音频可直接喂给 audio-minutes(转会议纪要)、video-to-srt(转字幕)、audio-to-notes(转学习笔记),识别准确率通常更好。
命令参考
(以下路径相对本技能根目录)
# 最常用:默认 afftdn 引擎 + mid 档
python3 scripts/denoise.py 录音.mp3 -o 录音_降噪.mp3
# 指定强度(low / mid / high)
python3 scripts/denoise.py 采访.wav -o 采访_降噪.wav --strength high
# 降噪 + 响度标准化到 -16 LUFS(适合发布)
python3 scripts/denoise.py 手机视频.mov -o 成品.mp3 --normalize
# 换引擎(慢但更自然,适合音乐性内容或 afftdn 效果不理想时)
python3 scripts/denoise.py 讲课.mp4 -o 讲课_降噪.mp3 --engine anlmdn
# 查看帮助
python3 scripts/denoise.py --help
档位与引擎内部参数(供排查调优):
| 强度 | afftdn (nr=降噪dB / nf=噪声底dB) | anlmdn (s=强度 / r=搜索窗s) |
|---|---|---|
| low | nr=12, nf=-40 | s=300, r=0.03 |
| mid | nr=24, nf=-32 | s=1000, r=0.03 |
| high | nr=36, nf=-26 | s=3000, r=0.03 |
> 注:anlmdn 的 r(研究窗) 默认 0.006s 时相似块太少、降噪几乎无效,已按实测调到 0.03s。
等价的手工 ffmpeg 命令(脚本不可用时的兜底):
ffmpeg -i in.mp3 -map 0:a:0 -af "afftdn=nr=24:nf=-32" -c:a libmp3lame -b:a 192k out.mp3
# 降噪 + 响度标准化(loudnorm 单遍动态模式,输出会重采样,显式 -ar 44100 收尾)
ffmpeg -i in.mp3 -map 0:a:0 -af "afftdn=nr=24:nf=-32,loudnorm=I=-16:TP=-1.5:LRA=11" -ar 44100 -c:a libmp3lame -b:a 192k out.mp3
# 小波降噪备选(afwtdn),对音乐内容损伤更小:
ffmpeg -i in.mp3 -map 0:a:0 -af "afwtdn=sn=12" -c:a libmp3lame -b:a 192k out.mp3
示例对话
例 1:手机录的课有底噪
> 用户:我用手机录了一节 40 分钟的课,房间空调声一直嗡嗡的,帮我处理一下。
> 助手:
> bash
> python3 scripts/denoise.py /path/to/第3节课.mp3 -o /path/to/第3节课_降噪.mp3 --strength mid
>
> 处理完汇报:mean_volume 从 -21.5 dB 降到 -26.8 dB(空调底噪被压低约 5 dB),已输出到 …。请试听一下,如果人声发闷我再调低一档;空调声如果还有残留,可以换 anlmdn 引擎再跑一次。
例 2:采访录音要发布
> 用户:这段街采噪声很大,明天要做成播客,帮我弄干净点。
> 助手:先 mid 档跑一遍,让用户试听;确认人声没受损后,加 --normalize 出发布版:
> bash
> python3 scripts/denoise.py /path/to/街采.wav -o /path/to/街采_降噪.wav --strength mid
> # 试听 OK 后:
> python3 scripts/denoise.py /path/to/街采.wav -o /path/to/街采_发布版.mp3 --normalize
>
例 3:只有视频文件
> 用户:这个录屏视频里人声太吵了,我只要音频,帮我降噪后导出 mp3。
> 助手:直接把视频当输入,脚本会自动抽音轨:
> bash
> python3 scripts/denoise.py /path/to/录屏.mp4 -o /path/to/录屏_降噪.mp3
>
运行环境
- 脚本:
scripts/denoise.py(相对技能根目录) - Python:3.9+
- 外部命令:
ffmpeg、ffprobe
开工前先跑一次自检,缺什么当场补,别等跑到一半报错:
command -v ffmpeg >/dev/null 2>&1 || echo "缺 ffmpeg,请先安装再重试"
command -v ffprobe >/dev/null 2>&1 || echo "缺 ffprobe,请先安装再重试"
> 缺依赖时用中文告诉用户缺什么、装完就能用,不要把 Python 的英文 traceback 原样贴给用户。
注意事项
- 降噪是双刃剑:强度过大会损伤人声——出现"水声感/机器人感"、齿音丢失、尾音发空等问题。务必建议先用默认 mid 档试听,不满意再升降档;对 quality 敏感的内容优先 low 档保人声。
- afftdn 擅长稳态噪声(空调、风扇、电流声、房间恒定底噪、白噪),对突发性噪声(关门声、键盘声、咳嗽、鼠标点击)效果有限,只能压低不能消除。
- 音乐/歌唱内容慎用降噪:降噪在削噪声的同时也会削音乐的泛音,伴奏尽量不降;确要处理,用
--engine anlmdn或更低强度,也可以尝试手工命令里的afwtdn小波方案。 - anlmdn 明显更慢(长文件可能需要数分钟),且内存占用高于 afftdn;给用户长文件用 anlmdn 前先说明耗时。
- 已经被有损压缩过多次的录音(如微信语音二次转存的 mp3)压缩噪声和信号纠缠在一起,降噪效果会打折扣,high 档也未必干净,管理预期。
--normalize只调响度不降噪:它把整体响度统一到 -16 LUFS,对"人声忽大忽小"请用响度标准化,对"环境噪声"请用降噪,两者经常配合使用。- 输出采样率:
--normalize时统一输出 44100 Hz;不 normalize 时保持输入采样率。 - 本技能只处理音频;降噪后的文件如需转文字,交给 audio-minutes / video-to-srt。