Communitygithub.com

motionkit

Erstelle Bewegtgrafik-Filme im Code mit der motionkit-Canvas-Engine – kopiere die Bewegung (Timing, Layout, Bewegung) eines Referenzvideos mit eigenen Worten und eigener Kunst oder erstelle einen neuen Filmschnitt im Takt aus 44 vorgefertigten Moves mit synthetisiertem Soundtrack. Es erzeugt auch transparente animierte Titel und Overlays und platziert sie auf einer EditMax-Zeitleiste via EditMax MCP-Tools.

Was ist motionkit?

Motionkit ist eine leistungsstarke Canvas-Engine zur Erstellung von Bewegtgrafik-Filmen direkt im Code. Entwickler schreiben eine einzelne HTML- und JavaScript-Seite mit einer `renderFrame(f)`-Funktion, die jeden Frame (30 fps, 1920×1080) zeichnet. Die Engine übernimmt das Rendering über einen versteckten Chrome-Browser, kodiert das Video mit ffmpeg in hochwertiges 60-fps-MP4 (ca. 4–5 MB/s Film) und synthetisiert den Soundtrack. Sie ist ideal, um die Bewegung eines Referenzvideos nachzuahmen („Clone dieses Video“), einen Launch- oder Produktfilm zu erstellen oder animierte Titel/Intros/Outros für die Videobearbeitung mit EditMax zu generieren. Die Engine wird über die Kommandozeile mit Befehlen wie `bun $E/build.ts <name>` bedient. Sie bietet 44 vorgefertigte Move-Typen (Wörter, Pfade, Bursts, Diagramme, Callouts, Logos, Bounces, Ticker sowie Übergänge). Entwickler legen Clips mit `M.clip()` fest, definieren Szenen und eine Zeitleiste mit BPM und Abschnitten. Das Build-System führt automatisch Sound-Synthese, Lesegeschwindigkeits- und Synchronisationsprüfungen durch. Für Launch-Filme gibt es spezielle Bühnenelemente wie `backdrop`, `glass`, `camera` und `term`. Motionkit unterstützt macOS und erfordert bun, ffmpeg, Python/uv und einen Chromium-Browser. EditMax-Nutzer können animierte Overlays (transparente Titel) oder Vollbild-Clips (Intros/Outros) rendern und per EditMax MCP-Tools direkt auf der Zeitleiste platzieren. Die Engine prüft, ob Tools wie `inspect_timeline` und `import_media` verfügbar sind, und fällt auf manuelles Importieren zurück, falls nötig. Die Arbeit als git-Repo wird empfohlen, wobei `out-*/` und `ref/` ignoriert werden sollten.

Funktioniert mit✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/SkidGod4444/motionkit/tree/HEAD/skills/motionkit

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht motionkit?

Ein Film ist eine Seite plus ein Skript, dessen renderFrame(f) den Frame f (30 pro Sekunde, 1920×1080) zeichnet – und sonst nichts. Ein versteckter Chrome durchläuft die Frames, ffmpeg kodiert (das MP4 wird auf 60 Frames pro Sekunde verdoppelt, in hoher Qualität, etwa 4 bis 5 MB pro Sekunde Film), der Soundtrack wird synthetisiert.

Wo die Dinge sind

  • Engine: der Ordner engine/ neben dieser Datei (Moves, Renderer, Sound, Prüfungen, Schriften). Nenne ihn $E und verwende seinen vollständigen Pfad. Lies daraus; lege niemals Filme hinein (das Setup fügt dort sein eigenes node_modules hinzu, das ist normal).
  • Arbeitsordner: der Ordner, in dem der Benutzer arbeitet. Filme (<name>.html, <name>.js), assets/, ref/ und out-<name>/ kommen alle dorthin, und jeder Befehl wird von dort ausgeführt. Eine Seite findet lib.js, moves.js und fonts/ in der Engine selbst. Wenn der Arbeitsordner ein git-Repo ist, füge out-*/ und ref/ zur .gitignore hinzu.

Zuerst: Einrichtung (einmal pro Rechner)

  1. Führe sh $E/setup.sh aus. Es prüft nur: bun, ffmpeg mit ffprobe, python3, uv, einen Chromium-Browser (Chrome, Chromium oder Edge; CHROME_PATH überschreibt) und das eine Paket der Engine.
  2. Wenn es Ready ausgibt, fahre fort. Fehlt nur engine package (normal bei einer frischen Installation), führe sh $E/setup.sh --install ohne Nachfrage aus: Es holt nur ein Paket in den eigenen Ordner des Skills. Fehlt ein Tool oder der Browser (MISSING), zeige dem Benutzer diese Liste und die ausgegebenen Installationsbefehle und frage einmal nach, bevor Software auf seinem Rechner installiert wird.
  3. Bei Ja: führe sh $E/setup.sh --install aus (Homebrew auf macOS, die offiziellen Installer für bun und uv), dann führe die Prüfung erneut durch. Zeilen, die run this yourself sagen, benötigen das Passwort des Benutzers (sudo auf Linux) oder einen manuellen Download: Führe diese niemals aus; gib dem Benutzer den genauen Befehl und warte. Schlägt eine Installation fehl, gib dem Benutzer den einen Befehl, den er selbst ausführen muss.
  4. Beweise, dass es funktioniert: Führe vom Arbeitsordner bun $E/build.ts hello aus und bestätige, dass out-hello/hello.mp4 existiert.

Nur auf macOS getestet; sage dies, wenn der Benutzer auf Linux oder Windows ist.

Arbeitsbeispiele zum Kopieren: $E/hello.js (ein Film auf einem Beat-Raster, jeder Ton aus Clips, Szenerie in Code gezeichnet), $E/title.js (ein transparenter Titel zum Überlagern von Filmmaterial), $E/moves-demo.js (jeder Move einmal).

Erstelle einen Film: Clips zuerst

Deklariere jede Verwendung eines Moves einmal als Clip. Das Bild, der Ton und die Lesegeschwindigkeitsprüfung stammen alle aus dieser einen Zeile.

const M = window.MOVES, B = M.brand, G = M.grid(120);          // 120 bpm: ein Beat ist 15 Frames, ein Takt 60
const K = { line: M.clip("words", G.bar(1) + 2, 10, { text: "Copy the motion.", x: 960, y: 590, size: 110, fam: B.display, stretch: B.wide, weight: 600, color: B.paper, until: G.bar(2) }) };
// in einer Szene:  K.line.draw(X, f)          K.line.on(f) ist wahr, solange es sichtbar sein soll
window.timeline = () => ({ fps: 30, total: TOTAL, bpm: G.bpm, sections: [[0, "intro"], [4, "build"], [8, "drop"], [24, "outro"]], cues: M.cues(), captions: M.captions() });

Lies für einen Launch- oder Produktfilm zuerst den Abschnitt „Launch- und Produktfilme“ unten. Beginne einen Film mit bun $E/new.ts <name>: Es schreibt <name>.html und <name>.js in den Arbeitsordner, kopiert aus dem hello-Beispiel. Schreibe die Clips, Szenen und den Text neu. bun $E/build.ts <name> führt dann in dieser Reihenfolge aus: Zeitleiste, Soundtrack (sound.py), Soundprüfung, Lesegeschwindigkeitsprüfung (lint.py), Render, Zusammenfügen, Synchronisationsprüfung (sync.py) und schreibt out-<name>/<name>.mp4. Eine Zeitleiste ohne bpm erhält einen einfacheren Soundtrack von audio.py (nur Schnitte). Zeitleisten-Schalter: sound: "fx" (nur Move-Sounds, keine Musik), sound: "none", alpha: true (transparenter Hintergrund, .mov-Ausgabe; siehe EditMax-Abschnitt).

Anatomie eines Film-Skripts

$E/hello.js ist das Vorbild; lies es einmal. Was die einzelnen Teile sind:

  • Globale Werte aus lib.js: W, H (1920, 1080), X (der Canvas-Kontext), clamp, lerp, TAU, hash, noise, txt(ctx, text, x, y, size, weight, color, fam, italic, align), rr (abgerundetes Rechteck), vignette(stärke, innenradius).
  • M.clip(move, start, length, options): start und length sind Frames; length gibt an, wie lange der Move zum Abspielen braucht, nicht wie lange er bleibt. Es gibt { draw(ctx, f), t(f) (0..1 während des Moves), on(f), o (die Optionen) } zurück. Nach seiner Länge zeichnet ein Clip weiterhin seinen Endzustand: Er versteckt sich nicht. Verstecke ihn durch Beenden der Szene oder mit if (K.x.on(f)), wobei on von start bis until (für immer ohne until) wahr ist. Um einen fertigen Text-Move innerhalb eines Übergangs' from anzuzeigen, zeichne ihn bei t = 1: M.words(ctx, 1, K.line.o). One-Shot-Effekte (burst, glitchCut) benötigen außerdem K.x.t(f) < 1.
  • Rufe Formen innerhalb eines Clips auf: Übergänge (transitions) benötigen from und to in den Optionen; Wrapper (punch, shake, sweep, smear) benötigen draw. Alles andere (pathDraw, burst, bars, chart, callout, logoDraw, bounce, ticker) benötigt nur Optionen. mesh und parallax sind Hintergründe: rufe sie direkt auf, M.mesh(ctx, f / 240, { colors }), wobei t einfach eine langsam wachsende Zahl ist.
  • Textoptionen: x ist die Mitte der Zeile (align: "center" ist standard), y die Grundlinie. stretch: B.wide ergibt den breiten Schnitt, stretch: null schaltet es aus. Nichts misst oder umbricht Text für dich: Bei Größe 150 breit umfassen 13 Zeichen etwa 1.340 Pixel, also rendere ein Standbild und überprüfe, ob jede Zeile mit Rand innerhalb des Rahmens liegt.
  • Szenentabelle: [erster Frame, draw(f), drawAfterFinish(f)]. renderFrame setzt den Kontextzustand zurück (behalte diese Zeile), zeichnet die aktuelle Szene, dann Korn und Vignette, dann den dritten Slot für alles, was sauber bleiben muss (Logos).
  • window.ready: ein Promise, auf das der Renderer wartet: Promise.all([M.fonts(), M.levels("out-<name>/levels.json"), M.load({ ... })]). M.levels wird nur für M.eq benötigt und ist sicher, bevor die Datei existiert.
  • Zeitleiste: sections sind [beat, name]; ein kurzer Film kann einfach [[0, "intro"], [8, "drop"], [16, "outro"]] verwenden, und jeder drop-Start erhält den halben Beat Stille (behalte oder stummschalte dort Clips). sync listet Frames auf, an denen ein Schnitt und ein Bassschlag zusammenfallen müssen: Verwende den ersten Frame jeder Szene ab dem Drop. „Änderung“ wird anhand der üblichen Frame-zu-Frame-Differenz des Films beurteilt, sodass ein Übergang, der genau auf einem Sync-Frame endet, dort nichts zu ändern hinterlässt und die Prüfung NO CHANGE ausgibt: Füge einen kurzen Blitz hinzu oder starte den nächsten Move auf diesem Frame. cuts ist jeder Szenenstart.
  • Farben: Lies alles aus M.brand (B). M.rgba(B.ink, 0.7) ergibt eine Farbe mit Deckkraft, M.mix(a, b, t) eine Farbe zwischen zwei. M.setBrand ändert M.brand direkt; rufe es auf, bevor irgendein Clip deklariert wird, und setze auch accentOnDark (der Akzent, der auf dunklem Hintergrund verwendet wird; er folgt nicht accent). Für eine Schrift ohne breiten Schnitt setze wide: null.
  • Länge: Die Lesegeschwindigkeit gibt das Minimum vor: Eine 3-Wort-Zeile benötigt etwa 1,3 s, nachdem sie erschienen ist, also eine Zeile pro Takt bei 120 bpm. Der Soundtrack läuft etwa eine halbe Sekunde über den letzten Frame hinaus und wird dort abgeschnitten; Ende mit einem outro-Abschnitt, damit der Schnitt in dessen Ende fällt.
  • Build-Ergebnisse: build.ts beendet sich mit 0, auch wenn eine Prüfung fehlschlägt; Fehlschläge werden als WARNING:-Zeilen mit den Details darüber ausgegeben. Behandle jede Warnung als Fehler: Lies die Ausgabe (filtere die frame n/total-Fortschrittszeilen aus), korrigiere, baue neu, bis keine mehr vorhanden sind. Standbilder werden als out-<name>/fNNNN.jpg geschrieben; lies sie. bun $E/pure.ts <name> bestätigt, dass Frames allein und nach anderen Frames gleich gerendert werden.
  • sound.py benötigt numpy und wird immer mit uv run ausgeführt; die anderen Python-Skripte verwenden nur die Standardbibliothek.

Launch- und Produktfilme: Zeige das Produkt

Ein Film aus großen Wörtern auf einem Hintergrund wirkt einfach. Launch-Filme, die funktionieren, halten das Produkt in einer visuellen Welt mit Tiefe und einer sich langsam bewegenden Kamera auf dem Bildschirm, verwenden kleine, kurze Texte und halten Einstellungen für 2 bis 6 Sekunden (einige Takte), nicht einen Schnitt pro Beat. Beginne für einen Launch- oder Produktfilm NICHT mit hello:

  1. Entscheide zuerst den Look: eine Hintergrundwelt, eine Akzentfarbe, eine Schriftfamilie. Sage es dem Benutzer in zwei Zeilen.
  2. Storyboard 6 bis 8 Einstellungen mit echten Dingen: den echten Bildschirm oder die Ausgabe des Produkts, echte Befehle, echter Code, echte Ergebnisse. Zeichne niemals ein Interface, das das Produkt nicht hat, erfinde niemals Zahlen und verwende niemals das Logo eines anderen Unternehmens. Beschriftungen sind kleine Etiketten (txt, Mono, unten links), keine Schlagzeilen.
  3. Erstelle zuerst eine Helden-Einstellung, rendere Standbilder und vergleiche mit einem echten Launch-Film, bevor der Rest gebaut wird.

Die Seite muss stage.js nach moves.js laden (Seiten, die mit new.ts erstellt wurden, tun dies). Beginne renderFrame mit M.frame(); M.reset(X);. Bühnenstücke (alle auf MOVES):

StückWas es ist
backdrop(ctx, f, { base, lights[], streak })Fast-schwarz mit langsamen Lichtpools: die Welt, in der alles sitzt
glass(ctx, x, y, w, h, { r, top, bottom, rim, shadow })Eine dunkle, abgerundete Tafel mit einem Lichtrand und einem weichen Schatten
camera(ctx, cam, draw) mit cam(a, b, t, ease)Schau auf einen Punkt einer größeren Szene: { x, y, zoom, rot }; beginne makronah und zoom heraus, oder drifte langsam
tilt(ctx, draw, { depth, focus, blur, fog, top, height, width, cx, roll })Zeichnet eine Vollbildszene als eine schräg geneigte Ebene; der ferne Rand ist kleiner, dunkler und unscharf
tiles(ctx, f, { cells: [{ draw(ctx, t), label, bg, len, hold }], cols, x, y, w, gap })Ein Raster kleiner Bildschirme, die jeweils einen Move live abspielen (setze niemals einen Übergang in eine Kachel)
term(ctx, f, { x, y, size, lines: [{ text, at, speed, prompt, mark: "ok" or "run", color }] })Terminalzeilen, die auf ihrem Frame eintippen oder erscheinen
code(ctx, { lines[], x, y, size, lead, hot, shown })JavaScript mit ruhiger Syntaxfarbe und einer leuchtenden Zeile
wave(ctx, { peaks, x, y, w, h, played, beats[], blocks[] })Die Form eines echten Soundtracks mit Abspielkopf, Beat-Ticks und Clips auf einer Spur

Bühnenstücke erzeugen keinen eigenen Ton: Füge Cues von Hand zur Zeitleiste hinzu, { f, kind, gain } mit Arten wie type, tick, pop, ding.

Zu einem echten Song schneiden

  1. Der Benutzer liefert die Musikdatei und muss das Recht haben, sie zu verwenden; sage das und setze den von der Lizenz geforderten Hinweis auf die Endkarte. Reiße niemals einen Song von einer Streaming-Seite.
  2. uv run $E/beats.py <datei> gibt das Tempo und die Lautstärke jedes Taktes aus. Wähle einen Ausschnitt, der auf einem Takt mit einem Abschnittswechsel einige Takte später beginnt, dann schreibt uv run $E/beats.py <datei> --from <sekunden> --len <sekunden> --out beats.json die Dateien beats.json und beats.js.
  3. Lade beats.js auf der Seite vor dem Filmskript. Schreibe jeden Szenenstart als Beat-Nummer: const b = (n) => window.BEATS.frames[n]. Schneide auf Takten (alle 4 Beats), wo der Track wechselt.
  4. Setze in der Zeitleiste music: { file, from }, sound: "fx" (die eigenen Sounds der Moves bleiben leise unter der Musik) oder "none", ein bpm und sync: [frames der echten Schnitte]. Der Build mischt den Track bei -16 LUFS ein, blendet sein Ende aus und prüft, ob jeder Schnitt innerhalb eines Frames einen Bassschlag hat. Füge keine Blitze hinzu, nur um diese Prüfung zu bestehen.

Motion für EditMax (ein Clip auf einer Videobearbeitungs-Zeitleiste)

Verwende dies, wenn der Benutzer in EditMax bearbeitet und eine Bewegung im Schnitt wünscht: einen animierten Titel über Filmmaterial, eine Intro- oder Outro-Karte, einen kinetischen Typografie-Beat zwischen Aufnahmen. Es benötigt zwei Dinge in derselben Agentensitzung: eine Shell (zum Rendern) und EditMax's MCP-Tools (inspect_timeline, import_media, ...; Einrichtung über den Reiter „Agents“ in EditMax). EditMax's eigener In-App-Chat verweigert Shell-Befehle, daher kann es diesen Skill nicht ausführen: Sage das und teile dem Benutzer mit, einen Agenten wie Claude Code zu verbinden. Wenn die EditMax-Tools fehlen oder nicht antworten, rendere den Clip trotzdem und gib dem Benutzer den Dateipfad zum Ziehen.

1. Wähle den Weg. Bevorzuge EditMax' eigene Tools, wenn sie die Bewegung abdecken, weil der Text in der App bearbeitbar bleibt:

GewünschtVerwende
Ein Titel oder Lower Third, der einblendet, schiebt, poppt, tippt oder wischtadd_text / add_lower_third + set_text_animation
Ein Dissolve, Push, Slide, Wipe oder Iris zwischen zwei Clipsset_transition
Ein Clip, der sich bewegt, skaliert oder einblendetset_keyframe, set_clip_transform, set_clip_fades
Alles andere: Slam, Scramble, Split-Flap, Wortrad, Cross-Out, Highlight, Pfad- oder Logo-Zeichnung, Diagramme, Zähler, Bursts, Multi-Move-Sequenzen, ein komplettes Intro oder OutroRendere einen Clip mit diesem Skill

2. Lies das Projekt. inspect_timeline: Notiere die Bildgröße, die Bildrate, die Spuren und den Zeitpunkt, an dem die Motion platziert werden soll. Diese Engine rendert 1920×1080 bei 30 Bildern pro Sekunde. Ein 16:9-Projekt einer anderen Größe skaliert es sauber. Bei einem vertikalen oder quadratischen Projekt sage klar, dass der Clip letterboxed oder mit set_clip_transform hochskaliert und beschnitten werden muss und dass ein nativer Titel möglicherweise besser geeignet ist.

3. Rendere.

  • Overlay (liegt auf Filmmaterial): bun $E/new.ts <name> --overlay, nach dem Vorbild von $E/title.js. Die Zeitleiste hat alpha: true und sound: "fx"; der Build schreibt out-<name>/<name>.mov (ProRes 4444 mit transparentem Hintergrund). Regeln: den Frame leeren (X.clearRect), niemals füllen; kein grain, vignette, mesh, parallax oder Vollbild-Übergänge; einen weichen Schatten oder eine Platte unter den Text setzen, damit er auf jedem Filmmaterial lesbar ist; Text innerhalb der mittleren 90 % des Frames halten; am Ende ausblenden.
  • Vollbild (Intro, Outro, eine Karte zwischen Aufnahmen): bun $E/new.ts <name>, nach dem Vorbild von $E/hello.js; der Build schreibt out-<name>/<name>.mp4.
  • Sound (setze sound: in der Zeitleiste): Lasse es weg für den vollständigen Soundtrack (ein alleinstehendes Intro oder Outro); "fx" für nur die Sounds, die die Moves machen (alles, was über Filmmaterial, Sprache oder die Musik des Benutzers läuft); "none" für Stille. Frage, was der Benutzer möchte, wenn der Schnitt bereits Musik hat.
  • Baue, behebe jedes WARNING und lies Standbilder, bevor du fortfährst.

4. Lege die Datei an einen dauerhaften Ort. EditMax referenziert importierte Dateien, es kopiert sie nicht. Kopiere die fertige Datei aus out-<name>/ in einen Ordner, den der Benutzer behält (frage einmal; schlage ~/Movies/Motions/ vor) und importiere von dort.

5. Platziere sie, ohne den Schnitt des Benutzers zu verschieben. insert_clip mit einer Zeit ist ein Riss...

Verwandte Skills