A text-led launch film: the voiceover drives everything. Words rise on the beat they are spoken, UI scenes carry the product story, and a closing logo card lands on a cursor click. Motion follows the ideas in howseen-ai/claude-motion-design (MIT), ported to framesmith's pure-Python seek(t) model in framesmith.motion:
- closed-form springs (snappy 320/30, default 170/26, playful 180/12)
- log-space camera push with a small punch on every phrase
- masked word rises with a slight rotation
- border beams and travelling connector beams
- code-synthesised click, tick, pop, thump and whoosh effects
Example: examples/prismor/ is a 67 s Prismor launch film with a marin voiceover.
Workflow
-
Start:
python3 scripts/main.py init my-filmcopies the Prismor example. -
Script (
vo.txt): the arc is:- a problem hook with a stretched word
- where the pain lives (label montage)
- three words on curves
- the question, and the flat answer with a falling word
- "Meet [Product]"
- what it does (big two-line headline over blurred UI)
- compatibility (logo cards)
- the stakes (a sentence that scatters)
- "[Product] can help"
- three or four UI proofs
- the hub
- the positioning lines
- the logo, tagline and URL
Run the script through the
no-ai-slopskill, and take every claim from the product's docs or site. -
Voice:
python3 scripts/main.py voice --brief my-film/brief.json. This uses the latest TTS snapshot (default voicemarin) and transcribes it in overlapping windows (narration.transcribe_windows), because Whisper drops stretches of long takes. -
Brief (
brief.json): every beat starts on a cue phrase (at), and so does every phrase, card and item inside it.holdsinsert silence after a phrase so a UI beat can breathe. -
Check → still → render. The render mixes the voice with the synthesised effects automatically.
Beats
| type | what it does | keys |
|---|---|---|
kin |
voice-synced masked word rises; *accent* words get a scrolling holographic fill; phrases swap with a blur |
phrases[{at, text, size, x, y, align, stretch, fall, scatter_at}], backdrop: "ui" + feed |
windows |
label montage: big white word over a tinted app window, with brand icon tiles floating | items[{at, label, kind: terminal/editor/browser/cloud, icons}] |
paths |
each word drawn along a dashed Bézier as it is spoken | items[{at, word, curve: 4 points (0–1), start}] |
meet |
"Meet" + mark pop; on the brand cue "Meet" lifts away and the wordmark rises | name_at, name |
logos |
headline + bordered logo cards on a playful spring, one per spoken name | phrases, items[{at, icon, name}], grid_y |
tilt |
a product window tilted in 3D settles flat while lines type and detection boxes land | box_at, curve_label, phrases |
activity |
live activity feed, spinner status, agent cursor with a label, the last call outlined | feed, status, agent |
approve2 |
approval card, cursor click on Approve, a toast with a border beam | click_at, action, cmd, who, toast |
structure |
a raw log's tokens highlight, then arc into a clean table | raw, columns, rows[[value, raw_line]], fly_at |
hub |
left list → product disc → right list, beams draw in and pulses travel | left, right, left_title, right_title |
end |
logo + wordmark, tagline, URL underlined by a cursor click, fade to black | tag_at, tagline, url |
Icons come from assets/icons/<slug>.svg (thesvg, via brand-icons) or lucide:<name>. Put the real logo in assets/logo.png.
Rules
- Design rules from
video-to-template/references/design-rules.mdapply:- no pills or chips (status is a dot plus a word, and the cursor label is plain text on a halo)
- the real logo
- no overflow
- no italics
- no trailing periods on on-screen text
- UI content must be the product's real UI or clearly generic. The
tiltexample rebuilds prismor.dev's own hero demo. Org, device and people names are sample data. - The shared compositor lives in
scripts/stage_engine/stage.py(the same file asarchive-launch-film), which provides the backgrounds, cards, cursor, console panels and holds.