Agent-driven short-form video production
kino turns an agent-authored JSON spec into a finished vertical video. The agent writes the spec, kino renders it: ElevenLabs voiceover, an optional AI avatar (HeyGen / Hedra / Replicate) or a faceless background, composited to a 9:16 / 3:4 MP4 by an in-house headless-Chrome render engine.
![]() |
![]() |
![]() |
| The self-demo kino types its own advert.json and builds the ad you're watching▶ watch with sound |
The Descent real footage into the motion-graphics finale of a 66s build ▶ watch full video with sound |
Lunara stock b-roll and a quiet voiceover ▶ watch with sound |
Fictional sample brands. Each is a real, deterministic kino build — faceless, 9:16, ElevenLabs voiceover. Previews are silent trimmed clips; click any preview (or the ▶ links) to play the full MP4 with sound in your browser.
spec.json ─▶ validate ─▶ voiceover (ElevenLabs) ─▶ avatar plan + trim
─▶ avatar (HeyGen/Hedra/Replicate) or faceless background / motion graphics
─▶ native render (headless Chrome) ─▶ ffmpeg ─▶ out/<title>/…mp4
No LLM inside the CLI: every step is deterministic, so the same spec renders the same video.
git clone https://github.com/sdkv2/kino.git ~/kino # clone the toolchain once
cd <your-project> && bash ~/kino/setup.sh # install `kino` + write a project .envOn Windows (or anywhere without bash): node ~/kino/setup.mjs — same installer, pure Node.
setup.sh/setup.mjs is a guided installer: prerequisite checks (Node 20+, ffmpeg, ImageMagick —
offers to install what's missing via brew/apt/winget), npm install / build / link, then an
API-key walkthrough (written to a chmod 600, git-ignored .env; re-runs keep existing keys).
Manual install:
cd ~/kino && npm install && npm run build && npm linkRequires Node 20+, ffmpeg/ffprobe (+ ImageMagick for storyboards). Real VO needs an ElevenLabs key (referral link — supports the project). Faceless builds need only that. Avatar builds also need the avatar provider's key, plus ElevenLabs whenever kino drives the voice (most setups).
cd <project> && npx @sdkv2/kino init acme # scaffold .env, brand.md, dirs + a sample spec
npx @sdkv2/kino doctor # preflight: API keys, ffmpeg/ffprobe, heygen CLI
npx @sdkv2/kino build projects/acme/specs/sample.json --mock # free structural preview (no API spend)
npx @sdkv2/kino build projects/acme/specs/sample.json # real render → projects/acme/out/sample/kino init writes a ready-to-build faceless sample (provider none, $0), so the first
kino build works with no editing. Swap in your own spec once the preview looks right.
npx pulls Node deps fresh each first run — Puppeteer's Chromium is bundled. ffmpeg/ffprobe use
your system install if on PATH, otherwise fall back to a bundled binary automatically. For
frequent use, npm i -g @sdkv2/kino avoids the npx resolve overhead.
Agent playbooks (video-production, ad-voice, adversarial-critique, …) are in
skills/ — the only copy in the repo.
From any project (Cursor / Claude Code / Codex / …):
npx skills add sdkv2/kino
# or one skill: npx skills add sdkv2/kino@ad-voiceInside a kino workspace (after clone / npm link):
kino skills --install # local symlinks → .agents .cursor .claude .codex (gitignored; also run by kino init)
kino skills --install --agents cursor,claudeAgent fan-out dirs stay off git so they do not clutter the tree. Details: skills/README.md.
- Avatar engines —
none(faceless, $0),heygen(Avatar-IV),hedra(Character-3),replicate(open-source lip-sync). Avatars are trimmed to on-camera segments to cut spend; VO + avatar are content-hash cached. - Faceless backgrounds —
glow,image,mesh,aurora,particles,grid,custom— frame-deterministic Canvas2D, auto-coloured from the brand. - Captions —
phrase(editorial block) orwords(revealed word-by-word, synced to real VO timestamps, with active-word highlight + per-segment emphasis). - Fonts — pick a name from
kino fonts(fetched on demand from Google Fonts into~/.kino/fonts/), or use any raw CSS family. - Stock media —
kino pexels(video) andkino photos(stills) search Pexels (portrait-first) into project assets; samePEXELS_API_KEY..mp4/.jpgwork in app cut-ins. - Animated backgrounds & overlays — backgrounds, logo, captions, and kickers are all tweenable
on one keyframe layer (
backgroundKeyframes/logoKeyframes/…), with timedbackgroundTriggers. - Motion graphics — author a self-contained HTML/CSS file in
assets/motion/; kino drives it per-frame via CSS variables, with scrubbed@keyframesand a.kino-cliptexthelper, sanitized and determinism-linted. See docs/motion-graphics.md. - Branding & compliance — logo mark + a per-mode AI
disclosure; brandbannedPhrasesfail the build (no guaranteed-outcome copy). - Inspect & iterate —
inspect(plan as JSON),still/storyboard(fast mock previews),frames(extract from a render). Built for tight agent loops. - Brands & projects —
brands/<name>/brand.md(markdown frontmatter + guidelines) is shared; every build runs inside aprojects/<name>/(its own specs/assets/out + aproject.jsonthat assigns a brand).kino init <brand>scaffolds the first one;kino projects --newadds more.
There is no running timeline: kino seeks headless Chrome to frame N, sets CSS custom properties on the graphic, and screenshots — every frame. The JSON spec owns the clock; the graphic is a stateless canvas that reads the variables and paints that one frame, so the same spec always renders the same pixels.
Each frame the graphic receives:
--progress(0 → 1across the beat) plus eased curves —--kino-out,--kino-inout,--kino-overshoot,--kino-spring, and seam-safe--kino-edge--pulse— a fast-attack, decaying envelope fired by spectriggers(punches timed to VO words)--<param>— every key in the spec'sparams, tweened bykeyframes- brand palette + fonts (
--kino-mint,--kino-font, …) and per-word voiceover timings (--kino-words-shown/env.words), so typed UIs land characters in sync with the speech
{ "kind": "motion", "source": "motion/stat.html", "text": "Eighty-six percent match.",
"params": { "pct": 0 },
"keyframes": [{ "at": 0.2, "params": { "pct": 86 }, "ease": "overshoot" }],
"triggers": [{ "at": 0.2, "action": "pulse" }] }Real CSS @keyframes work too: kino force-pauses all animations and scrubs .kino-anim elements
across the beat via a --progress-driven negative animation-delay. Three tiers by file extension:
| Source | Model |
|---|---|
.html |
declarative CSS reading the variable contract |
.js |
pure render(env) → HTML, re-evaluated per frame (loops, computed geometry) |
.json |
Lottie, frame-seeked with goToAndStop — stretched, looped, or word-fired by triggers |
Every graphic is lint-checked for determinism (no transition, timers, Date.now,
Math.random, network) and sanitized into a Shadow DOM before render. Full contract:
docs/motion-graphics.md.
Longer guides are in docs/:
- Getting started — install, scaffold, first render.
- CLI reference — every command + flag.
- Spec reference — the JSON spec,
brand.md,project.json. - Motion graphics — author custom animated beats/overlays in HTML/CSS.
- Backgrounds & overlays — faceless backgrounds, logo, captions, kickers.
npm run build # tsc → dist/
npm test # vitest (run once); npm run test:watch to watch
npm run dev -- <args> # run the CLI from source via tsxWork on a feature branch (feat/…, fix/…, chore/…), bump version in package.json for
releases, and open a PR to main. Version history lives in CHANGELOG.md.
Full guidelines: CONTRIBUTING.md.
MIT © sdkv2



