# 詳細設計書 この文書は主要クラス・関数の詳細、データ構造、例外ケース、スレッドの振る舞いを記載する。 目次 - Model - Controller - Main (mainloop) - DeviceManager - Utils - Clipboard(クリップボード機能) - Telemetry(テレメトリ機能) - モデルの重みダウンロードと整合性 ## Model - シングルトン: `model = Model()` - 遅延初期化: `init()` と `ensure_initialized()` を備え、init は重いリソース(Overlay, Translator, Watchdog, OSC ハンドラ等)を構築する。 - 主な責務 - 翻訳/文字起こし関連の起動停止ラッパ - Overlay/OSChandler/WebSocket の操作 - キーワード検出(flashtext)と重複検出 - VRAM エラー検出とフォールバック - クリップボード操作(copy/paste) - テレメトリ初期化・シャットダウン - 重要属性(抜粋) - `translator` : Translator インスタンス - `overlay` / `overlay_image` : Overlay 系 - `mic_*`, `speaker_*` : 録音、トランスクリプタ、energy recorder - `watchdog` : Watchdog - `osc_handler`, `websocket_server` - `clipboard` : Clipboard インスタンス(2026-01-11 追加) - `telemetry` : テレメトリシステム(2026-01-11 追加) - スレッド制御 - threadFnc を用いて周期処理を回す。stop/pause/resume が可能。 - Clipboard の VR 監視スレッドはデーモンスレッド(アプリ終了時に強制停止可能) ## Controller - GUI からの要求を受け、Model を操作して結果を run() コールバックへ返す。 - 各種設定変更 (/set/ や /get/ エンドポイント) を実装。 - 翻訳/文字起こし/オーバーレイ連携ロジックを持ち、メッセージ整形(messageFormatter)や OSC の送信を行う。 - ダウンロード作業は別スレッドで行い、進捗を run_mapping を通して通知。 - クリップボード/テレメトリ制御エンドポイント追加(2026-01-11) - `getClipboard()` / `setEnableClipboard()` / `setDisableClipboard()` - `getTelemetry()` / `setEnableTelemetry()` / `setDisableTelemetry()` ## Main (mainloop.Main) - stdin を readline() で受け取り JSON を parse、endpoint と data をキューへ投入。 - worker_count 個の handler スレッドが queue を取り出し `_call_handler` を実行。 - endpoint ロック正規化: `/set/enable/...` と `/set/disable/...` は同じ正規化キー `/lock/set/...` を共有して排他制御。 - エラーレスポンスの標準化と再試行ロジック(status==423 は再キュー化)。 ## DeviceManager - シングルトン。初期化は軽量で、`init()` により内部構造をセット、実デバイスは `update()` で取得。 - Windows 環境では COM イベント (pycaw/MMNotificationClient) を用いた検出か、PyAudio によるポーリングでデバイス一覧を構成。 - コールバック設計: 変更検出時に Controller のコールバックを呼び出して UI 更新を促す。 ## Utils - `validateDictStructure(data, structure)` : JSON 構造検証。 - `getComputeDeviceList()` / `getBestComputeType()` : CPU/CUDA を列挙し、推奨 compute_type を返す。 - `setupLogger()` / `printLog()` / `printResponse()` / `errorLogging()` : ログ、標準出力の整形、エラー記録。 - ネットワーク/ソケット/IP アドレス検査ユーティリティ。 ## Clipboard(クリップボード機能) ### 概要(2026-01-11 追加) VRChat 内でのテキスト送信効率向上のため、翻訳結果をクリップボードにコピーし、自動ペースト機能を提供。 ### 設計 - **シングルトン**: `models.clipboard.clipboard.Clipboard` クラス - **初期化**: `Model.__init__()` で `self.clipboard = Clipboard()` インスタンス化 - **VR監視スレッド**: デーモンスレッドで 10 秒間隔 SteamVR 監視、VRChat アプリ名を自動検出 - **コピー・ペースト**: - `setCopyToClipboard(text: str) -> bool`: 複数バックエンド対応(Windows clip、pyperclip、tkinter) - `setPasteFromClipboard() -> bool`: PyAutoGUI による Ctrl+V 送信、VRChat ウィンドウ自動フォーカス ### 依存ライブラリ - `pyautogui==0.9.54`: キー入力シミュレーション(requirements.txt 追加) - `openvr`: VR アプリ名検出 - `psutil`: プロセス検索 - `pyperclip`(オプション): クリップボード操作フォールバック ### 設定・制御 - `config.ENABLE_CLIPBOARD`: True/False で機能制御 - Controller エンドポイント - `/get/data/clipboard`: 状態取得(`config.ENABLE_CLIPBOARD` の値) - `/set/enable/clipboard`: `config.ENABLE_CLIPBOARD` を True に設定 - `/set/disable/clipboard`: `config.ENABLE_CLIPBOARD` を False に設定 ### 動作フロー 1. Model 初期化時に Clipboard インスタンス生成(VR 監視スレッド起動) 2. Controller が `config.ENABLE_CLIPBOARD == True` をチェック 3. 有効時のみ `model.setCopyToClipboard(result)` と `model.setPasteFromClipboard()` を呼び出し 4. Clipboard インスタンス自体は常に稼働(`clipboard.is_enabled` は常に True) ### エラーハンドリング - コピー失敗: False を返却、リトライなし - ペースト失敗: False を返却 - VR アプリ名検出失敗: app_name = None、現在フォーカスウィンドウにペースト - 例外はログ出力し握りつぶし ## Telemetry(テレメトリ機能) ### 概要(2026-01-11 追加) Aptabase を用いた匿名な使用状況データ収集。デフォルト有効、ユーザー制御可能。 ### 設計 - **デフォルト有効**: `config.ENABLE_TELEMETRY = True` - **初期化**: `model.telemetryInit(enabled=config.ENABLE_TELEMETRY, app_version=config.VERSION)` - **シャットダウン**: `model.telemetryShutdown()` で app_closed イベント送信 - **プライバシー重視**: 個人情報・入力内容・音声データ一切送信なし ### イベント種別(送信固定) - `app_started`: アプリ起動 - `app_closed`: アプリ終了(最後のイベント) - `session_heartbeat`: 5 分間隔アクティブ確認 - `core_feature`: 機能開始(translation / mic_speech_to_text / speaker_speech_to_text / text_input) - `settings_opened`: 設定画面開閉 - `config_changed`: 設定変更 - `error`: エラー発生 ### 動作フロー 1. アプリ起動時に telemetryInit() 呼び出し 2. ユーザーアクティビティ検出時に telemetryTouchActivity() 呼び出し 3. 機能開始時に track_core_feature() で 1 セッション 1 回のみ送信 4. アプリ終了時に telemetryShutdown() で app_closed 送信 5. config.ENABLE_TELEMETRY = False で一切の通信・スレッド停止 ### 設定・制御 - `config.ENABLE_TELEMETRY`: True/False で機能制御 - `model.telemetry.enabled`: 現在の有効状態 - Controller エンドポイント - `/get/data/telemetry`: 状態取得 - `/set/enable/telemetry`: 有効化(telemetryInit 呼び出し) - `/set/disable/telemetry`: 無効化(telemetryShutdown 呼び出し) ### エラーハンドリング - API 通信失敗時: 例外握りつぶし、アプリ動作に影響なし - オフライン時: 機能停止のみ、再送・バッファリングなし - 無効化時: 一切の通信・スレッド・処理停止 ## モデル重みダウンロード - `models.translation.translation_utils` と `models.transcription.transcription_whisper` にダウンロード/チェック関数があり、チェックサムやファイル存在を検証する。 - GUI からの要求は Controller により非同期スレッドで実行され、進捗コールバックが run_mapping を介してフロントエンドに渡る。 ## エッジケース / 例外処理 - 外部 API のレート制限や認証エラーは呼び出し元に 400 系のレスポンスを返し、必要であればフォールバック実装(CTranslate2 への切替)を行う。 - 大きなモデル実行時の VRAM エラーは検出し、当該機能を無効化してユーザへ通知する。 - 音声デバイスが存在しない場合は NoDevice を返し、UI 側で扱う。 ## テスト観点 - メッセージ受信/送信のエンドツーエンド: stdin -> handler -> Controller -> Model -> printResponse の流れ。 - デバイス挙動: DeviceManager.update() がデバイス一覧を取得できるか(PyAudio 経由)。 - モデルダウンロード: ダウンロード成功・失敗、チェックサム検証。 - ログ/エラー: errorLogging() による例外トレースが error.log に記録されるか。