chenpi 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chenpi-0.1.0/LICENSE +21 -0
- chenpi-0.1.0/LICENSES/cc3dsfs.txt +21 -0
- chenpi-0.1.0/PKG-INFO +204 -0
- chenpi-0.1.0/README.md +182 -0
- chenpi-0.1.0/pyproject.toml +43 -0
- chenpi-0.1.0/pyproject.toml.orig +39 -0
- chenpi-0.1.0/src/chenpi/USAGE.md +135 -0
- chenpi-0.1.0/src/chenpi/__init__.py +21 -0
- chenpi-0.1.0/src/chenpi/__main__.py +148 -0
- chenpi-0.1.0/src/chenpi/capture.py +479 -0
- chenpi-0.1.0/src/chenpi/devices.py +74 -0
- chenpi-0.1.0/src/chenpi/firmware.py +111 -0
- chenpi-0.1.0/src/chenpi/optimize3ds.py +940 -0
- chenpi-0.1.0/src/chenpi/py.typed +0 -0
- chenpi-0.1.0/src/chenpi/virtualcam.py +65 -0
chenpi-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lizz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Lorenzooone
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
chenpi-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chenpi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Read DS/3DS capture boards (Loopy DS, Optimize Old 3DS) as OpenCV/numpy images on Windows
|
|
5
|
+
Author: Lizz
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
License-File: LICENSES/cc3dsfs.txt
|
|
9
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Topic :: Multimedia :: Video :: Capture
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Requires-Dist: numpy>=1.26
|
|
15
|
+
Requires-Dist: opencv-python>=4.9
|
|
16
|
+
Requires-Dist: sounddevice>=0.5.6 ; extra == 'audio'
|
|
17
|
+
Requires-Dist: pyvirtualcam>=0.15.0 ; extra == 'virtualcam'
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Provides-Extra: audio
|
|
20
|
+
Provides-Extra: virtualcam
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# chenpi
|
|
24
|
+
|
|
25
|
+
**chenpi** (陳皮) は、DS / 3DS 用キャプチャ機器の映像・音声を、公式ビューアやウィンドウキャプチャを使わずに
|
|
26
|
+
numpy / OpenCV の画像として直接取り込むための Windows 用ライブラリです。
|
|
27
|
+
`cv2.VideoCapture` と同じ `read()` で読めるので、OpenCV 前提のコードにそのまま渡せます。
|
|
28
|
+
[cc3dsfs](https://github.com/Lorenzooone/cc3dsfs) (MIT License) の処理を Python に移植しています。
|
|
29
|
+
|
|
30
|
+
| 機種 | 映像 | 音声 | 備考 |
|
|
31
|
+
|---|---|---|---|
|
|
32
|
+
| 新型 Loopy DS キャプチャ (USB Type-C 版) | 256x192 × 2 画面 / 60fps | あり | |
|
|
33
|
+
| Optimize 3DS キャプチャ (Old 3DS 用) | 400x240 + 320x240 / 60fps | あり | 公式ソフトのプロダクトキーが必要 |
|
|
34
|
+
|
|
35
|
+
Optimize の New 3DS 用 / 2DS 用、RGB888、3D 表示、Loopy 製 3DS キャプチャには未対応です。
|
|
36
|
+
|
|
37
|
+
## 準備
|
|
38
|
+
|
|
39
|
+
1. **ドライバ**: 各機器の公式ソフトに付属するドライバをそのまま使います (公式ソフトが動く環境なら導入済み)。
|
|
40
|
+
- Loopy DS: FTDI の D2XX ドライバ
|
|
41
|
+
- Optimize 3DS: 公式ドライバ (NSTDUSB3)
|
|
42
|
+
- Zadig などで WinUSB に差し替えると動きません。
|
|
43
|
+
2. **インストール**
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
uv add "chenpi[audio,virtualcam]" # 別のプロジェクトから使う場合 (pip install でも可。音声・仮想カメラが不要なら [] は省略)
|
|
47
|
+
uv sync # このリポジトリで開発する場合
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
3. **ファームウェアの取得**: 基板に書き込むファームウェアは同梱していないので、cc3dsfs から取得します
|
|
51
|
+
(理由は[ファームウェアについて](#ファームウェアについて))。ビューアは、無ければ取得してよいか尋ねます。
|
|
52
|
+
|
|
53
|
+
```powershell
|
|
54
|
+
uv run scripts/fetch_firmware.py # %LOCALAPPDATA%\chenpi\firmware に保存
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
4. **Optimize 3DS のプロダクトキー**: `--key` か環境変数 `OPTIMIZE_3DS_KEY` で渡します (カンマ区切りで複数可)。
|
|
58
|
+
|
|
59
|
+
```powershell
|
|
60
|
+
setx OPTIMIZE_3DS_KEY "XXXX-XXXX-XXXX-XXXX-XXXX" # VS Code / ターミナルを開き直すと有効
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
公式ソフトや cc3dsfs とは同時に使えません。先に閉じてください。
|
|
64
|
+
|
|
65
|
+
## ビューアで試す
|
|
66
|
+
|
|
67
|
+
```powershell
|
|
68
|
+
uv run chenpi-view --list # 接続されている機器の一覧
|
|
69
|
+
uv run chenpi-view # 見つかった機器を表示 (q で終了)
|
|
70
|
+
uv run chenpi-view --device 3ds --audio # 機種を指定し、音声も再生 (+ / - キーで音量)
|
|
71
|
+
uv run chenpi-view --layout horizontal --scale 3
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
| オプション | 内容 |
|
|
75
|
+
|---|---|
|
|
76
|
+
| `--device auto\|ds\|3ds` | 機種 (既定 `auto`: DS → 3DS の順に探す) |
|
|
77
|
+
| `--key` | Optimize 3DS のプロダクトキー |
|
|
78
|
+
| `--layout vertical\|horizontal\|top\|bottom` | 画面の並べ方 |
|
|
79
|
+
| `--scale` | 表示の拡大率 (既定 2) |
|
|
80
|
+
| `--audio` / `--volume` / `--audio-latency` | 音声の再生 / 音量の倍率 / 出力バッファ (秒) |
|
|
81
|
+
|
|
82
|
+
## ライブラリとして使う
|
|
83
|
+
|
|
84
|
+
### OpenCV と同じように読む
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from chenpi import open_capture
|
|
88
|
+
|
|
89
|
+
with open_capture("auto", layout="vertical") as cap: # "ds" / "3ds" も指定できる
|
|
90
|
+
ok, frame = cap.read() # BGR uint8。vertical なら DS は 256x384、3DS は 400x480 (下画面の左右は黒帯)
|
|
91
|
+
audio = cap.read_audio() # 前回以降の音声 int16 (N, 2) [L, R]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
機種ごとのクラス (`LoopyDSCapture` / `Optimize3DSCapture`) を直接使うこともできます。
|
|
95
|
+
|
|
96
|
+
API の一覧・frame の大きさ・例外・注意点は [src/chenpi/USAGE.md](src/chenpi/USAGE.md) にまとめてあります。
|
|
97
|
+
このファイルはパッケージにも入るので、chenpi を使う別のプロジェクトでは、その CLAUDE.md などに次のように書いておくと、
|
|
98
|
+
コーディングエージェントが正しい使い方を参照できます。
|
|
99
|
+
|
|
100
|
+
```markdown
|
|
101
|
+
- キャプチャには chenpi を使う。使い方は `.venv/Lib/site-packages/chenpi/USAGE.md` を読むこと。
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 機器の一覧から選んで開く (GUI 向け)
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from chenpi import list_devices, open_device
|
|
108
|
+
|
|
109
|
+
infos = list_devices() # 機器には触らずに一覧だけ返す (ファーム書き込みなどはしない)
|
|
110
|
+
for info in infos:
|
|
111
|
+
print(info, info.available) # 例: "Optimize Old 3DS [使用中]" False
|
|
112
|
+
cap = open_device(infos[0], key=["XXXX-...", "YYYY-..."]) # 3DS は保存してあるキーを全部渡せば合うものを使う
|
|
113
|
+
print(cap.serial) # 3DS ならデバイス ID。キーとの対応を保存しておくとよい
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- `info.status` は `ready` / `in_use` (他のプログラムが使用中) / `replug` (公式ソフト使用後で USB の抜き差しが必要)。
|
|
117
|
+
- Optimize 3DS のデバイス ID は開くまで分からないので、一覧では `info.id` が `None` です。
|
|
118
|
+
挿した直後は「未初期化」と表示されます (Old 3DS 用 / New 3DS v2 用 / 2DS 用の区別は付きません)。
|
|
119
|
+
- Optimize を 2 台つないでいても、キーの合う空いている方が開きます。
|
|
120
|
+
- 同じ機器を 2 つのプログラムで同時に開くことはできません (cc3dsfs との間でも)。
|
|
121
|
+
- 使用中の Loopy DS は、ID (シリアル) が大文字で表示されます (Windows の記録による)。比べるときは大文字小文字を区別しないでください。
|
|
122
|
+
|
|
123
|
+
### 音声
|
|
124
|
+
|
|
125
|
+
- DS・3DS とも `SAMPLE_RATE` (≒ 32728.5 Hz) のステレオ int16 です。
|
|
126
|
+
- `read_audio()` は待たずに、溜まっている分を全部返します (読まれない分は約 2 秒で古い順に捨てます)。
|
|
127
|
+
- 音量は `cap.volume` (倍率、既定 1.0) で変えられ、`read_audio()` の結果にかかります。再生中に変えてもすぐ反映されます。
|
|
128
|
+
1.0 より大きくすると増幅し、int16 をはみ出す分は頭打ちになります。GUI のスライダーなら `cap.volume = value / 100` のように使えます。
|
|
129
|
+
|
|
130
|
+
### GUI に組み込むときの注意
|
|
131
|
+
|
|
132
|
+
- **ファームウェアが無いとき**は `FirmwareMissing` (足りないファイル名は `e.names`) になります。
|
|
133
|
+
勝手にダウンロードせず、利用者に確認してから取得してください。
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from chenpi import FirmwareMissing, download_firmware, open_device
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
cap = open_device(info, key=keys)
|
|
140
|
+
except FirmwareMissing as e:
|
|
141
|
+
if ask_user(f"{e.names} を cc3dsfs から取得しますか?"):
|
|
142
|
+
download_firmware()
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
- **CPU 使用率**: 毎フレーム OpenCV で拡大や表示をするなら、アプリの最初で `cv2.setNumThreads(1)` を呼んでください。
|
|
146
|
+
OpenCV は小さな処理も複数スレッドに分け、その後スレッドが空回りするため、ビューアでは 1 コアの約 9 割 → 約 3 割に下がりました。
|
|
147
|
+
プロセス全体の設定なので、ライブラリ側では変えていません。
|
|
148
|
+
- `read()` は新しいフレームが来るまで待つので、GUI のメインスレッドではなく別スレッドで回してください。
|
|
149
|
+
- 機器を切り替えるときは、先に `cap.release()` を呼んでください。
|
|
150
|
+
- 受信中に USB が抜かれると、`read()` が `(False, None)` を返し、`cap.isOpened()` が False になります (固まりません)。
|
|
151
|
+
|
|
152
|
+
## 仮想カメラ
|
|
153
|
+
|
|
154
|
+
OBS Studio (OBS Virtual Camera) が入っていれば、普通の Web カメラとして他のアプリから使えます。
|
|
155
|
+
OBS 側の「仮想カメラ開始」は止めておいてください (同時には使えません)。
|
|
156
|
+
|
|
157
|
+
```powershell
|
|
158
|
+
uv run chenpi-virtualcam --device 3ds # --layout / --scale / --audio / --key もビューアと同じ
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
import cv2
|
|
163
|
+
cap = cv2.VideoCapture(3, cv2.CAP_DSHOW) # 番号は環境による (OBS Virtual Camera の番号)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
仮想カメラには音声は乗りません (OBS Virtual Camera は映像のみ)。
|
|
167
|
+
|
|
168
|
+
## 機種ごとの注意
|
|
169
|
+
|
|
170
|
+
### Optimize 3DS
|
|
171
|
+
|
|
172
|
+
- 公式ソフトを使った後は、USB を抜き差ししてから開いてください (公式ソフトが別のファームウェアを書き込むため)。
|
|
173
|
+
- 3DS 本体の「本体設定 → その他の設定 → サウンド」は **ステレオ** にしてください。
|
|
174
|
+
サラウンドのままだと、スピーカー用のサラウンド処理 (中音域を左右逆位相で混ぜる) がかかった音が届き、PC で聞くとこもって聞こえます。
|
|
175
|
+
- 本体の音量スライダーはキャプチャの音には効きません。`cap.volume` か PC 側で調整してください。
|
|
176
|
+
|
|
177
|
+
### Loopy DS
|
|
178
|
+
|
|
179
|
+
- DS 本体の電源が切れていると、開くことはできますが映像が届きません (ビューアは「信号待ち」と表示します)。
|
|
180
|
+
|
|
181
|
+
## ファームウェアについて
|
|
182
|
+
|
|
183
|
+
キャプチャ基板に毎回書き込むファームウェア (と Optimize のキー計算用テーブル) は、このライブラリに **同梱していません**。
|
|
184
|
+
これらは cc3dsfs で公開されているファイルですが、cc3dsfs の MIT ライセンスの対象外で、著作権は各メーカーにあります
|
|
185
|
+
(Loopy DS 用は Loopy 社提供、Optimize 用は non-standard)。利用者自身が cc3dsfs から取得してください。
|
|
186
|
+
|
|
187
|
+
- 取得元は動作確認した cc3dsfs のコミットに固定していて、SHA-256 が合わないファイルは保存しません。
|
|
188
|
+
- 探す場所は、引数 `firmware_dir` → 環境変数 `CHENPI_FIRMWARE_DIR` → `./firmware` → このリポジトリの `firmware/` →
|
|
189
|
+
`%LOCALAPPDATA%\chenpi\firmware` の順です。
|
|
190
|
+
|
|
191
|
+
## 開発
|
|
192
|
+
|
|
193
|
+
```powershell
|
|
194
|
+
uv sync
|
|
195
|
+
uv run pytest # 実機不要。ファームウェアが無い環境では、それを読む数件のテストはスキップされる
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
GitHub Actions では、Windows 上でファームウェアを取得してからテストを回します (`.github/workflows/test.yml`)。
|
|
199
|
+
|
|
200
|
+
## ライセンス
|
|
201
|
+
|
|
202
|
+
MIT License ([LICENSE](LICENSE))。
|
|
203
|
+
cc3dsfs の処理を移植しているため、cc3dsfs のライセンス表示を [LICENSES/cc3dsfs.txt](LICENSES/cc3dsfs.txt) に含めています。
|
|
204
|
+
ファームウェアは上記のとおり同梱していません。
|
chenpi-0.1.0/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# chenpi
|
|
2
|
+
|
|
3
|
+
**chenpi** (陳皮) は、DS / 3DS 用キャプチャ機器の映像・音声を、公式ビューアやウィンドウキャプチャを使わずに
|
|
4
|
+
numpy / OpenCV の画像として直接取り込むための Windows 用ライブラリです。
|
|
5
|
+
`cv2.VideoCapture` と同じ `read()` で読めるので、OpenCV 前提のコードにそのまま渡せます。
|
|
6
|
+
[cc3dsfs](https://github.com/Lorenzooone/cc3dsfs) (MIT License) の処理を Python に移植しています。
|
|
7
|
+
|
|
8
|
+
| 機種 | 映像 | 音声 | 備考 |
|
|
9
|
+
|---|---|---|---|
|
|
10
|
+
| 新型 Loopy DS キャプチャ (USB Type-C 版) | 256x192 × 2 画面 / 60fps | あり | |
|
|
11
|
+
| Optimize 3DS キャプチャ (Old 3DS 用) | 400x240 + 320x240 / 60fps | あり | 公式ソフトのプロダクトキーが必要 |
|
|
12
|
+
|
|
13
|
+
Optimize の New 3DS 用 / 2DS 用、RGB888、3D 表示、Loopy 製 3DS キャプチャには未対応です。
|
|
14
|
+
|
|
15
|
+
## 準備
|
|
16
|
+
|
|
17
|
+
1. **ドライバ**: 各機器の公式ソフトに付属するドライバをそのまま使います (公式ソフトが動く環境なら導入済み)。
|
|
18
|
+
- Loopy DS: FTDI の D2XX ドライバ
|
|
19
|
+
- Optimize 3DS: 公式ドライバ (NSTDUSB3)
|
|
20
|
+
- Zadig などで WinUSB に差し替えると動きません。
|
|
21
|
+
2. **インストール**
|
|
22
|
+
|
|
23
|
+
```powershell
|
|
24
|
+
uv add "chenpi[audio,virtualcam]" # 別のプロジェクトから使う場合 (pip install でも可。音声・仮想カメラが不要なら [] は省略)
|
|
25
|
+
uv sync # このリポジトリで開発する場合
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
3. **ファームウェアの取得**: 基板に書き込むファームウェアは同梱していないので、cc3dsfs から取得します
|
|
29
|
+
(理由は[ファームウェアについて](#ファームウェアについて))。ビューアは、無ければ取得してよいか尋ねます。
|
|
30
|
+
|
|
31
|
+
```powershell
|
|
32
|
+
uv run scripts/fetch_firmware.py # %LOCALAPPDATA%\chenpi\firmware に保存
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
4. **Optimize 3DS のプロダクトキー**: `--key` か環境変数 `OPTIMIZE_3DS_KEY` で渡します (カンマ区切りで複数可)。
|
|
36
|
+
|
|
37
|
+
```powershell
|
|
38
|
+
setx OPTIMIZE_3DS_KEY "XXXX-XXXX-XXXX-XXXX-XXXX" # VS Code / ターミナルを開き直すと有効
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
公式ソフトや cc3dsfs とは同時に使えません。先に閉じてください。
|
|
42
|
+
|
|
43
|
+
## ビューアで試す
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
uv run chenpi-view --list # 接続されている機器の一覧
|
|
47
|
+
uv run chenpi-view # 見つかった機器を表示 (q で終了)
|
|
48
|
+
uv run chenpi-view --device 3ds --audio # 機種を指定し、音声も再生 (+ / - キーで音量)
|
|
49
|
+
uv run chenpi-view --layout horizontal --scale 3
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| オプション | 内容 |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `--device auto\|ds\|3ds` | 機種 (既定 `auto`: DS → 3DS の順に探す) |
|
|
55
|
+
| `--key` | Optimize 3DS のプロダクトキー |
|
|
56
|
+
| `--layout vertical\|horizontal\|top\|bottom` | 画面の並べ方 |
|
|
57
|
+
| `--scale` | 表示の拡大率 (既定 2) |
|
|
58
|
+
| `--audio` / `--volume` / `--audio-latency` | 音声の再生 / 音量の倍率 / 出力バッファ (秒) |
|
|
59
|
+
|
|
60
|
+
## ライブラリとして使う
|
|
61
|
+
|
|
62
|
+
### OpenCV と同じように読む
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from chenpi import open_capture
|
|
66
|
+
|
|
67
|
+
with open_capture("auto", layout="vertical") as cap: # "ds" / "3ds" も指定できる
|
|
68
|
+
ok, frame = cap.read() # BGR uint8。vertical なら DS は 256x384、3DS は 400x480 (下画面の左右は黒帯)
|
|
69
|
+
audio = cap.read_audio() # 前回以降の音声 int16 (N, 2) [L, R]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
機種ごとのクラス (`LoopyDSCapture` / `Optimize3DSCapture`) を直接使うこともできます。
|
|
73
|
+
|
|
74
|
+
API の一覧・frame の大きさ・例外・注意点は [src/chenpi/USAGE.md](src/chenpi/USAGE.md) にまとめてあります。
|
|
75
|
+
このファイルはパッケージにも入るので、chenpi を使う別のプロジェクトでは、その CLAUDE.md などに次のように書いておくと、
|
|
76
|
+
コーディングエージェントが正しい使い方を参照できます。
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
- キャプチャには chenpi を使う。使い方は `.venv/Lib/site-packages/chenpi/USAGE.md` を読むこと。
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 機器の一覧から選んで開く (GUI 向け)
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from chenpi import list_devices, open_device
|
|
86
|
+
|
|
87
|
+
infos = list_devices() # 機器には触らずに一覧だけ返す (ファーム書き込みなどはしない)
|
|
88
|
+
for info in infos:
|
|
89
|
+
print(info, info.available) # 例: "Optimize Old 3DS [使用中]" False
|
|
90
|
+
cap = open_device(infos[0], key=["XXXX-...", "YYYY-..."]) # 3DS は保存してあるキーを全部渡せば合うものを使う
|
|
91
|
+
print(cap.serial) # 3DS ならデバイス ID。キーとの対応を保存しておくとよい
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- `info.status` は `ready` / `in_use` (他のプログラムが使用中) / `replug` (公式ソフト使用後で USB の抜き差しが必要)。
|
|
95
|
+
- Optimize 3DS のデバイス ID は開くまで分からないので、一覧では `info.id` が `None` です。
|
|
96
|
+
挿した直後は「未初期化」と表示されます (Old 3DS 用 / New 3DS v2 用 / 2DS 用の区別は付きません)。
|
|
97
|
+
- Optimize を 2 台つないでいても、キーの合う空いている方が開きます。
|
|
98
|
+
- 同じ機器を 2 つのプログラムで同時に開くことはできません (cc3dsfs との間でも)。
|
|
99
|
+
- 使用中の Loopy DS は、ID (シリアル) が大文字で表示されます (Windows の記録による)。比べるときは大文字小文字を区別しないでください。
|
|
100
|
+
|
|
101
|
+
### 音声
|
|
102
|
+
|
|
103
|
+
- DS・3DS とも `SAMPLE_RATE` (≒ 32728.5 Hz) のステレオ int16 です。
|
|
104
|
+
- `read_audio()` は待たずに、溜まっている分を全部返します (読まれない分は約 2 秒で古い順に捨てます)。
|
|
105
|
+
- 音量は `cap.volume` (倍率、既定 1.0) で変えられ、`read_audio()` の結果にかかります。再生中に変えてもすぐ反映されます。
|
|
106
|
+
1.0 より大きくすると増幅し、int16 をはみ出す分は頭打ちになります。GUI のスライダーなら `cap.volume = value / 100` のように使えます。
|
|
107
|
+
|
|
108
|
+
### GUI に組み込むときの注意
|
|
109
|
+
|
|
110
|
+
- **ファームウェアが無いとき**は `FirmwareMissing` (足りないファイル名は `e.names`) になります。
|
|
111
|
+
勝手にダウンロードせず、利用者に確認してから取得してください。
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from chenpi import FirmwareMissing, download_firmware, open_device
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
cap = open_device(info, key=keys)
|
|
118
|
+
except FirmwareMissing as e:
|
|
119
|
+
if ask_user(f"{e.names} を cc3dsfs から取得しますか?"):
|
|
120
|
+
download_firmware()
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
- **CPU 使用率**: 毎フレーム OpenCV で拡大や表示をするなら、アプリの最初で `cv2.setNumThreads(1)` を呼んでください。
|
|
124
|
+
OpenCV は小さな処理も複数スレッドに分け、その後スレッドが空回りするため、ビューアでは 1 コアの約 9 割 → 約 3 割に下がりました。
|
|
125
|
+
プロセス全体の設定なので、ライブラリ側では変えていません。
|
|
126
|
+
- `read()` は新しいフレームが来るまで待つので、GUI のメインスレッドではなく別スレッドで回してください。
|
|
127
|
+
- 機器を切り替えるときは、先に `cap.release()` を呼んでください。
|
|
128
|
+
- 受信中に USB が抜かれると、`read()` が `(False, None)` を返し、`cap.isOpened()` が False になります (固まりません)。
|
|
129
|
+
|
|
130
|
+
## 仮想カメラ
|
|
131
|
+
|
|
132
|
+
OBS Studio (OBS Virtual Camera) が入っていれば、普通の Web カメラとして他のアプリから使えます。
|
|
133
|
+
OBS 側の「仮想カメラ開始」は止めておいてください (同時には使えません)。
|
|
134
|
+
|
|
135
|
+
```powershell
|
|
136
|
+
uv run chenpi-virtualcam --device 3ds # --layout / --scale / --audio / --key もビューアと同じ
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
import cv2
|
|
141
|
+
cap = cv2.VideoCapture(3, cv2.CAP_DSHOW) # 番号は環境による (OBS Virtual Camera の番号)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
仮想カメラには音声は乗りません (OBS Virtual Camera は映像のみ)。
|
|
145
|
+
|
|
146
|
+
## 機種ごとの注意
|
|
147
|
+
|
|
148
|
+
### Optimize 3DS
|
|
149
|
+
|
|
150
|
+
- 公式ソフトを使った後は、USB を抜き差ししてから開いてください (公式ソフトが別のファームウェアを書き込むため)。
|
|
151
|
+
- 3DS 本体の「本体設定 → その他の設定 → サウンド」は **ステレオ** にしてください。
|
|
152
|
+
サラウンドのままだと、スピーカー用のサラウンド処理 (中音域を左右逆位相で混ぜる) がかかった音が届き、PC で聞くとこもって聞こえます。
|
|
153
|
+
- 本体の音量スライダーはキャプチャの音には効きません。`cap.volume` か PC 側で調整してください。
|
|
154
|
+
|
|
155
|
+
### Loopy DS
|
|
156
|
+
|
|
157
|
+
- DS 本体の電源が切れていると、開くことはできますが映像が届きません (ビューアは「信号待ち」と表示します)。
|
|
158
|
+
|
|
159
|
+
## ファームウェアについて
|
|
160
|
+
|
|
161
|
+
キャプチャ基板に毎回書き込むファームウェア (と Optimize のキー計算用テーブル) は、このライブラリに **同梱していません**。
|
|
162
|
+
これらは cc3dsfs で公開されているファイルですが、cc3dsfs の MIT ライセンスの対象外で、著作権は各メーカーにあります
|
|
163
|
+
(Loopy DS 用は Loopy 社提供、Optimize 用は non-standard)。利用者自身が cc3dsfs から取得してください。
|
|
164
|
+
|
|
165
|
+
- 取得元は動作確認した cc3dsfs のコミットに固定していて、SHA-256 が合わないファイルは保存しません。
|
|
166
|
+
- 探す場所は、引数 `firmware_dir` → 環境変数 `CHENPI_FIRMWARE_DIR` → `./firmware` → このリポジトリの `firmware/` →
|
|
167
|
+
`%LOCALAPPDATA%\chenpi\firmware` の順です。
|
|
168
|
+
|
|
169
|
+
## 開発
|
|
170
|
+
|
|
171
|
+
```powershell
|
|
172
|
+
uv sync
|
|
173
|
+
uv run pytest # 実機不要。ファームウェアが無い環境では、それを読む数件のテストはスキップされる
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
GitHub Actions では、Windows 上でファームウェアを取得してからテストを回します (`.github/workflows/test.yml`)。
|
|
177
|
+
|
|
178
|
+
## ライセンス
|
|
179
|
+
|
|
180
|
+
MIT License ([LICENSE](LICENSE))。
|
|
181
|
+
cc3dsfs の処理を移植しているため、cc3dsfs のライセンス表示を [LICENSES/cc3dsfs.txt](LICENSES/cc3dsfs.txt) に含めています。
|
|
182
|
+
ファームウェアは上記のとおり同梱していません。
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "chenpi"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Read DS/3DS capture boards (Loopy DS, Optimize Old 3DS) as OpenCV/numpy images on Windows"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = [
|
|
8
|
+
"LICENSE",
|
|
9
|
+
"LICENSES/*",
|
|
10
|
+
]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Operating System :: Microsoft :: Windows",
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Programming Language :: Python :: 3.12",
|
|
15
|
+
"Topic :: Multimedia :: Video :: Capture",
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
]
|
|
18
|
+
requires-python = ">=3.12"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"numpy>=1.26",
|
|
21
|
+
"opencv-python>=4.9",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[[project.authors]]
|
|
25
|
+
name = "Lizz"
|
|
26
|
+
|
|
27
|
+
[project.scripts]
|
|
28
|
+
chenpi-view = "chenpi.__main__:main"
|
|
29
|
+
chenpi-virtualcam = "chenpi.virtualcam:main"
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
audio = ["sounddevice>=0.5.6"]
|
|
33
|
+
virtualcam = ["pyvirtualcam>=0.15.0"]
|
|
34
|
+
|
|
35
|
+
[dependency-groups]
|
|
36
|
+
dev = [
|
|
37
|
+
"pytest>=8",
|
|
38
|
+
"chenpi[audio,virtualcam]",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[build-system]
|
|
42
|
+
requires = ["uv_build>=0.11.32,<0.12.0"]
|
|
43
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "chenpi"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Read DS/3DS capture boards (Loopy DS, Optimize Old 3DS) as OpenCV/numpy images on Windows"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE", "LICENSES/*"] # LICENSES/cc3dsfs.txt: 移植元 cc3dsfs の MIT ライセンス (表示が条件)
|
|
8
|
+
authors = [{ name = "Lizz" }]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Operating System :: Microsoft :: Windows",
|
|
11
|
+
"Programming Language :: Python :: 3",
|
|
12
|
+
"Programming Language :: Python :: 3.12",
|
|
13
|
+
"Topic :: Multimedia :: Video :: Capture",
|
|
14
|
+
"Development Status :: 3 - Alpha",
|
|
15
|
+
]
|
|
16
|
+
requires-python = ">=3.12"
|
|
17
|
+
dependencies = [
|
|
18
|
+
"numpy>=1.26",
|
|
19
|
+
"opencv-python>=4.9",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
chenpi-view = "chenpi.__main__:main"
|
|
24
|
+
chenpi-virtualcam = "chenpi.virtualcam:main"
|
|
25
|
+
|
|
26
|
+
[project.optional-dependencies]
|
|
27
|
+
audio = [
|
|
28
|
+
"sounddevice>=0.5.6",
|
|
29
|
+
]
|
|
30
|
+
virtualcam = [
|
|
31
|
+
"pyvirtualcam>=0.15.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[dependency-groups]
|
|
35
|
+
dev = ["pytest>=8", "chenpi[audio,virtualcam]"]
|
|
36
|
+
|
|
37
|
+
[build-system]
|
|
38
|
+
requires = ["uv_build>=0.11.32,<0.12.0"]
|
|
39
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# chenpi の使い方 (このライブラリを使うコードを書く人・エージェント向け)
|
|
2
|
+
|
|
3
|
+
chenpi は DS / 3DS 用キャプチャ基板の映像・音声を numpy / OpenCV の画像として読む **Windows 専用** のライブラリ。
|
|
4
|
+
`cv2.VideoCapture` と同じ形 (`read()` → `(ok, frame)`, `isOpened()`, `release()`) で使える。
|
|
5
|
+
このファイルはインストール先 (`site-packages/chenpi/USAGE.md`) にも入っている。
|
|
6
|
+
|
|
7
|
+
## 対応機種
|
|
8
|
+
|
|
9
|
+
| kind | 機種 | クラス | 画面 |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| `"ds"` | 新型 Loopy DS キャプチャ (USB Type-C 版, FTDI) | `LoopyDSCapture` | 上下とも 256x192 |
|
|
12
|
+
| `"3ds"` | Optimize 3DS キャプチャ Old 3DS 用 (Cypress) | `Optimize3DSCapture` | 上 400x240、下 320x240 |
|
|
13
|
+
|
|
14
|
+
どちらも約 60fps、音声はステレオ int16 / `SAMPLE_RATE` (≒ 32728.5 Hz)。
|
|
15
|
+
未対応: Optimize の New 3DS 用 / 2DS 用、RGB888、3D 表示、Loopy 製 3DS キャプチャ。
|
|
16
|
+
|
|
17
|
+
## 最小の例
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
import cv2
|
|
21
|
+
from chenpi import open_capture
|
|
22
|
+
|
|
23
|
+
cv2.setNumThreads(1) # 毎フレーム OpenCV で処理するなら推奨 (下の「注意」参照)
|
|
24
|
+
with open_capture("auto") as cap: # "ds" / "3ds" も可。見つからなければ RuntimeError など
|
|
25
|
+
while True:
|
|
26
|
+
ok, frame = cap.read() # BGR uint8 の numpy 配列
|
|
27
|
+
if not ok:
|
|
28
|
+
if not cap.isOpened(): # 切断・受信エラー
|
|
29
|
+
break
|
|
30
|
+
continue # 1 秒以内に新しいフレームが来なかった (本体の電源が切れている等)
|
|
31
|
+
cv2.imshow("chenpi", frame)
|
|
32
|
+
if cv2.waitKey(1) & 0xFF == ord("q"):
|
|
33
|
+
break
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 公開 API
|
|
37
|
+
|
|
38
|
+
`from chenpi import ...` で使えるもの。これ以外 (先頭が `_` のもの、各モジュール内の関数) は内部用。
|
|
39
|
+
|
|
40
|
+
### 開く
|
|
41
|
+
|
|
42
|
+
- `open_capture(device="auto", key=None, **kwargs) -> LoopyDSCapture | Optimize3DSCapture`
|
|
43
|
+
- `device`: `"auto"` (DS → 3DS の順に、空いている機器を探す) / `"ds"` / `"3ds"`。`DEVICES` にこの 3 つが入っている。
|
|
44
|
+
- `key`: Optimize 3DS のプロダクトキー (後述)。DS では使わない。
|
|
45
|
+
- `kwargs`: `layout`, `swap_rb`, `firmware_dir` (両クラス共通の引数)。
|
|
46
|
+
- `list_devices() -> list[DeviceInfo]`: 接続中の機器の一覧。**機器の状態を変えない** (ファーム書き込み等をしない) ので何度呼んでもよい。
|
|
47
|
+
- `open_device(info, key=None, **kwargs)`: `list_devices()` で選んだ 1 台を開く。GUI のコンボボックス向け。
|
|
48
|
+
- `DeviceInfo` (frozen dataclass): `kind` ("ds"/"3ds"), `name`, `id`, `path`, `status`, `needs_key`, `available` (property)。
|
|
49
|
+
- `status`: `"ready"` / `"in_use"` (他のプログラムが開いている) / `"replug"` (Optimize を公式ソフトで使った後。USB の抜き差しが必要)。
|
|
50
|
+
- `id`: DS は FTDI のシリアル。**Optimize は開くまで分からないので None** (開いた後の `cap.serial` がデバイス ID)。
|
|
51
|
+
- `str(info)` が表示用の文字列 (例 `"Optimize Old 3DS [使用中]"`)。
|
|
52
|
+
|
|
53
|
+
### クラスを直接使う
|
|
54
|
+
|
|
55
|
+
- `LoopyDSCapture(serial=None, layout="vertical", firmware_dir=None, swap_rb=False, dll_path="ftd2xx.dll")`
|
|
56
|
+
- `serial` を指定するとその機器だけを開く (見つからなければ FTError。別の機器にはフォールバックしない)。
|
|
57
|
+
- `Optimize3DSCapture(key=None, path=None, layout="vertical", firmware_dir=None, swap_rb=False)`
|
|
58
|
+
- `key` 省略時は環境変数 `OPTIMIZE_3DS_KEY`。**キーが無いと開けない** (キーなしだと約 4 分で転送が止まる機器のため)。
|
|
59
|
+
- `key` は文字列 (カンマ・セミコロン・空白区切りで複数可) か文字列のリスト。デバイス ID が合うものが使われる。
|
|
60
|
+
- `path` 省略時は、空いていてキーの合う 1 台を探して開く。
|
|
61
|
+
|
|
62
|
+
### 開いた後 (両クラス共通)
|
|
63
|
+
|
|
64
|
+
| メンバー | 内容 |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `read(timeout=1.0) -> (bool, ndarray \| None)` | **次の新しいフレーム** を待って返す。同じフレームを二度は返さない。timeout 秒来なければ `(False, None)` |
|
|
67
|
+
| `read_audio() -> ndarray` | 前回の呼び出し以降の音声。int16, shape `(N, 2)` [L, R]。待たない (無ければ N=0)。約 2 秒分を超えて読まれない分は古い順に捨てる |
|
|
68
|
+
| `isOpened() -> bool` | 受信中か。切断・エラーで False |
|
|
69
|
+
| `release()` | 閉じる。`with` 文でも閉じる |
|
|
70
|
+
| `volume` (float, 既定 1.0) | `read_audio()` にかかる倍率。0 で無音、1 超で増幅 (int16 の範囲で頭打ち)。いつ変えてもよい |
|
|
71
|
+
| `layout` | `"vertical"` / `"horizontal"` / `"top"` / `"bottom"` |
|
|
72
|
+
| `serial` | DS: FTDI シリアル。3DS: デバイス ID (16 桁の 16 進) |
|
|
73
|
+
| `description` | 機種名 (`"NDS.2"` / `"Optimize Old 3DS"` など) |
|
|
74
|
+
|
|
75
|
+
`read()` が返す frame の shape (高さ, 幅, 3):
|
|
76
|
+
|
|
77
|
+
| layout | DS | 3DS |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| vertical (上に上画面) | (384, 256, 3) | (480, 400, 3) 下画面は左右に 40px の黒帯 |
|
|
80
|
+
| horizontal (左に上画面) | (192, 512, 3) | (240, 720, 3) |
|
|
81
|
+
| top | (192, 256, 3) | (240, 400, 3) |
|
|
82
|
+
| bottom | (192, 256, 3) | (240, 320, 3) |
|
|
83
|
+
|
|
84
|
+
### ファームウェア
|
|
85
|
+
|
|
86
|
+
基板に書き込むファームウェアは **著作権の都合で同梱していない**。初回は cc3dsfs から取得する必要がある。
|
|
87
|
+
|
|
88
|
+
- 無い状態で開くと `FirmwareMissing` (`FileNotFoundError` のサブクラス)。`e.names` に足りないファイル名。
|
|
89
|
+
- `download_firmware(names=None, dest=None, progress=print) -> Path`: cc3dsfs の固定コミットから取得し、SHA-256 を照合して保存。
|
|
90
|
+
既定の保存先は `user_firmware_dir()` (`%LOCALAPPDATA%\chenpi\firmware`)。
|
|
91
|
+
- `missing_firmware(kind=None) -> list[str]`: 足りないファイル名 (`kind` は "ds" / "3ds" / None)。
|
|
92
|
+
- **利用者に確認せずにダウンロードしないこと** (第三者のファイルをネットから取得するため)。例:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from chenpi import FirmwareMissing, download_firmware, open_capture
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
cap = open_capture("auto", key=keys)
|
|
99
|
+
except FirmwareMissing as e:
|
|
100
|
+
if ask_user(f"{e.names} を cc3dsfs から取得しますか?"):
|
|
101
|
+
download_firmware()
|
|
102
|
+
cap = open_capture("auto", key=keys)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 例外
|
|
106
|
+
|
|
107
|
+
| 例外 | 主な原因 | 対処 |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `FirmwareMissing` | ファームウェアが無い | 利用者に確認して `download_firmware()` |
|
|
110
|
+
| `OptimizeError` | 3DS: キーが無い・合わない、機器が無い、使用中、要抜き差し、切断 | メッセージを利用者に見せる |
|
|
111
|
+
| `FTError` | DS: 機器が無い、使用中、FPGA 設定の失敗 | 同上 |
|
|
112
|
+
| `RuntimeError` | `open_capture("auto")` でどの機器も開けなかった (各機種の理由をまとめたメッセージ) | 同上 |
|
|
113
|
+
| `OSError` | DS 用の `ftd2xx.dll` (FTDI ドライバ) が無い | ドライバの導入を案内 |
|
|
114
|
+
|
|
115
|
+
受信中の切断は例外にならない。`read()` が `(False, None)` を返し、`isOpened()` が False になる。
|
|
116
|
+
|
|
117
|
+
### 低レベル
|
|
118
|
+
|
|
119
|
+
- `SAMPLE_RATE`: 音声のサンプルレート (DS / 3DS 共通)。
|
|
120
|
+
- `parse_frame(raw, swap_rb=False)` / `parse_audio(raw)`: Loopy DS の生データ 1 フレームの解析 (テスト・解析用)。
|
|
121
|
+
|
|
122
|
+
## 注意 (よくある間違い)
|
|
123
|
+
|
|
124
|
+
- **`cv2.setNumThreads(1)`**: 毎フレーム `cv2.resize` / `imshow` などをするアプリでは、最初に呼ぶと CPU 使用率が大きく下がる
|
|
125
|
+
(OpenCV のスレッドが空回りするため。1 コア約 9 割 → 約 3 割)。プロセス全体の設定なのでライブラリは変えていない。
|
|
126
|
+
- **スレッド**: `read()` は新しいフレームまで待つ (最大 `timeout` 秒)。GUI のメインスレッドで呼ばず、別スレッドで回す。
|
|
127
|
+
`volume` の変更や `read_audio()` は他のスレッドからでよい。
|
|
128
|
+
- **同時に 1 プログラムだけ**: 同じ機器を 2 つのプロセスで開くことはできない (公式ソフト・cc3dsfs とも)。機器を切り替えるときは先に `release()`。
|
|
129
|
+
- **Optimize 3DS**:
|
|
130
|
+
- 公式ソフトを使った後は USB の抜き差しが必要 (`status == "replug"`)。
|
|
131
|
+
- 3DS 本体のサウンド設定は「ステレオ」に。サラウンドだと PC で聞くとこもる。本体の音量スライダーはキャプチャの音に効かない (`volume` で調整)。
|
|
132
|
+
- **フレームの時刻**: `read()` の戻り値は `(ok, frame)` から変えない方針 (cv2 互換)。受信時刻が必要なら将来 `get(cv2.CAP_PROP_POS_MSEC)` で提供する予定 (未実装)。
|
|
133
|
+
- **音声の再生**: 音声は約 16.7ms (1 フレーム) ごとにまとめて届く。sounddevice などで鳴らすなら、25ms 程度溜めてから再生を始めないとプツプツ途切れる
|
|
134
|
+
(実装例: このパッケージの `__main__.py` の `_play_audio`)。
|
|
135
|
+
- ビューア `chenpi-view` (`python -m chenpi`) と仮想カメラ `chenpi-virtualcam` はコマンドとして入る。`--help` で使い方。
|