# Headspace — Webカメラ・ネームプレート

Webカメラの顔の上へ、自分で割り当てた名前をリアルタイム表示する独立Webアプリです。写真アップロード版ではありません。既存の画像認識実験の配置に合わせ、このディレクトリだけで動作します。

## ローカルで開く

ランタイムとモデルは同梱済みです。Nodeやビルドは起動だけなら不要です。

```powershell
cd D:\Project\html5-game-ideas\experiments\webgl\headspace
python -m http.server 8017 --bind 127.0.0.1
```

http://127.0.0.1:8017/ を開きます。リポジトリ直下でサーバーを起動した場合は `/experiments/webgl/headspace/` です。カメラには localhost または HTTPS が必要です。`file://` やスマホからの LAN 内 HTTP では使えません。

## 使い方

1. 入力カメラを選び、**カメラを開始**を押して許可します。初回許可前は機器名が表示されない場合があります。許可後、停止すると別のカメラを選べます。
2. 明るい場所で正面を向き、顔を大きめに映します。表示名と色を編集します。
3. 映像上の番号または右側の「顔 #番号」を選び、プルダウンで名前を割り当てます。名前は人の自動識別結果ではありません。
4. 大きさ・頭からの高さ・なめらかさ・ミラー表示・推論頻度を調整します。
5. 交差・接近・見失い時は名前が解除されます。顔が離れてから、番号を見て再割当してください。名前の入力内容は残ります。
6. **停止**で全カメラトラックと推論ワーカーを終了します。再開時の割当は空です。タブを非表示にした場合も停止し、自動再開しません。

「カメラなしで動きを試す」は2人の移動・交差・見失いを描く合成デモです。顔検出結果を模擬するUI確認用であり、カメラやモデルは使いません。

## 最小仕様と制約

- 最大6件の顔枠、6個の手動プロフィール。顔の矩形から頭上位置を近似し、画面に正対する自作CSSプレートを描きます。頭髪・頭頂点や身体の3D位置を推定するものではありません。
- 位置・大きさによる対応付けと時間依存の指数平滑化。接近、候補の競合、1回でも検出欠落、450ms超の更新断で名前を解除します。見失った名前の自動復帰はしません。
- 顔認証・再識別は行いません。高速な入替など、幾何的な追跡では判別できないケースもあり、誤割当を完全には防げません。必要に応じて全解除できます。
- **近距離・正面の大きい顔向け**。モデルカードは概ね2m以内を想定し、顔が画面の辺の20%程度以上という条件を記載しています。小さい顔、横顔、背面、暗所、遮蔽、集団では検出が途切れます。6人の安定追跡を保証する意味ではありません。
- 推論用画像は幅640pxに縮小。CPU/WASMを専用Web Workerで実行し、同時処理は1フレーム、待ち行列は作りません。設定は10/15/24回毎秒の**上限**です。描画はrequestAnimationFrame。30fpsや完全な識別を保証しません。
- Chrome / Edge系のデスクトップを初期対象にしています。モバイルUIは検証済みですが、iOS Safari / Android端末の実カメラは未検証です。

## プライバシーと通信

- カメラ開始はボタン操作のみ。音声は取得しません。録画、画像保存、映像送信、解析API、分析タグはありません。名前もメモリ内のみでタブを閉じると消えます。
- 実行時は同じローカルサーバーからJavaScript・WASM・モデルを読み込みます。外部CDN不要。CSPで外部接続を禁止しています。
- 開発用の `npm ci` と、同梱ファイルを再取得する `npm run setup` は npm / Google / GitHub から依存ファイルを**ダウンロード**します。これは映像送信とは異なります。既存ファイルがあればセットアップ時のモデル再取得も不要です。

## 依存・モデル・出典

| 対象 | 固定版 | ライセンス / 出典 |
|---|---|---|
| MediaPipe Tasks Vision | `0.10.22-rc.20250304` | Apache-2.0 / Google、[ソース](https://github.com/google-ai-edge/mediapipe/tree/v0.10.22)、npmの同版パッケージ |
| BlazeFace short-range | `float16/1` | Apache-2.0 / Google、[モデル](https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/1/blaze_face_short_range.tflite)、[公式モデルカード](https://storage.googleapis.com/mediapipe-assets/MediaPipe%20BlazeFace%20Model%20Card%20(Short%20Range).pdf) p.1にライセンス明記 |
| Playwright（開発テストのみ） | `1.58.2` | Apache-2.0 / Microsoft |

同梱ライセンスは `licenses/Apache-2.0.txt`。モデルカードも `licenses/` に同梱。実モデル・WASM・JSのSHA-256と取得URLは `asset-manifest.json` に固定しています。モデルのSHA-256は `b4578f35940bf5a1a655214a1cce5cab13eba73c1297cd78e1a04c2380b0152f`。セットアップの再実行は既存ハッシュとの一致を検査します。CJSバンドルはクラシックWorker用に拡張子のみ `.js` へ変更し、内容は変更していません。

APIは[公式Webガイド](https://ai.google.dev/edge/mediapipe/solutions/vision/face_detector/web_js)を参照。モデル推論の外側の追跡・平滑化・描画・UIは自作です。HaloLink独自JS、RTMFの学習重み、ヘイロー素材、VRChat公式ロゴ・素材は使用していません。各サービスの公式アプリではありません。

## 開発と検証

```powershell
npm ci --ignore-scripts
npm run setup
npm test
# 別ターミナルで上記のローカルサーバーを起動
npx playwright install chromium
npm run test:browser
npm run test:video
npm run test:lifecycle
```

インストール済みChromiumを使う場合は `CHROME_EXECUTABLE` 環境変数に実行ファイルを指定できます。テストは疑似カメラまたはCanvasの動画ストリームを使い、実カメラを開きません。`test:video` の素材はパブリックドメインのNASA画像を動かしたテスト映像で、出典は `tests/fixtures/README.md` です。同一素材の複製なので、異なる2人の実写精度を検証したものではありません。

検証結果は [TESTING.md](TESTING.md)。レポートとスクリーンショットは `tests/results/`（Git対象外）に生成されます。今回の作業はローカルのみで、commit / push / 公開はしていません。

主要ファイル: `app.js`（カメラ・UI・描画）、`tracker.js`（対応付け・安全な解除）、`detector-worker.js`（MediaPipe推論）、`styles.css`、`index.html`。
