流式ASR远场声音过滤是一个用于提升WebSocket实时语音识别准确性的功能。通过音频信号分析,自动过滤远场声音(如远处的说话声、电视人声等环境音),只处理近场说话人的声音,有效减少误触发。
核心优势:
- ✅ 智能过滤:基于音量阈值的简单高效检测机制
- ✅ 零性能开销:RMS计算 <0.1ms,对实时性无影响
- ✅ 完全可配置:支持3个环境变量灵活调整
- ✅ 开箱即用:默认启用宽松模式,适合大多数场景
- ✅ 动态阈值:句子进行中自动降低阈值,避免数据丢失
远场声音过滤采用RMS能量阈值检测方案:
- RMS能量检测:计算音频的均方根(RMS)能量,判断音量大小
- 阈值判断:音频RMS能量必须达到阈值才会被送入ASR处理
- 动态调整:句子进行中自动降低阈值到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.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-
启用调试日志
ASR_NEARFIELD_FILTER_LOG_ENABLED=true
-
观察日志输出
docker-compose logs -f | grep "近场\|远场"
-
分析实际数值
- 近距离说话时的 RMS 能量值
- 远场声音/环境音的 RMS 能量值
-
调整阈值
- 根据日志数据微调
RMS_THRESHOLD
- 根据日志数据微调
-
验证效果
- 测试近场说话:应正常识别
- 测试远场声音:应被过滤
-
关闭日志
ASR_NEARFIELD_FILTER_LOG_ENABLED=false
ASR_NEARFIELD_RMS_THRESHOLD=0.01 # 宽松模式(默认)特点:适合大多数场景,正常说话都能识别,同时能过滤大部分远场声音
ASR_NEARFIELD_RMS_THRESHOLD=0.015 # 严格模式特点:强力过滤背景噪音和环境音,适合嘈杂环境,但需要比较大声说话
ASR_NEARFIELD_RMS_THRESHOLD=0.005 # 最宽松特点:最大化识别灵敏度,小声说话也能识别,但远场过滤效果较弱
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)
-
观察RMS数值
- 近场说话通常 >0.010
- 远场声音通常 <0.008
- 环境音通常 <0.005
-
根据实际数据调整
- 如果近场RMS普遍在0.02左右,阈值可设为0.015
- 如果近场RMS较小(0.01左右),保持默认0.01或降低到0.008
-
动态阈值观察
- 句子进行中,阈值会自动降低到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为了防止句子进行中因音量变化导致的数据丢失,系统实现了动态阈值:
- 初始状态:使用完整阈值(如0.01)
- 句子开始后:自动降低到60%(如0.006)
- 句子结束后:恢复到完整阈值
这样可以确保:
- 远场声音不会触发新句子
- 句子进行中即使音量略有下降也不会中断
核心代码位于:
app/utils/audio_filter.py:音频过滤算法实现(仅RMS计算)app/services/websocket_asr.py:300-370:集成到流式ASR处理循环,包含动态阈值逻辑app/core/config.py:64-67:配置参数定义(3个参数)
- ✅ 简化为纯RMS能量检测(移除频谱分析)
- ✅ 实现动态阈值机制(句子进行中自动降低60%)
- ✅ 减少配置参数到3个
- ✅ 调试日志功能
- ✅ 默认启用宽松模式(RMS=0.01)
- ✅ 实现音量阈值检测
- ✅ 实现高频衰减检测(已废弃)
- ✅ AND逻辑组合判断(已废弃)
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能量检测更简单可靠。
- 部署指南 - 完整的部署和配置说明
- README.md - 项目主页
- WebSocket ASR协议 - 阿里云协议文档
如果遇到问题或有改进建议,请:
- 查看本文档的常见问题章节
- 启用调试日志分析具体情况
- 访问项目仓库提交Issue