$npx -y skills add gooseworks-ai/goose-skills --skill render-vo-anchored-motion-listicleAssemble an expert/educator motion-graphic LISTICLE video ad from a config — a spoken authoritative voiceover carries a numbered listicle while N web-animated hyperframe beats (HTML plus the Web Animations API, one branded design system of alternating tiles, big hero numerals, an
| 1 | # render-vo-anchored-motion-listicle |
| 2 | |
| 3 | Assemble an **expert/educator motion-graphic listicle** ad from a config: an authoritative spoken |
| 4 | voiceover carries a numbered listicle (hook + N points + CTA) and every visual beat is anchored to |
| 5 | the VO's word-level timestamps. Each beat is a **web-animated hyperframe** (an HTML page + the Web |
| 6 | Animations API driven by `window.renderAt(t)`) rendered to video frame-by-frame with Playwright, all |
| 7 | in ONE branded design system (alternating background tiles, big hero numerals, body type, decorative |
| 8 | SVG accents, glass-pill callouts). Periodic color-graded **B-roll windows** give visual breath, and |
| 9 | captions burn **only on the B-roll windows**. The shipped master is pure motion-graphic + VO — there |
| 10 | is NO lipsync (the still expert headshot is kept only for a future lipsync variant). This capability |
| 11 | is the **FREE, deterministic assembly** — the Playwright beat render, the ffmpeg concat, the |
| 12 | window-masked caption burn, the VO+music mix, and the final composite. |
| 13 | |
| 14 | `scripts/config.example.json` is the worked example (Everself "doctor-educator" listicle, ~66s |
| 15 | 1080×1920 9:16 at 25fps); `scripts/PIPELINE.md` maps every config block to its source step and |
| 16 | `scripts/README.md` documents the free assembly. |
| 17 | |
| 18 | ## Run |
| 19 | |
| 20 | This is the **FREE, deterministic** assembly stage — it spends nothing. The paid inputs are separate |
| 21 | capabilities — the spoken VO (`create-vo-elevenlabs`, a cloned or cast expert voice, `eleven_v3` + |
| 22 | `atempo`) whose word-level timestamps (Groq `whisper-large-v3` word-level) set the timeline; the low |
| 23 | music bed (`create-music-elevenlabs`); and the stock B-roll (`media-proxy`, trimmed + color-graded). |
| 24 | Given the VO + `words-flat.json` + the N authored hyperframe beats + the color-graded B-roll windows + |
| 25 | the brand wordmark SVG, `render-vo-anchored-motion-listicle` renders each beat frame-by-frame via |
| 26 | Playwright (all beats at fps 25), concats the beats + B-roll, burns the window-masked captions, mixes |
| 27 | the VO under the low music bed, and composites → the master. Re-cuts reuse the existing VO / beats / |
| 28 | B-roll and cost **$0**. |
| 29 | |
| 30 | ## Contract (the free assembly) |
| 31 | |
| 32 | - **The spoken VO carries the listicle — it sets the timeline.** The cloned/cast expert VO is the |
| 33 | spine; Whisper-transcribe it to word-level timestamps and anchor every beat reveal to those word |
| 34 | times. There is no on-camera human and NO lipsync in the shipped master. |
| 35 | - **Beats are web-animated hyperframes, rendered deterministically.** Each beat is an HTML page + the |
| 36 | Web Animations API driven by `window.renderAt(t)`; Playwright screenshots it frame-by-frame and |
| 37 | ffmpeg encodes it. This is NOT i2v — it is deterministic web motion graphics. |
| 38 | - **ALL beats share the same fps (25).** A mismatched-fps beat stutters at the concat seam. Render |
| 39 | every beat and every B-roll window at fps 25. |
| 40 | - **ONE design system across every beat.** A single `_shared.css` (palette + type + alternating |
| 41 | tiles + accents + glass-pill) so N beats read as one designed reel; alternate only the background |
| 42 | tile, keep numerals / body / accents / pills consistent. |
| 43 | - **Periodic color-graded B-roll windows for breath.** Trim + color-grade each stock/brand clip to |
| 44 | the palette (fps 25). These windows are the ONLY captioned windows. |
| 45 | - **Captions ONLY on the B-roll windows.** On the motion-graphic beats the on-screen type IS the |
| 46 | caption — burning Whisper captions there double-stacks text. Build the caption ASS from the VO word |
| 47 | timings, kept only inside the B-roll windows, 2-word chunks, closing a cue on any >0.4s word gap. |
| 48 | The ASS `Format:` header MUST carry a `Name` field — without it the leading-comma bug eats the |
| 49 | first field and captions silently drop. If the host ffmpeg lacks libass, render the cues as timed |
| 50 | PIL PNG overlays (ffmpeg `overlay=…:enable='between(t,st,en)'`) at the same placement. |
| 51 | - **Low music bed under the VO.** The VO is the spine; the ElevenLabs Music bed sits ~0.18 vol under |
| 52 | it. No ducking needed at that level. |
| 53 | - **Never AI- |