Motion Canvas
Stand 2026-10: @motion-canvas/core, /2d, /ffmpeg 3.17. Benötigt Node 16+.
Remotion vs Motion Canvas: Remotion = React, Frame → UI, skaliert auf datengetriebene/vorlagenbasierte Videos und Server-Rendering. Motion Canvas = imperative Timeline (yield* Schritt für Schritt) mit einem Editor zum Timing auf eine Voiceover-Spur. Wähle eines pro Video; nicht mischen.
Einrichtung
npm init @motion-canvas@latest # Name, TypeScript, „Video (FFmpeg)“-Exporter wählen
npm install
npm run serve # Editor unter http://localhost:9000
src/project.ts # makeProject({ scenes: [...] })
src/scenes/*.tsx # eine Szene pro Datei
// src/project.ts
import {makeProject} from '@motion-canvas/core';
import intro from './scenes/intro?scene'; // ?scene-Anhängsel ist erforderlich
export default makeProject({scenes: [intro]});
Szene
import {Circle, Rect, Txt, makeScene2D} from '@motion-canvas/2d';
import {all, chain, createRef, easeInOutCubic, sequence, waitFor, waitUntil} from '@motion-canvas/core';
export default makeScene2D(function* (view) {
const circle = createRef<Circle>();
view.add(<Circle ref={circle} x={-300} size={240} fill="#e13238" />);
yield* all( // parallel, warte auf alle
circle().position.x(300, 1).to(-300, 1), // Tween: Wert(Wert, Sekunden), mit .to() verketten
circle().fill('#e6a700', 1).to('#e13238', 1),
);
yield* waitUntil('title'); // benanntes Zeitereignis, in der Editor-Timeline verschiebbar
yield* circle().scale(2, 0.6, easeInOutCubic);
});
- Koordinaten: Ursprung in der Mitte der Ansicht;
x,y,size,width,height,rotation,scale,opacity,fill,stroke,lineWidth. - Komponenten:
Rect(radiusfür abgerundete Ecken),Circle,Line/Spline(points,endfür Zeicheneffekt),Txt,Img,Video,Layout(Flexbox:layout direction gap),Code,Latex. - Ein Prop mit einem Wert setzt ihn; mit
(Wert, Sekunden[, Easing])wird ein Tween erzeugt und muss mityield*aufgerufen werden; ohne Argumente wird der Wert gelesen.
Ablauf
| Aufruf | Effekt |
|---|---|
all(...t) | zusammen ausführen, auf alle warten |
any(...t) | zusammen ausführen, auf das erste warten |
chain(...t) | nacheinander |
sequence(0.2, ...t) | jedes startet 0,2 s nach dem vorherigen (ohne Warten) |
delay(0.5, t) | starte nach 0,5 s |
loop(3, () => t) | wiederholen |
waitFor(1.5) | pausiere 1,5 s |
waitUntil('event') | pausiere bis zum benannten Ereignis im Editor – für Voiceover-Synchronisation nutzen |
useDuration('event') | Länge eines benannten Ereignisses, als Dauer für ein Tween |
Rendern
- Editor → Rendering-Panel: Auflösung, Bildrate (24/30/60), Bereich, Exporter. Klicke RENDER.
- Ausgabe landet in
/output. Der Standard-Exporter schreibt eine Bildsequenz; für MP4 mit Audio füge den FFmpeg-Exporter hinzu:
npm install --save @motion-canvas/ffmpeg
// vite.config.ts
import {defineConfig} from 'vite';
import motionCanvas from '@motion-canvas/vite-plugin';
import ffmpeg from '@motion-canvas/ffmpeg';
export default defineConfig({plugins: [motionCanvas(), ffmpeg()]});
Wähle dann unter Video Settings Video (FFmpeg).
- Auflösungsänderungen skalieren das Layout nicht; entscheide die endgültige Größe (z. B. 1920×1080 oder 1080×1920) vor dem Anordnen.