从“会说”到“会让”:视障辅助 Demo3 的一次音频交互系统升级
在 Demo1 和 Demo2 阶段,系统已经具备了两类核心能力:
-
能够理解环境(检测 + 视觉模型)
-
能够表达信息(语音播报)
但在真实使用场景中,一个更关键的问题逐渐显现:
系统在说话的时候,是否考虑了“人正在说话”?
如果播报始终以固定音量输出,就会出现典型问题:
-
用户说话时被系统打断
-
环境中有声音时信息互相覆盖
-
多源声音竞争,导致信息不可理解
因此,在 Demo3 阶段,系统开始引入一个新的能力:
基于环境人声的动态音量控制(反向增益)****
目标不是“让系统更响”,而是:
让系统在该让的时候让。****
一、目标:基于人声的反向增益控制
本次设计的核心目标是:
-
在检测到环境中有人声时,自动降低播报音量
-
在人声减弱后,平滑恢复音量
-
避免系统与环境声音“互抢声道”
该方案在 Contexta 架构中的实现说明见 。
这属于一个典型的“交互层能力”,而不是视觉或模型能力。
二、系统接入位置
当前反向增益能力,已经接入两条链路:
1 Demo1:风险播报链路(已生效)
流程如下:
-
启动检测时,开启环境人声监测
-
每次 YOLO TTS 播报时
-
使用动态音量 adaptiveSpeechGain
也就是说:
检测播报已经具备真实的动态音量能力
2 Demo2:任务播报链路(状态机已接入)
在任务播报(简洁/复杂识图)中:
-
状态机已接入音量控制开关
-
播报开始时进入 GainActive 状态
-
播报结束后退出
当前默认实现为:
MockSpeechGainController(仅逻辑接入)
也就是说:
结构已完成,但实际音量控制还未完全接管
三、模块拆分
整个反向增益系统拆分为四个核心模块:
1 AdaptiveAudioSessionManager
负责:
-
麦克风权限申请
-
AVAudioSession 配置
关键模式:
playAndRecord + duckOthers
2 EnvironmentVoiceMonitor
负责:
-
采集 PCM 音频
-
计算环境音特征
输出:
- 环境分贝(envDb)
- 人声概率(speechProbability)
3 AdaptiveVolumeController
核心模块,负责:
-
输入:speechProbability
-
输出:targetGain / appliedGain
即:
决定“应该降多少音量”
4 LiveObjectDetector
负责:
- 接收 appliedGain
- 应用于 TTS 播报音量
四、人声检测:不是识别内容,而是估计概率
系统并不需要识别“人在说什么”,
只需要判断:
当前是否“可能存在人声”
采用两个特征:
1 RMS 分贝(能量)
db
反映声音强度。
2 过零率(ZCR)
zcr
反映声音的频率变化特征。
3 合成概率
最终计算:
speechProbability =
0.70 * energyScore
+ 0.30 * zcrScore
并限制在 [0,1]。
说明:
- envDb 只用于展示
- 实际控制完全基于 speechProbability
五、增益映射:从概率到音量
当检测到人声后,系统需要决定:
降多少音量?
整个过程分为三步:
1 门控(是否触发)
speechProbability < gateThreshold
→ 不降音量
否则进入衰减阶段。
2 衰减曲线
normalizedSpeech
→ drivenSpeech
→ curvedSpeech
→ targetGain
关键思想:
- 不是线性降低
- 使用非线性曲线(pow)
- 保证响应自然
3 平滑处理(避免突变)
appliedGain += alpha * (target - applied)
其中:
-
attack:快速降音量
-
release:慢速恢复
效果:
听起来是“自然变小”,而不是“突然静音”
六、当前参数配置
当前参数如下(与实现一致):
-
baseGain = 1.00
-
minGain = 0.08
-
maxGain = 1.00
-
attenuationSensitivity = 1.15
-
attenuationCurveExponent = 0.45
-
speechDriveMultiplier = 1.60
-
gateThreshold = 0.35
-
attack = 0.07s
-
release = 1.30s
设计意图:
- 快速响应人声
- 缓慢恢复系统音量
七、与播报优先级系统的关系
系统已有统一播报优先级:
高危 > 任务 > 复杂 > 简单 > 中危 > 低危
反向增益的定位是:
音量层能力,而非调度层能力
因此:
- 不改变优先级
- 不改变打断策略
- 只影响当前播报的音量
八、当前边界
当前实现仍存在几个边界:
- 动态增益主要作用于 Demo1 播报
- Demo2 播报仍为 mock 控制
- 多设备(耳机 / 蓝牙)未做参数适配
九、下一步方向
下一阶段重点:
- 替换 MockSpeechGainController 为真实实现
- 接管所有播报声道
- 按音频设备做参数分组
- 增加埋点数据用于调优
结语
如果说:
-
Demo1 解决的是“系统能看到什么”
-
Demo2 解决的是“系统能理解什么”
那么 Demo3 开始关注的是:
系统在现实环境中如何“存在”****
它不再只是输出信息,
而是开始参与到人与环境的声音关系中。
当系统学会在合适的时机降低音量,
它才真正具备进入真实场景的基础。