Skip to content
Conduit

skill

kamishibai

Turn a web page into a video — every frame a pure function of its time, so capture is reproducible and parallel.

reearth/kamishibaicommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/reearth/kamishibai itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 25, 2026

kamishibai

Turn any web page into a video. kamishibai only seeks the page to each moment and captures it. A mechanism, not a framework. How you draw — React, plain DOM, canvas, WebGL — is up to you.

Rendered by kamishibai from site/demo/reel.ts: plain DOM, the one contract, and the Lexicon's drawings. (full mp4)

  • 🧩 Minimal. One contract: the page exposes window.kamishibai = { meta, seek }. No framework to adopt, no editor.
  • 🎨 Draw it any way. React, plain DOM, canvas, three.js: anything a browser can show. The React helpers are optional.
  • ⚡ Edit, then render only what changed. --incremental captures again only the frames an edit touched. After one heading edit in an 86-second reel, it rendered again in 25 s, where Remotion took 48 s and HyperFrames 51 s (benchmarks).
  • 🔁 Reproducible and parallel. In a pinned environment, any order of frames gives the same video, so the frames are captured on several pages at once.
  • 🔊 Sound included. Audio clips, background music with ducking, TTS narration and frame-accurate video clips.
  • 🤖 Made for agents. The usage guide ships in the package (npx kamishibai skill), with agent skills to point to it.
  • 🆓 MIT. Free for any use, by anyone, companies of any size included.

kamishibai turns any web page (DOM, canvas, anything) into a video by seeking to each moment and capturing a still, then assembling the stills with ffmpeg. Because every frame is a pure function of its time, capture is reproducible — in a pinned environment, any order of frames gives the same video — and trivially parallelisable across several pages of a headless Chrome.

It deliberately does not try to be a frame-accurate compositing engine or ship an editor. It gives you the renderer and one tiny contract; the rest is yours.

Website: reearth.github.io/kamishibai · Lexicon of motion, from camera moves and cuts to type, texture and generative art, each with a loop and words to hand an agent.


Quick start

npm i kamishibai react react-dom         # react / react-dom are peer deps
npx playwright install chromium          # the headless browser that captures frames
# plus ffmpeg on your PATH (not bundled) — e.g. `brew install ffmpeg`

Write a reel.tsx — a page that draws "the state at time ms". With the optional React sugar that's just a component plus mount:

import { mount, useClock, ramp, eases } from "kamishibai/react";

const Reel = () => {
  const { ms } = useClock();                       // current time, in milliseconds
  const x = ramp(ms, 0, 1000, 0, 400, eases.smooth); // map a time window onto a value
  return (
    <div style={{ font: "700 96px system-ui", transform: `translateX(${x}px)` }}>
      hello
    </div>
  );
};

// mount() renders the tree AND exposes window.kamishibai for the renderer.
mount(<Reel />, { fps: 30, durationMs: 3000, width: 1280, height: 720 });

Watch it while you edit, then render it:

npx kamishibai dev reel.tsx              # a player that reloads on save
npx kamishibai render reel.tsx -o reel.mp4

There's no GUI editor; you're the editor. The loop is edit → look → render: the dev player shows the reel as you save, and a render writes the frames you can inspect one by one.

Requirements: Node.js ≥ 20 · ffmpeg on PATH (not bundled) · a Chromium for Playwright (npx playwright install chromium).


Kinds of reel

A reel is the thing kamishibai turns into a video. It comes in three kinds:

What you writeDrawn byWrite one when
Pagea web page that sets window.kamishibai: React, plain DOM, canvas, WebGLheadless Chromeyou want anything a browser can show. The default
Canvasa module that paints each frame on a 2D canvasSkia on the CPU, no browserit must render with no browser. One reel lays itself out as 16:9 and as 9:16
Kitscenes as data, in YAML, JSON or code: titles, cards, flows, numbersthe kit, as a canvas reelyou want many videos fast. Parts move from scene to scene, and each scene is timed to its narration

kamishibai export makes a reel of any kind one HTML file that plays with no server (more).


Agent skills

Building videos with an AI coding agent? Install the skill (as of October 2026 we recommend Claude Opus 5.5):

npx skills add reearth/kamishibai --skill kamishibai
# or
gh skills install reearth/kamishibai kamishibai

It points the agent at kamishibai skill, which prints the guide for the installed version. A program can take the same text from kamishibai/skill.


How it works

The one and only contract

A capturable page exposes exactly one global:

window.kamishibai = {
  meta: { fps: 30, durationMs: 6000, width: 1920, height: 1080 },
  // Build the still state for `ms` and resolve once the DOM has settled.
  // Return false to mean "identical to the previous frame", or a fingerprint
  // string for the frame's content (see below).
  seek(ms: number): Promise<boolean | string | void> | boolean | string | void;
};

Whatever happens inside seek — a React re-render, ctx.clearRect + hand-drawing, a Konva layer.draw() — is entirely up to you. The renderer just calls seek(ms), screenshots, advances, and repeats. It never plays back in real time, so a slow frame takes longer but never drops, and in a pinned environment the output is reproducible (see Determinism & guarantees).

Parallel capture

A reel of N frames is cut into contiguous chunks of frame indices, and each chunk is captured by its own page in one headless Chrome. Since frame i depends only on its time, it doesn't matter which page renders which chunk:

frames 0–684     → page #1 ┐
frames 685–1369  → page #2 ├ run at once → PNG sequence → ffmpeg → mp4
frames 1370–…    → page #3 ┘

seek can also say a frame is the same as the one before, by returning false or a fingerprint of its content. The renderer then copies the previous still instead of capturing it, and with --incremental it reuses frames from the last run whose fingerprint didn't change, so after an edit only the changed frames are captured again. kamishibai/react returns the fingerprint for you. See Skipping frames & incremental builds.


What's in the box

React sugarkamishibai/react: a clock, scenes back-to-back with crossfades, a camera over a world layer, positions along a path, easing and springs. Optional: any page that sets window.kamishibai works
Audiodeclare files and start times; they're muxed after capture, with fades, loops and auto-ducking
Videovideo clips decoded frame by frame with WebCodecs, so a clip is a pure function of time too
Subtitlesa soft track and a sidecar .srt by default, or burned into the pixels
Narrationtext to speech once, before capture, content-hashed and cached, with scenes sized to each line. Kokoro (free, local), OpenAI, Google, Gemini, Polly, ElevenLabs, or macOS say
Live previewkamishibai dev: play, scrub, a range to loop, sound or a storyboard, and which frames a render will capture
CLIrender, or its halves capture and encode, plus tts to bake narration
Librarythe same from code: render, capture, encode and the building blocks under them

All docs: docs/


Examples

  • examples/basics — a 6s reel showcasing the kamishibai/react sugar: fade in/out, an eased progress meter + count-up, staggered reveals, and eased motion.
  • examples/video — frame-accurate video via WebCodecs, both raw (index.ts) and React (react.tsx). The clip is an AV1-in-MP4 test pattern generated by ffmpeg (testsrc, synthetic — no copyright).
  • examples/narration — TTS as a build pre-pass: synthesize the voice-over up front with say, size each scene to its line with narrationLayout, and add the text as captions.
pnpm build
node dist/cli.js render examples/basics/index.tsx -o basics.mp4 -w 4
node dist/cli.js render examples/video/react.tsx --public examples/video/public -o video.mp4 -w 4
node dist/cli.js render examples/narration/index.tsx -o narration.mp4 -w 4   # macOS `say`

Determinism & guarantees

kamishibai does not guarantee pixel-identical output across environments. It gives you the levers to make output stable, and the philosophy is to verify in CI rather than promise:

  • Fonts are awaited (document.fonts.ready) before the first capture, so text doesn't reflow mid-reel.
  • Pin Chromium via your Playwright version — emoji and sub-pixel rendering depend on the Chrome build.
  • Keep seek(ms) a pure function of ms (no Date.now(), no un-seeded randomness) so any Chrome renders any frame identically.
  • The worker count doesn't change the pixels. Each worker starts partway through the reel, so a frame must not depend on what its Chrome drew before. Before each screenshot the renderer drops the paint state Chrome keeps between frames, and kamishibai/react makes the page paint exactly the values its fingerprint describes, so a run of copied frames starts from the same still however the reel is split.

The intended workflow: pin the environment, render in CI, and let a frame/checksum check fail loudly when something drifts.


License

MIT.

Name

紙芝居 (kamishibai) is a Japanese form of storytelling that advances a tale one picture at a time — precisely this tool's "show one still per moment" approach.

↑↓ navigate openesc close