Voiceオーバーレイライフサイクル(macOS)
対象読者:macOSアプリの開発者。目的:ウェイクワードとプッシュトゥトークが重なったときにVoiceオーバーレイの動作を予測可能に保つこと。
現在の意図
- ウェイクワードでオーバーレイが既に表示されている状態でユーザーがホットキーを押した場合、ホットキーセッションは既存のテキストをリセットせずに引き継ぎます。ホットキーが押されている間オーバーレイは表示され続けます。リリース時:トリミングされたテキストがあれば送信、なければ閉じる。
- ウェイクワード単独の場合は無音時に自動送信。プッシュトゥトークはリリースで即座に送信。
実装済み(2025年12月9日)
- オーバーレイセッションはキャプチャごと(ウェイクワードまたはプッシュトゥトーク)にトークンを保持。部分/最終/送信/閉じる/レベル更新はトークンが一致しない場合にドロップされ、古いコールバックを回避。
- プッシュトゥトークは表示中のオーバーレイテキストをプレフィックスとして引き継ぎ(ウェイクオーバーレイが表示されている間にホットキーを押すとテキストを保持して新しい音声を追加)。最終トランスクリプトを最大1.5秒待ってから現在のテキストにフォールバック。
- チャイム/オーバーレイのログはカテゴリ
voicewake.overlay、voicewake.ptt、voicewake.chimeでinfoレベルとして出力(セッション開始、部分、最終、送信、閉じる、チャイム理由)。
次のステップ
- VoiceSessionCoordinator(アクター)
- 同時に1つの
VoiceSessionのみを保持。 - API(トークンベース):
beginWakeCapture、beginPushToTalk、updatePartial、endCapture、cancel、applyCooldown。 - 古いトークンを持つコールバックをドロップ(古い認識器によるオーバーレイの再表示を防止)。
- 同時に1つの
- VoiceSession(モデル)
- フィールド:
token、source(wakeWord|pushToTalk)、committed/volatileテキスト、チャイムフラグ、タイマー(自動送信、アイドル)、overlayMode(display|editing|sending)、クールダウン期限。
- フィールド:
- オーバーレイバインディング
VoiceSessionPublisher(ObservableObject)がアクティブセッションをSwiftUIにミラーリング。VoiceWakeOverlayViewはパブリッシャー経由でのみレンダリング。グローバルシングルトンを直接変更しない。- オーバーレイのユーザーアクション(
sendNow、dismiss、edit)はセッショントークンを使ってコーディネータにコールバック。
- 統一された送信パス
endCapture時:トリミングされたテキストが空 → 閉じる、そうでなければperformSend(session:)(送信チャイムを1回再生、転送、閉じる)。- プッシュトゥトーク:遅延なし。ウェイクワード:自動送信のオプション遅延。
- プッシュトゥトーク終了後、ウェイクランタイムに短いクールダウンを適用して即座の再トリガーを防止。
- ログ
- コーディネータがサブシステム
ai.openclaw、カテゴリvoicewake.overlayおよびvoicewake.chimeで.infoログを出力。 - 主要イベント:
session_started、adopted_by_push_to_talk、partial、finalized、send、dismiss、cancel、cooldown。
- コーディネータがサブシステム
デバッグチェックリスト
-
オーバーレイが固着する問題を再現しながらログをストリーム:
sudo log stream --predicate 'subsystem == "ai.openclaw" AND category CONTAINS "voicewake"' --level info --style compact -
アクティブなセッショントークンが1つのみであることを確認。古いコールバックはコーディネータによってドロップされるべき。
-
プッシュトゥトークのリリースが常にアクティブトークンで
endCaptureを呼び出すことを確認。テキストが空の場合、チャイムや送信なしのdismissが期待される。
移行手順(推奨)
VoiceSessionCoordinator、VoiceSession、VoiceSessionPublisherを追加。VoiceWakeRuntimeをリファクタリングし、VoiceWakeOverlayControllerを直接触る代わりにセッションの作成/更新/終了を行うように変更。VoicePushToTalkをリファクタリングし、既存セッションの引き継ぎとリリース時のendCapture呼び出し、ランタイムクールダウンの適用を実装。VoiceWakeOverlayControllerをパブリッシャーに接続。ランタイム/PTTからの直接呼び出しを削除。- セッション引き継ぎ、クールダウン、空テキスト閉じるの統合テストを追加。