Merge branch 'docs' into develop

This commit is contained in:
misyaguziya
2026-01-11 08:55:45 +09:00
6 changed files with 445 additions and 1 deletions

View File

@@ -0,0 +1,250 @@
# Clipboard 機能設計書
## 概要
VRCT のクリップボード機能は、VRChat 内でのテキスト送信効率を向上させるため、翻訳結果をクリップボードにコピーし、ペースト機能を提供します。
## 主要機能
### 1. テキストコピー
- 翻訳結果をシステムクリップボードにコピー
- 複数のバックエンド対応Windows clip、pyperclip、tkinter
- UTF-16LE BOM 対応でクロスプラットフォーム互換性を確保
### 2. テキストペースト
- `Ctrl+V` による自動ペースト
- VRChat ウィンドウの自動フォーカス
- カウントダウン機能で準備時間を確保
### 3. VR アプリ検出
- OpenVR を用いた VRChat アプリ名の自動検出
- バックグラウンドスレッドによる非同期監視
- SteamVR の起動を待機・検出
## クラス設計
### Clipboard クラス
```python
class Clipboard:
def __init__(self)
def enable(self) -> None
def disable(self) -> None
def copy(self, message: str) -> bool
def paste(self, window_name: str|None = None, countdown: int = 0) -> bool
```
#### メンバ変数
- `is_enabled`: クリップボード機能の有効/無効状態
- `app_name`: VRChat アプリケーション名(自動検出)
- `_vr_monitor_thread`: SteamVR 監視スレッド
- `_stop_monitoring`: スレッド停止フラグ
### 主要メソッド
#### `__init__()`
初期化処理:
1. VR 監視スレッドを起動
2. SteamVR の起動を待機10秒間隔で確認
#### `enable()`
クリップボード機能を有効化:
1. `is_enabled` フラグを True に設定
2. `_initialize()` を呼び出し VR 監視を再開
#### `disable()`
クリップボード機能を無効化:
1. `is_enabled` フラグを False に設定
2. `_stop_monitoring` フラグを設定しスレッド停止
3. スレッド終了を待機(タイムアウト 1秒
#### `copy(message: str) -> bool`
**パラメータ:**
- `message`: クリップボードにコピーするテキスト
**戻り値:**
- `True`: コピー成功
- `False`: コピー失敗または無効状態
**動作:**
1. `is_enabled` チェック
2. `copy_to_clipboard()` 関数を呼び出し
#### `paste(window_name: str|None = None, countdown: int = 0) -> bool`
**パラメータ:**
- `window_name`: フォーカス対象ウィンドウ(タイトル部分一致 or プロセス名)
- `countdown`: ペースト前の待機秒数
**戻り値:**
- `True`: ペースト送信成功
- `False`: ペースト失敗または無効状態
**動作:**
1. `is_enabled` チェック
2. `window_name` 未指定時は自動検出した VRChat アプリ名を使用
3. Windows 環境下でウィンドウをフォーカス(以下の順序)
- ウィンドウタイトルで部分一致検索
- マッチしない場合、プロセス名で検索
4. ウィンドウフォーカス成功時、`paste_via_pyautogui()` でペースト実行
### 内部メソッド
#### `_initialize()`
VR 監視スレッドの初期化:
1. `_stop_monitoring` を False に設定
2. デーモンスレッドで `_monitor_steamvr()` を起動
#### `_monitor_steamvr()`
バックグラウンドスレッド処理:
1. 10秒間隔で `checkSteamvrRunning()` を確認
2. SteamVR 検出時に `_setup_vr_app_name()` を呼び出し
3. `_stop_monitoring` が True になるまで監視
#### `_setup_vr_app_name()`
OpenVR を用いた VR アプリ名検出:
1. OpenVR 初期化(`VRApplication_Background` モード)
2. すべてのアプリケーション情報を取得
3. `steam.app` で始まるキーを検索し `app_name` に設定
4. 例外発生時は `app_name` を None に設定
## 支援関数
### `checkSteamvrRunning() -> bool`
SteamVR が起動しているかを確認
- プロセス名 `vrmonitor.exe`Windowsまたは `vrmonitor`(その他)を検索
### `copy_to_clipboard(text: str) -> bool`
複数バックエンド対応のコピー関数
1. Windows: `clip` コマンド + UTF-16LE BOM
2. 汎用: `pyperclip` ライブラリ
3. フォールバック: `tkinter` 使用
### `paste_via_pyautogui(countdown: int = 0) -> bool`
PyAutoGUI を用いたペースト
- `pyautogui.hotkey('ctrl', 'v')` で Ctrl+V を送信
- カウントダウン実行
### ウィンドウ検索関数Windows のみ)
#### `find_windows_by_title_substring(substring: str) -> list`
ウィンドウタイトルで部分一致検索
#### `find_windows_by_process_name(proc_name: str) -> list`
プロセス名でウィンドウを検索
#### `focus_window(hwnd) -> bool`
指定ウィンドウをアクティブ化
## 依存ライブラリ
| ライブラリ | 用途 | オプション |
|-----------|------|----------|
| pyautogui | キー入力シミュレーション | 必須(ペースト機能) |
| pyperclip | クリップボード操作 | オプション(フォールバック) |
| tkinter | クリップボード操作 | オプション(フォールバック) |
| openvr | VR アプリ名検出 | 必須 |
| psutil | プロセス検索 | 必須 |
## 動作フロー
### 初期化フロー
```
Clipboard.__init__()
└─ _initialize()
└─ スレッド起動: _monitor_steamvr()
└─ 10秒間隔で SteamVR 監視
└─ 検出時: _setup_vr_app_name()
└─ VRChat アプリ名を app_name に設定
```
### コピー・ペーストフロー
```
Model.setCopyToClipboard(text)
└─ clipboard.copy(text)
└─ copy_to_clipboard(text) [成功/失敗]
Model.setPasteFromClipboard()
└─ clipboard.paste(window_name=self.app_name)
└─ find_windows_by_title_substring() [Windows]
or find_windows_by_process_name()
└─ focus_window(hwnd)
└─ paste_via_pyautogui(countdown)
```
## 有効/無効制御
### コンフィグ設定
- `config.ENABLE_CLIPBOARD`: True/False でクリップボード機能を制御
- Controller 側で `config.ENABLE_CLIPBOARD` をチェックし、True の場合のみ `setCopyToClipboard()``setPasteFromClipboard()` を呼び出し
### 制御メソッドClipboard クラス内部)
```python
# 有効化内部API、通常は使用しない
clipboard.enable()
# 無効化内部API、通常は使用しない
clipboard.disable()
```
**注意**: 現在の実装では、Controller は `clipboard.enable()/disable()` を呼び出さず、`config.ENABLE_CLIPBOARD` フラグのみで制御します。Clipboard インスタンスは常に初期化されており、VR 監視スレッドも稼働し続けます。
### API エンドポイントController
```
/get/data/clipboard - 現在の有効/無効状態を取得
/set/enable/clipboard - config.ENABLE_CLIPBOARD を True に設定
/set/disable/clipboard - config.ENABLE_CLIPBOARD を False に設定
```
## エラーハンドリング
### 失敗時の動作
- コピー失敗: `False` を返却、リトライなし
- ペースト失敗: `False` を返却、リトライなし
- VR アプリ名検出失敗: `app_name` を None に設定、現在フォーカス中のウィンドウにペースト
### 例外処理
- OpenVR 初期化失敗時は `app_name = None` に設定
- プロセス検索例外も握りつぶし
- ウィンドウフォーカス失敗はログのみ出力
## パフォーマンス考慮
### スレッド設計
- VR 監視スレッドは **デーモンスレッド**(アプリ終了時の強制停止可能)
- 10秒間隔で監視CPU 負荷最小化)
### クリップボード操作
- コピー・ペースト操作はメインスレッド実行
- ウィンドウフォーカス後に 0.2秒スリープで安定性向上
## セキュリティ・プライバシー
### データ保護
- クリップボードデータは一切ログ出力されない
- VR アプリ名のみ app_name として保持
### OS 依存性
- Windows: `clip` コマンド、ctypes によるウィンドウ制御
- その他 OS: pyperclip/tkinter フォールバック、自動フォーカス機能なし
## 制限事項・既知の問題
1. **非 Windows 環境**
- ウィンドウフォーカス機能は Windows のみ対応
- その他 OS では現在フォーカス中のウィンドウにペースト
2. **VRChat アプリ名検出**
- OpenVR が利用可能で SteamVR が起動している必要がある
- `steam.app` 接頭辞のアプリのみ認識
3. **PyAutoGUI の制限**
- キー入力シミュレーションはOS依存
- 一部アプリケーションではセキュリティ制限により失敗する可能性あり
4. **クリップボードバッファ**
- Ctrl+V 送信のタイミングはユーザー判断(カウントダウン機能あり)
- クリップボード内容の永続化はしない
## 参考資料
- [PyAutoGUI 公式ドキュメント](https://pyautogui.readthedocs.io/)
- [OpenVR Python バインディング](https://github.com/ValvePython/openvr)
- [psutil ドキュメント](https://psutil.readthedocs.io/)

View File

@@ -189,6 +189,24 @@ def WEBSOCKET_PORT(self) -> int
``` ```
- WebSocketサーバーポート - WebSocketサーバーポート
### クリップボード設定
```python
@property
def ENABLE_CLIPBOARD(self) -> bool
```
- クリップボード機能(コピー・ペースト)の有効・無効
### テレメトリ設定
```python
@property
def ENABLE_TELEMETRY(self) -> bool
```
- テレメトリAptabaseの有効・無効
- デフォルト: True有効
- ユーザーは設定から任意で無効化可能
### 計算デバイス設定 ### 計算デバイス設定
```python ```python
@@ -341,6 +359,12 @@ config.saveConfig("ENABLE_TRANSLATION", True, immediate_save=True)
- WebSocket ホスト: "127.0.0.1" - WebSocket ホスト: "127.0.0.1"
- WebSocket ポート: 8765 - WebSocket ポート: 8765
### クリップボード設定
- クリップボード機能: 無効
### テレメトリ設定
- テレメトリ: **有効(デフォルト)**
## 依存関係 ## 依存関係
### 必須依存関係 ### 必須依存関係

View File

@@ -247,12 +247,39 @@ setDisableWebSocketServer(data) -> dict
- WebSocketサーバーの制御 - WebSocketサーバーの制御
### クリップボード制御
```python
getClipboard() -> dict
setEnableClipboard() -> dict
setDisableClipboard() -> dict
```
- クリップボード機能(コピー・ペースト)の状態取得・設定変更
- `config.ENABLE_CLIPBOARD` フラグを変更True/False
- 取得結果は `{"status": 200, "result": bool}`
- **注意**: `model.clipboard.enable()/disable()` は呼び出されません
### テレメトリ制御
```python
getTelemetry() -> dict
setEnableTelemetry() -> dict
setDisableTelemetry() -> dict
```
- テレメトリAptabaseの有効化・無効化・状態取得
- 有効化時は `telemetryInit()` を呼び出し
- 無効化時は `telemetryShutdown()` を呼び出し
### WebSocket接続設定
```python ```python
setWebSocketHost(data) -> dict setWebSocketHost(data) -> dict
setWebSocketPort(data) -> dict setWebSocketPort(data) -> dict
``` ```
- WebSocket接続設定 - WebSocketホスト・ポートの設定
### システム管理 ### システム管理

View File

@@ -125,6 +125,18 @@ class Main:
- `/set/data/websocket_host`: サーバーホスト設定 - `/set/data/websocket_host`: サーバーホスト設定
- `/set/data/websocket_port`: サーバーポート設定 - `/set/data/websocket_port`: サーバーポート設定
### クリップボード機能
- `/get/data/clipboard`: クリップボード機能の状態取得(`config.ENABLE_CLIPBOARD` の値)
- `/set/enable/clipboard`: `config.ENABLE_CLIPBOARD` を True に設定
- `/set/disable/clipboard`: `config.ENABLE_CLIPBOARD` を False に設定
### テレメトリ機能
- `/get/data/telemetry`: テレメトリの状態取得
- `/set/enable/telemetry`: テレメトリの有効化Aptabase初期化
- `/set/disable/telemetry`: テレメトリの無効化(シャットダウン)
### システム管理 ### システム管理
- `/run/update_software`: ソフトウェアアップデート - `/run/update_software`: ソフトウェアアップデート

View File

@@ -4,6 +4,25 @@
VRCTアプリケーションの中核となるModelクラスを定義するモジュールです。音声認識、翻訳、VRオーバーレイ、OSC通信、WebSocketサーバーなどの主要機能を統合管理し、システム全体の動作を制御します。 VRCTアプリケーションの中核となるModelクラスを定義するモジュールです。音声認識、翻訳、VRオーバーレイ、OSC通信、WebSocketサーバーなどの主要機能を統合管理し、システム全体の動作を制御します。
## 最近の更新 (2026-01-11)
### クリップボード機能
- `clipboard` インスタンスを Model 内に保持
- `setCopyToClipboard(text: str) -> bool`: 翻訳結果をクリップボードにコピー
- `setPasteFromClipboard() -> bool`: Ctrl+V でペースト実行VRChat ウィンドウ自動フォーカス)
- OpenVR による VRChat アプリ名の自動検出
### テレメトリ機能
- `telemetryInit(enabled: bool, app_version: str)`: Aptabase を用いたテレメトリ初期化
- `telemetryShutdown()`: テレメトリのシャットダウンapp_closed イベント送信)
- `telemetryTouchActivity()`: ユーザーアクティビティの記録
- `telemetry.*()`: イベント送信メソッド群
- デフォルト有効、ユーザー制御可能な設計
### その他の更新
## 最近の更新 (2025-10-20) ## 最近の更新 (2025-10-20)
### VRAMエラー検出とフォールバック ### VRAMエラー検出とフォールバック
@@ -315,6 +334,30 @@ message = {"type": "translation", "text": "Hello", "translation": "こんにち
success = model.websocketSendMessage(message) success = model.websocketSendMessage(message)
``` ```
### クリップボード機能の使用
```python
# テキストをクリップボードにコピー
text = "翻訳結果"
success = model.setCopyToClipboard(text)
# ペースト実行VRChat ウィンドウに自動フォーカス)
success = model.setPasteFromClipboard()
```
### テレメトリの初期化・シャットダウン
```python
# テレメトリ初期化(アプリ起動時)
model.telemetryInit(enabled=config.ENABLE_TELEMETRY, app_version=config.VERSION)
# テレメトリシャットダウン(アプリ終了時)
model.telemetryShutdown()
# アクティビティ記録
model.telemetryTouchActivity()
```
## 依存関係 ## 依存関係
### 必須モジュール ### 必須モジュール

View File

@@ -8,6 +8,8 @@
- Main (mainloop) - Main (mainloop)
- DeviceManager - DeviceManager
- Utils - Utils
- Clipboardクリップボード機能
- Telemetryテレメトリ機能
- モデルの重みダウンロードと整合性 - モデルの重みダウンロードと整合性
## Model ## Model
@@ -18,20 +20,28 @@
- Overlay/OSChandler/WebSocket の操作 - Overlay/OSChandler/WebSocket の操作
- キーワード検出flashtextと重複検出 - キーワード検出flashtextと重複検出
- VRAM エラー検出とフォールバック - VRAM エラー検出とフォールバック
- クリップボード操作copy/paste
- テレメトリ初期化・シャットダウン
- 重要属性(抜粋) - 重要属性(抜粋)
- `translator` : Translator インスタンス - `translator` : Translator インスタンス
- `overlay` / `overlay_image` : Overlay 系 - `overlay` / `overlay_image` : Overlay 系
- `mic_*`, `speaker_*` : 録音、トランスクリプタ、energy recorder - `mic_*`, `speaker_*` : 録音、トランスクリプタ、energy recorder
- `watchdog` : Watchdog - `watchdog` : Watchdog
- `osc_handler`, `websocket_server` - `osc_handler`, `websocket_server`
- `clipboard` : Clipboard インスタンス2026-01-11 追加)
- `telemetry` : テレメトリシステム2026-01-11 追加)
- スレッド制御 - スレッド制御
- threadFnc を用いて周期処理を回す。stop/pause/resume が可能。 - threadFnc を用いて周期処理を回す。stop/pause/resume が可能。
- Clipboard の VR 監視スレッドはデーモンスレッド(アプリ終了時に強制停止可能)
## Controller ## Controller
- GUI からの要求を受け、Model を操作して結果を run() コールバックへ返す。 - GUI からの要求を受け、Model を操作して結果を run() コールバックへ返す。
- 各種設定変更 (/set/ や /get/ エンドポイント) を実装。 - 各種設定変更 (/set/ や /get/ エンドポイント) を実装。
- 翻訳/文字起こし/オーバーレイ連携ロジックを持ち、メッセージ整形messageFormatterや OSC の送信を行う。 - 翻訳/文字起こし/オーバーレイ連携ロジックを持ち、メッセージ整形messageFormatterや OSC の送信を行う。
- ダウンロード作業は別スレッドで行い、進捗を run_mapping を通して通知。 - ダウンロード作業は別スレッドで行い、進捗を run_mapping を通して通知。
- クリップボード/テレメトリ制御エンドポイント追加2026-01-11
- `getClipboard()` / `setEnableClipboard()` / `setDisableClipboard()`
- `getTelemetry()` / `setEnableTelemetry()` / `setDisableTelemetry()`
## Main (mainloop.Main) ## Main (mainloop.Main)
- stdin を readline() で受け取り JSON を parse、endpoint と data をキューへ投入。 - stdin を readline() で受け取り JSON を parse、endpoint と data をキューへ投入。
@@ -50,6 +60,84 @@
- `setupLogger()` / `printLog()` / `printResponse()` / `errorLogging()` : ログ、標準出力の整形、エラー記録。 - `setupLogger()` / `printLog()` / `printResponse()` / `errorLogging()` : ログ、標準出力の整形、エラー記録。
- ネットワーク/ソケット/IP アドレス検査ユーティリティ。 - ネットワーク/ソケット/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` にダウンロード/チェック関数があり、チェックサムやファイル存在を検証する。 - `models.translation.translation_utils``models.transcription.transcription_whisper` にダウンロード/チェック関数があり、チェックサムやファイル存在を検証する。
- GUI からの要求は Controller により非同期スレッドで実行され、進捗コールバックが run_mapping を介してフロントエンドに渡る。 - GUI からの要求は Controller により非同期スレッドで実行され、進捗コールバックが run_mapping を介してフロントエンドに渡る。