Skip to content

Latest commit

 

History

History
387 lines (257 loc) · 9.98 KB

File metadata and controls

387 lines (257 loc) · 9.98 KB

流式ASR远场声音过滤功能

功能概述

流式ASR远场声音过滤是一个用于提升WebSocket实时语音识别准确性的功能。通过音频信号分析,自动过滤远场声音(如远处的说话声、电视人声等环境音),只处理近场说话人的声音,有效减少误触发。

核心优势:

  • 智能过滤:基于音量阈值的简单高效检测机制
  • 零性能开销:RMS计算 <0.1ms,对实时性无影响
  • 完全可配置:支持3个环境变量灵活调整
  • 开箱即用:默认启用宽松模式,适合大多数场景
  • 动态阈值:句子进行中自动降低阈值,避免数据丢失

工作原理

技术方案

远场声音过滤采用RMS能量阈值检测方案:

  1. RMS能量检测:计算音频的均方根(RMS)能量,判断音量大小
  2. 阈值判断:音频RMS能量必须达到阈值才会被送入ASR处理
  3. 动态调整:句子进行中自动降低阈值到60%,防止中间帧丢失

物理原理

为什么RMS能量能判断距离?

声音在空气中传播时,能量随距离衰减:

  • 近场声音(1-2米内):RMS能量较高,通常 >0.01
  • 远场声音(3米外):RMS能量较低,通常 <0.008
  • 环境音:RMS能量很低,通常 <0.005

通过设置合适的阈值,可以有效区分:

  • 近距离正常说话 ✅
  • 远距离说话声 ❌
  • 电视/广播人声 ❌
  • 小音量环境音 ❌

配置参数

环境变量

变量名 类型 默认值 说明
ASR_ENABLE_NEARFIELD_FILTER bool true 总开关,设为false完全禁用功能
ASR_NEARFIELD_RMS_THRESHOLD float 0.01 RMS能量阈值(宽松模式,推荐)
ASR_NEARFIELD_FILTER_LOG_ENABLED bool true 调试日志开关,默认启用便于初期调优

阈值范围

模式 RMS阈值 适用场景 特点
宽松(默认) 0.01 安静办公室、家庭 正常说话即可识别,过滤大部分远场声音
严格 0.015 嘈杂环境 强力过滤背景噪音,需要稍大声说话
保守 0.005 安静环境 最大灵敏度,小声说话也能识别

使用指南

Docker Compose 配置

方式一:环境变量

编辑 docker-compose.yml

services:
  funspeech:
    image: docker.cnb.cool/nexa/funspeech:latest
    environment:
      # ... 其他配置 ...

      # 远场声音过滤(默认已启用,以下为自定义配置示例)
      - ASR_ENABLE_NEARFIELD_FILTER=true              # 总开关(默认启用)
      - ASR_NEARFIELD_RMS_THRESHOLD=0.01              # RMS能量阈值(默认宽松模式)
      - ASR_NEARFIELD_FILTER_LOG_ENABLED=true         # 调试日志(默认启用,调优后可关闭)

方式二:.env 文件

创建 .env 文件:

# 远场声音过滤配置
ASR_ENABLE_NEARFIELD_FILTER=true
ASR_NEARFIELD_RMS_THRESHOLD=0.01
ASR_NEARFIELD_FILTER_LOG_ENABLED=true

然后在 docker-compose.yml 中引用:

services:
  funspeech:
    env_file:
      - .env

本地开发配置

# 启用远场过滤(默认已启用)
export ASR_ENABLE_NEARFIELD_FILTER=true

# 自定义阈值
export ASR_NEARFIELD_RMS_THRESHOLD=0.01

# 启用调试日志
export ASR_NEARFIELD_FILTER_LOG_ENABLED=true

# 启动服务
python main.py

参数调优

调优流程

  1. 启用调试日志

    ASR_NEARFIELD_FILTER_LOG_ENABLED=true
  2. 观察日志输出

    docker-compose logs -f | grep "近场\|远场"
  3. 分析实际数值

    • 近距离说话时的 RMS 能量值
    • 远场声音/环境音的 RMS 能量值
  4. 调整阈值

    • 根据日志数据微调 RMS_THRESHOLD
  5. 验证效果

    • 测试近场说话:应正常识别
    • 测试远场声音:应被过滤
  6. 关闭日志

    ASR_NEARFIELD_FILTER_LOG_ENABLED=false

典型场景配置

场景1:安静办公室(默认宽松模式,推荐)

ASR_NEARFIELD_RMS_THRESHOLD=0.01       # 宽松模式(默认)

特点:适合大多数场景,正常说话都能识别,同时能过滤大部分远场声音


场景2:嘈杂环境(严格模式)

ASR_NEARFIELD_RMS_THRESHOLD=0.015      # 严格模式

特点:强力过滤背景噪音和环境音,适合嘈杂环境,但需要比较大声说话


场景3:安静环境 + 最大灵敏度(保守模式)

ASR_NEARFIELD_RMS_THRESHOLD=0.005      # 最宽松

特点:最大化识别灵敏度,小声说话也能识别,但远场过滤效果较弱


场景4:完全禁用(兼容旧版本行为)

ASR_ENABLE_NEARFIELD_FILTER=false

特点:恢复到无过滤的原始行为


常见问题及解决

问题 症状 解决方案
正常说话被过滤 近距离说话无响应 降低阈值:RMS_THRESHOLD=0.008
远场声音仍触发 电视/远处说话被识别 提高阈值:RMS_THRESHOLD=0.015
小声说话不识别 轻声说话无效 降低RMS阈值:RMS_THRESHOLD=0.005
句子中断 说话过程中识别中断 动态阈值已启用,检查基础阈值是否过高

调试日志示例

启用日志后的输出

近场声音(通过检测):

[aliyun_ws_asr_xxx] 近场声音检测通过 - RMS: 0.025000
[aliyun_ws_asr_xxx] 识别结果: 你好

远场声音(被过滤):

[aliyun_ws_asr_xxx] 远场声音已过滤 - RMS: 0.008000 (阈值: 0.010)

环境音(被过滤):

[aliyun_ws_asr_xxx] 远场声音已过滤 - RMS: 0.003000 (阈值: 0.010)

动态阈值生效:

[aliyun_ws_asr_xxx] 近场声音检测通过 - RMS: 0.007000 (动态阈值: 0.006, 原始: 0.010)

日志分析技巧

  1. 观察RMS数值

    • 近场说话通常 >0.010
    • 远场声音通常 <0.008
    • 环境音通常 <0.005
  2. 根据实际数据调整

    • 如果近场RMS普遍在0.02左右,阈值可设为0.015
    • 如果近场RMS较小(0.01左右),保持默认0.01或降低到0.008
  3. 动态阈值观察

    • 句子进行中,阈值会自动降低到60%(如0.01→0.006)
    • 如果仍被过滤,说明基础阈值设置过高

性能影响

计算开销

操作 音频块大小 耗时
RMS计算 3840 samples (240ms) <0.1ms
总耗时 - <0.1ms

对实时性的影响

  • 忽略不计:<0.1ms的开销对实时语音识别(通常200-600ms延迟)几乎无影响
  • 无额外内存:使用NumPy向量化操作,无内存分配
  • 无额外IO:纯CPU计算,无网络或磁盘操作

技术细节

核心算法

RMS能量计算:

RMS = sqrt(mean(audio_array^2))

判断逻辑:

# 动态阈值:句子进行中降低到60%
effective_threshold = base_threshold * 0.6 if sentence_active else base_threshold

# 判断
is_nearfield = RMS >= effective_threshold

动态阈值机制

为了防止句子进行中因音量变化导致的数据丢失,系统实现了动态阈值:

  1. 初始状态:使用完整阈值(如0.01)
  2. 句子开始后:自动降低到60%(如0.006)
  3. 句子结束后:恢复到完整阈值

这样可以确保:

  • 远场声音不会触发新句子
  • 句子进行中即使音量略有下降也不会中断

代码实现

核心代码位于:

  • app/utils/audio_filter.py:音频过滤算法实现(仅RMS计算)
  • app/services/websocket_asr.py:300-370:集成到流式ASR处理循环,包含动态阈值逻辑
  • app/core/config.py:64-67:配置参数定义(3个参数)

版本历史

v1.1.0 (2025-12)

  • ✅ 简化为纯RMS能量检测(移除频谱分析)
  • ✅ 实现动态阈值机制(句子进行中自动降低60%)
  • ✅ 减少配置参数到3个
  • ✅ 调试日志功能
  • ✅ 默认启用宽松模式(RMS=0.01)

v1.0.0 (2025-12)

  • ✅ 实现音量阈值检测
  • ✅ 实现高频衰减检测(已废弃)
  • ✅ AND逻辑组合判断(已废弃)

FAQ

Q1: 这个功能会影响识别准确率吗?

A: 不会。过滤只在音频进入ASR模型之前进行,近场声音完全正常处理,不影响识别准确率。


Q2: 可以针对不同麦克风调整吗?

A: 可以。不同麦克风灵敏度不同,建议启用调试日志观察实际RMS数值,然后调整阈值。


Q3: 支持多说话人场景吗?

A: 支持。只要说话人在近场(1-2米内),都会被正常识别。远场说话人会被过滤。


Q4: 能区分电视声音和真人说话吗?

A: 大部分情况可以。电视声音通常:

  • 音量较小(RMS低)或距离远
  • 如果电视很近且音量大,需要提高阈值

Q5: 对非中文语言有效吗?

A: 有效。该方案基于物理声学原理,与语言无关,适用于所有语言。


Q6: 如何完全禁用此功能?

A: 设置环境变量 ASR_ENABLE_NEARFIELD_FILTER=false 即可。


Q7: 句子中间会不会因为音量变化而中断?

A: 不会。系统实现了动态阈值机制,句子进行中阈值会自动降低到60%,防止数据丢失。


Q8: 为什么不使用频谱分析?

A: 实测发现频谱分析(高频/低频能量比)在实际使用中不够稳定,不同麦克风、录音设备的频率响应差异很大。纯RMS能量检测更简单可靠。


相关链接


技术支持

如果遇到问题或有改进建议,请:

  1. 查看本文档的常见问题章节
  2. 启用调试日志分析具体情况
  3. 访问项目仓库提交Issue