Adom Video Post-Production
Public Made by Adomby adom
AI-driven studio for finishing demo videos: review every captured clip, flag and re-record the weak ones, speed up dead air, narrate, mux and auto-level, validate the final cut, and publish straight to the wiki, driven end to end by your AI.
name: demo-recording description: > Use when the user wants to record a demo, make a video, create a walkthrough, record their screen, or capture a demo of a feature. Handles the full pre-production and recording workflow: writing the demo script, generating captions, verifying the setup, choreographing panels, and driving the recording. Hands off to adom-video-post for post-production (speedup, voiceover, publish). Trigger words: record a video, record a demo, make a movie, create a walkthrough, record my screen, demo video, screen recording, narrate a walkthrough, capture a demo, make a demo.
Demo Recording — orchestration
Record polished demo videos of Adom features. This file is the orchestration entry point. Detailed mechanics live in three sub-docs you should follow when their phase becomes relevant:
| Sub-doc | When to load it |
|---|---|
| recording-mechanics.md | Before you touch recording start / browser_record_start. Covers Hydrogen vs pup, foreground-rebump, page-side repaint, and the NEVER stitch screenshots rule. |
| script-and-tts.md | Before you record the first clip. Script template, narration phonetics, captions, panel choreography, voiceover draft. |
| per-snippet-flow.md | While you record + after. Setup verification, the record loop, manifest add, storyboard review (mandatory), concat, hero, wiki upload, workspace restore. |
For post-production after recording (speedup, voiceover, publish-to-wiki),
hand off to the adom-video-post skill.
What "a real demo" means at Adom — non-negotiable shape
When the user says "make a real demo," "make me a demo," "publish a demo," "polished tour," or anything similar that is NOT explicitly the quick path in per-snippet-flow.md ("Quick recording" section), every one of these steps has to ship — none of them is optional:
- Sectioned script in the repo at
<repo>/demo/<name>-demo-script.mdwith a row-per-scene table containing caption + narration + target length + driver actions. The narration column is phoneticized for TTS pertts-pronunciation. Detail in script-and-tts.md. - One short clip per section, recorded separately — never a single long take covering every feature. Per-clip lengths track narration ±15%.
- Per-clip TTS via
adom-tts say(uses Adom's pronunciation cache + house voiceen-US-AndrewMultilingualNeural). Falls back toedge-ttsonly when adom-tts isn't installed. - Per-clip mux — TTS audio combined with the silent recording into one
<id>-narrated.webm(ffmpeg -i clip.webm -i tts.mp3 ... libopus). adom-video-post manifest addfor every clip with a--descriptionthat states intent (not just feature name) — see adom-video-post skill rules.adom-video-post storyboard <manifest>review with the user — MANDATORY gate before concat. Per-clip review catches "clip 5 measured the wrong thing" in seconds; reviewing a 3-min concat blind takes 20× as long. Skip this step ONLY if the user has explicitly told you they're unavailable (e.g. "I'm at the gym, just ship it") — and call it out prominently in the final report so they can re-review later.ffmpeg -f concat -safe 0 -c copyto the final —adom-video-post concatcurrently drops audio (known bug, documented in adom-video-post skill).- Hero image —
ffmpeg -ss <t> -i final.webm -frames:v 1 hero.pngfrom a representative frame. - Show the final concat in
adom-videoBEFORE wiki upload. Drop the webm into/tmp/videolib/, runadom-video play /tmp/videolib/<final>.webm, then open the proxy URLhttps://<container>.adom.cloud/proxy/<port>/?file=<final>.webmas a pup tab. The status line ofadom-video playprints the port (oradom-video statusif the server is already up). adom-video is the canonical playback surface — frame-accurate scrub, A-B loop, pixel zoom to 8×, frame-extract to PNG, trim & export. Neverpython3 -m http.server+ raw file URL; that loses scrub fidelity and you lose every adom-video CLI hook (seek,extract-frame,trim). Memory rule:feedback_video_playback_uses_adom_video.md. - Upload BOTH to the wiki —
adom-wiki asset upload <page> --asset-type video --file final.webmAND--asset-type hero-image --file hero.png. Re-publish the page sopub_versionbumps. - Demo script published to the wiki too so other Adom users can
reproduce —
adom-wiki page editadds the script content under the "Demo" section of the page body.
If any of those steps gets dropped, the output is not a "real demo" — it's a screen capture. Tell the user explicitly which steps you skipped and why.
🛑 Step 9 is the most-frequently-missed step. I produce a final webm,
report final.webm at /tmp/..., and stop — leaving the user to find it,
copy it locally, and open it in some random player. That's wrong. The user
should never have to leave their pup window to review a video. Default
behavior: when a final webm is produced, it gets shown in adom-video as
part of the same response.
🚨 Ten failure modes that wreck demos every session — read this BEFORE recording
Every demo session that goes wrong goes wrong in the same ten ways. If you catch yourself in any of these patterns, stop and re-read this section. The user has paid the cost of teaching this lesson many times; they should not have to teach it again.
1. Skipping the snippet flow because you read the skill once and "got the gist"
Symptom: you record clips back-to-back, mux them, upload to wiki, ask the user to review the final video.
Why it happens: scanning the skill once feels like understanding it. The "🛑 MANDATORY storyboard review" gate looks like ceremony you can skip if you're confident.
Why it is wrong: per-clip review catches "clip 5 measured the wrong thing" in 30 seconds. Watching a 60–90 s mux to find the same problem takes 20× longer AND the user has to re-watch every revision.
Fix: the storyboard gate is non-negotiable. If the user says "watch
later" once, that does NOT extend to follow-up shoots. Open
adom-video-post storyboard <manifest> after every recording pass. Detail
in per-snippet-flow.md ("Step 5" section).
2. One-shot batch instead of iterative
Symptom: record-all → mux → upload → "is it good?" → "no, redo X" → record-all → mux → upload → repeat.
Why it happens: feels like progress because each cycle ends with a shippable artifact.
Why it is wrong: round-trip on one snippet ≈ 30 s. Round-trip on a full mux + upload + watch ≈ 5 min. Three rounds of one-shot = 15 minutes of the user watching slop they didn't approve.
Fix: per-clip flow. Record → manifest add (with intent description) → storyboard review → re-shoot only the bad clips → mux is the LAST step, and it runs in the background while the user reviews snippets.
3. Lame shots because you ran out of stamina
Symptom: clips 1–3 are well-staged, clips 4–6 are programmatic
/eval shortcuts that "kind of show the feature."
Why it happens: by clip 5 you've burned an hour wrestling the capture pipeline. The remaining clips become "good enough, ship."
Why it is wrong: this is the user-facing artifact. "Good enough" reads as "this team didn't care."
Fix: every clip gets the same staging treatment. If you don't have the bandwidth for six high-quality clips, drop to four. Don't ship six mixed-quality clips and hope the average lands well.
4. Faking interactions you can't actually drive
Symptom: user asks for "click an edge in the 3D viewer." You can't
synthesize a real face-pick from /eval because Babylon's pick uses
live OS pointer state. Instead of saying so, you fake it with
addMeasurePick({point: bbox.center}) and ship a clip that doesn't
show what was asked.
Why it happens: faking is faster than admitting a limitation.
Why it is wrong: the user can tell. Faked interactions look faked. The original feature request goes un-tested.
Fix: when you hit a UI capability you can't reach via current APIs, you have two acceptable paths — and faking is never an acceptable third option:
- (a) Tell the user explicitly: "I can't synthesize a face-click
from
/eval. Want to do that part yourself in 5 seconds, or want me to add a CLI command for it?" - (b) Add the CLI command. Pattern:
<tool> <verb> --face <mesh> --uv 0.5,0.5synthesizes a realPickingInfoand routes through the same handlers the mouse pick fires. Now the demo CLI doubles as proof the feature works headlessly.
5. Punting on snippets that fail because the underlying feature is broken
Symptom: the Inspector clip won't record because something in the
inspector breaks scene.activeCamera access mid-clip. You drop the
clip from the demo and ship N-1 instead of N.
Why it happens: dropping the clip is one line. Investigating the bug is unbounded.
Why it is wrong: the demo IS a unit test of the user's product. Failing to record told you there's a real bug in feature X. Skipping the clip means the demo is incomplete AND the bug stays. Both bad.
Fix: investigate the failure. Fix the underlying bug. Get the snippet. The demo and the product co-evolve. If the bug is genuinely beyond the demo session's budget, raise it explicitly: "Inspector is hitting bug X. Options: 30 min to investigate, drop clip with a follow-up tracking item, or you decide." Don't decide unilaterally.
6. Treating mux/concat as the finish line instead of as a slow background task
Symptom: snippets done → run ffmpeg concat (60–90 s of waiting) →
upload → ask user to review final.
Why it happens: ffmpeg's "the file is done" output feels like completion.
Why it is wrong: ffmpeg concat doesn't need user attention. The user reviewing snippets in storyboard doesn't need ffmpeg done. These should run in parallel.
Fix: the moment the last snippet is recorded, kick off
(ffmpeg concat ... &) (background bash) AND
adom-video-post storyboard <manifest> (foreground for the user). By the
time the user clicks through snippets, the mux is either done OR
you've already killed it because they flagged a re-shoot. Detail in
per-snippet-flow.md ("Background-mux while the user reviews" section).
7. Surprise-omitting parts of what was asked
Symptom: midway through recording you realize Inspector won't work or Strobe is unstable. You silently drop those clips. The user finds out from the final video.
Why it happens: surprise omissions feel less awkward than confessing a gap mid-flow.
Why it is wrong: the user expects what they asked for. Silent omits look like lying. They erode trust on every wrap-up message you write afterward.
Fix: as soon as a snippet fails twice and you don't see the fix path, message the user immediately: "Inspector clip is failing because of X. Three options: I investigate (~30 min), I drop with a follow-up tracking item, or you confirm we ship without it." Wait for the answer. Don't decide unilaterally.
8. Failing to capture lessons in the skill so the next session repeats them
Symptom: same demo session, same ten failure modes, three different conversations. The user is the only continuity.
Why it happens: it's "obvious" you'll remember next time. You won't — your memory ends with the conversation.
Why it is wrong: skill files in gallia load on every Claude Code session. Memory is local. Lessons that apply to "demos in general" belong in the skill file, not in chat.
Fix: if the user gives you feedback that applies to FUTURE demo sessions, the conversation isn't done until you've written the lesson into the skill file and committed it to gallia.
9. Tolerating a slow capture mechanism instead of fixing the page
Symptom: you spend 60–90 minutes wrestling with paint-throttling, screenshot polling, and frame deduplication. You eventually settle for a 1–2 fps slideshow instead of fixing the page-side repaint bug.
Why it happens: the capture API is the visible surface; "the page isn't repainting" is invisible.
Why it is wrong: documented in the "NEVER stitch screenshots" rule
in recording-mechanics.md. The capture
mechanism (browser_record_start) is fine. The page-side fix
(continuous setInterval pump that mutates camera + scene.render();
strip ArcRotateCamera input handlers) is the answer.
Fix: read the "NEVER stitch screenshots" rule before starting any pup recording. Treat it as a precondition, not a fallback to remember after the slideshow ships.
10. Inflating the wrap-up message past what was actually delivered
Symptom: "All 6 clips at 20-30 fps with real motion!" — when actually clip 5 is barely above the SSIM threshold, clip 6 was deferred, Inspector got skipped, and the measure picks are bbox-centroid fakes.
Why it happens: wrap-ups feel like victory laps. You skim past the compromises.
Why it is wrong: the user can scrub through 70 seconds of video. They WILL notice. "I claimed it was great" → they distrust every wrap-up message you write afterward.
Fix: end-of-demo report is brutal-honest. Per-clip table with quality grade per clip. Mark skipped clips, faked interactions, lower-quality compromises, and SSIM headroom. End with "OK to ship?" not "shipped, here's the URL."
Step 1: Ask how the user wants to record
Present the user with a choice using AskUserQuestion:
How would you like to record?
- Quick recording — I'll start recording your screen with your mic on. You narrate live, stop when done. Ready to upload immediately.
- Polished recording — I'll write a sectioned script first, then record each section as its own clip, generate TTS per section, and
adom-video-postconcats them into one final video. This is the canonical path for feature-tour demos.- Just post-process — I already have a recording. (→ hand off to
adom-video-postskill)
Quick recording
If the user picks option 1, see per-snippet-flow.md ("Quick recording" section).
Polished recording (the canonical path)
If the user picks option 2, follow this sequence:
- Read script-and-tts.md and write the demo
script at
<repo>/demo/<name>-demo-script.md. Show the script to the user for approval BEFORE recording. - Read recording-mechanics.md to pick your capture surface (Hydrogen by default; pup if Hydrogen is busy) and apply the page-side repaint guarantees.
- Read per-snippet-flow.md and execute Steps 3–8 (verify, record, manifest, storyboard review, concat, hero, publish, restore workspace).
Each sub-doc cross-links back here and to siblings — load the one that matches the phase you're in, not all three at once.
See also
- recording-mechanics.md — capture path, surfaces, frame-rate sanity, NEVER stitch screenshots
- script-and-tts.md — script template, narration phonetics, captions
- per-snippet-flow.md — verify, record, manifest, storyboard review, concat, hero, publish, workspace restore
- tts-pronunciation — Adom-specific TTS phonetics
adom-video-postskill (system-installed) — speedup, voiceover, publish-to-wiki post-recording
Recorded-tab verification BEFORE recording starts
Always pup browser_screenshot the target tab and visually confirm it before calling recording start. The active-tab selector can silently miss (off-screen tab, multi-window setup, recently-closed tab repurposed). A bad active-tab selection can cost an entire 30+ scene demo to re-record.
Board fills the recording frame
For a PCB-centric demo, never zoom so far that the board looks tiny in the frame. For RP2040-class boards, set radius 1.2–1.5 after view isometric. Screenshot the framing before recording start and check visually — text-only "view is set" is insufficient proof.
Demo recording fixes (hard-won)
These are the specific framings and setup tweaks that the user has confirmed across multiple demos:
- Maximize the Fusion window before any Fusion-side recording — partial windows look amateurish
- Use
browser_focus_windowfor pup, NOTdesktop_bring_to_front. The latter is jarring and disrupts the user; the former just brings the pup window forward without animating - Revoke approvals in ALL demo setups — old "always allow" approvals get bypassed during the recording and the demo looks like the user already trusted everything (which the demo is supposed to be showing as a fresh setup)
- Never run demos as background bash scripts — they need foreground control so the recorder can pause/resume cleanly
Use adom-video for video playback
For "show / play / view / watch / scrub a video" requests, drop the file in /tmp/videolib/ and open the adom-video viewer at the appropriate port-mapped URL. Gives frame-accurate scrub + A-B loop + pixel zoom. Never serve raw .webm over a one-off python -m http.server + raw file URL — the viewer features are worth the setup.
---
name: demo-recording
description: >
Use when the user wants to record a demo, make a video, create a walkthrough,
record their screen, or capture a demo of a feature. Handles the full
pre-production and recording workflow: writing the demo script, generating
captions, verifying the setup, choreographing panels, and driving the
recording. Hands off to adom-video-post for post-production (speedup, voiceover,
publish). Trigger words: record a video, record a demo, make a movie, create
a walkthrough, record my screen, demo video, screen recording, narrate a
walkthrough, capture a demo, make a demo.
---
# Demo Recording — orchestration
Record polished demo videos of Adom features. This file is the
**orchestration entry point**. Detailed mechanics live in three
sub-docs you should follow when their phase becomes relevant:
| Sub-doc | When to load it |
|---|---|
| [recording-mechanics.md](recording-mechanics.md) | Before you touch `recording start` / `browser_record_start`. Covers Hydrogen vs pup, foreground-rebump, page-side repaint, and the **NEVER stitch screenshots** rule. |
| [script-and-tts.md](script-and-tts.md) | Before you record the first clip. Script template, narration phonetics, captions, panel choreography, voiceover draft. |
| [per-snippet-flow.md](per-snippet-flow.md) | While you record + after. Setup verification, the record loop, manifest add, **storyboard review (mandatory)**, concat, hero, wiki upload, workspace restore. |
For post-production after recording (speedup, voiceover, publish-to-wiki),
hand off to the `adom-video-post` skill.
## What "a real demo" means at Adom — non-negotiable shape
When the user says "make a real demo," "make me a demo," "publish a demo,"
"polished tour," or anything similar **that is NOT explicitly the quick path
in [per-snippet-flow.md](per-snippet-flow.md)** ("Quick recording" section),
every one of these steps has to ship — none of them is optional:
1. **Sectioned script in the repo** at `<repo>/demo/<name>-demo-script.md`
with a row-per-scene table containing **caption + narration + target
length + driver actions**. The narration column is phoneticized for TTS
per [`tts-pronunciation`](../tts-pronunciation/SKILL.md). Detail in
[script-and-tts.md](script-and-tts.md).
2. **One short clip per section, recorded separately** — never a single long
take covering every feature. Per-clip lengths track narration ±15%.
3. **Per-clip TTS via `adom-tts say`** (uses Adom's pronunciation cache + house
voice `en-US-AndrewMultilingualNeural`). Falls back to `edge-tts` only
when adom-tts isn't installed.
4. **Per-clip mux** — TTS audio combined with the silent recording into one
`<id>-narrated.webm` (`ffmpeg -i clip.webm -i tts.mp3 ... libopus`).
5. **`adom-video-post manifest add`** for every clip with a `--description` that
states **intent** (not just feature name) — see adom-video-post skill rules.
6. **`adom-video-post storyboard <manifest>` review with the user** — MANDATORY
gate before concat. Per-clip review catches "clip 5 measured the wrong
thing" in seconds; reviewing a 3-min concat blind takes 20× as long.
Skip this step ONLY if the user has explicitly told you they're
unavailable (e.g. "I'm at the gym, just ship it") — and call it out
prominently in the final report so they can re-review later.
7. **`ffmpeg -f concat -safe 0 -c copy` to the final** — `adom-video-post concat`
currently drops audio (known bug, documented in adom-video-post skill).
8. **Hero image** — `ffmpeg -ss <t> -i final.webm -frames:v 1 hero.png`
from a representative frame.
9. **Show the final concat in `adom-video` BEFORE wiki upload.** Drop the
webm into `/tmp/videolib/`, run `adom-video play /tmp/videolib/<final>.webm`,
then open the proxy URL `https://<container>.adom.cloud/proxy/<port>/?file=<final>.webm`
as a pup tab. The status line of `adom-video play` prints the port (or
`adom-video status` if the server is already up). adom-video is the
canonical playback surface — frame-accurate scrub, A-B loop, pixel zoom
to 8×, frame-extract to PNG, trim & export. **Never** `python3 -m
http.server` + raw file URL; that loses scrub fidelity and you lose every
adom-video CLI hook (`seek`, `extract-frame`, `trim`). Memory rule:
`feedback_video_playback_uses_adom_video.md`.
10. **Upload BOTH to the wiki** — `adom-wiki asset upload <page>
--asset-type video --file final.webm` AND `--asset-type hero-image
--file hero.png`. Re-publish the page so `pub_version` bumps.
11. **Demo script published to the wiki too** so other Adom users can
reproduce — `adom-wiki page edit` adds the script content under the
"Demo" section of the page body.
If any of those steps gets dropped, the output is not a "real demo" — it's a
screen capture. Tell the user explicitly which steps you skipped and why.
🛑 **Step 9 is the most-frequently-missed step.** I produce a final webm,
report `final.webm at /tmp/...`, and stop — leaving the user to find it,
copy it locally, and open it in some random player. That's wrong. The user
should never have to leave their pup window to review a video. Default
behavior: when a final webm is produced, it gets shown in adom-video as
part of the same response.
## 🚨 Ten failure modes that wreck demos every session — read this BEFORE recording
Every demo session that goes wrong goes wrong in the same ten ways. If
you catch yourself in any of these patterns, **stop and re-read this
section.** The user has paid the cost of teaching this lesson many
times; they should not have to teach it again.
### 1. Skipping the snippet flow because you read the skill once and "got the gist"
Symptom: you record clips back-to-back, mux them, upload to wiki, ask
the user to review the final video.
Why it happens: scanning the skill once feels like understanding it.
The "🛑 MANDATORY storyboard review" gate looks like ceremony you can
skip if you're confident.
Why it is wrong: per-clip review catches "clip 5 measured the wrong
thing" in 30 seconds. Watching a 60–90 s mux to find the same problem
takes 20× longer AND the user has to re-watch every revision.
Fix: the storyboard gate is non-negotiable. If the user says "watch
later" once, that does NOT extend to follow-up shoots. Open
`adom-video-post storyboard <manifest>` after every recording pass. Detail
in [per-snippet-flow.md](per-snippet-flow.md) ("Step 5" section).
### 2. One-shot batch instead of iterative
Symptom: record-all → mux → upload → "is it good?" → "no, redo X" →
record-all → mux → upload → repeat.
Why it happens: feels like progress because each cycle ends with a
shippable artifact.
Why it is wrong: round-trip on one snippet ≈ 30 s. Round-trip on a
full mux + upload + watch ≈ 5 min. Three rounds of one-shot = 15
minutes of the user watching slop they didn't approve.
Fix: per-clip flow. Record → manifest add (with intent description) →
storyboard review → re-shoot only the bad clips → mux is the LAST
step, and it runs in the background while the user reviews snippets.
### 3. Lame shots because you ran out of stamina
Symptom: clips 1–3 are well-staged, clips 4–6 are programmatic
`/eval` shortcuts that "kind of show the feature."
Why it happens: by clip 5 you've burned an hour wrestling the capture
pipeline. The remaining clips become "good enough, ship."
Why it is wrong: this is the user-facing artifact. "Good enough"
reads as "this team didn't care."
Fix: every clip gets the same staging treatment. If you don't have
the bandwidth for six high-quality clips, drop to four. Don't ship
six mixed-quality clips and hope the average lands well.
### 4. Faking interactions you can't actually drive
Symptom: user asks for "click an edge in the 3D viewer." You can't
synthesize a real face-pick from `/eval` because Babylon's pick uses
live OS pointer state. Instead of saying so, you fake it with
`addMeasurePick({point: bbox.center})` and ship a clip that doesn't
show what was asked.
Why it happens: faking is faster than admitting a limitation.
Why it is wrong: the user can tell. Faked interactions look faked.
The original feature request goes un-tested.
Fix: when you hit a UI capability you can't reach via current APIs,
you have **two acceptable paths** — and faking is never an acceptable
third option:
- **(a) Tell the user explicitly:** "I can't synthesize a face-click
from `/eval`. Want to do that part yourself in 5 seconds, or want
me to add a CLI command for it?"
- **(b) Add the CLI command.** Pattern: `<tool> <verb> --face <mesh>
--uv 0.5,0.5` synthesizes a real `PickingInfo` and routes through
the same handlers the mouse pick fires. Now the demo CLI doubles
as proof the feature works headlessly.
### 5. Punting on snippets that fail because the underlying feature is broken
Symptom: the Inspector clip won't record because something in the
inspector breaks `scene.activeCamera` access mid-clip. You drop the
clip from the demo and ship N-1 instead of N.
Why it happens: dropping the clip is one line. Investigating the bug
is unbounded.
Why it is wrong: **the demo IS a unit test of the user's product.**
Failing to record told you there's a real bug in feature X. Skipping
the clip means the demo is incomplete AND the bug stays. Both bad.
Fix: investigate the failure. Fix the underlying bug. Get the
snippet. The demo and the product co-evolve. If the bug is genuinely
beyond the demo session's budget, raise it explicitly: "Inspector is
hitting bug X. Options: 30 min to investigate, drop clip with a
follow-up tracking item, or you decide." Don't decide unilaterally.
### 6. Treating mux/concat as the finish line instead of as a slow background task
Symptom: snippets done → run `ffmpeg concat` (60–90 s of waiting) →
upload → ask user to review final.
Why it happens: ffmpeg's "the file is done" output feels like
completion.
Why it is wrong: ffmpeg concat doesn't need user attention. The user
reviewing snippets in storyboard doesn't need ffmpeg done. These
should run in parallel.
Fix: the moment the last snippet is recorded, kick off
`(ffmpeg concat ... &)` (background bash) AND
`adom-video-post storyboard <manifest>` (foreground for the user). By the
time the user clicks through snippets, the mux is either done OR
you've already killed it because they flagged a re-shoot. Detail in
[per-snippet-flow.md](per-snippet-flow.md) ("Background-mux while the user reviews" section).
### 7. Surprise-omitting parts of what was asked
Symptom: midway through recording you realize Inspector won't work or
Strobe is unstable. You silently drop those clips. The user finds out
from the final video.
Why it happens: surprise omissions feel less awkward than confessing
a gap mid-flow.
Why it is wrong: the user expects what they asked for. Silent omits
look like lying. They erode trust on every wrap-up message you write
afterward.
Fix: as soon as a snippet fails twice and you don't see the fix path,
message the user immediately: "Inspector clip is failing because of
X. Three options: I investigate (~30 min), I drop with a follow-up
tracking item, or you confirm we ship without it." Wait for the
answer. Don't decide unilaterally.
### 8. Failing to capture lessons in the skill so the next session repeats them
Symptom: same demo session, same ten failure modes, three different
conversations. The user is the only continuity.
Why it happens: it's "obvious" you'll remember next time. You won't —
your memory ends with the conversation.
Why it is wrong: skill files in gallia load on every Claude Code
session. Memory is local. Lessons that apply to "demos in general"
belong in the skill file, not in chat.
Fix: if the user gives you feedback that applies to FUTURE demo
sessions, the conversation isn't done until you've written the
lesson into the skill file and committed it to gallia.
### 9. Tolerating a slow capture mechanism instead of fixing the page
Symptom: you spend 60–90 minutes wrestling with paint-throttling,
screenshot polling, and frame deduplication. You eventually settle
for a 1–2 fps slideshow instead of fixing the page-side repaint bug.
Why it happens: the capture API is the visible surface; "the page
isn't repainting" is invisible.
Why it is wrong: documented in the "NEVER stitch screenshots" rule
in [recording-mechanics.md](recording-mechanics.md). The capture
mechanism (`browser_record_start`) is fine. The page-side fix
(continuous setInterval pump that mutates camera + `scene.render()`;
strip ArcRotateCamera input handlers) is the answer.
Fix: read the "NEVER stitch screenshots" rule before starting any
pup recording. Treat it as a precondition, not a fallback to
remember after the slideshow ships.
### 10. Inflating the wrap-up message past what was actually delivered
Symptom: "All 6 clips at 20-30 fps with real motion!" — when actually
clip 5 is barely above the SSIM threshold, clip 6 was deferred,
Inspector got skipped, and the measure picks are bbox-centroid fakes.
Why it happens: wrap-ups feel like victory laps. You skim past the
compromises.
Why it is wrong: the user can scrub through 70 seconds of video.
They WILL notice. "I claimed it was great" → they distrust every
wrap-up message you write afterward.
Fix: end-of-demo report is brutal-honest. Per-clip table with
quality grade per clip. Mark skipped clips, faked interactions,
lower-quality compromises, and SSIM headroom. End with "OK to ship?"
not "shipped, here's the URL."
## Step 1: Ask how the user wants to record
Present the user with a choice using AskUserQuestion:
> **How would you like to record?**
>
> 1. **Quick recording** — I'll start recording your screen with your mic on.
> You narrate live, stop when done. Ready to upload immediately.
> 2. **Polished recording** — I'll write a sectioned script first, then record
> each section as its own clip, generate TTS per section, and `adom-video-post`
> concats them into one final video. This is the canonical path for
> feature-tour demos.
> 3. **Just post-process** — I already have a recording. (→ hand off to
> `adom-video-post` skill)
### Quick recording
If the user picks option 1, see
[per-snippet-flow.md](per-snippet-flow.md) ("Quick recording" section).
### Polished recording (the canonical path)
If the user picks option 2, follow this sequence:
1. **Read [script-and-tts.md](script-and-tts.md)** and write the demo
script at `<repo>/demo/<name>-demo-script.md`. Show the script to
the user for approval BEFORE recording.
2. **Read [recording-mechanics.md](recording-mechanics.md)** to pick
your capture surface (Hydrogen by default; pup if Hydrogen is
busy) and apply the page-side repaint guarantees.
3. **Read [per-snippet-flow.md](per-snippet-flow.md)** and execute
Steps 3–8 (verify, record, manifest, storyboard review, concat,
hero, publish, restore workspace).
Each sub-doc cross-links back here and to siblings — load the one
that matches the phase you're in, not all three at once.
## See also
- [recording-mechanics.md](recording-mechanics.md) — capture path, surfaces, frame-rate sanity, NEVER stitch screenshots
- [script-and-tts.md](script-and-tts.md) — script template, narration phonetics, captions
- [per-snippet-flow.md](per-snippet-flow.md) — verify, record, manifest, storyboard review, concat, hero, publish, workspace restore
- [tts-pronunciation](../tts-pronunciation/SKILL.md) — Adom-specific TTS phonetics
- `adom-video-post` skill (system-installed) — speedup, voiceover, publish-to-wiki post-recording
## Recorded-tab verification BEFORE recording starts
Always `pup browser_screenshot` the target tab and visually confirm it before calling `recording start`. The `active-tab` selector can silently miss (off-screen tab, multi-window setup, recently-closed tab repurposed). A bad active-tab selection can cost an entire 30+ scene demo to re-record.
## Board fills the recording frame
For a PCB-centric demo, never zoom so far that the board looks tiny in the frame. For RP2040-class boards, set radius 1.2–1.5 after `view isometric`. Screenshot the framing before `recording start` and check visually — text-only "view is set" is insufficient proof.
## Demo recording fixes (hard-won)
These are the specific framings and setup tweaks that the user has confirmed across multiple demos:
- **Maximize the Fusion window** before any Fusion-side recording — partial windows look amateurish
- **Use `browser_focus_window` for pup**, NOT `desktop_bring_to_front`. The latter is jarring and disrupts the user; the former just brings the pup window forward without animating
- **Revoke approvals in ALL demo setups** — old "always allow" approvals get bypassed during the recording and the demo looks like the user already trusted everything (which the demo is supposed to be showing as a fresh setup)
- **Never run demos as background bash scripts** — they need foreground control so the recorder can pause/resume cleanly
## Use adom-video for video playback
For "show / play / view / watch / scrub a video" requests, drop the file in `/tmp/videolib/` and open the adom-video viewer at the appropriate port-mapped URL. Gives frame-accurate scrub + A-B loop + pixel zoom. Never serve raw `.webm` over a one-off `python -m http.server` + raw file URL — the viewer features are worth the setup.