diff --git a/.claude/skills/capturing-voltius-media/SKILL.md b/.claude/skills/capturing-voltius-media/SKILL.md new file mode 100644 index 00000000..defdcd57 --- /dev/null +++ b/.claude/skills/capturing-voltius-media/SKILL.md @@ -0,0 +1,112 @@ +--- +name: capturing-voltius-media +description: Use when producing screenshots or videos of the Voltius app UI for docs, blog posts, changelog, or demos — capturing or recording the live headless dev build and editing the result (crop, zoom, loop) with ffmpeg. +--- + +# Capturing Voltius Media (screenshots & video) + +Produce real screenshot and video assets of the Voltius desktop app by driving the +**headless dev build** and screen-grabbing its Xvfb framebuffer. Same stack as +[[iterating-on-voltius-ui]] (`compose.headless.yml`: `tauri-headless` = app + Xvfb + +tauri-driver on 4444; `ssh-host-1` = throwaway SSH host `voltius`/`voltius`). + +**Path note:** the screenshot pipeline and brand framing live in the **docs sibling repo**, +`../docs/tools/screenshots/` — one level *up* from the voltius repo (there is no `docs/` +inside voltius). All references below are to that sibling path. + +## ⚠️ The one thing that will silently ruin captures + +**WebKitGTK renders opacity/transform animations (CSS transitions, `animate-fadeIn`, +dropdown/modal open) on GPU compositor layers. Under Xvfb's software path those layers +are NOT flushed to the X framebuffer that a screen grab reads** — so recordings show +**instant jumps with no transitions**, and a screenshot taken mid-animation shows the +pre-animation state. There is no error; it just looks wrong. + +**Fix: run the app with `WEBKIT_DISABLE_COMPOSITING_MODE=1`.** It's baked into +`compose.headless.yml` (`tauri-headless` `environment:`). Verify before trusting a capture: + +```bash +docker exec tauri-headless sh -c 'pid=$(pgrep -f target/debug/voltius|head -1); \ + tr "\0" "\n" ` — put the scene .mjs directly + in `/tmp` and pass a **bare filename**, not a path. +2. **Recording.** ffmpeg `x11grab` on the app's display. Derive `DISPLAY`/`XAUTHORITY` + from the running app process (the Xvfb auth path regenerates per boot). Grab the exact + window region (set the window to a known size first, e.g. `1200x800@0,0`). See + `record-video.sh` — it also logs an `event → epoch` **timeline** so edits can key zooms + to real moments. +3. **Editing = ffmpeg only.** `edit-video.sh` has the recipes: crop, **smooth keyed zoom + via `zoompan`** (NOT `crop` — `crop` evaluates `w`/`h` once at config time, so it can't + animate; `zoompan` can), supersample-then-downscale to kill zoom shimmer, clean loop, + and web encode (`-pix_fmt yuv420p -movflags +faststart`, silent). + +Blog `