---
tier: hero
reliability: 4.3 # LLM authors HTML .9 + hyperframes-render .8 + gemini-tts narration .9 + bed/mix .9; legible-by-construction (text is HTML, not generated pixels)
---

# Doc → Animation — a paragraph becomes a narrated animated explainer ⭐

> Paste this whole file (with the BRIEF filled in) into Claude cowork, chat, or Code with the Storyboard MCP attached. Hand it a dense paragraph, a spec, or a concept — it returns a **narrated, animated explainer video** where every word on screen is crisp (because it's HTML, not generated pixels). The "explain this clearly in 45 seconds" format.

## What you'll get

- A **30–60s animated explainer** (9:16 / 1:1 / 16:9) — timed scene beats with motion, big legible type, simple diagrams, a progress bar.
- A **clear narration** in the voice + language you choose, plus a music bed.
- The **editable HTML page** itself as a deliverable (re-render after a one-line edit — the text is real, not baked into pixels).

**The wow:** the on-screen text, equations, labels, and UI are **pixel-perfect and legible** because the animation is authored as HTML/CSS/SVG and composited to video by `hyperframes-render` — the one thing AI video generation cannot do reliably. For precise math/diagram motion, escalate to the sibling **`manim-render`** cap (see the `doc-to-manim-animation` playbook).

## The caps

| Step | Cap |
|---|---|
| (opt) ingest a doc / URL / transcript | `gemini-text` (paste/URL), `wizper` (audio), `marlin-video` (video) |
| Plan the beats + script | LLM (the agent) |
| Author the animated HTML page | LLM (the agent) — timed scenes, CSS/SVG, a progress bar |
| **Render HTML → video** | **`hyperframes-render`** (Playwright + Chromium compositor) |
| Narration | `gemini-tts` (named voice + tone direction; multilingual) |
| Music bed | `sonilo-t2m` (licensed) / `minimax-music` |
| Mix + finish | `ffmpeg-audio-mix` / local `ffmpeg` |

## Tell the agent about the explainer

```yaml
source:        # the doc / paragraph / concept (or a URL / transcript)
title:         # short on-screen title
beats:         # OPTIONAL 4-7 beat outline; omit to let the agent structure it
aspect:        # 9:16 | 1:1 | 16:9
voice:         # gemini-tts voice + tone (e.g. "Leda, clear friendly explainer")
language:      # narration language
music_brief:   # bed mood
launch_slug:   # e.g. how-https-works
```

## How the agent should run this (interaction contract)

1. **STRUCTURE.** Read the source → write a 4–7 beat outline (hook → problem → mechanism steps → payoff) + a tight narration script (~2 words/sec). Show it; GATE.
2. **AUTHor the HTML.** One self-contained 9:16 page: each beat a full-screen scene, revealed on a JS timeline (`setTimeout`), with a progress bar. Big type, high contrast, one idea per beat. The animation MUST auto-run on load (hyperframes captures a fixed window).
3. **RENDER.** `hyperframes-render` with `{ html, duration, aspect_ratio }` → MP4. **Look at sampled frames** (render-and-look) — confirm every beat is on-screen and legible at its time.
4. **NARRATE + SCORE.** `gemini-tts` (named voice + a plain-language tone direction — the directive is interpreted, not spoken; verify with a quick ASR pass). `sonilo-t2m` bed.
5. **MIX.** Narration full + bed ducked (~0.13) + fade out; map onto the silent render. Deliver the MP4 + the editable HTML.

## What can disappoint (cap ceilings)

- **The animation must auto-play on load** — hyperframes records a fixed `duration`; anything gated on a click never fires. Drive scenes on a `setTimeout` timeline.
- **Narration pacing ≠ beat timing exactly** — one TTS pass tracks the beats only roughly. For tight sync, split narration per beat and place each, or keep beats long enough to absorb drift.
- **Emoji/icon fonts** render via the compositor's font set — prefer CSS/SVG shapes for anything brand-critical; test once.
- **Math equations** in HTML are fiddly — if the explainer is equation-heavy, use `manim-render` (true MathTex) instead.

## When you're done

```
✅ Explainer: public/launches/{launch_slug}.html  +  {launch_slug}.mp4  +  the editable .html page
✅ Narrated, scored, every on-screen word legible
Total spent: $X.XX
```

## What to do next
1. **Re-cut aspects** — the same HTML renders 1:1 / 16:9 by changing the viewport.
2. **Localize** — swap the narration language (gemini-tts) + re-render; the visuals are language-agnostic.
3. **Edit the text** — change a word in the HTML and re-render; nothing is baked into pixels.

---

## Notes for the agent (only read if a step fails)

**hyperframes-render.** Via `create_media({model_override:"hyperframes-render", html, aspect_ratio})` (≤15s) or direct-SDK `POST /inference {"capability":"hyperframes-render","params":{"html":"…","duration":N,"aspect_ratio":"9:16"}}` for longer. The output URL can be nested at `data.url` or `data.data.url` — extract recursively. Caller HTML runs in a sandboxed `--no-sandbox` Chromium with non-`file:`/`data:` requests blocked, so inline all CSS/SVG; don't rely on external assets.

**Narration.** `gemini-tts` takes `prompt` + a named `voice`. Lead the prompt with a tone directive ("Say in a clear, friendly explainer tone:") — interpreted, not spoken. `sonilo-t2m` returns `.m4a`.
