68 lines
3.9 KiB
Markdown
68 lines
3.9 KiB
Markdown
---
|
||
read_when:
|
||
- 调整语音浮层行为
|
||
summary: 唤醒词与按键说话重叠时的语音浮层生命周期
|
||
title: 语音浮层
|
||
x-i18n:
|
||
generated_at: "2026-02-01T21:33:26Z"
|
||
model: claude-opus-4-5
|
||
provider: pi
|
||
source_hash: 3be1a60aa7940b2368ff62cd49f04b2b8422876030e8ea206b467f66a5a6bd4d
|
||
source_path: platforms/mac/voice-overlay.md
|
||
workflow: 15
|
||
---
|
||
|
||
# 语音浮层生命周期(macOS)
|
||
|
||
受众:macOS 应用贡献者。目标:在唤醒词与按键说话重叠时保持语音浮层行为可预测。
|
||
|
||
### 当前意图
|
||
|
||
- 如果浮层已因唤醒词显示,此时用户按下热键,热键会话会*接管*现有文本而非重置。浮层在热键按住期间保持显示。用户松开时:如果有去除空白后的文本则发送,否则关闭。
|
||
- 单独使用唤醒词时仍在静音后自动发送;按键说话在松开时立即发送。
|
||
|
||
### 已实现(2025 年 12 月 9 日)
|
||
|
||
- 浮层会话现在为每次捕获(唤醒词或按键说话)携带一个令牌。当令牌不匹配时,部分/最终/发送/关闭/音量更新会被丢弃,避免过时回调。
|
||
- 按键说话会接管任何可见的浮层文本作为前缀(因此在唤醒浮层显示时按下热键会保留文本并追加新语音)。它最多等待 1.5 秒获取最终转录结果,然后回退到当前文本。
|
||
- 提示音/浮层日志以 `info` 级别输出,分类为 `voicewake.overlay`、`voicewake.ptt` 和 `voicewake.chime`(会话开始、部分、最终、发送、关闭、提示音原因)。
|
||
|
||
### 后续步骤
|
||
|
||
1. **VoiceSessionCoordinator(actor)**
|
||
- 同一时间只拥有一个 `VoiceSession`。
|
||
- API(基于令牌):`beginWakeCapture`、`beginPushToTalk`、`updatePartial`、`endCapture`、`cancel`、`applyCooldown`。
|
||
- 丢弃携带过时令牌的回调(防止旧识别器重新打开浮层)。
|
||
2. **VoiceSession(模型)**
|
||
- 字段:`token`、`source`(wakeWord|pushToTalk)、已提交/临时文本、提示音标志、计时器(自动发送、空闲)、`overlayMode`(display|editing|sending)、冷却截止时间。
|
||
3. **浮层绑定**
|
||
- `VoiceSessionPublisher`(`ObservableObject`)将活跃会话镜像到 SwiftUI。
|
||
- `VoiceWakeOverlayView` 仅通过 publisher 渲染;绝不直接修改全局单例。
|
||
- 浮层用户操作(`sendNow`、`dismiss`、`edit`)携带会话令牌回调到 coordinator。
|
||
4. **统一发送路径**
|
||
- `endCapture` 时:如果去除空白后文本为空 → 关闭;否则 `performSend(session:)`(播放一次发送提示音、转发、关闭)。
|
||
- 按键说话:无延迟;唤醒词:可选自动发送延迟。
|
||
- 按键说话结束后对唤醒运行时施加短暂冷却,防止唤醒词立即重新触发。
|
||
5. **日志**
|
||
- Coordinator 在子系统 `bot.molt`、分类 `voicewake.overlay` 和 `voicewake.chime` 下输出 `.info` 级别日志。
|
||
- 关键事件:`session_started`、`adopted_by_push_to_talk`、`partial`、`finalized`、`send`、`dismiss`、`cancel`、`cooldown`。
|
||
|
||
### 调试清单
|
||
|
||
- 复现浮层粘滞问题时流式查看日志:
|
||
|
||
```bash
|
||
sudo log stream --predicate 'subsystem == "bot.molt" AND category CONTAINS "voicewake"' --level info --style compact
|
||
```
|
||
|
||
- 验证只有一个活跃会话令牌;过时回调应被 coordinator 丢弃。
|
||
- 确保按键说话松开时始终使用活跃令牌调用 `endCapture`;如果文本为空,预期 `dismiss` 且不播放提示音或发送。
|
||
|
||
### 迁移步骤(建议)
|
||
|
||
1. 添加 `VoiceSessionCoordinator`、`VoiceSession` 和 `VoiceSessionPublisher`。
|
||
2. 重构 `VoiceWakeRuntime`,使其创建/更新/结束会话,而非直接操作 `VoiceWakeOverlayController`。
|
||
3. 重构 `VoicePushToTalk`,使其接管现有会话并在松开时调用 `endCapture`;施加运行时冷却。
|
||
4. 将 `VoiceWakeOverlayController` 连接到 publisher;移除来自 runtime/PTT 的直接调用。
|
||
5. 添加会话接管、冷却和空文本关闭的集成测试。
|