Home

2026-01-31 音声通知統合

音声通知統合 検討メモ

概要

Ghostrunnerの処理(plan/command実行)完了時に、OpenAI Realtime APIを使って音声で通知する機能。通知後も音声で対話を続けられる。

要件

  • トリガー: 処理完了時 + エラー発生時
  • 通知内容: 状況に応じた音声応答 + 対話可能
  • UI: メインページにトグル追加
  • 接続タイミング: トグルONで即接続

案A: MVP(推奨)

概要

メインページにシンプルなトグルを追加し、既存の useOpenAIRealtime フックを活用。

UI設計

[Project path] [Command dropdown] [Args input]
[PR workflow toggle] [音声通知 toggle] ← 新規追加
[Submit button]

トグルON時:

  • Realtime APIに自動接続
  • 処理完了/エラー時に音声で通知
  • マイクボタンを押すと対話モードに移行

実装方針

  1. フック改修: useOpenAIRealtime に「テキスト送信」機能を追加

    • sendText(message: string) で任意のテキストをAIに送信
    • AIが音声で応答
  2. ページ統合: page.tsx でフックを使用

    • handleStreamEventcomplete / errorsendText 呼び出し
    • 完了時: 「処理が完了しました。結果は ${summary} です。詳細を聞きますか?」
    • エラー時: 「エラーが発生しました。${error}。どうしますか?」
  3. UIコンポーネント: トグル + 状態表示

    • 接続状態インジケーター(小さいドット)
    • マイクボタン(対話したい時に押す)

コンポーネント構成

page.tsx
├── CommandForm
│   └── VoiceNotificationToggle(新規)
├── ProgressContainer
└── VoiceNotificationWidget(新規)
    ├── 接続状態表示
    ├── マイクボタン
    └── useOpenAIRealtime

エフェメラルキー有効期限対策

OpenAIのエフェメラルキーは発行から約1分で失効。対策:

  1. WebSocket切断時に自動再接続

    • onclose イベントで新しいトークンを取得して再接続
    • 指数バックオフで最大3回リトライ
  2. 接続維持用のping(オプション)

    • 30秒ごとに空のメッセージを送信して接続維持

変更ファイル一覧

ファイル変更内容
frontend/src/hooks/useOpenAIRealtime.tssendText 関数追加、自動再接続ロジック
frontend/src/components/VoiceNotificationWidget.tsx新規作成: トグル + 状態表示 + マイク
frontend/src/app/page.tsxウィジェット統合、完了/エラー時の通知呼び出し

実装ステップ

  1. useOpenAIRealtimesendText 関数を追加
  2. 自動再接続ロジックを追加
  3. VoiceNotificationWidget コンポーネント作成
  4. page.tsx に統合
  5. 完了/エラー時の通知メッセージ実装

案B: 高機能版(将来拡張)

案Aの拡張として、以下を追加:

  • フローティングウィジェット: 画面隅に常時表示
  • 音声コマンド: 「承認して」「キャンセル」などの音声操作
  • 会話履歴: 過去の通知と会話を表示
  • 複数AI対応: OpenAI / Gemini の切り替え

懸念点と対策

懸念点対策
エフェメラルキーの有効期限(約1分)WebSocket切断時に自動再接続
常時接続のリソース消費トグルOFFで完全切断
マイク権限最初は音声出力のみ、マイクボタン押下で入力開始
API料金待機中は会話がないのでほぼゼロ、通知時のみ課金
ブラウザバックグラウンド時WebSocket維持、ただし音声再生は制限される可能性

通知メッセージ例

処理完了時

処理が完了しました。PRを作成しました。URLは xxx です。
何か質問がありますか?

エラー発生時

エラーが発生しました。ビルドに失敗したようです。
詳細を確認しますか?

質問待ち状態

Claudeから質問があります。
「認証方式はどれにしますか?OAuth、JWT、セッションから選んでください」
どれにしますか?

次のステップ

  1. /plan で詳細な実装計画を作成
  2. useOpenAIRealtime の改修
  3. UIコンポーネント実装
  4. 統合テスト

参考

  • 現在の処理完了検知: page.tsxhandleStreamEventcomplete イベント
  • 既存の音声AI: /openai-realtime ページ、useOpenAIRealtime フック