Claude Skill

render-vo-anchored-motion-listicle

Assemble 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

LLM Mart · 0 points · 4 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download gooseworks-ai-goose-skills-skills_ads_capabilities_render-vo-anchored-motion-listicle-e1592ee.zip · 11 KB
Part of gooseworks-ai/goose-skills — 44 skills

Install

skills CLI npx skills add https://github.com/gooseworks-ai/goose-skills/tree/main/skills/ads/capabilities/render-vo-anchored-motion-listicle
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install gooseworks-ai-goose-skills@llmmart
Git git clone https://github.com/gooseworks-ai/goose-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole gooseworks-ai/goose-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

render-vo-anchored-motion-listicle

Assemble an expert/educator motion-graphic listicle ad from a config: an authoritative spoken voiceover carries a numbered listicle (hook + N points + CTA) and every visual beat is anchored to the VO's word-level timestamps. Each beat is a web-animated hyperframe (an HTML page + the Web Animations API driven by window.renderAt(t)) rendered to video frame-by-frame with Playwright, all in ONE branded design system (alternating background tiles, big hero numerals, body type, decorative SVG accents, glass-pill callouts). Periodic color-graded B-roll windows give visual breath, and captions burn only on the B-roll windows. The shipped master is pure motion-graphic + VO — there is NO lipsync (the still expert headshot is kept only for a future lipsync variant). This capability is the FREE, deterministic assembly — the Playwright beat render, the ffmpeg concat, the window-masked caption burn, the VO+music mix, and the final composite.

scripts/config.example.json is the worked example (Everself "doctor-educator" listicle, ~66s 1080×1920 9:16 at 25fps); scripts/PIPELINE.md maps every config block to its source step and scripts/README.md documents the free assembly.

Run

This is the FREE, deterministic assembly stage — it spends nothing. The paid inputs are separate capabilities — the spoken VO (create-vo-elevenlabs, a cloned or cast expert voice, eleven_v3 + atempo) whose word-level timestamps (Groq whisper-large-v3 word-level) set the timeline; the low music bed (create-music-elevenlabs); and the stock B-roll (media-proxy, trimmed + color-graded). Given the VO + words-flat.json + the N authored hyperframe beats + the color-graded B-roll windows + the brand wordmark SVG, render-vo-anchored-motion-listicle renders each beat frame-by-frame via Playwright (all beats at fps 25), concats the beats + B-roll, burns the window-masked captions, mixes the VO under the low music bed, and composites → the master. Re-cuts reuse the existing VO / beats / B-roll and cost $0.

Contract (the free assembly)

  • The spoken VO carries the listicle — it sets the timeline. The cloned/cast expert VO is the spine; Whisper-transcribe it to word-level timestamps and anchor every beat reveal to those word times. There is no on-camera human and NO lipsync in the shipped master.
  • Beats are web-animated hyperframes, rendered deterministically. Each beat is an HTML page + the Web Animations API driven by window.renderAt(t); Playwright screenshots it frame-by-frame and ffmpeg encodes it. This is NOT i2v — it is deterministic web motion graphics.
  • ALL beats share the same fps (25). A mismatched-fps beat stutters at the concat seam. Render every beat and every B-roll window at fps 25.
  • ONE design system across every beat. A single _shared.css (palette + type + alternating tiles + accents + glass-pill) so N beats read as one designed reel; alternate only the background tile, keep numerals / body / accents / pills consistent.
  • Periodic color-graded B-roll windows for breath. Trim + color-grade each stock/brand clip to the palette (fps 25). These windows are the ONLY captioned windows.
  • Captions ONLY on the B-roll windows. On the motion-graphic beats the on-screen type IS the caption — burning Whisper captions there double-stacks text. Build the caption ASS from the VO word timings, kept only inside the B-roll windows, 2-word chunks, closing a cue on any >0.4s word gap. The ASS Format: header MUST carry a Name field — without it the leading-comma bug eats the first field and captions silently drop. If the host ffmpeg lacks libass, render the cues as timed PIL PNG overlays (ffmpeg overlay=…:enable='between(t,st,en)') at the same placement.
  • Low music bed under the VO. The VO is the spine; the ElevenLabs Music bed sits ~0.18 vol under it. No ducking needed at that level.
  • Never AI-render the brand lockup. The CTA / end beat composites the brand's real wordmark, never text-in-diffusion.
  • FFmpeg composite, deterministic, FREE. Render each beat via Playwright, concat the beats + B-roll (ffmpeg demuxer), burn the window-masked caption ASS, mix the VO under the music bed, loudnorm I=-14 → a 1080×1920 25fps h264 crf18 + aac 192k master. No paid calls, no keys.
Files (goose-skills)
  • scripts
    • config.example.json 8.6 KB
      {
        "_comment": "Everself 'doctor-educator' listicle — THE WORKED EXAMPLE. Copy to config.json and edit. A ~66s 9:16 (1080x1920, 25fps, h264 crf18 + aac 192k) EXPERT motion-graphic LISTICLE where a CLONED authoritative clinician VO narrates a numbered listicle and every beat reveal is anchored to the VO's word-level timestamps. Pipeline: (1) lock the VO (ElevenLabs clone, eleven_v3, atempo) — it sets the timeline; (2) Groq whisper-large-v3 word-level -> working/whisper/words-flat.json; (3) author N hyperframe beats (HTML + Web Animations window.renderAt(t)) in ONE design system (_shared.css / _shared.js); (4) periodic color-graded B-roll windows for breath; (5) render each beat frame-by-frame via Playwright (render_hf.py, ALL beats fps 25), concat, mix the VO under a low music bed, composite + burn window-masked captions (build_master_v4.py) -> finals/everself-v4-master.mp4. NO lipsync — the still headshot is kept only for a future lipsync variant. See scripts/PIPELINE.md for the source scripts.",
        "brand_name": "Everself",
        "campaign": "doctor-educator listicle",
        "title": "What your dermatologist wishes you knew",
        "width": 1080,
        "height": 1920,
        "fps": 25,
        "duration_sec": 66.0,
        "aspect_ratio": "9:16",
        "video_codec": "h264 crf18",
        "audio_codec": "aac 192k",
        "voice": {
          "_comment": "Locked FIRST — the VO sets the timeline. mode 'clone' here: an ElevenLabs voice cloned from a short reference sample of the clinician (Dr. McGowan), then narrated over the listicle script with eleven_v3, then atempo'd to the target pace. Word-level timestamps come from Groq whisper-large-v3 on the RENDERED VO. The clinician headshot is retained only for a FUTURE lipsync variant — this master has NO lipsync.",
          "mode": "clone",
          "provider": "elevenlabs",
          "model": "eleven_v3",
          "voice_id": "cloned-mcgowan",
          "atempo": 1.06,
          "reference_sample": "voice/dr-mcgowan-all-shorts.mp3",
          "clone_script": "voice/clone_voice.py",
          "narrate_script": "voice/render_listicle_v2.py",
          "outputs": {
            "audio": "voice/listicle-mcgowan-v2-render.mp3",
            "raw": "voice/listicle-mcgowan-v2-raw.mp3",
            "word_timings": "working/whisper/words-flat.json"
          }
        },
        "design": {
          "_comment": "ONE branded design system for all N beats. _shared.css holds the tokens (palette, type, alternating background tiles, decorative SVG accents, glass-pill callout); _shared.js holds initRenderer + revealWords + easing. Alternate ONLY the background tile per beat; keep the big hero numerals, body type, accents, and pills CONSISTENT so the reel reads as one designed piece.",
          "name": "EVERSELF_EDUCATOR",
          "heading_font": "Editorial serif (heading)",
          "body_font": "Grotesk sans (body)",
          "numeral_style": "big hero numeral in the brand accent color, top-left of each point beat",
          "palette": ["warm cream #F6F1EA", "deep clinical teal", "brand accent coral", "soft charcoal type"],
          "background_tiles": ["cream-tile", "teal-tile"],
          "accents": ["hand-drawn arc underlines", "dotted rule", "small SVG plus marks"],
          "callout_style": "glass-pill (frosted rounded rectangle, coral border, charcoal type)",
          "shared_css": "working/hyperframes-v4/_shared.css",
          "shared_js": "working/hyperframes-v4/_shared.js"
        },
        "beats": [
          { "id": "B01", "role": "hook", "anchor_word": "wishes", "anchor_t": 0.0, "hero_numeral": "", "headline": "What your dermatologist wishes you knew", "body": "5 things most routines get wrong.", "callout": "", "accent": "cream-tile" },
          { "id": "B02", "role": "point", "anchor_word": "first", "anchor_t": 6.4, "hero_numeral": "1", "headline": "More product isn't more results", "body": "Layering actives fights your barrier.", "callout": "Barrier first", "accent": "teal-tile" },
          { "id": "BR01", "role": "broll", "anchor_word": "", "anchor_t": 12.2, "broll_ref": "broll[0]", "_comment": "B-roll breath window — captions burn HERE only." },
          { "id": "B03", "role": "point", "anchor_word": "second", "anchor_t": 16.8, "hero_numeral": "2", "headline": "Sunscreen is the actual anti-aging step", "body": "Daily SPF beats every serum.", "callout": "SPF > serum", "accent": "cream-tile" },
          { "id": "B04", "role": "point", "anchor_word": "third", "anchor_t": 24.5, "hero_numeral": "3", "headline": "Retinol works slowly — on purpose", "body": "Twelve weeks, not twelve days.", "callout": "12 weeks", "accent": "teal-tile" },
          { "id": "BR02", "role": "broll", "anchor_word": "", "anchor_t": 32.0, "broll_ref": "broll[1]", "_comment": "Second B-roll breath window." },
          { "id": "B05", "role": "point", "anchor_word": "fourth", "anchor_t": 36.6, "hero_numeral": "4", "headline": "Fragrance is the hidden irritant", "body": "It's the first thing to cut.", "callout": "Cut fragrance", "accent": "cream-tile" },
          { "id": "B06", "role": "point", "anchor_word": "fifth", "anchor_t": 44.9, "hero_numeral": "5", "headline": "Consistency beats the fancy routine", "body": "Three steps you'll actually do.", "callout": "3 steps", "accent": "teal-tile" },
          { "id": "BCTA", "role": "cta", "anchor_word": "start", "anchor_t": 58.0, "hero_numeral": "", "headline": "Build a routine that actually works", "body": "", "callout": "everself.com", "wordmark": "brand-assets/logos/everself-wordmark.svg", "accent": "cream-tile", "_comment": "CTA / end beat — Everself wordmark composited from the real SVG (NEVER AI-rendered text)." }
        ],
        "broll": [
          { "id": "broll[0]", "source": "media-proxy", "query": "close-up serum drop skincare macro", "brand_clip": "", "t_start": 12.2, "t_end": 16.8, "graded": true, "captioned": true, "_comment": "Stock macro via media-proxy, trimmed + color-graded to the palette. Captions burn ONLY inside this window." },
          { "id": "broll[1]", "source": "media-proxy", "query": "woman applying sunscreen morning bathroom", "brand_clip": "", "t_start": 32.0, "t_end": 36.6, "graded": true, "captioned": true, "_comment": "Second stock breath window, graded to the palette; captioned." }
        ],
        "captions": {
          "_comment": "Built from the VO word timings (working/whisper/words-flat.json), kept ONLY inside the B-roll windows (broll[0], broll[1]), 2-word chunks, closing a cue on any >0.4s word gap. The ASS `Format:` header MUST include a `Name` field or the leading-comma bug eats the first field and captions silently drop. The motion-graphic beats are NOT captioned — their on-screen type IS the caption.",
          "source": "working/whisper/words-flat.json",
          "mask": "broll_windows_only",
          "chunk_words": 2,
          "gap_close_s": 0.4,
          "ass_format_has_name_field": true,
          "position": "lower-third",
          "no_pill": false,
          "font": "Grotesk sans Bold",
          "base_color": "#FFFFFF",
          "outline_px": 4
        },
        "music": {
          "_comment": "Low ElevenLabs Music bed UNDER the VO (~0.18 vol). The VO is the spine — the bed must not fight it. No artist names in the prompt (ElevenLabs Music ToS filter).",
          "provider": "elevenlabs",
          "model": "music_v1",
          "prompt": "Warm, minimal, editorial lo-fi bed — soft rhodes, brushed percussion, unobtrusive, clinical-calm. Sits low under a spoken voiceover.",
          "bed_volume": 0.18
        },
        "audio_mix": {
          "_comment": "VO at full, music bed ~0.18 under it. Loudnorm to -14 LUFS. No ducking needed at this bed level.",
          "vo_volume": 1.0,
          "music_bed_volume": 0.18,
          "loudness_lufs": -14
        },
        "headshot": {
          "_comment": "The still clinician headshot is kept for a FUTURE lipsync variant. The shipped motion-graphic + VO master does NOT use it.",
          "asset": "source/mcgowan-headshot.png",
          "used_in_master": false
        },
        "render_engine": {
          "_comment": "Each beat is an HTML hyperframe + the Web Animations API driven by window.renderAt(t); Playwright screenshots it frame-by-frame and ffmpeg encodes it. Deterministic web motion graphics, NOT i2v. ALL beats MUST share fps 25 — a mismatched-fps beat stutters at the concat seam.",
          "engine": "playwright+ffmpeg",
          "renderer": "window.renderAt(t) per frame -> Playwright screenshot -> ffmpeg encode",
          "fps": 25,
          "script": "working/render_hf.py",
          "hyperframes_dir": "working/hyperframes-v4/",
          "shared_css": "working/hyperframes-v4/_shared.css",
          "shared_js": "working/hyperframes-v4/_shared.js"
        },
        "post_production": {
          "voiceover": { "default": "on", "note": "the cloned/cast expert VO IS the spine and sets the timeline" },
          "music": { "default": "on", "note": "low ElevenLabs Music bed (~0.18 vol) under the VO" },
          "captions": { "default": "on", "note": "window-masked (B-roll only), 2-word chunks, close on >0.4s gaps, ASS Name-field header" },
          "end_card": { "default": "on", "note": "CTA beat uses the brand's real wordmark, never AI-rendered text" }
        }
      }
      
    • PIPELINE.md 6 KB
      # Pipeline — VO-anchored motion-graphic listicle
      
      How `config.example.json` maps to the real production steps. This molecule ships a
      **config + this map**, not a bundled runner: the worked example (Everself "doctor-educator"
      listicle) was produced by per-project drivers that live in
      `clients/everself-hb/working/doctor-christopher-avatar/` (`voice/render_listicle_v2.py`,
      `working/render_hf.py`, `working/build_pexels_beats.py`, `working/grade_brolls_v4.py`,
      `working/build_master_v4.py`). Reference those directly, or drive the whole run via
      `video-orchestrator-with-control-plane`.
      
      The steps run **in order** because each depends on the last: the VO sets the timeline (its
      word-level timestamps), the word times anchor every beat reveal, the beats + B-roll seed the
      render, the render + concat build the silent master, and assembly mixes the VO under the music
      bed + burns the window-masked captions.
      
      ## Field → source-script map
      
      | Config field | Phase | Source step / script (in the run) | Paid? |
      |---|---|---|---|
      | `voice.mode`, `voice.voice_id`, `voice.model`, `voice.atempo`, `voice.script_ref` | 1 VO | ElevenLabs clone/cast (`eleven_v3`) + ffmpeg `atempo` -> `voice/vo-render.mp3` | **PAID** |
      | `voice.outputs.word_timings` | 2 Transcribe | Groq `whisper-large-v3` word-level on the rendered VO -> `working/whisper/words-flat.json` | ~$0.10 |
      | `design.*`, `beats[].hero_numeral/headline/body/callout/accent` | 3 Beats | author N hyperframes (HTML + Web Animations `window.renderAt(t)`) in ONE design system -> `working/hyperframes-v4/beat-NN.html` + `_shared.css` + `_shared.js` | free |
      | `beats[].anchor_word`, `beats[].anchor_t` | 3 Beats | reveals anchored to word times in `words-flat.json` | free |
      | `render_engine`, `fps` | 5 Render | `working/render_hf.py` (Playwright frame-by-frame `renderAt(t)` -> ffmpeg encode; ALL beats share fps 25) | free |
      | `broll[].query`, `broll[].brand_clip`, `broll[].t_start/t_end`, `broll[].graded` | 4 B-roll | `working/build_pexels_beats.py` (download/trim) + `working/grade_brolls_v4.py` (color-grade to palette) | media-proxy (stock) |
      | `captions`, `captions.mask`, `captions.chunk_words`, `captions.gap_close_s`, `captions.ass_format_has_name_field` | 5 Captions | Whisper words -> ASS, kept only inside B-roll windows, 2-word chunks, close on >0.4s gaps (`Name`-field header) | free |
      | `music`, `music.bed_volume`, `audio_mix` | 5 Assembly | ElevenLabs Music bed (~0.18 vol) mixed under the VO | **PAID** (music bed) |
      | assembly | 5 Assembly | `working/build_master_v4.py` (concat beats + B-roll, mix VO+music, composite silent video + audio + burn window-masked captions -> `finals/everself-v4-master.mp4`) | free |
      | `headshot` | — | kept for a FUTURE lipsync variant; UNUSED in the shipped master | — |
      
      ## 1. VO -> ElevenLabs clone/cast  (config: `voice`)  [PAID]
      
      **Lock the VO FIRST — it sets the timeline.** `voice/render_listicle_v2.py` narrates the listicle
      script with ElevenLabs `eleven_v3` — either a **cloned** voice (train from a short reference sample
      of the expert, then narrate) or a **cast** `voice_id` — then `atempo` to the target pace (v3's speed
      param is weak; use ffmpeg `atempo` for real time-stretch) -> `voice/vo-render.mp3`. The delivered VO
      and its word-level timings, NOT the plan, set the timeline.
      
      ## 2. Transcribe -> Whisper word timings  (config: `voice.outputs.word_timings`)  [~$0.10]
      
      Groq `whisper-large-v3` word-level on the RENDERED VO -> `working/whisper/words-flat.json` (a flat
      list of `{word, start, end}`). Every beat reveal in step 3 anchors to a word time here. Whisper is
      the right tool for SPOKEN VO word-level; script-window timing is only for SUNG audio (not this format).
      
      ## 3. Beats -> hyperframe authoring  (config: `design`, `beats[]`)
      
      One HTML hyperframe per beat in ONE design system: `working/hyperframes-v4/beat-NN.html`, each
      exposing `window.renderAt(t)` driven by the Web Animations API so a renderer can seek any frame.
      Shared `working/hyperframes-v4/_shared.css` holds the design tokens (palette, type, alternating
      `background_tiles`, decorative SVG `accents`, the glass-pill callout) and `_shared.js` holds
      `initRenderer` + `revealWords` + easing. Reveals fire at each beat's `anchor_word`/`anchor_t` from
      `words-flat.json`. Alternate the background tile per beat for rhythm; keep numerals / body type /
      accents / pills CONSISTENT so N beats read as one designed reel. This is deterministic web motion
      graphics — NOT i2v.
      
      ## 4. B-roll windows -> download/trim + color-grade  (config: `broll[]`)  [media-proxy stock]
      
      For each `broll[]` window, `working/build_pexels_beats.py` downloads/trims the stock clip (or ingests
      a brand/procedure clip) and `working/grade_brolls_v4.py` color-grades it to the palette. Render B-roll
      at fps 25 to match the beats. These are the ONLY windows where captions burn — on the motion-graphic
      beats the on-screen type IS the caption.
      
      ## 5. Render + captions + assembly  (config: `render_engine`, `captions`, `music`, `audio_mix`)
      
      - **Render (`render_hf.py`):** for each beat, Playwright loads the hyperframe, calls
        `window.renderAt(t)` per frame, screenshots it, and ffmpeg encodes -> a silent mp4 per beat. **ALL
        beats MUST share fps 25** — a mismatched-fps beat stutters at the concat seam.
      - **Captions:** built from `words-flat.json`, kept **ONLY inside the B-roll windows**, 2-word chunks,
        closing a cue on any >0.4s word gap. The ASS `Format:` header MUST include a `Name` field — without
        it the leading-comma bug eats the first field and captions silently drop.
      - **Assembly (`build_master_v4.py`):** concat all beats + B-roll windows (ffmpeg demuxer) ->
        `master-silent.mp4`, mix the VO (full) under a LOW ElevenLabs Music bed (~0.18 vol), composite the
        silent video + the mixed audio + burn the window-masked captions, loudnorm to -14 LUFS ->
        `finals/everself-v4-master.mp4` (1080×1920, 25fps, h264 crf18 + aac 192k, ~66s).
      
      Re-cuts (new caption chunking, re-timed beats, swapped B-roll, a different music bed level) reuse the
      existing VO / beats / B-roll and cost **$0** — only the VO clone/narration and the music bed spend.
      
    • README.md 3.5 KB
      # render-vo-anchored-motion-listicle scripts — the FREE assembly
      
      `render-vo-anchored-motion-listicle` is the **deterministic, $0 assembly stage** of the
      VO-anchored motion-graphic listicle format. The paid/metered stages (the spoken expert VO, the low
      music bed, the stock B-roll) are separate capabilities — `create-vo-elevenlabs`,
      `create-music-elevenlabs`, `media-proxy`. This capability spends nothing: it takes the VO +
      `words-flat.json` + the N authored hyperframe beats + the color-graded B-roll windows + the brand
      wordmark SVG and stitches the finished master. Re-cuts (new caption chunking, re-timed beats, a
      swapped B-roll window, a different music-bed level) reuse the existing VO / beats / B-roll and cost
      **$0**.
      
      `config.example.json` is the worked example (Everself "doctor-educator" listicle, ~66s 1080×1920 at
      25fps). `PIPELINE.md` maps every config block to its source step. This README documents the FREE
      assembly pieces that `render-vo-anchored-motion-listicle` owns.
      
      ## 1. Beat render — Playwright frame-by-frame, all beats at fps 25
      
      Each beat is an HTML hyperframe + the Web Animations API driven by `window.renderAt(t)`. The renderer
      (`render_hf.py`-style) loads the hyperframe headless in Playwright, calls `window.renderAt(t)` for
      each frame time, screenshots it, and ffmpeg encodes the frames → a silent mp4 per beat. This is
      deterministic web motion graphics — NOT i2v, no diffusion, no keys. **ALL beats MUST share fps 25** —
      a beat rendered at a different fps stutters at the concat seam. The reveals inside each beat are
      anchored to the VO's word-level timestamps (`words-flat.json`), so authoring order is: lock the VO
      first, transcribe it, then time each beat's reveals to its anchor words.
      
      ## 2. Concat on the timeline
      
      The VO sets the timeline. Assembly concats the rendered beats + the color-graded B-roll windows in
      order (ffmpeg demuxer) → `master-silent.mp4`. Beats and B-roll are all fps 25 so the seams are clean.
      
      ## 3. B-roll windows — color-graded, the only captioned windows
      
      Each B-roll window is a stock (via `media-proxy`) or brand/procedure clip, trimmed and color-graded
      to the palette, rendered at fps 25. These give the eye a rest between the dense motion-graphic beats
      and are the **only** windows where captions burn — on the beats themselves the on-screen type IS the
      caption.
      
      ## 4. Captions — from the VO word timings, masked to the B-roll windows
      
      Captions come from the VO's `words-flat.json`, kept **ONLY inside the B-roll windows**, chunked to
      ~2 words, closing a cue on any >0.4s word gap. Rendered as an ASS overlay in a lower-third. **The ASS
      `Format:` header MUST include a `Name` field** — without it the leading-comma bug eats the first
      field and captions silently drop. Never caption the motion-graphic beats (double-stacks text). If the
      host ffmpeg lacks libass (no `subtitles`/`ass` filter), render the cues as timed PIL PNG overlays
      composited with ffmpeg `overlay=…:enable='between(t,st,en)'` instead — same placement, no libass
      dependency.
      
      ## 5. VO + music mix
      
      The VO is the spine at full level; the ElevenLabs Music bed sits ~0.18 vol under it (no ducking
      needed at that level). Mix → the master audio.
      
      ## 6. FFmpeg composite
      
      FFmpeg composites the master: the silent concatenated video + the mixed audio (VO + low bed) + the
      burned window-masked captions, loudnorm `I=-14` → a 1080×1920 25fps h264 crf18 + aac 192k master
      (~66s). The CTA / end beat composites the brand's real wordmark — **never** AI-rendered text (a
      diffusion model garbles a wordmark). Deterministic, no paid calls, no keys.
      
  • tests
    • smoke-test.md 1.4 KB
      # Smoke Test
      
      Given the spoken expert VO (mp3 + `words-flat.json` word timings), N authored web-animated hyperframe
      beats in ONE design system, periodic color-graded B-roll windows, a low music bed, and the brand
      wordmark SVG, `render-vo-anchored-motion-listicle` assembles the master: render each beat
      frame-by-frame via Playwright (all beats fps 25), concat the beats + B-roll, burn window-masked
      captions, mix the VO under the low music bed, composite → 1080×1920 h264 crf18 + aac 192k (~66s).
      
      Pass when the assembly runs to a valid MP4 and:
      - every beat reveal is anchored to the VO's word-level timestamps; the ONE design system holds across
        every beat (tiles alternate; numerals / body / accents / pills consistent);
      - all beats and B-roll windows share fps 25 (no concat-seam stutter);
      - captions appear ONLY inside the B-roll windows (2-word chunks, no dropped cues — the ASS `Format:`
        header carries a `Name` field), never over the motion-graphic beats;
      - the VO carries the listicle under a low music bed (~0.18); the CTA / end beat shows the real
        wordmark (never AI-rendered text);
      - there is NO lipsync / talking head in the master (the still headshot is a future-variant input, not
        used here);
      - **no paid call is made** — the VO, the music bed, and the stock B-roll come from the paid/metered
        capabilities (create-vo-elevenlabs / create-music-elevenlabs / media-proxy); this assembly is $0 and
        a re-cut reuses the existing VO / beats / B-roll.
      
  • SKILL.md 5.3 KB
    ---
    name: render-vo-anchored-motion-listicle
    description: Assemble 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, and glass-pill callouts) are rendered frame-by-frame via Playwright and anchored to the VO's word-level timestamps, periodic color-graded B-roll windows give visual breath, and captions burn ONLY inside those B-roll windows (2-word chunks, ASS Format header carrying a Name field so none drop) with the VO mixed under a low music bed. This is the FREE deterministic assembly stage (Playwright beat render plus ffmpeg concat plus window-masked caption burn plus VO-and-music mix plus final composite) — the VO, the music bed, and the stock B-roll come from create-vo-elevenlabs, create-music-elevenlabs, and media-proxy. Use for the vo-anchored-motion-listicle format.
    status: active
    ---
    
    # render-vo-anchored-motion-listicle
    
    Assemble an **expert/educator motion-graphic listicle** ad from a config: an authoritative spoken
    voiceover carries a numbered listicle (hook + N points + CTA) and every visual beat is anchored to
    the VO's word-level timestamps. Each beat is a **web-animated hyperframe** (an HTML page + the Web
    Animations API driven by `window.renderAt(t)`) rendered to video frame-by-frame with Playwright, all
    in ONE branded design system (alternating background tiles, big hero numerals, body type, decorative
    SVG accents, glass-pill callouts). Periodic color-graded **B-roll windows** give visual breath, and
    captions burn **only on the B-roll windows**. The shipped master is pure motion-graphic + VO — there
    is NO lipsync (the still expert headshot is kept only for a future lipsync variant). This capability
    is the **FREE, deterministic assembly** — the Playwright beat render, the ffmpeg concat, the
    window-masked caption burn, the VO+music mix, and the final composite.
    
    `scripts/config.example.json` is the worked example (Everself "doctor-educator" listicle, ~66s
    1080×1920 9:16 at 25fps); `scripts/PIPELINE.md` maps every config block to its source step and
    `scripts/README.md` documents the free assembly.
    
    ## Run
    
    This is the **FREE, deterministic** assembly stage — it spends nothing. The paid inputs are separate
    capabilities — the spoken VO (`create-vo-elevenlabs`, a cloned or cast expert voice, `eleven_v3` +
    `atempo`) whose word-level timestamps (Groq `whisper-large-v3` word-level) set the timeline; the low
    music bed (`create-music-elevenlabs`); and the stock B-roll (`media-proxy`, trimmed + color-graded).
    Given the VO + `words-flat.json` + the N authored hyperframe beats + the color-graded B-roll windows +
    the brand wordmark SVG, `render-vo-anchored-motion-listicle` renders each beat frame-by-frame via
    Playwright (all beats at fps 25), concats the beats + B-roll, burns the window-masked captions, mixes
    the VO under the low music bed, and composites → the master. Re-cuts reuse the existing VO / beats /
    B-roll and cost **$0**.
    
    ## Contract (the free assembly)
    
    - **The spoken VO carries the listicle — it sets the timeline.** The cloned/cast expert VO is the
      spine; Whisper-transcribe it to word-level timestamps and anchor every beat reveal to those word
      times. There is no on-camera human and NO lipsync in the shipped master.
    - **Beats are web-animated hyperframes, rendered deterministically.** Each beat is an HTML page + the
      Web Animations API driven by `window.renderAt(t)`; Playwright screenshots it frame-by-frame and
      ffmpeg encodes it. This is NOT i2v — it is deterministic web motion graphics.
    - **ALL beats share the same fps (25).** A mismatched-fps beat stutters at the concat seam. Render
      every beat and every B-roll window at fps 25.
    - **ONE design system across every beat.** A single `_shared.css` (palette + type + alternating
      tiles + accents + glass-pill) so N beats read as one designed reel; alternate only the background
      tile, keep numerals / body / accents / pills consistent.
    - **Periodic color-graded B-roll windows for breath.** Trim + color-grade each stock/brand clip to
      the palette (fps 25). These windows are the ONLY captioned windows.
    - **Captions ONLY on the B-roll windows.** On the motion-graphic beats the on-screen type IS the
      caption — burning Whisper captions there double-stacks text. Build the caption ASS from the VO word
      timings, kept only inside the B-roll windows, 2-word chunks, closing a cue on any >0.4s word gap.
      The ASS `Format:` header MUST carry a `Name` field — without it the leading-comma bug eats the
      first field and captions silently drop. If the host ffmpeg lacks libass, render the cues as timed
      PIL PNG overlays (ffmpeg `overlay=…:enable='between(t,st,en)'`) at the same placement.
    - **Low music bed under the VO.** The VO is the spine; the ElevenLabs Music bed sits ~0.18 vol under
      it. No ducking needed at that level.
    - **Never AI-render the brand lockup.** The CTA / end beat composites the brand's real wordmark,
      never text-in-diffusion.
    - **FFmpeg composite, deterministic, FREE.** Render each beat via Playwright, concat the beats +
      B-roll (ffmpeg demuxer), burn the window-masked caption ASS, mix the VO under the music bed,
      loudnorm `I=-14` → a 1080×1920 25fps h264 crf18 + aac 192k master. No paid calls, no keys.
    
  • skill.meta.json 345 B
    {
      "slug": "render-vo-anchored-motion-listicle",
      "category": "capabilities",
      "domain": "ads",
      "tags": [
        "ads"
      ],
      "installation": {
        "base_command": "npx goose-skills install render-vo-anchored-motion-listicle",
        "supports": [
          "claude",
          "cursor",
          "codex"
        ]
      },
      "requires_skills": [
        "watch"
      ]
    }
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related