| name | create-how-we-made-this-hook |
| description | Produce a 9:16 "proof-then-recipe" social hook reel — open on the most jaw-dropping seconds of a finished brand film (the flex), hard-cut on a record-scratch, then a felt-Goose mascot reveals the exact AI tool-stack that made it (the recipe) with fast cuts, brand-colored tool cards, per-beat pop SFX, and word-level karaoke captions. Use when you have an impressive existing deliverable and want a behind-the-scenes / "how we made this" / "the stack behind this" video for Instagram/TikTok/Shorts. Composes a conform-cut proof montage + the talking-goose explainer engine. NOT for a plain talking-head explainer with no proof footage (use talking-goose-creator-video) or a straight recut of one video (use ugc-ad/recut-video-to-creator-grammar). |
create-how-we-made-this-hook
Purpose
The production line for the proof-then-recipe format: show an impressive result, then reveal the AI pipeline that produced it.
Structure (always two acts):
- The flex (proof hook, ~3–5s): a fast beat-cut montage of the most scroll-stopping moments from a finished brand film, riding the film's own music, with a small context caption ("we made this ad."). No VO.
- The recipe (explainer, ~22–30s): a hard record-scratch cut to the felt-Goose mascot (lip-synced), who names the stack one tool per beat — orchestration → video model → voice → editor → "one afternoon, one person" — over brand-colored tool cards, with a pop SFX on every beat and word-level karaoke captions. Closes on a follow CTA.
The reusable abstraction: point it at (a) a finished deliverable to use as proof and (b) a tool-stack to credit, and it returns the reel. First shipped as gooseworks-ads/how-we-made-this-touchland/.
NOT the right molecule for:
- A plain mascot explainer with no "proof" footage — use
talking-goose-creator-video.
- A straight creator-grammar recut of a single source video — use
ugc-ad/recut-video-to-creator-grammar.
- A long-form (>45s) walkthrough — this format lives or dies on pace; keep it under ~35s.
Inputs
| Input | Required | Notes |
|---|
proof_film | yes | Path to the finished brand film used as the proof hook. Must be visually strong — the "wow" has to land in under 5s. Any aspect; it is scaled/cropped to 1080×1920. |
tool_stack | yes | Ordered list of {role, name, brand_color, badge} (e.g. orchestration=Claude Code, video=Seedance, voice=ElevenLabs, editor=FFmpeg). Drives the tool cards + the VO rundown. |
voice | yes | ElevenLabs voice id + model. Default Goose character voice QzTKubutNn9TjrB7Xb2Q (eleven_v3). Must be listed in VOICES.md or explicitly approved. |
character | no | Lip-sync anchor still (neutral closed-mouth, head-and-shoulders). Default felt Goose; reuse a materialized anchor PNG (LFS pointers will not lip-sync). |
script | no | Override the auto-generated VO. If omitted, the molecule writes the pivot → tool-rundown → CTA script from tool_stack. |
hook_caption | no | Lower-third context caption over the proof montage. Default "we made this ad." Keep it from spoiling the explainer's reveal. |
output_dir | yes | Project folder (canonical 5-folder layout). |
auto | no | bool, default false. Pass through the script + composite gates with prior preferences. |
Composed Atoms
atoms/voiceover/create-voiceover-elevenlabs — eleven_v3 VO with-timestamps for the recipe narration (approved voice only).
atoms/source/transcribe-audio-fal — word-level timestamps on the final (speed-tuned) VO; drives beat boundaries + caption cues.
atoms/lipsync/create-lipsync-veed-fal — one Veed Fabric 1.0 call on the full VO to lip-sync the mascot (the PIP source).
atoms/captions/burn-in-captions — word-level karaoke reference (ASS + libass); here captions are dark-ink + brand-color karaoke placed in the band above the circular cam.
atoms/overlays/render-video-overlay-track — Playwright/Chromium HTML→PNG renderer used for the premium overlay cards (real brand logos, glass cards, step bars).
atoms/assembly/stitch-videos-ffmpeg — concat the proof hook + the explainer into the master.
atoms/review/watch — mandatory frame + transcript self-QC on the final master (VIDEO_GEN_RULES.md rule 3).
molecules/talking-goose-creator-video — the mascot-explainer lineage (VO + lip-sync + pop-SFX + brand-name caption patching). This molecule supersedes its flat overlay/rectangle-PIP look with premium HTML cards + a circular Loom-style cam.
Workflow
Step 1 — Intake + project setup
Validate proof_film exists and voice is in VOICES.md. Create the 5-folder layout under output_dir; copy proof_film to source/. Write script/script-locked.md.
Step 2 — Cut the proof hook (conform, local)
Sample frames across proof_film; pick the 4–6 most arresting ~0.7–0.9s moments. Trim each (scale to 1080:1920:force_original_aspect_ratio=increase,crop=1080:1920, fps=30), hard-concat, and lay a single continuous music slice from the film (its climax) as the bed with a short fade. Overlay the hook_caption (looped image + alpha fade) only over a clean cut and remove it before any text-bearing end card.
Step 3 — Write + lock the VO script (GATE)
Author the recipe VO: pivot line ("Want to make ads like these? Here's how.") → one line per tool in tool_stack → "one afternoon, one person" → CTA. Save clean + eleven_v3-tagged versions. Human-approve before spending on VO/lip-sync.
Step 4 — Generate + pace the VO
Generate eleven_v3 with-timestamps. eleven_v3 reads slow/dramatic — measure the result and apply atempo (~1.4–1.5) to hit a snappy ~30s and to cut lip-sync cost. Re-run transcribe-audio-fal on the paced VO for accurate word timings. Verify the transcript matches the script with no audio-tag leakage.
Step 5 — SFX
Generate a pop (card snap), a record-scratch (the turn), and an optional whoosh via ElevenLabs sound-generation.
Step 6 — Overlays (premium HTML/CSS via Playwright)
Render each beat as two layers at 1080×1920 so content can animate over a stable bg:
- bg layer (opaque): light/studio cream gradient + a faint brand-tint glow + step bars (01→04) +
@handle watermark.
- content layer (transparent,
omitBackground): the card/hero only.
Tool cards use real brand logos — fetch official SVG marks from cdn.simpleicons.org/<slug> (claude, elevenlabs, ffmpeg, anthropic, bytedance) and CSS-filter them white on a brand-color app-tile. For a tool with no simpleicons entry (e.g. Seedance), use a clean inline glyph (play triangle). Beats: kinetic title, "no camera/studio/crew" strikes, one tool card per tool_stack entry (logo tile + role eyebrow + name + descriptor), "one afternoon / one person", and a centered-Follow CTA. Type: Space Grotesk + Inter (Google Fonts). Render via a small Playwright script (render.js) at 2× then downscale for crispness.
Step 7 — Lip-sync the mascot
One create-lipsync-veed-fal call (image=character, audio=paced VO, 720p). Reuse a materialized anchor; never feed a 130-byte LFS pointer.
Step 8 — Composite the explainer (with motion)
Per beat (timings from the word timestamps): show the static bg for its duration and overlay the content layer with a subtle entrance — fade-in ~0.24s + slide-up ~18px. Concat beats → bg-track. Then composite the circular Loom cam: crop the mascot's face from the lip-sync clip, mask to a circle, and overlay it as a unit with a gentle float (y = base + 8*sin(2πt/3.6)). Layer order is critical: shadow UNDER the cam, white ring OVER it — never a fill or glow over the face, or the mascot reads as a brown tint / dull. Lift the masked face with a small eq (brightness +0.05, saturation ~1.15) so it pops on the light bg. Mix audio = VO + pop at each beat + record-scratch at t=0 — or, when only visuals change, re-mux a previously approved audio track of the same timeline.
Step 9 — Stitch
Concat proof hook + explainer (normalize fps/SAR/sample-rate via the concat filter) → edits/master-nocaption.mp4.
Step 10 — Captions
Generate word-level karaoke ASS from the paced-VO timestamps: short 1–3 word cues, dark-ink base + brand-color (coral) active word + soft white halo for the light bg, placed in the band between the card and the circular cam (MarginV ≈ 930 at 1080×1920) so they never cover the mascot or the cards. Offset by the proof-hook duration; leave the CTA sentence uncaptioned. Pre-merge split brand names in the word stream (e.g. "Eleven"+"Labs" → "ElevenLabs"). Burn with ffmpeg-full (libass) → edits/master-final.mp4.
Step 11 — QC + deliver
Run atoms/review/watch on the final. Copy to finals/, build storyboard.html, print the absolute master path.
Decision Rules
- Captions: ASS karaoke, not Klap. Compound tool names (Claude Code, Seedance, FFmpeg, ElevenLabs) reliably break Klap's homophone handling, AND captions must be precisely placed in the narrow band above the PIP — Klap's auto-placement would land on the mascot's mouth. Both conditions trigger the
VIDEO_GEN_RULES.md ASS fallback, and the talking-goose-creator-video lineage uses ASS anyway.
- Suppress captions on the proof hook and the CTA end card (LEARNINGS #7 — never stack two text layers in the same spot). The hook caption and the CTA card already carry their own text.
- Pace the VO with
atempo. eleven_v3 with expressive tags runs ~1.8 words/sec; the proven Goose pace is ~2.7. Speed-tuning 1.4–1.5× hits the snappy target and lowers Veed cost proportionally. Lip-sync the paced audio.
- Premium HTML/CSS overlays, not flat Pillow. Render cards via Playwright (gradients, glass, real type, layered shadows). Split each beat into a static bg layer + an animated content layer.
- Use real brand logos via
cdn.simpleicons.org. The repo's logo PNGs are Git-LFS pointers (~130 bytes) and won't composite. Fetch official SVG marks and CSS-filter them white on a brand-color tile. For a tool with no simpleicons entry (Seedance), use a clean inline glyph — intentional, not hand-drawn.
- Circular Loom-style cam, not a rectangle PIP. Mask the mascot face into a circle with a white ring + soft shadow. Shadow UNDER, ring OVER; never a fill/glow over the face (it reads as a brown tint / dull mascot). A small
eq lift makes the face pop on the light bg.
- Subtle motion sells "premium." Content slides up + fades in per beat; the cam floats gently; step-bars advance; captions karaoke. Keep it subtle, never busy.
- Light/studio premium background. Cream gradient + a faint brand-tint glow; the brand color lives in the tile, bars, and accent — not a heavy wash.
- Reuse the proof film on the video-model beat. Showing a clip from the result while crediting the video model ties the recipe back to the flex and adds motion mid-explainer.
- Voice gate. If
voice is not in VOICES.md and not explicitly approved, stop at Step 1.
- Proof film must be strong. If the film is music-only, use its music as the hook bed; if it carries VO, duck or drop it under the montage. If nothing in the first scenes is scroll-stopping, the format will not land — flag it.
Output
<output_dir>/
├── script/script-locked.md # clean + eleven_v3-tagged VO, per-scene map
├── source/ # the proof film (read-only)
├── audio/
│ ├── voiceover.mp3 # paced (atempo) — canonical
│ ├── voiceover_raw.mp3 # pre-atempo
│ ├── words.json # fal word timestamps on the paced VO
│ └── sfx-{pop,scratch,whoosh}.mp3
├── generated/overlays/*.png # title, word flashes, tool cards, afternoon, CTA, hook caption
├── clips/goose-talking.mp4 # one Veed Fabric lip-sync of the full VO
├── edits/
│ ├── explainer.mp4
│ ├── master-nocaption.mp4
│ ├── captions.ass
│ └── master-final.mp4 # burned captions
├── working/ # build_*.py scripts + QC frames (regeneratable)
├── finals/<slug>.mp4 # shippable 9:16 master
└── storyboard.html
Quality Checks
finals/*.mp4 exists, is 1080×1920, h264 + AAC, total runtime ~30–36s.
- Proof hook is ≤5s and the strongest moment lands in the first ~2s.
- Captions: word-level, gold karaoke sweep, no phantom leading comma (correct ASS Dialogue field count), no two cues stacked at once, every tool name spelled correctly, none covering the mascot's mouth.
- Captions suppressed during the proof hook and the CTA end card.
- Audio: continuous,
max_volume < 0 dB (no clipping); the music→VO transition is marked by the record-scratch.
- One tool card per
tool_stack entry, each with the correct brand color + a one-line descriptor.
atoms/review/watch pass finds no subtitle/overlay collisions on any frame.
storyboard.html embeds the final and lists the stack.
Failure Modes
| Symptom | Likely cause | Fix |
|---|
| VO is 40s+ and feels slow | eleven_v3 expressive pacing | atempo 1.4–1.5 on the VO before lip-sync; rescale/re-transcribe timestamps |
| Phantom leading comma on every caption | extra comma in the ASS Dialogue: line → empty field pushes a comma into Text | Use exactly Dialogue: 0,{start},{end},Style,0,0,0,,{text} (MarginL,MarginR,MarginV,Effect,Text) |
| Two caption lines stacked on screen | adjacent cues overlap (hold time runs past the next cue's start) | Clamp each cue's end to next_cue_start − 0.02s |
| Captions cover the mascot's mouth | MarginV too low | Place in the band above the PIP head (MarginV ≈ 848 at 1080×1920) |
| Tool card shows a blank/garbled logo | logo PNG is a Git-LFS pointer (~130 bytes) | Use a drawn Pillow wordmark + brand-colored badge instead |
| Lip-sync clip is silent/static or 403s | LFS-pointer anchor, or Veed storage auth under parallel load | Use a materialized anchor PNG; keep Veed calls sequential |
fal_client cannot authenticate | .env has FAL_API_KEY but fal reads FAL_KEY | export FAL_KEY="$FAL_API_KEY" before fal scripts (LEARNINGS #10) |
| ASS burn does nothing | default brew ffmpeg lacks libass | Use /opt/homebrew/opt/ffmpeg-full/bin/ffmpeg for the ass= filter |
| Hook caption invisible / fades wrong | image overlaid without -loop 1 is a single frame at t=0 so fades never animate | Add -loop 1 to the caption image input |
| Proof hook feels random/choppy | cuts picked without checking content, or music jumps between cuts | Confirm each cut frame; use one continuous music slice as the bed |
| Mascot in the cam looks brown / dull | a glow disc or the drop shadow is composited OVER the face | Compose shadow UNDER the cam and the white ring OVER it — nothing tinted over the face; add a small eq lift |
| Tool card shows a blank/garbled logo |