DeepFilterNet ONNX 导出与跨平台部署:从导出命令到三条集成路径的完整教程
【免费下载链接】DeepFilterNetNoise supression using deep filtering项目地址: https://gitcode.com/GitHub_Trending/de/DeepFilterNet
DeepFilterNet 是一个面向 48kHz 全频带音频的低复杂度实时降噪(语音增强)框架。如果你想在 Python 服务、Rust/C++ 程序或移动端里调用它的降噪能力,又不想把整个 PyTorch 训练栈带进产品,把模型导出成 ONNX 是最省事的路径。这篇教程带你走完完整动线:选模型、装依赖、执行导出、验证一致性,再落到三条平台集成路线上。
先选模型:DeepFilterNet2、DeepFilterNet3 还是低延迟版
仓库提供三个预训练模型,通过-m参数切换:
DeepFilterNet3:默认模型,也是当前主线,降噪能力最强;DeepFilterNet2:上一代模型。注意 Rust 运行时已将其标记为 deprecated(会直接报错,要求回退旧版 libDF v0.3.1),它只适合走 Python/ONNX 路线;- 低延迟变体:文件名带
_ll后缀的模型(如DeepFilterNet3_ll_onnx.tar.gz),libDF提供default-model-llfeature 可直接内嵌该模型做默认加载。
选型建议:离线批处理、延迟不敏感的链路用标准版DeepFilterNet3;实时链路或嵌入式设备优先评估_ll版本,并用本文的校验流程确认精度可接受。如果你根本不打算重新训练,models/目录里已经放好了各模型的 ONNX 产物,可以直接下载、跳过导出。
准备环境:克隆仓库并安装导出依赖
git clone https://gitcode.com/GitHub_Trending/de/DeepFilterNet cd DeepFilterNet pip install torch torchaudio pip install deepfilternet pip install onnx onnxruntime onnxsim MonkeyTypedeepfilternet包会带上df模块和 Rust 编译的 STFT/ISTFT 封装libdf(导出脚本用它做特征提取);onnx/onnxruntime/onnxsim分别负责导出、校验推理和模型简化;MonkeyType是导出脚本启动时会强制检查的依赖,缺了会直接退出。如果你想用仓库内代码而不是 PyPI 版本,按 README 的 Manual Installation 一节操作:设置PYTHONPATH=$PWD/DeepFilterNet,并用maturin develop --release -m pyDF/Cargo.toml编译 libdf。
把 PyTorch 模型导出成 ONNX
核心命令(在仓库根目录执行):
python DeepFilterNet/df/scripts/export.py -m DeepFilterNet3 --simplify ./onnx_export导出脚本 会把模型拆成三段独立导出:编码器enc、ERB 解码器erb_dec、深度滤波解码器df_dec。拆开的原因很实际——运行时本来就是"编码器 → 两个解码器"的顺序调用,拆开后每段可以单独量化、单独优化。脚本还会顺带跑一遍随机测试样本,若当前目录存在out/,增强结果会存到out/enhanced.wav,方便你听一下。
关键参数如下(--help可查全部):
| 参数 | 作用 | 默认值 |
|---|---|---|
export_dir(位置参数) | ONNX 输出目录,不存在会自动创建 | 必填 |
-m, --model-base-dir | 预训练模型名(DeepFilterNet/DeepFilterNet2/DeepFilterNet3)或本地模型目录 | DeepFilterNet3 |
--simplify | 导出后用 onnxsim 简化计算图 | 关闭 |
--opset | ONNX 算子集版本 | 12 |
--no-check | 跳过 ONNX 与 PyTorch 输出的一致性校验 | 校验开启 |
-e, --epoch | 加载哪个 checkpoint(best/latest/ 整数) | best |
导出完成后目录结构大致是:
onnx_export/ ├── enc.onnx / erb_dec.onnx / df_dec.onnx # 三个子模型 ├── config.ini / version.txt # 配置与版本(形如 DeepFilterNet3_epoch_best) ├── enc_input.npz … df_dec_output.npz # 参考输入输出,供一致性复验 └── DeepFilterNet3_onnx.tar.gz # 打包产物,Rust/C 运行时直接吃这个导出后先跑一致性校验
check默认开启,只有想跳过才加--no-check。它对每个子模型做三件事:
onnx.checker.check_model(..., full_check=True)做图结构静态检查;- 用 ONNX Runtime(跨平台的模型推理引擎)的
CPUExecutionProvider会话实际推理一遍; - 对每个输出张量执行
np.testing.assert_allclose(torch_out, onnx_out, rtol=1e-6, atol=1e-5),逐输出比对。
命令跑完之后,如果日志里出现Elements not close for xxx警告,说明该输出没对上——先固定 onnxruntime 版本重跑,再考虑调整--opset,不建议直接跳过。脚本同时把参考输入输出存成.npz文件,之后任何改动(量化、换 opset)都可以用仓库自带的 scripts/assert_close_npz.py 离线复验,不必重新导出。
在你的应用里加载 ONNX 模型
三段式结构决定了集成时要按enc → erb_dec / df_dec的顺序喂数据;帧参数以config.ini为准(默认 48kHz、fft_size 960、hop 480,即每 10ms 一帧)。
Python:ONNX Runtime 直连三个子模型
import onnxruntime as ort enc = ort.InferenceSession("onnx_export/enc.onnx") out = enc.run( ["e0", "e1", "e2", "e3", "emb", "c0", "lsnr"], {"feat_erb": feat_erb, "feat_spec": feat_spec}, )enc.onnx的输入是 ERB 特征feat_erb和复数谱feat_spec(实部/虚部放在通道维),输出里e0-e3是逐层编码器特征,emb是共享嵌入,c0是深度滤波分支的输入。接着erb_dec.onnx(输入emb, e3, e2, e1, e0,输出掩码m)和df_dec.onnx(输入emb, c0,输出滤波系数coefs)依次接管。完整的逐帧循环(STFT → 特征 → 推理 → 掩码/滤波 → ISTFT)在 libDF/src/tract.rs 里都有实现,照着抄最可靠。如果只做原型验证,也可以直接用 Python API 绕过 ONNX:
from df import enhance, init_df model, df_state, _ = init_df() enhanced = enhance(model, df_state, noisy_audio)Rust / C++:复用 libDF 的 tract 运行时
Rust 侧不需要手写推理循环,libDF的tractfeature 已实现"读 tar.gz → 建推理会话 → 逐帧处理"全流程:
use libdf::tract::{DfParams, DfTract, RuntimeParams}; let params = DfParams::new("models/DeepFilterNet3_onnx.tar.gz".into())?; let mut df = DfTract::new(params, &RuntimeParams::default())?; // 每帧: df.process(noisy.view(), enh.view_mut())? // 均为 [n_ch, 480] 的 f32 矩阵注意DfParams::new接收的是 tar.gz 整体(内部解析enc.onnx、erb_dec.onnx、df_dec.onnx与config.ini),所以直接用导出脚本生成的压缩包或 models/ 里的文件即可。C/C++ 侧则开启capifeature,入口是 libDF/src/capi.rs 的df_create(path, atten_lim, log_level),头文件可用仓库根目录的cbindgen.toml生成。
Android:ONNX Runtime Mobile 路线
仓库没有现成的 Android 工程,可行做法是:把三个 .onnx 文件打进 APK 资源,用 ONNX Runtime Android(onnxruntime-android)在端侧建三个 session;音频先重采样到 48kHz,按 480 采样一帧地处理,调用顺序与 Python 一节完全一致。如果端侧推理性能不达标,备选方案是把 libDF 的capifeature 用 NDK 编成 so 直接调用,此时推理走的是 tract 而非 ONNX Runtime。
上线前的调优清单
- Execution Provider:默认
CPUExecutionProvider够用;有 GPU 的机器可把CUDAExecutionProvider放到 providers 列表前面,收益主要体现在离线批处理,实时链路一般仍留在 CPU。 - 模型简化:
--simplify走 onnxsim,图会变小、部分算子融合;简化失败时脚本会保留原文件并打日志,不会静默丢结果。 - 量化:导出脚本没有内置量化参数,需要时可用 onnxruntime 的量化工具对产物做 INT8 后训练量化,再用导出的
.npz参考数据复验输出偏差是否可接受。 - opset 版本:默认 12 兼容性最好,除非目标运行时明确要求,不要随手抬高版本;抬完务必重跑校验。
- 延迟预算:每帧 10ms(480 采样 @ 48kHz),DeepFilterNet3 还有若干帧 lookahead(
config.ini中conv_lookahead/df_lookahead),实时链路要把这部分算进去;延迟敏感就换_ll模型。 - 批处理:输入通道维是单通道设计,离线批量处理按"逐文件、逐帧"循环即可,不要试图塞 batch 维。
常见报错速查表
| 现象 | 原因 | 处理 |
|---|---|---|
| 脚本报 "Please install it via $ pip install MonkeyType" 并退出 | 缺少 MonkeyType 依赖 | pip install MonkeyType后重跑 |
日志出现Elements not close for xxx | 某子模型 ONNX 输出与 PyTorch 不一致 | 固定 onnxruntime 版本重跑;调整--opset后必须重新校验 |
日志出现Failed to simplify ... Skipping | onnxsim 简化失败,已保留未简化文件 | 升级 onnxsim,或去掉--simplify重新导出 |
| Rust 端报 "DeepFilterNet2 models are deprecated ... use version v0.3.1" | 当前 libDF 不再支持 DFN2 模型 | 换DeepFilterNet3_onnx.tar.gz或_ll版本 |
DfParams::new打开文件失败 | 传了目录或 zip,运行时只认 tar.gz | 用导出脚本生成的*_onnx.tar.gz |
| 增强后残留明显噪声或出现 artifacts | post-filter / 衰减限制参数不当 | 调整--pf,或 Rust 端RuntimeParams的post_filter_beta、atten_lim_db |
回顾与资源
整条动线回顾:git clone→ 安装依赖 →python DeepFilterNet/df/scripts/export.py -m DeepFilterNet3 --simplify ./onnx_export→ 确认日志里没有Elements not close警告 → 按目标平台从 Python / Rust / Android 三条路中挑一条集成。后续改动模型后,随时可以用.npz参考数据复验。相关入口:
- 导出脚本:导出、校验、简化、打包一条龙
- 预训练模型:各模型检查点与 ONNX tar.gz 产物
- Rust 推理运行时:逐帧处理主循环
- C/C++ 接口:
capifeature 入口 - Python 增强入口:不碰 ONNX 时的快速验证路径
- 一致性对比脚本:量化或改 opset 后的离线复验工具
【免费下载链接】DeepFilterNetNoise supression using deep filtering项目地址: https://gitcode.com/GitHub_Trending/de/DeepFilterNet
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考