Miraiclip: an open-source engine for building video editors in the browser
I've been building Miraiclip, an open-source (MIT) engine for video editors that run in the browser. It isn't an editor app. It's the part underneath: project state, a microsecond timeline, undo/redo, a WebGL renderer an
I've been building Miraiclip, an open-source (MIT) engine for video editors that run in the browser. It isn't an editor app. It's the part underneath: project state, a microsecond timeline, undo/redo, a WebGL renderer and export. You build the UI in React, Vue, Svelte or plain JS.
Here's a 90-second demo of an editor built on it: https://comaniacs.github.io/miraiclip/#demo
A project is a store, edits are commands
import { createProject } from "@miraiclip/core";
const project = createProject({ width: 1920, height: 1080, fps: 30 });
project.dispatch({
type: "asset/add",
payload: { id: "intro", kind: "video", src: "/intro.mp4", durationUs: 12_000_000 },
});
project.dispatch({ type: "track/add", payload: { id: "v1", kind: "video" } });
project.dispatch({
type: "clip/add",
payload: { kind: "video", id: "c1", trackId: "v1", assetId: "intro", startUs: 0, durationUs: 5_000_000 },
});
// Several edits, one undo step
project.transaction(() => {
project.dispatch({ type: "clip/split", payload: { clipId: "c1", atUs: 2_000_000, newClipId: "c1b" } });
project.dispatch({ type: "clip/move", payload: { clipId: "c1", startUs: 1_000_000 } });
});
project.undo();
// Every change arrives as JSON patches: the hook for sync and collaboration
project.events.on("patches", ({ patches }) => console.log(patches));
Times are integers in microseconds, so frame math never drifts at 24, 25, 29.97 or 60 fps.
Preview and export with the same compositor
import { exportProject } from "@miraiclip/renderer";
const mp4 = await exportProject(project, { format: "mp4", quality: "high" });
Decoding is WebCodecs, compositing is WebGL (PixiJS), and the export reuses the preview's compositor, so the file matches what you saw. It also runs in a worker, and from Node through @miraiclip/server-export (headless Chrome, plus a miraiclip-export CLI).
Overlays in HTML and CSS
project.dispatch({
type: "clip/add",
payload: {
kind: "html", id: "badge", trackId: "overlay",
startUs: 0, durationUs: 4_000_000,
template: `<div class="badge">{{label}}</div>`,
params: { label: "Just launched" },
widthPx: 640, heightPx: 120,
animated: true, // CSS animations play and export frame-exactly
},
});
Placeholders make every overlay a form field. The editor in the demo uses exactly this for its templates and its live code editor.
One template, many videos
import { hydrate } from "@miraiclip/templates";
const doc = hydrate(template, { name: "Vinamra", accent: "#2e8f63" });
const personalized = createProject(doc); // preview it, edit it, export it
Hydration is pure and deterministic, and batch rendering in Node takes JSON, NDJSON or CSV rows.
Let a model edit
import { createAssistant, openAIChatModel } from "@miraiclip/assistant";
const assistant = createAssistant({
model: openAIChatModel({ apiKey: process.env.OPENAI_API_KEY, model: "gpt-5.4-mini" }),
});
const turn = await assistant.run(project, "add dissolves between the clips and make the title pop in");
project.undo(); // the whole request is one undo step
Prefer agents you already use? npx @miraiclip/mcp --project ./video.miraiclip.json gives Claude, Codex or any MCP client the same commands, plus rendered frames it can look at.
Also in the box
79 effects, transitions with audio crossfades, keyframes and animation presets, karaoke captions with SRT/VTT import, and stock or AI-generated audio with license tracking.
Status
Pre-1.0 and moving fast: APIs can change between minor versions. Issues, questions and "I tried it and X broke" are all welcome.
โข Docs and live examples: https://comaniacs.github.io/miraiclip/
โข GitHub: https://github.com/comaniacs/miraiclip
โข Discord: https://discord.gg/7S2XmHBeX
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes โ full credit and traffic to the original publisher.