语音叠层生命周期(macOS)¶
读者对象:macOS 应用贡献者。目标:在唤醒词与按键通话(push-to-talk)重叠时,让语音叠层的行为保持可预测。
在 Dashboard → Settings → Talk → This Mac 下配置语音输入。叠层与麦克风测试仍保持原生实现;它们的设备设置由 Dashboard 统一管理。控件和权限说明请参阅 语音唤醒。
行为¶
- 当用户按下快捷键时,叠层可能已由唤醒词显示出来。此时快捷键会话会采用现有文本,而不是将其重置。按住快捷键期间,叠层保持显示;松开时,如果存在去除首尾空白后的文本则发送,否则关闭叠层。
- 仅靠唤醒词时,检测到静音后仍会自动发送。按键通话(push-to-talk)则在松开时立即发送。
实现¶
VoiceSessionCoordinator(apps/macos/Sources/OpenClaw/VoiceSessionCoordinator.swift)是活动语音会话的唯一所有者。它是一个@MainActor @Observable单例,而不是 actor。API:startSession、updatePartial、finalize、sendNow、dismiss、updateLevel、snapshot。每个会话携带一个UUID令牌。协调器会丢弃带有过期或不匹配令牌的调用。VoiceWakeOverlayController(VoiceWakeOverlayController+Session.swift)负责渲染叠层,并通过会话令牌将用户操作(requestSend、dismiss)转发回协调器。它本身从不持有会话状态。- 按键通话(push-to-talk)会通过
VoiceSessionCoordinator.shared.snapshot()将任何可见的叠层文本作为adoptedPrefix采用。因此,在唤醒叠层显示时按下快捷键会保留原有文本并追加新的语音。松开时,按键通话会等待最多 1.5 秒以获取最终转写文本,否则回退到当前文本。 - 在
dismiss时,叠层会调用VoiceSessionCoordinator.overlayDidDismiss。该调用会触发VoiceWakeRuntime.refresh(state:)。因此,手动点击 X 关闭、空文本关闭以及发送后关闭,都会恢复唤醒词监听。 - 统一发送路径:如果去除首尾空白后的文本为空,则关闭叠层;否则
sendNow播放一次发送提示音,通过VoiceWakeForwarder转发,然后关闭叠层。
日志¶
语音子系统为 ai.openclaw。每个组件在自己的类别下记录日志:
| 类别 | 组件 |
|---|---|
voicewake.coordinator |
VoiceSessionCoordinator |
voicewake.overlay |
VoiceWakeOverlayController/VoiceWakeOverlay |
voicewake.ptt |
按键通话热键与采集 |
voicewake.runtime |
唤醒词运行时 |
voicewake.chime |
提示音播放 |
voicewake.sync |
全局设置同步 |
voicewake.forward |
转写文本转发 |
voicewake.meter |
麦克风电平监控 |
调试检查清单¶
- 复现叠层卡住不消失时,流式查看日志:
sudo log stream --predicate 'subsystem == "ai.openclaw" AND category CONTAINS "voicewake"' --level info --style compact
- 确认只有一个活动会话令牌。协调器会丢弃过期的回调。
- 确认按键通话在松开时始终使用活动令牌调用
end()。如果文本为空,预期会直接关闭叠层,不播放提示音,也不发送。
相关¶
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw