Voice Overlay
ウェイクワードとプッシュツートークが重なる場合のボイスオーバーレイのライフサイクル
対象:macOS アプリの貢献者。目標:ウェイクワードとプッシュツートークが重なる場合にボイスオーバーレイを予測可能に保ちます。
#
現在の意図
- オーバーレイがウェイクワードで既に表示されており、ユーザーがホットキーを押すと、ホットキーセッションは既存のテキストを採用してリセットしません。オーバーレイはホットキーが押されている間、表示されたままになります。ユーザーが解放すると:トリムされたテキストがある場合は送信し、それ以外の場合は閉じます。
- ウェイクワードのみは静音時に自動送信します。プッシュツートークは解放時に即座に送信します。
#
実装済み(2025 年 12 月 9 日)
- オーバーレイセッションは、各キャプチャ(ウェイクワードまたはプッシュツートーク)ごとにトークンを運ぶようになりました。トークンが一致しない場合、部分/最終/送信/閉じる/レベルの更新は破棄され、古いコールバックが回避されます。
- プッシュツートークは、表示されているオーバーレイテキストをプレフィックスとして採用します(したがって、ウェイクオーバーレイが表示されているときにホットキーを押すと、テキストが保持され、新しい音声が追加されます)。最終的な転写を待ってから現在のテキストにフォールバックするまで、最大 1.5 秒待機します。
- チャイム/オーバーレイログは、カテゴリ ''voicewake.chime''、''voicewake.overlay''、および ''voicewake.ptt'' で ''voicewake.chime'' レベルで出力されます(セッション開始、部分、最終、送信、閉じる、チャイムの理由)。
#
次のステップ
1. VoiceSessionCoordinator(アクター)
- 一度に 1 つの ''VoiceSession'' のみを所有します。
- API(トークンベース):''beginWakeCapture''、''beginPushToTalk''、''updatePartial''、''endCapture''、''cancel''、''applyCooldown''。
- 古いトークンを運ぶコールバックを破棄します(古い認識器がオーバーレイを再開くのを防ぎます)。
2. VoiceSession(モデル)
- フィールド:''token''、''source''(wakeWord|pushToTalk)、コミットされた/揮発性テキスト、チャイムフラグ、タイマー(自動送信、アイドル)、''overlayMode''(display|editing|sending)、クールダウン期限。
3. オーバーレイバインディング
- ''VoiceSessionPublisher''(''ObservableObject'')はアクティブなセッションを SwiftUI にミラーリングします。
- ''VoiceWakeOverlayView'' はパブリッシャー経由のみでレンダリングされます。グローバルシングルトンを直接変更することはありません。
- オーバーレイユーザーアクション(''sendNow''、''dismiss''、''edit'')はセッショントークンでコーディネーターにコールバックします。
4. 統合送信パス
- ''endCapture'' で:トリムされたテキストが空の場合 → 閉じる。それ以外の場合 ''performSend(session:)''(送信チャイムを 1 回再生、転送、閉じる)。
- プッシュツートーク:遅延なし。ウェイクワード:自動送信のオプション遅延。
- プッシュツートークが完了した後、ウェイクワードがすぐに再トリガーしないように、ウェイクランタイムに短いクールダウンを適用します。
5. ログ記録
- コーディネーターはサブシステム ''voicewake.chime''、カテゴリ ''bot.molt'' および ''voicewake.overlay'' で ''voicewake.chime'' ログを出力します。
- 主要なイベント:''session_started''、''adopted_by_push_to_talk''、''partial''、''finalized''、''send''、''dismiss''、''cancel''、''cooldown''。
#
デバッグチェックリスト
- スティッキーオーバーレイを再現している間、ログをストリーミングします:
''''`bash", "p3": "sudo log stream --predicate 'subsystem == "bot.molt" AND category CONTAINS "voicewake"' --level info --style compact", "p4": "''''`
sudo log stream --predicate 'subsystem == "bot.molt" AND category CONTAINS "voicewake"' --level info --style compact
''''`
- アクティブなセッショントークンが 1 つのみであることを確認します。古いコールバックはコーディネーターによって破棄される必要があります。
- プッシュツートークの解放が常にアクティブなトークンで ''endCapture'' を呼び出すことを確認します。テキストが空の場合、チャイムや送信なしで ''dismiss'' が予想されます。
#
Migration steps (suggested)
1. ''VoiceSessionCoordinator''、''VoiceSession''、および ''VoiceSessionPublisher'' を追加します。
2. ''VoiceWakeRuntime'' をリファクタリングして、''VoiceWakeOverlayController'' に直接触れるのではなく、セッションを作成/更新/終了するようにします。
3. ''VoicePushToTalk'' をリファクタリングして、既存のセッションを採用し、解放時に ''endCapture'' を呼び出すようにします。ランタイムクールダウンを適用します。
4. ''VoiceWakeOverlayController'' をパブリッシャーに接続します。ランタイム/PTT からの直接呼び出しを削除します。
5. セッション採用、クールダウン、空テキスト閉じるの統合テストを追加します。