语音AI
Media Center(Java 语音中控)降噪与声纹锁定对接方案
核心结论(TL;DR)
结论 1
Java 语音中控对接声纹+降噪的最短路径是 sherpa-onnx 官方 Java API(JNI):同一个依赖同时获得声纹嵌入(加载 3D-Speaker/WeSpeaker ONNX 模型)与 GTCRN 降噪,全程免 Python、CPU 可跑。
结论 2
RNNoise 没有维护良好的 Java JNI 绑定(jitsi 只维护了 WASM 版),所以 RNNoise 应放在 FreeSWITCH 层(社区 mod_rnnoise),不要试图在 Java 里对接它。
结论 3
「声纹锁定」是两件事:身份锁定(验证本人/持续认证)在 Java 进程内做;声音锁定(从混音中只提取目标人声,VoiceFilter 路线)算力重,放 Python sidecar 经 gRPC 对接、检测到多人声时按需触发。
结论 4
降噪不是越多越好:现代 ASR 本身抗噪,激进降噪的频谱伪影反而拉高 WER。上线前以 WER/EER 为准绳做 A/B,实时链路降噪、落盘录音存原始信号。
一、总体架构:FreeSWITCH 分流 + Media Center 旁路处理
原则:FreeSWITCH 上不跑任何模型,只做媒体分流与轻量 DSP;所有 AI 组件按算力分三层落位——Java 进程内(轻)、gRPC sidecar(重)、FreeSWITCH 模块(零成本 DSP)。
PSTN/SIP(8kHz)
│
▼
FreeSWITCH ── mod_rnnoise(①稳态噪,进门先洗一遍)
│
├── mod_audio_stream ──WebSocket(L16 PCM)──▶ Media Center(Java 语音中控)
│ ├─ VAD / 断句(既有能力)
│ ├─ GTCRN 增强(sherpa-onnx,按语音段批处理)
│ ├─ 声纹模块(sherpa-onnx JNI,身份锁定/持续认证)
│ │ └─ 检测到多人声重叠 ──gRPC──▶ TSE sidecar(Python,声音锁定)
│ └─ 干净语音段 ──▶ ASR / 业务
├── ESL(8021) ◀──控制指令/认证事件──▶ Media Center
└── uuid_record ──▶ 原始录音落盘 ──▶ 离线分析(pyannote 分离 / 1:N 声纹聚类 / 反合成检测)
声纹与降噪都走旁路:与 ASR 并行消费同一路音频,绝不阻塞主对话链路。声纹验证需累积 5–10 秒有效语音,结果作为「会话级风险分」异步回注业务。
二、降噪方案对接矩阵(按噪声类型分层)
电话场景的「噪」是四类不同问题,各有最优解,Media Center 只需要在正确的层对接正确的方案:
| 噪声类型 | 推荐方案 | 落位 | 对接方式 | 成本 |
|---|---|---|---|---|
| ① 非人声环境噪 (街道/风扇/电流) | RNNoise(C 库,电话降噪事实标准) | FreeSWITCH 层 | mod_rnnoise media bug 挂通道,Java 侧零对接 | 几乎为零 |
| ① 精细增强 (ASR/声纹前) | GTCRN(48.2K 参数超轻量) | Java 进程内 | sherpa-onnx JNI(已集成)或 ONNX Runtime Java 加载官方流式 ONNX | CPU 毫秒级/段 |
| ② 背景人声串音 (电视/旁人说话) | VoiceFilter 路线 TSE(声纹条件提取,即「声音锁定」) | Python sidecar | gRPC/REST,检测到多人声时按需触发 | 重(GPU 可选) |
| ③ 回声自串扰 (TTS 漏回采集) | WebRTC AEC3 / Speex AEC | FreeSWITCH/RTC 层 | PSTN 纯呼入回声在线路侧,半双工门控可简化 | 低 |
| ④ 信道劣化 (8k 窄带) | ClearerVoice 超分(8k→16k 带宽扩展) | Python sidecar(可选) | gRPC,离线/准实时 | 中,锦上添花 |
主流开源降噪模型参数量对比(K,越小越省算力)
数据来源:各模型论文/官方仓库自述(GTCRN 48.2K;RNNoise 论文约 88K 权重;DTLN 论文 <1M;DeepFilterNet2 论文约 2.31M)。GTCRN 是高并发「每路一实例」场景的算力最优选。
商用兜底
Krisp SDK(C++,可经 JNI 封装进 Java)提供降噪+回声移除+口音转换;对比竞品 ai-coustics 主打音质保真。适合不想自维护模型、按坐席付费可接受的场景。
工程铁律:注册声纹和验证声纹必须走同一条降噪链路,否则降噪本身会造成声纹分数漂移(自己制造信道失配)。
三、声纹锁定方案(身份锁定 + 声音锁定)
3.1 身份锁定:Java 进程内声纹验证(sherpa-onnx)
sherpa-onnx 官方提供 Java API 与 SpeakerIdentification 示例(PR #822 起),内置 Fbank 特征提取,直接加载 3D-Speaker / WeSpeaker 导出的 ONNX 声纹模型:
// Media Center 内声纹验证骨架(sherpa-onnx Java API) var config = SpeakerEmbeddingExtractorConfig.builder() .setModel("campplus_cn_common.onnx") // 中文:3D-Speaker CAM++;多语种:WeSpeaker VoxBlink2 系 .setNumThreads(1).build(); var extractor = new SpeakerEmbeddingExtractor(config); var manager = new SpeakerEmbeddingManager(extractor.dim()); // 注册:客户历史通话 20~30 秒有效语音 → 嵌入入库 manager.add("customer-8001", embeddingOf(enrollSamples)); // 验证:断句模块累积 5~10 秒语音段 → 滚动打分(持续认证) boolean isOwner = manager.verify("customer-8001", embeddingOf(segment), threshold);
| 模型选择 | 适用 | 说明 |
|---|---|---|
| 3D-Speaker CAM++(中文常用版) | 国内业务 | ModelScope 免费商用,sherpa-onnx 模型仓有现成转换 |
| WeSpeaker × VoxBlink2(11 万人/15+ 语系) | 东南亚/拉美多语种 | 跨语种衰减最小的开源选择;配合分市场阈值校准 + 同语种 AS-Norm |
| AASIST 反合成检测 | 金融/认证场景必配 | 与声纹并联(Python sidecar),两分数联合决策,防 AI 拟声 |
3.2 声音锁定:目标说话人提取(TSE sidecar)
- 做什么:用注册声纹作条件,从混合语音中只留客户本人的声音——通用降噪无法解决的②类背景人声问题只有这条路线能解;
- 怎么接:Python sidecar(ClearerVoice TSE / SpeakerBeam / VoiceFilter 复现),Media Center 经 gRPC 送「语音段 + 注册声纹嵌入」,返回提取后音频;
- 何时触发:学 VoiceFilter-Lite 的「自适应抑制」思路——只在声纹模块检测到多人声重叠时触发,无重叠时直通,避免伪影损伤 ASR 且省算力。
四、Java 对接关键事实核查(本次检索验证)
| 事实 | 结论 | 依据 |
|---|---|---|
| sherpa-onnx 有官方 Java API? | ✓ 有 | 仓库 java-api 目录 + SpeakerIdentification.java 官方示例(PR #822);Maven Central 另有社区打包件 com.litongjava:sherpa-onnx-java-api |
| RNNoise 有 Java 绑定? | ✕ 无成熟维护版 | jitsi 只维护 rnnoise-wasm(浏览器用);故 RNNoise 落位 FreeSWITCH 层而非 Java |
| GTCRN 可在 Java 里跑? | ✓ 可 | 官方提供流式 ONNX;经 sherpa-onnx(当前离线批处理模式,issue #2670)或 ONNX Runtime Java(com.microsoft.onnxruntime)自行逐帧驱动 |
| FreeSWITCH 实时分流给 Java? | ✓ 成熟 | mod_audio_stream(社区版标注 production-ready)WebSocket 推 L16 PCM;ESL 有 netty 实现的 Java client |
| TSE 有 Java 原生实现? | ✕ 无 | VoiceFilter/SpeakerBeam/ClearerVoice 均为 Python 生态,gRPC sidecar 是唯一现实路径 |
五、落地路线图(按投入产出排序)
| 阶段 | 动作 | 产出 |
|---|---|---|
| P0(1 周内) | FreeSWITCH 装 mod_rnnoise + mod_audio_stream;Media Center 加 WebSocket 收流端 | ①类噪声消除 + 音频进 Java 链路 |
| P1(2–3 周) | 引入 sherpa-onnx Java API:GTCRN 段级增强 + CAM++/WeSpeaker 声纹注册-验证;用真实话务 A/B 测 WER 与 EER 定阈值 | 降噪+身份锁定进程内闭环 |
| P2(1–2 月) | Python sidecar:TSE 声音锁定(按需触发)+ AASIST 反合成并联;多语种市场分语种阈值校准 | ②类人声串音可解 + 防拟声欺诈 |
| P3(持续) | 业务录音回流 → WeSpeaker 微调小语种;离线 1:N 声纹聚类风控 | 精度持续爬坡 + 团伙欺诈挖掘 |
来源列表(多信源交叉验证)
- 官方仓库k2-fsa/sherpa-onnx(Java API + Speaker ID 示例,PR #822;增强离线模式见 issue #2670)
- 官方仓库modelscope/3D-Speaker · wenet-e2e/wespeaker(Speech Communication 2024)
- 官方仓库mod_audio_stream(production-ready WebSocket 分流)· xiph/rnnoise · jitsi/rnnoise-wasm
- 官方仓库Xiaobin-Rong/gtcrn(48.2K 参数/33 MMACs)· DeepFilterNet · ClearerVoice-Studio(arXiv 2025)
- 论文Google VoiceFilter · VoiceFilter-Lite 多用户版(2021) · VoxBlink2(Interspeech 2024)
- 论文AASIST 反合成 · ASVspoof 5(评测报告 2026-01)
- 社区实践博客园《FreeSWITCH 使用 RNNoise 进行实时通话降噪》(2025-11,8k↔48k 重采样坑)· Maven Central com.litongjava:sherpa-onnx-java-api
- 商用参照Krisp SDK · Pindrop(多因子+Deepfake 检测路线)