| # Phantom Grid β Demo Video Script & Production Reference |
|
|
| > **Purpose:** A complete, hand-off-ready reference for an editor/agent to assemble a |
| > ~90β120 second demo video for **Phantom Grid** (the local, browser-based London |
| > investigation game) and its new first-run tutorial. |
| > |
| > This document is the **single source of truth** for the video. It lists every shot, |
| > what asset to use, exactly what voiceover/on-screen text goes with it, and β where a |
| > static screenshot is not enough β a clearly marked **`[CAPTURE NEEDED]`** placeholder |
| > with precise instructions for recording the missing footage. |
|
|
| --- |
|
|
| ## 1. Format & delivery specs |
|
|
| | Field | Value | |
| | --- | --- | |
| | Target length | 90β120 s (trailer-paced) | |
| | Resolution | 1920Γ1080, 30 fps (screenshots were captured at 1680Γ945 @2x β crop/scale to fit) | |
| | Aspect | 16:9 | |
| | Output | `docs/demo/phantom_grid_demo.mp4` (H.264, ~10β12 Mbps), plus a 1080Γ1080 square cut for social if time allows | |
| | Captions | Burn-in optional; also export an `.srt` from the voiceover script in Β§6 | |
| | Audio | One music bed + light UI SFX from the game; voiceover optional (script provided) | |
|
|
| **Tone:** noir detective / "Lantern Watch Bureau" period-dossier framing. Warm gold on deep |
| teal-green (the game's own palette). Confident, brisk, a little mysterious. |
|
|
| **Brand palette (for lower-thirds / titles):** |
| - Gold text `#ffe39a`, accent gold `#d9ae50` |
| - Crimson accent `#d4513e` / `#a73a29` |
| - Deep background `#071f21`, panel border `#9a6926` |
| - Display font: a serif close to Georgia / "Cinzel" for titles; UI text is system serif. |
|
|
| --- |
|
|
| ## 2. Assets already captured (ready to use) |
|
|
| All under [`ui/web/static/assets/tutorial/`](../ui/web/static/assets/tutorial/). Real frames |
| from the running game, 1680Γ945 @2x (β3360Γ1890 px): |
|
|
| | File | Shows | Best used for | |
| | --- | --- | --- | |
| | `01_board_overview.png` | Full game board: Wanted poster, units, map, notepad, turn counter | Establishing shot / "the board" | |
| | `02_briefing.png` | Case briefing dossier (crime, suspect, last-seen trail) | "Every case starts with a briefing" | |
| | `03_map_layers.png` | Map on the **Taxi** transport layer | Transport layers / routes | |
| | `04_tactics_tray.png` | The 5 tactics with unit counts (Roadblock, Junction Lockdown, Patrol Unit, Search Team, Lookout Board) | Tactics explainer | |
| | `06_notice.png` | "Issue Public Notice" composer dialog | Public-notice mechanic | |
| | `07_witness_interview.png` | Witness interview panel (profile, statement, chat input, voice controls) | Witness interview | |
| | `08_witnesses_map.png` | Map in Witness Mode covered with witness pins | "Read the city" / leads | |
|
|
| > **Note:** `05_placed_tactic.png` was intentionally removed; the tactics story is told |
| > better with the tray (`04`) plus the **`[CAPTURE NEEDED]`** drag clip (Shot 6). |
|
|
| **To re-capture or refresh any still:** run the project app + AI backend, then |
| `tools/shotenv/Scripts/python.exe tools/capture_tutorial_shots.py` |
| (see [`tools/capture_tutorial_shots.py`](../tools/capture_tutorial_shots.py)). Output lands |
| back in `assets/tutorial/`. |
|
|
| --- |
|
|
| ## 3. How to capture the MISSING footage (`[CAPTURE NEEDED]`) |
|
|
| The demo needs **motion** that stills can't convey. Two ways to record: |
|
|
| **Option A β Playwright video (deterministic, no narrator cursor):** |
| Playwright can record a context to webm. Reuse the working selectors/flows in |
| [`tools/capture_tutorial_shots.py`](../tools/capture_tutorial_shots.py). Minimal recorder: |
|
|
| ```python |
| # tools/record_clips.py (to be written by the video agent) |
| from playwright.sync_api import sync_playwright |
| with sync_playwright() as pw: |
| b = pw.chromium.launch(headless=False) # headed = smoother cursor |
| ctx = b.new_context(viewport={"width":1680,"height":945}, |
| record_video_dir="docs/demo/clips", |
| record_video_size={"width":1680,"height":945}) |
| page = ctx.new_page() |
| page.goto("http://127.0.0.1:7860") |
| # ...drive the exact interaction for the shot (see per-shot notes below)... |
| ctx.close(); b.close() # video is flushed on context close |
| ``` |
|
|
| Prerequisites (same as the screenshot tool): the app is running at |
| `http://127.0.0.1:7860` and the AI backend reports healthy |
| (`GET /api/omni/status` β `"ready": true`). Starting a case and advancing turns |
| **requires** the local model to be up. |
|
|
| **Option B β OBS / native screen capture:** record a real play session at 1080p, 30 fps, |
| hiding the OS cursor trail. Use this for anything with audio (the witness voice reply). |
|
|
| **Selector cheat-sheet (verified working):** |
| - Start a case from the ready overlay: `#setupStartButton` (force-click; it pulses) |
| - Dismiss briefing: `#beginInvestigationButton` |
| - Layer tabs: buttons in `#layerTabs` (text "Normal/Taxi/Bus/Subway") |
| - Tactics in tray: `#tacticTray > *`; drag onto `#mapCanvas` |
| - Lookout board placement opens `#noticeDialog`; publish with `#raiseLookoutButton` |
| - Witness Mode toggle: `#witnessModeButton`; pins in `#witnessLayer [data-witness-id]` |
| - Advance a turn: `#advanceButton` |
| - Tutorial: auto-opens first run; replay via `#helpButton`; nav `#tutorialNext`/`#tutorialBack` |
|
|
| --- |
|
|
| ## 4. Shot list (the actual edit, in order) |
|
|
| Legend: π’ = asset ready Β· π΄ = `[CAPTURE NEEDED]` |
|
|
| | # | Len | Visual | On-screen text | Source | |
| | --- | --- | --- | --- | --- | |
| | 1 | 0:00β0:06 | Title card: logo "PHANTOM GRID" over a slow push-in on the board, vignette | **PHANTOM GRID** / "A London manhunt, played on your desk." | π΄ **[CAPTURE NEEDED: title animation]** built over `01_board_overview.png` (Ken Burns zoom 100%β108%) | |
| | 2 | 0:06β0:14 | The case briefing dossier reveals (cards slide/stamp in) | "Every case opens with a dossier." | π’ `02_briefing.png` (animate the three cards in; or π΄ record the real reveal β see Shot notes) | |
| | 3 | 0:14β0:22 | Full board establishing; subtle callouts pop on Wanted / Map / Turn counter | "You're the Commissioner. Catch the thief before time runs out." | π’ `01_board_overview.png` + motion-graphic callout arrows | |
| | 4 | 0:22β0:32 | Map layers switching NormalβTaxiβBusβSubway | "The suspect can only move along the transport grid." | π΄ **[CAPTURE NEEDED: layer-switch clip]** (fallback still: `03_map_layers.png`) | |
| | 5 | 0:32β0:40 | Witness Mode: city fills with witness pins | "Sightings light up across the city β some true, some false." | π’ `08_witnesses_map.png` (push-in) or π΄ record the toggle | |
| | 6 | 0:40β0:50 | Dragging a tactic chip from the tray onto a junction; pin lands | "Deploy your units: roadblocks, patrols, search teams." | π΄ **[CAPTURE NEEDED: tactic drag clip]** + cutaway to π’ `04_tactics_tray.png` | |
| | 7 | 0:50β0:58 | Issue Public Notice dialog; type wording; Publish | "Issue a public appeal to draw out fresh leads." | π’ `06_notice.png` or π΄ record the type+publish | |
| | 8 | 0:58β1:12 | Witness interview: type a question, AI witness replies (ideally with voice audio) | "Interview witnesses β ask what they saw, where it went, when." | π΄ **[CAPTURE NEEDED: live interview clip w/ audio]** (fallback still: `07_witness_interview.png`) | |
| | 9 | 1:12β1:20 | Advance Turn β suspect moves; tension beat; a Search Team triggers the catch | "Close the net. One move too slow and they vanish." | π΄ **[CAPTURE NEEDED: advance-turn + win/lose moment]** | |
| | 10 | 1:20β1:30 | The first-run tutorial flips through 2β3 slides | "New here? A built-in tutorial walks you through it." | π΄ **[CAPTURE NEEDED: tutorial slide flips]** (stills available as fallback: the 7 tutorial slides render the assets in Β§2) | |
| | 11 | 1:30β1:40 | End card: logo + setup line + URL | "Runs locally. Your case, your machine." / `127.0.0.1:7860` | π΄ **[CAPTURE NEEDED: end card]** | |
|
|
| > Trim to 90 s by dropping Shots 7 and 10 and tightening 8β9. Extend to 2 min by letting |
| > the interview (Shot 8) breathe with real audio. |
|
|
| --- |
|
|
| ## 5. Per-shot capture notes for `[CAPTURE NEEDED]` items |
|
|
| - **Shot 1 / 3 (title + callouts):** pure motion-graphics over the ready still |
| `01_board_overview.png`. No new game capture required. |
| - **Shot 2 (briefing reveal, optional live):** start a case via `#setupStartButton`; the |
| briefing `#caseIntroDialog` animates open. Record ~3 s, then it can be sped up. |
| - **Shot 4 (layer switch):** after `#beginInvestigationButton`, click the `#layerTabs` |
| buttons in order with ~1 s between. Record the map area (`.map-shell`). |
| - **Shot 6 (tactic drag):** mouse-down on a `#tacticTray` chip, move over `#mapCanvas` |
| to a junction, mouse-up. Headed mode (Option A) shows the cursor; or use OBS. Capture |
| the "pin lands + event ticker confirms" beat (~3β4 s). |
| - **Shot 8 (interview, highest value):** open a witness (`#witnessLayer [data-witness-id]` |
| β interview dialog), type a question in `#witnessMessage`, hit Send, wait for the AI |
| reply to render in `#witnessTranscript`. If demonstrating **voice**, enable voice output |
| in Settings and use OBS (Option B) so the audio reply is recorded. Note: surfacing an |
| *interviewable* witness depends on crowd density β if pins show "crowd too dense", |
| advance a turn or two, or (dev-only) raise `PHANTOM_GRID_INDIVIDUAL_WITNESS_THRESHOLD` |
| to make all reports interviewable for the recording, then revert. |
| - **Shot 9 (advance + outcome):** press `#advanceButton` to show the turn tick and suspect |
| movement. For the **win moment**, place a `search_team` on the suspect's likely junction |
| and advance; the case ends and the story reveal becomes available. Capture the result |
| banner / `#storyDialog` opening as the payoff. (A loss/"vanished" beat also works for |
| tension β director's choice.) |
| - **Shot 10 (tutorial flips):** fresh browser (clears `localStorage` so it auto-opens), or |
| click `#helpButton`. Record clicking `#tutorialNext` through 2β3 slides; the dots and |
| "1/7 β¦ Start Playing" progression read well on camera. |
| - **Shot 11 (end card):** motion-graphics card; reuse logo + palette from Β§1. |
|
|
| --- |
|
|
| ## 6. Voiceover script (timed to Β§4) |
|
|
| > Keep delivery measured; ~135 wpm. Lines map 1:1 to the shot numbers. |
|
|
| 1. "London. A thief is loose on the grid β and you're the one they sent to catch him." |
| 2. "Every case begins with a dossier: the crime, the suspect, the last place they were seen." |
| 3. "You're the Commissioner. Read the trail, and move before the clock runs out." |
| 4. "Your quarry can only travel the transport grid β taxi, bus, and underground lines." |
| 5. "Across the city, sightings surface. Some are real. Some are decoys." |
| 6. "Deploy your units β roadblocks, patrols, and search teams β onto the junctions that matter." |
| 7. "Post a public notice, and the right words will draw out fresh witnesses." |
| 8. "Then question them. What did they see? Which way did it go? Every answer narrows the net." |
| 9. "Advance the turn⦠and hope you've closed the gap. One move too slow, and he's gone." |
| 10. "New to the Bureau? A built-in tutorial walks you through your first case." |
| 11. "Phantom Grid. It runs entirely on your machine. Open the file. Start the hunt." |
|
|
| --- |
|
|
| ## 7. Music & SFX |
|
|
| - **Music:** one cinematic-noir/spy bed, ~110β120 bpm, builds at Shot 8β9. License-clear. |
| - **SFX (from the game where possible):** the app emits cues such as `lookout_raise`, |
| `witness_popup`, `blockade_set`, `map_select`, `turn_advance` β pull matching beats for |
| pin-drops, notice-publish, tactic-place, and turn-tick. A soft "stamp" on the briefing |
| card and a low "snare/impact" on the catch (Shot 9). |
|
|
| --- |
|
|
| ## 8. Pre-flight checklist for the video agent |
|
|
| - [ ] App running at `http://127.0.0.1:7860`; `GET /api/omni/status` β `ready: true`. |
| - [ ] Confirm the 7 stills in Β§2 exist; re-run `tools/capture_tutorial_shots.py` if stale. |
| - [ ] Record the 6 `[CAPTURE NEEDED]` clips (Shots 1/3 are graphics-only) β `docs/demo/clips/`. |
| - [ ] Build the edit per Β§4; lay voiceover (Β§6) and music/SFX (Β§7). |
| - [ ] Export `docs/demo/phantom_grid_demo.mp4` (1080p) + `.srt`. |
| - [ ] If a dev-only setting was changed for Shot 8, revert it (check `.env`). |
|
|