MotionActor
Write motion as code. Resolve any frame as a pure function.
A generator-driven actor runtime for deterministic, frame-based video. The scene generator records what you authored; at(frame) reconstructs it — for any frame, in any order, with the same answer every time.
card.reveal({ duration: 1 })ctx.wait(1)The scene above, in full. The player is reading compiled.at(frame).
import { createScene, LayoutActor, signal } from "@motionactor/core";
class Card extends LayoutActor {
progress = signal(0);
*reveal({ duration }) {
yield* this.progress.tween(1, duration);
}
}
const compiled = createScene(function* (ctx) {
const card = ctx.spawn(Card);
yield* card.reveal({ duration: 1 }); // 30 frames at 30fps
yield* ctx.wait(1); // 30 more
return { card };
});
compiled.at(15).scene.card.progress; // 0.5 — no playback, no side effects
compiled.at(15).scene.card.progress; // 0.5 — every single timeTwo stages, and that is all
Compile runs your generator once and writes down what it authored. Resolution reconstructs actor state for a frame from that record. Every property worth having follows from keeping them apart.
Sequential to author
The generator reads like a storyboard — do this, wait, then do that. yield* advances an authored cursor; nothing plays.
Random access to render
Frame 400 costs the same whether or not you asked for frame 399. Seeking never replays.
Pure by contract
at(frame) depends on the frame, the channel values it reads, and the options you pass. Nothing else may influence it.
Host values have a door
Measured boxes, physics, fetched data — everything observed enters through a channel, recorded per frame so seeking stays honest.
One hosting model
Slots are named positions; child declarations are their occupants. No structural/mounted split, no second mechanism.
Testable without pixels
Compile a scene, resolve a frame, assert on the actors. No canvas, no browser, no render.
Start reading
Getting started
Install, compile a scene, resolve a frame, render it with Remotion.
How it works
Compile and resolve, authored time, and what each stage is allowed to do.
Reactivity
signal, reactiveSignal, derived, channel — and which one a given value wants.
Complete example
A whole composition in two files, typechecked in CI.
Component library
102 actor families and effects, installed into your repo with shadcn.