跳转至

语音叠层生命周期(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