# adom-tsci/demo-recording — making 30-second adom-tsci demos that don't suck

**Read this before recording a demo of any adom-tsci board.** Captures
the rules, layout choices, and beat structure that produce a watchable
30-second showcase video. Written after several false starts on the
Brianna LED Nameplate demo where captions covered the 3D viewer,
captions wrapped to four lines, and the x-ray shot was missing.

## The non-negotiables

These are the rules. Violating any of them fails the demo, so check
them up-front rather than after the recording.

### 1. Workspace layout: 30% AI chat (VS Code) / 70% content (3D viewer)

A demo where the 3D viewer is anything less than 70% of the frame
looks cramped and amateur. The chat panel exists so the viewer reads
"this is being driven by an AI", but it should not compete for
attention.

**Set this before you start the recording.** Find the horizontal
split that holds VS Code on the left and the adom-tsci tab on the
right, then resize:

```bash
# 1. Find the split
adom-cli hydrogen workspace get | python3 -c '
import json, sys
d = json.load(sys.stdin)
def walk(n, parent=None):
    if n.get("type") == "leaf": return
    yield n
    yield from walk(n["first"], n)
    yield from walk(n["second"], n)
print([(s["id"], s.get("ratio")) for s in walk(d["root"])])
'

# 2. Resize the relevant split to 30/70
adom-cli hydrogen workspace resize --split-id <ID> --ratio 0.30
```

The ratio is the proportion of width given to the **first** child of
the split (VS Code is typically the first child).

### 2. Captions: ALWAYS use `-s small` for adom-tsci demos

`adom-cli hydrogen caption show "<text>" -d <sec> -p bottom -s small`

`-s large` and `-s medium` produce captions that wrap to 3-4 lines
even at moderate text length, dominate the 3D viewer, and look like a
slideshow not a demo. `-s small` produces a single-line caption at
the bottom of the workspace that doesn't compete with the content.

**Pre-flight test before recording — required.** Show one sample
caption at the size you plan to use, screenshot the panel, and
verify visually:

```bash
adom-cli hydrogen caption show "Sample caption text — does this wrap?" -d 4 -p bottom -s small
adom-cli hydrogen screenshot panel --tab-id <BRIANNA_TAB_ID> --reason "test caption size for demo"
# Read the screenshot and confirm: single line, no wrap, no scrollbar
```

If the test caption wraps OR shows a scrollbar (overflow:auto on the
caption container kicking in), shorten the text *or* drop to a
smaller size before recording. Once you're committed to the recording,
you can't fix it without re-recording.

**Caption text length budget:** about 35 characters at `-s small` to
guarantee a single line on a typical workspace width. If the demo
demands a longer line, split the thought into two beats with two
captions instead of one wrapped caption.

### 3. The x-ray shot is mandatory — and it is the Nets HUD's net-isolate-with-GlowLayer view, not "hide some components"

EE viewers literally clap when they see this. It is the differentiator
of adom-tsci's 3D viewer.

**The actual x-ray** is what `enableTraceMode()` + `selectNet(<id>)`
produce together: the FR4 substrate goes 30% alpha (you see THROUGH
the board), every routed `pcb_trace` lifts off the baked surface as a
live 3D copper polygon, every plated through-hole renders as a real
via, the SELECTED net's traces and vias get HighlightLayer + GlowLayer
bloom on top, and the GlowLayer intensity throbs ~1.5 Hz. You can see
the conductive path light up *through* the board. That's the shot.

**It is NOT "hide some chips and look at the resistor mesh underneath."**
That just exposes the baked surface — no transparency, no glow, no
vias-through-board. Don't confuse the two. Hiding components is a
useful *secondary* shot for some demos, but it's not the x-ray.

**How to drive it:**

```bash
# Open the Nets HUD — auto-glow picks the biggest power/ground net
# (or the biggest signal net if no power/ground), so the GlowLayer
# x-ray is on the moment the panel opens. v1.3.91+.
adom-tsci net --on --port $PORT
sleep 4   # let the substrate fade and the auto-pick fire

# Or: manually select a specific net to focus the glow on it.
adom-tsci net VBUS --port $PORT      # by net name
adom-tsci net "J1.VBUS1 ↔ R0.pin1" --port $PORT   # by id

# Close to dispose the heavy trace meshes and return to baked surface.
adom-tsci net --off --port $PORT
```

**For boards where every net is a tiny 2-port pair** (e.g. a 70-LED
nameplate where each LED-to-resistor is its own net), auto-glow still
works but the highlighted segment is only ~1 mm long and barely reads
on camera. In those cases, declare an explicit power rail
(`<net name="VBUS"/>` plus `<trace from="..." to="net.VBUS"/>` for
every endpoint) so the autorouter merges them into one mega-net the
HUD can light up gloriously. If you can't change the board, fall back
to a `tour` orbit while panning slowly — the substrate transparency
alone is striking even without a single net selected.

The non-mandatory secondary shot of "hide letter B's LEDs to expose
the baked resistor row" is fine to include, but it goes in the same
beat as the x-ray, not as a replacement for it.

### 4. Captions AND TTS — both, not either

Captions handle sound-off viewers. TTS handles eyes-elsewhere
viewers. A demo with only one is half-finished. The two carry the
same script — the caption is a tighter rendering of the same thought
spoken in TTS.

**Voice:** `en-US-AndrewNeural` (Adom house voice — see
`adom-tts` skill). Generate one MP3 per beat in parallel:

```bash
mkdir -p /tmp/<project>-tts
adom-tts say --out /tmp/<project>-tts/01.mp3 "BRIANNA. A USB-C powered desk nameplate." &
adom-tts say --out /tmp/<project>-tts/02.mp3 "Each letter is a 3 by 5 LED bitmap." &
# ... one per beat
wait
```

Mix the TTS clips into the recorded webm with ffmpeg, transcoding to
mp4 for portability:

```bash
ffmpeg -y -i recording.webm \
  -i 01.mp3 -i 02.mp3 -i 03.mp3 -i 04.mp3 \
  -i 05.mp3 -i 06.mp3 -i 07.mp3 -i 08.mp3 \
  -filter_complex "
    [1:a]adelay=0|0[a1];
    [2:a]adelay=3000|3000[a2];
    [3:a]adelay=6000|6000[a3];
    [4:a]adelay=10000|10000[a4];
    [5:a]adelay=15500|15500[a5];
    [6:a]adelay=19000|19000[a6];
    [7:a]adelay=23000|23000[a7];
    [8:a]adelay=28500|28500[a8];
    [a1][a2][a3][a4][a5][a6][a7][a8]amix=inputs=8:dropout_transition=0:normalize=0[a]" \
  -map 0:v -map "[a]" \
  -t 32 \
  -c:v libx264 -preset veryfast -crf 22 -pix_fmt yuv420p \
  -c:a aac -b:a 160k \
  demo.mp4
```

The `adelay` offsets are milliseconds and should match the beat
timing in the recording script. **Set them with the same script
that drove the recording** — copy the timestamps directly so audio
and captions stay in sync.

### 5. ~30 seconds total, 8 beats of 3-5 s each

A 30-second demo is the sweet spot — long enough to show the x-ray,
short enough that someone scrolling Slack will actually watch it.
Going over 30 s for an adom-tsci demo means you're showing too many
components. Going under 20 s means you skipped the x-ray.

The beat structure that's worked:

| Beat | Time | Caption | Camera | Purpose |
|---|---|---|---|---|
| 1 | 0-3   | "<board name> — <one-line pitch>" | iso | hero shot |
| 2 | 3-6   | "<key concept>" | top | establish board geometry |
| 3 | 6-10  | "Real CAD bodies, autorouted" | tour start | cinematic flyover |
| 4 | 10-15 | "X-ray. See through the FR4." | `adom-tsci net --on` → substrate goes transparent, traces lift off, GlowLayer pulse on the auto-selected net | **the money shot** |
| 5 | 15-18 | "<per-pixel or per-net detail>" | optionally `adom-tsci net <NAME>` for a specific rail; or close panel | secondary detail |
| 6 | 18-22 | "<USB-C / power detail>" | iso | power input |
| 7 | 22-27 | "Bottom silkscreen documents how it all works" | bottom | flip to docs |
| 8 | 27-30 | "Plug it in. <thing> happens." | iso | closing |

Beat 4's text says "X-ray" explicitly. EEs scan for that word.

## Pre-flight checklist (run before `recording start`)

```bash
# 1. Layout: 30/70
adom-cli hydrogen workspace resize --split-id <ID> --ratio 0.30

# 2. Tab is active and on the correct slingshot URL
adom-cli hydrogen workspace active-tab --tab-id <ID> --panel-id <ID>
# screenshot to confirm 3D scene is rendered, not stuck on "Loading…"
adom-cli hydrogen screenshot panel --tab-id <ID> --reason "verify 3D rendered before recording"
# Read the screenshot. Does the board fill the right pane?

# 3. Caption size test
adom-cli hydrogen caption show "Sample caption text" -d 4 -p bottom -s small
sleep 1
adom-cli hydrogen screenshot panel --tab-id <ID> --reason "verify caption single line"
# Read the screenshot. Single line? No scrollbar? If yes, proceed.

# 4. Hide the components HUD so it doesn't dominate the recording
adom-tsci eval "document.querySelector('#toggle-components-btn')?.click()" --port $PORT

# 5. Start at iso view
adom-tsci view iso --port $PORT
```

## Post-flight checklist

```bash
# 1. Frame-extract at the x-ray timestamp and confirm subset is hidden
ffmpeg -hide_banner -loglevel error -i recording.webm -ss 12 -vframes 1 /tmp/xray-check.png
# Read it. Are the right LEDs missing?

# 2. Frame-extract at every caption beat — confirm single-line, readable
for t in 1 5 12 20 25 28; do
  ffmpeg -hide_banner -loglevel error -i recording.webm -ss $t -vframes 1 /tmp/caption-$t.png
done
# Read them. Any wrapping? Any overflow? Any scrollbar pixels?

# 3. Mix TTS, transcode to mp4, verify duration is 30-32 s
ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 demo.mp4

# 4. RE-ENCODE to add keyframes every 1 s — wiki video element can't
#    scrub a webm with only one keyframe at frame 0. Mandatory for any
#    single-shot demo bound for `adom-wiki asset upload --asset-type video`.
ffmpeg -y -i recording.webm -c:v libvpx-vp9 -b:v 2M -deadline good \
  -g 30 -keyint_min 30 -c:a copy demo.webm
# (mp4 path: -c:v libx264 -g 30 -keyint_min 30 \
#   -force_key_frames "expr:gte(t,n_forced*1)" -c:a aac demo.mp4)

# Verify keyframes landed at ~1 s intervals (should print multiple K_ lines):
ffprobe -v error -select_streams v:0 -show_entries packet=pts_time,flags \
  -of csv=p=0 demo.webm | awk -F, '$2 ~ /K/' | head

# 5. Upload to wiki page as asset-type=video
adom-wiki asset upload <type>/<slug> --asset-type video --file demo.mp4 \
  --caption "30-second demo: …"
```

## Failure modes to recognise instantly

| Symptom in the recording | Likely cause | Fix |
|---|---|---|
| Caption wraps to 2-4 lines | `-s large` or `-s medium`; long caption text | Re-record with `-s small` and ≤35-char captions |
| Caption shows a scrollbar | Caption container CSS `overflow:auto`; text too long | Shorten text, split into two beats |
| 3D viewer feels cramped | Workspace split is 50/50 or worse | Resize to 30/70 before recording |
| Skipped the x-ray shot (only hid components) | Confused "x-ray" with "hide subset". Real x-ray = substrate-transparent + GlowLayer-on-selected-net via the Nets HUD | Re-record using `adom-tsci net --on` (auto-glow picks the biggest power/ground net) |
| Substrate doesn't go transparent | Trace mode never enabled | `adom-tsci net --on` (or click the ⌇ toolbar button) |
| Substrate transparent but no glow on any net | No net selected; auto-glow disabled or failed to pick | Click the ✦ button in the Nets HUD header to re-arm; or `adom-tsci net <NAME>` to pick manually |
| Selected net glows but the highlight is barely visible | Every net on this board is tiny (2-port LED-R pair). Single-segment glow doesn't read on camera | Add an explicit `<net name="VBUS"/>` + connect every endpoint to it so the autorouter merges into one mega-rail |
| Audio out of sync | `adelay` offsets don't match beat timing | Re-derive offsets from the recording script's `sleep` accumulation |
| Camera doesn't actually move | `adom-tsci view` called before tab was active | Active-tab the recording tab BEFORE the demo script |

## Tooling stack

- **adom-cli hydrogen recording start/stop** — produces a webm
- **adom-cli hydrogen caption show** — bottom overlay, recordable
- **adom-cli hydrogen workspace resize** — set the 30/70 split
- **adom-tsci view / tour / toggle-component** — drive the 3D viewer
- **adom-tts say** — Andrew Neural TTS clip per beat
- **ffmpeg** — mix TTS audio onto the webm, transcode to mp4

The demo workflow lives entirely on adom CLIs + ffmpeg. No GUI
post-production needed for a 30-second showcase.

## See also

- **Brianna LED Nameplate** — first board this guide was written
  against. Wiki page:
  `https://wiki-ufypy5dpx93o.adom.cloud/molecules/brianna-led-nameplate`.
  Demo video at `/static/apps/brianna-led-nameplate/brianna-demo.mp4`
  is the canonical example.
- **adom-tts** — TTS skill, voice selection, pronunciation overrides.
- **video-post** — for longer-form post-production (speedup, voice
  re-recording, multi-clip stitching). Not needed for the 30-second
  case described here.
