kinetic-type turns a YAML timeline and a voiceover into a finished motion-graphics film — typography, camera, physics, and a fully synthesized sound mix. No editor. One command.
A miniature in-browser version of four blocks. Play it, then take the generated YAML — the same words with the same timings — straight into your spec.
Every block renders itself for a time window and emits its own sound events. All footage below is real engine output.
Staggered hero lines. fontcycle glitches a word through typefaces before it lands on the one you chose.
- type: title
lines:
- y: 400
size: 150
groups:
- {text: "GEN Z", t: 0.10, font: bold}
- text: "customizes"
t: 0.70
fontcycle: {cycle: [bold, mono, med, lora],
step: 0.09, land_t: 1.50, land_font: lora}VO-synced word-by-word reveal — each word pops with scale + blur at its exact spoken moment.
- type: word_pop
align: center
size: 84
lines:
- [["to", 7.98], ["one", 8.11], ["of", 8.26],
["the", 8.36], ["choices", 8.52, bold]]Footage sequences, drawn device screens with typed lines, fly-in entrances, idle float, soft shadows.
- type: media
layers:
- {kind: sequence, dir: assets/L, count: 266,
rect: [55, 42, 590, 1038],
enter: {t: 3.24, from: left, dur: 0.38}, shadow: true}
- kind: device_text
enter: {t: 3.30, from: bottom, dur: 0.38}
lines: [["Their coffee.", 3.35], ["Their food.", 4.12]]Char-by-char with a live caret. Words complete on their VO timestamps; slam words punch in whole.
- type: typewriter
x: 220
char_dur: 0.055
lines:
- y: 300
size: 80
words: [["21", 14.80, bold], ["million", 15.15, bold],
["eligible", 15.65]]Point it at a typewriter block and everything drops — staggered release, spin, one floor bounce. Falls by words or by chars.
- type: gravity from: stats # id of the typewriter block start: 23.85 t0: 23.85 stagger: 0.32 mode: words # or: chars — every glyph tumbles alone
The quiet beat. A centered line whose letter-tracking settles as it fades in, then slips away.
- type: fade_line t_in: 24.45 t_out: 26.60 size: 46 color: dim text: "So we started with a simple human truth."
Words pop in, get cursor-selected on cue, then vanish with an RGB-split glitch and a cut sound.
- type: select_delete
select: [30.02, 30.76]
delete_t: 30.82
dots: [29.55, 29.72, 29.89]
lines:
- [["the", 28.20], ["value", 28.42, bold], ["of", 28.62],
["having", 28.85], ["a", 29.05], ["choice", 29.24, "bold,accent"]]The typed end card — keyed-in headline, two-tone sub-line, accent underline sweep with a bass hit.
- type: cta
keys: [["V", 32.25], ["O", 32.43], ["T", 32.60],
["E", 32.78], [".", 32.98]]
sub: {t0: 33.50, a_text: "your future. ",
b_text: "customize it.", b_font: lora}
underline: [34.85, 35.03]Blocks overlap. Draw order is spec order — here a left-aligned word_pop shares its window with a media block: a live phone screen flying in with a whoosh, plus a floating image layer fading in on cue.
kinetic-type was extracted from a real production — a Gen Z voter-turnout PSA. The full spec ships in the repo as examples/genz.yaml; a script regenerates its footage crops from the campaign master.
$ kinetic analyze assets/vo.m4a pauses (>=0.10s below -38dB) — likely sentence breaks: 13.76 - 13.92 (0.16s) 14.17 - 14.58 (0.41s) 23.94 - 24.09 (0.15s) syllable nuclei (energy peaks) per speech span: [0.00-4.71] 17 nuclei: 0.11 0.26 0.42 0.71 1.00 ... [4.82-13.76] 35 nuclei: 4.88 5.29 5.69 5.98 6.22 ... hint: one nucleus ~= one syllable; map words to nuclei to fill word times in the spec. $ kinetic build examples/genz.yaml -o genz.mp4 frame 2100/2160 wrote genz.mp4
One field — invert_at — cuts the background, flips the ink, fires the sub-drop, and ends the riser. Timed to the acoustic onset of the word “worse”.
A gravity block pointed at the stats typewriter. Every word releases on a stagger, spins, bounces once. Nothing stays anchored.
“The value of having a choice” gets cursor-selected, then removed — selection sweep, RGB-split glitch, cut sound. Then the CTA types itself.
No ML needed — signal analysis finds sentence pauses and syllable nuclei so you can pin every word to the voice.
$ kinetic analyze vo.m4aRender single frames at any timestamp to check a beat before committing to a full render.
$ kinetic preview my.yaml 21.26 33.2Frames pipe straight into x264; the SFX mix is synthesized from the spec and ducked under your VO. Move a timestamp — picture and sound move together.
$ kinetic build my.yaml -o film.mp4$ unzip kinetic-type.zip && cd kinetic-type $ pip install -e . # or: python3 -m kinetic ... $ kinetic build examples/genz.yaml -o genz.mp4 requires: python 3.9+, ffmpeg, numpy scipy Pillow PyYAML
kinetic-type/ ├─ kinetic/ │ ├─ engine.py # scene, bg wipes, drift, shake, ffmpeg │ ├─ blocks.py # the 8 animation blocks │ ├─ fxaudio.py # synth kit + mixdown │ ├─ analyze.py # VO pauses + syllable nuclei │ └─ text.py # sprites, baseline layout └─ examples/ ├─ genz.yaml # the reference film └─ extract_assets.sh