Skip to main content

语音叠加生命周期(macOS)

受众:macOS 应用贡献者。目标:在唤醒词与按键说话功能发生重叠时,确保语音叠加的行为具有可预测性。

当前意图

  • 如果叠加已因唤醒词而可见,且用户按下快捷键,则快捷键会话会采用现有文本,而不是重置文本。在按住快捷键期间,叠加将持续显示。当用户松开快捷键时:如果有修剪后的文本,则发送;否则关闭叠加。
  • 单独的唤醒词仍会在静音时自动发送;按键说话则在松开时立即发送。

已实现(2025年12月9日)

  • 叠加会话现在为每次捕获(唤醒词或按键说话)携带一个标记。当标记不匹配时,部分、最终、发送、关闭以及级别更新将被丢弃,从而有效避免过时回调。
  • 按键说话会将任何可见的叠加文本作为前缀附加到语音输入中(因此,在唤醒叠加显示时按下快捷键会保留现有文本,并在其后追加新语音)。它最多会等待1.5秒以获取最终转录结果,如果在此期间未收到结果,则回退到当前文本。
  • 钟声和叠加日志在info处按voicewake.overlayvoicewake.pttvoicewake.chime类别发出,分别对应会话开始、部分转录、最终转录、转录发送、会话关闭以及钟声触发原因。

下一步

  1. VoiceSessionCoordinator(角色)
    • 同一时间仅拥有一个VoiceSession
    • API(基于标记):beginWakeCapturebeginPushToTalkupdatePartialendCapturecancelapplyCooldown
    • 丢弃携带过时标记的回调(防止旧识别器重新打开叠加)。
  2. VoiceSession(模型)
    • 字段:tokensource(唤醒词|按键说话)、已提交/易失性文本、钟声标志、计时器(自动发送、空闲)、overlayMode(显示|编辑|发送)、冷却截止时间。
  3. 叠加绑定
    • VoiceSessionPublisherObservableObject)将活动会话镜像到 SwiftUI。
    • VoiceWakeOverlayView仅通过发布者渲染;它从不直接修改全局单例。
    • 叠加用户操作(sendNowdismissedit)会使用会话标记回调协调器。
  4. 统一发送路径
    • endCapture上:如果修剪后的文本为空→关闭;否则performSend(session:)(播放一次发送钟声,转发,关闭)。
    • 按键说话:无延迟;唤醒词:可选延迟用于自动发送。
    • 在按键说话结束后对唤醒运行时应用短暂冷却,以防止唤醒词立即再次触发。
  5. 日志记录
    • 协调器在子系统bot.molt中以voicewake.overlayvoicewake.chime类别发出.info日志。
    • 关键事件:session_startedadopted_by_push_to_talkpartialfinalizedsenddismisscancelcooldown

调试检查清单

  • 在重现卡滞叠加时流式传输日志:
    sudo log stream --predicate 'subsystem == "bot.molt" AND category CONTAINS "voicewake"' --level info --style compact
    
  • 验证是否只有一个活动会话标记;过时回调应由协调器丢弃。
  • 确保按键说话释放始终使用活动标记调用endCapture;如果文本为空,预期为dismiss,不带钟声或发送。

迁移步骤(建议)

  1. 添加VoiceSessionCoordinatorVoiceSessionVoiceSessionPublisher
  2. 重构VoiceWakeRuntime,以通过创建、更新或结束会话来管理会话状态,而不是直接操作VoiceWakeOverlayController
  3. 重构VoicePushToTalk,使其采用现有会话,并在释放会话时调用endCapture;同时应用运行时冷却机制。
  4. VoiceWakeOverlayController连接到发布者;移除来自运行时/PTT的直接调用。
  5. 添加针对会话采用、冷却以及空文本关闭的集成测试。