File size: 3,075 Bytes
d932265 cd06905 d932265 cd06905 d932265 ea4ccbd a42ebc7 d932265 a42ebc7 d932265 e8b8f2a cd06905 0dddc64 d932265 ea4ccbd d932265 cd06905 0dddc64 d932265 0dddc64 d932265 e8b8f2a d932265 0dddc64 d932265 0dddc64 d932265 e8b8f2a d932265 cd06905 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | #!/usr/bin/env python3
"""音频降噪增强:DeepFilterNet2 人声增强。
上传带噪音频(口播、讲座录音等),输出降噪后的 wav。
模型在首次请求时加载并缓存,之后常驻内存。
"""
import shutil
import subprocess
import threading
import uuid
import gradio as gr
_lock = threading.Lock()
_model = None
_df_state = None
def get_model():
global _model, _df_state
if _model is None:
with _lock:
if _model is None:
from df.enhance import init_df
_model, _df_state, _ = init_df()
return _model, _df_state
def to_wav(audio_path):
"""把任意格式(m4a/mp3/flac 等)经 ffmpeg 转成 48k 单声道 wav。
df 自带的 torchaudio 2.0 sox 后端解不了 m4a/AAC,这是报错的根源。
若容器里没有 ffmpeg,则原样返回,让 load_audio 自己试。
"""
if shutil.which("ffmpeg") is None:
return audio_path
out = f"/tmp/conv_{uuid.uuid4().hex}.wav"
r = subprocess.run(
["ffmpeg", "-y", "-v", "error", "-i", audio_path, "-ar", "48000", "-ac", "1", out],
capture_output=True,
text=True,
)
if r.returncode != 0:
raise gr.Error(f"音频转码失败:{r.stderr.strip()[-300:]}")
return out
def denoise(audio_path, atten_lim, mix):
if not audio_path:
return None
from df.enhance import enhance, load_audio, save_audio
model, df_state = get_model()
audio, _ = load_audio(to_wav(audio_path), sr=df_state.sr())
lim = None if atten_lim == 0 else atten_lim
enhanced = enhance(model, df_state, audio, atten_lim_db=lim)
# 混回原声:mix=1 为纯降噪结果,调低可找回被吃掉的细节
n = min(enhanced.shape[-1], audio.shape[-1])
out_audio = enhanced[..., :n] * mix + audio[..., :n] * (1.0 - mix)
out = "/tmp/enhanced.wav"
save_audio(out, out_audio, df_state.sr())
return out
with gr.Blocks(title="音频降噪增强") as demo:
gr.Markdown(
"# 🎧 音频降噪增强\n"
"基于 DeepFilterNet2 的人声降噪:上传带底噪、环境声的录音,输出干净版 wav(48kHz)。\n\n"
"适合口播、讲座这类以人声为主的素材。CPU 推理,长音频请按时长耐心等。"
)
inp = gr.Audio(label="原始音频", type="filepath")
atten = gr.Slider(
0, 40, value=20, step=1,
label="最大衰减上限 (dB)",
info="限制模型对每个频点的抑制强度:数值越小越温和、损失越小;0 = 不限制(最强降噪)。默认 20。",
)
mix = gr.Slider(
0, 1, value=1.0, step=0.05,
label="降噪结果占比",
info="1 = 纯降噪结果;调低可按比例混回原声,找回被吃掉的细节(相声里的笑声、掌声也适用)。",
)
btn = gr.Button("开始降噪", variant="primary")
out = gr.Audio(label="降噪后", type="filepath")
btn.click(denoise, inputs=[inp, atten, mix], outputs=out)
if __name__ == "__main__":
demo.launch(show_error=True)
|