# ステークホルダー通しデモ — P2 コンクール（約 8〜12 分）

**目的:** 「遠隔の複数人が、同じ曲で公平に一発撮りし、結果を並べて見られる／聴ける」をローカル PoC で見せる。  
**正本:** [remote-singing.md](../features/remote-singing.md) · 技術: [contest-sync.md](../architecture/contest-sync.md) · ロードマップ: [roadmap-p2-p3.md](../architecture/roadmap-p2-p3.md)

---

## 1. 一言で言うと

| 見せるもの | 一言 |
|------------|------|
| **並列** | サーバーの 3,2,1,GO で伴奏スタート **＋ 双方自動録画** → 終端で自動停止・upload |
| **分割プレビュー** | 同ルームの **実写（＋音声）** を左右で同期再生 · 任意で分割合成保存 |
| **バトン** | 順番ワンテイク · 次の人だけ前テイクを初見ガイド（ブラインド）· 24h |

**PoC の境界（必ず先に言う）:**

- 実写は **チャンク upload 済**。サーバー ffmpeg 合成は任意（未導入時は **ブラウザ Canvas 合成**）
- 本番の R2 署名 URL / TTL / 権利 UI は未
- ローカル `127.0.0.1` · 短尺デモ曲（約 8 秒）

---

## 2. デモ前チェック（5 分）

### 起動（ターミナル）

| # | サービス | コマンド（各リポのルート） |
|---|----------|----------------------------|
| 1 | Platform 静的 **8780** | `py -m http.server 8780 --bind 127.0.0.1` |
| 2 | Work API **8782** | `npm run dev:api` |
| 3 | Karaoke **8790** | `py -m http.server 8790 --bind 127.0.0.1` |
| 4 | CDS3D **8765**（任意 · 3D を見せるとき） | `py cds3d_serve.py` |

コード変更直後は **8782 再起動** · Player / Karaoke は **Ctrl+Shift+R**。

### ブラウザ

- **通常ウィンドウ** = ユーザー A（ホスト）
- **シークレット（InPrivate）** = ユーザー B（ゲスト）  
  ※ 同じブラウザだとログインが共有される  
- 初回は **カメラ／マイク許可**（自動録画のため双方で許可）

### 固定 URL

| 用途 | URL |
|------|-----|
| ログイン | http://127.0.0.1:8780/apps/web/login.html |
| Player（デモ曲） | http://127.0.0.1:8780/apps/web/player.html?work=work_demo_001&api=1 |
| Work 詳細 | http://127.0.0.1:8780/apps/web/work.html?work=work_demo_001&api=1 |
| 分割プレビュー | http://127.0.0.1:8780/apps/web/contest-result.html?work=work_demo_001&api=1 |
| 設計索引 | http://127.0.0.1:8780/docs/index.html |

### 煙テスト（任意 · 余裕があれば）

```powershell
npm run smoke:contest-s1
npm run smoke:contest-s4
npm run smoke:contest-s6
npm run smoke:contest-video
```

---

## 3. 通し脚本（推奨 10 分）

### 0:00〜1:00 — オープニング

**話すこと**

- Muvic＆joy の Remote Singing には **カジュアル重ね録り（済）** と **コンクール（本日）** がある  
- コンクールは **回線遅延で「同時」を壊さない** — 各自ローカル録画 + サーバー時刻でスタート  
- 今日は **並列（自動録画）→ 実写分割 →（時間があれば）バトン**

**操作:** A でログイン（表示名例: `デモA`）→ Player を開く → 右サイド「コンクール」が見えること

---

### 1:00〜4:30 — シーン A: 並列 2 人（本命）

**話すこと**

- オーディション／グループ審査向けの **同時一発撮り**  
- **手動で録画ボタンを押す必要はない** — カウントダウン開始で双方が録り始める  
- GO の瞬間に親 transport（伴奏）が揃い、曲終了で **自動停止 → API へ送信**

**操作**

1. A: モード **並列** → **ルームを作成** → **招待リンク** をコピー  
2. B: シークレットでログイン（`デモB`）→ 招待 URL を開く → 参加者 2 名  
3. （任意）双方でカメラ ON を確認。未 ON でも自動録画時にカメラ取得を試行  
4. A: **カウントダウン開始**  
   - 双方トースト「コンクール自動録画を開始」  
   - 3→2→1→GO · 親 transport 再生  
5. 曲終了を待つ（約 8 秒）→ 自動停止  
   - 「コンクールテイクを保存しました」  
   - 「コンクール動画をチャンク送信中…」→「保存しました（○○KB）」  
6. Work 詳細で **コンクールテイク** が session / room 付きで 2 本

**つまずきやすい点**

- カメラ／マイク許可が片方だけだと映像なし・音声のみになる  
- トーストは **Karaoke iframe 側**（画面下部）— Player モーダルの「ローカルのみ」は旧文言の名残が出る場合あり（コンクール時は送信する）  
- GO 前に手動録画を押す必要は **ない**（押すと二重になるので触らない）

---

### 4:30〜6:30 — シーン B: 分割プレビュー（実写）

**話すこと**

- 審査・SNS 向けの「並んで見る／聴く」体験  
- 実写パネル + 同期再生（音あり）  
- 任意: **分割合成して保存**（ffmpeg があればサーバー、なければブラウザ合成）

**操作**

1. Work 詳細または Player ロビーの **分割プレビュー**  
   （または contest-result URL。可能なら `&room=<今回の roomId>`）  
2. ルーム選択で本日のルーム（`video` ラベルの 2 パネル）  
3. **▶ 同期再生** — 左右の実写が同時に動き、**音声も出る**  
4. （任意）**分割合成して保存** → 合成結果のプレビュー

---

### 6:30〜9:00 — シーン C: バトン（任意 · 時間があれば）

**話すこと**

- 空き時間に順番参加 · **次の人だけ前テイクを初見**（ブラインド）  
- ルームは **24 時間**で期限切れ（公平性の枠）

**操作**

1. 新規ルーム · モード **バトン** · A 作成 → B 参加（参加順 = 番順）  
2. A: **自分の番を開始** → カウントダウンで自動録画 → 終端で保存  
3. B: 「ブラインドガイド」トースト → **自分の番を開始** → 録画  
4. `done` → 分割プレビューで並べて確認

**短縮版:** バトンは口頭説明のみにし、並列 + 実写分割に時間を使う（推奨 8 分枠）

---

### 9:00〜10:00 — クロージング

**話すこと / スライド相当**

| できた（P2 PoC） | これから |
|------------------|----------|
| ルーム · WS 同期 GO · 並列 / バトン | R2 署名 URL · TTL · 権利 UI |
| **自動録画 / 自動停止** · 動画チャンク | ffmpeg 本番パイプラインの常設 |
| 実写分割プレビュー · クライアント合成 | ワンテイク証明の強化 |
| セッション付きメタ | P3: AR ステージ（背景除去 · 同居） |

**聞きたいフィードバック（例）**

1. 審査・タイアップで先に欲しいのは **並列** か **バトン** か  
2. 実写分割 + 同期再生で稟議に足りるか / **提出用 1 本 MP4**が必須か  
3. 次スプリントの優先: R2/TTL vs 長尺曲 vs 本番認証

---

## 4. 役割分担メモ（質問用）

| 層 | 担当 |
|------|------|
| ルーム · countdown / go / startAtMs | Platform WS（8782） |
| ロビー UI · 招待 · 自動録画指示 | Player（8780）→ Karaoke `muvic:contestRecord` |
| 録画 · テイク / 動画チャンク upload | Karaoke（8790）→ Contest API |
| 分割プレビュー · 合成 | `contest-result.html` |

---

## 5. バックアップ（失敗したとき）

| 症状 | 対処 |
|------|------|
| コンクールパネルが無い | `?api=1` · `work_demo_001` · ログイン |
| ゲストが同じユーザー | シークレットを使う |
| 自動録画が始まらない | Karaoke Ctrl+Shift+R · カメラ許可 · 8782 再起動 |
| 動画が 360B / 再生不能 | 古いテイク — **新しいルームで再録**（base64 修正済） |
| result で無音 | 「同期再生」を押す（unmute）。ダメなら mute+音声テイク表示を確認 |
| 録画が止まらない | 曲尺（約 8s）待ち · 手動で停止ボタン |
| 時間が無い | シーン A + B のみ（並列自動録画 + 実写分割） |

API だけ確認:

```powershell
npm run smoke:contest-s1
npm run smoke:contest-video
npm run smoke:contest-s6
```

---

## 6. 関連リンク

| 文書 | 内容 |
|------|------|
| [contest-sync.md](../architecture/contest-sync.md) | REST / WS / S1〜S7 · 自動録画 |
| [roadmap-p2-p3.md](../architecture/roadmap-p2-p3.md) | P2/P3 全体 |
| [local-dev-guide.md](../local-dev-guide.md) | 4 サービス · embed 再読込 |
| [regression-checklist.md](../regression-checklist.md) | P1 回帰 |
