Communitygithub.com

Lob0Garou/opus-visual-motion-engine

Disziplinierte Motion-Graphics-Pipeline: code-basierte Video/UI, deterministisches seek(t), automatisierte Render-QA, MP4-Export – funktioniert auch für text-only Modelle.

Was ist opus-visual-motion-engine?

Die **Opus Visual Motion Engine** ist eine strikt geregelte Pipeline für die Erstellung von Motion Graphics, Videos und UI-Seiten. Sie besteht aus den Phasen: Planen → aus Vorlage bauen → Rendern → QA → Korrigieren → Exportieren. Die Qualität wird durch erzwungene Prüfungen vor und nach dem Rendern sichergestellt, nicht durch subjektiven Geschmack. Jeder Schritt muss in der vorgegebenen Reihenfolge ausgeführt werden; kein Schritt darf übersprungen werden, auch wenn die Aufgabe 'einfach aussieht'. Die Engine funktioniert mit jedem Sprachmodell, das Text und Code verarbeiten kann, und ist speziell für Claude Code, Cursor und Codex optimiert. Sie basiert auf einem deterministischen Zeitsystem: `render(t)` ist der einzige Zustandstreiber, sodass jeder Frame reproduzierbar ist. Die Pipeline unterstützt JavaScript-Animationen, CSS-Übergänge, SVG-Draw-On-Effekte und die Gestaltung von Benutzeroberflächen. Sie enthält ein automatisiertes QA-Skript (`qa.mjs`), das auf Einhaltung der Regeln prüft, und eine `audio-data.mjs`-Hilfe zur Synchronisation mit Musik oder Sprache. Der Workflow folgt einer strengen, aber klaren Methodik, die KI-typische Designfehler vermeidet und zu professionellen Ergebnissen führt. Ziel ist es, dass das Endprodukt absichtlich gestaltet und nicht nur generiert aussieht.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add Lob0Garou/opus-visual-motion-engine

In Ihrer bevorzugten KI fragen

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

Dokumentation

Opus Visual Motion Engine

Eine disziplinierte Pipeline für visuelle Liefergegenstände: planen → aus der Vorlage bauen → rendern → QA → korrigieren → exportieren. Qualität entsteht durch Kontrollen vor und nach dem Rendern, nicht durch Geschmack. Folge den Schritten in der angegebenen Reihenfolge. Überspringe keinen Schritt, weil die Aufgabe „einfach aussieht“.

Die folgenden Pfade sind relativ zum Verzeichnis dieses Skills (der skill_resources-Basis, die dir gegeben wurde). Nenne es $SKILL.

0. Zuerst lesen (unbedingt)

Bevor du Code schreibst, lies die Referenzen, die zum Liefergegenstand passen. Sie sind maßgeblich für ihr Thema:

LiefergegenstandLesen
Video, Motion Graphic, Erklärvideo, Produktvideoreferences/video-generation.md, references/motion-design.md, references/javascript-animation.md
Kinetische Typografie / Typografie-geführtes Stückdas Video-Set oben + references/typography.md
Landing Page, Dashboard, Mockup, UIreferences/visual-design.md, references/typography.md
Diagramm, Schema, Datenvisualisierungreferences/visual-design.md §4
Bildausschnitt / Kamerentscheidungenreferences/cinematography.md
Dauern und Easing-Funktionenreferences/animation-primitives.md
Musik oder Sprache zum SynchronisierenSKILL.md §10 + references/video-generation.md §6

Ausgearbeitete Beispiele befinden sich in examples/*.md. Lies das, das dem Brief am nächsten kommt.

1. Vor dem Codieren planen (ausschreiben)

Schreibe den Plan in deine Antwort (oder in eine PLAN.md neben der Ausgabe), bevor du das HTML erstellst. Ein Plan, der nur in deinem Kopf existiert, zählt nicht.

UI / Seite

  1. Primäre Botschaft: ein Satz. Was muss der Betrachter in 3 Sekunden verstehen?
  2. Benannte Richtung: ein Name, 4–6 benannte Hex-Token mit zugewiesenen Bedeutungen, Schriftarten mit Rollen, Formbehandlung. Leite sie aus der Branche, den Materialien und der Ausdrucksweise des Themas ab. Ein Spielwarenladen und ein Fintech-Dashboard teilen nie eine Richtung.
  3. Hierarchie: Markiere jeden Block als PRIMARY / SECONDARY / TERTIARY. Nur PRIMARY erhält die eine kühne Geste.
  4. Abschnittsabfolge: eine Zeile pro Abschnitt, die seine Aufgabe beschreibt und wie er zum nächsten überleitet.
  5. Vor-Render-Mathematik: Textbreite ≈ chars × 0.55 × font-size (serifenlos) oder × 0.5 (Serife); Kastenbreite = max(title_chars × 8, subtitle_chars × 7) + 24 bei 14px; Zeilenpassung = ΣBreiten + Lücken ≤ Container. Verfolge jeden Verbinder gegen jede Box. Wenn er eine kreuzt, zeichne einen L-förmigen Pfad.

Video / Motion Graphic

  1. Kernbotschaft: ein Satz. Wenn es zwei braucht, gibt es zwei Videos.
  2. Beats: 3–7. Jeder Beat beantwortet die Frage „Was weiß der Betrachter jetzt?“.
  3. Szenenkarte pro Beat: Start/Ende (s), Komposition, Kamera, Schriftgrößen, Primitiven (2–4), Ausgang. Verwende die Vorlage in references/motion-design.md §2.
  4. Signature-Moment: Nenne den EINEN Frame, in dem der Mechanismus gezeigt wird, nicht beschriftet (z. B. Rauschen in Signal gefiltert). Wenn die Geschichte nur mit ihren Untertiteln funktioniert, gestalte den Beat neu.
  5. Globale Zeitleiste: absolute Zeitstempel. Der AUSGANG einer Szene ist abgeschlossen, bevor die nächste Szene den Platz beansprucht. Setze DURATION auf das wahre Ende (Standard 10–20s; 30–45s nur mit Erzählung).

Eine Szene ohne Karte gehört nicht in das Video.

2. Aus der Vorlage bauen (Video)

Kopiere assets/composition-template.html neben den Liefergegenstand und fülle die EDIT-Blöcke. Schreibe die ENGINE-Blöcke nicht um. Sie bieten bereits:

  • eine 1920×1080 #stage (ändere STAGE_W/H für 1080×1920 oder 1080×1080), an jedes Fenster angepasst;
  • window.DURATION, window.seek(t), window.render(t), window.SCENES: den Capture/Export-Vertrag (QA erfasst jede Szene aus SCENES);
  • at(), ease.*, lerp, mulberry32 (gesäter PRNG) und layer() für Szenensichtbarkeit plus AUSGANG;
  • Audio-Helfer audioAt(t, "rms"|"low"), since(t, list), hit(t, list, dur), die window.AUDIO (§10) lesen und 0 ohne es zurückgeben;
  • einen Vorschau-Player (Leertaste, ←/→, Pos1/Ende), der unter Capture und reduzierter Bewegung automatisch deaktiviert wird;
  • Farb-Token in den erforderlichen 3 Ebenen (hell, prefers-color-scheme geschützt, [data-theme]).

Für Seiten schreibe ein normales Single-File-HTML gemäß §6.

3. Deterministische Zeit (Video)

  • render(t) ist der einzige Zustandstreiber. Jede Position, Deckkraft, Größe, Zahl und jeder Dashoffset wird aus t in Sekunden berechnet. seek(x) rendert den identischen Frame, unabhängig davon, was vorher gerendert wurde.
  • t ist in Sekunden. Begrenze t auf [0, DURATION], niemals auf [0, 1]: Wenn Sekunden auf 0..1 begrenzt werden, friert dies die gesamte Zeitleiste stillschweigend ein.
  • Verboten: setTimeout, setInterval, CSS-Animationen/Übergänge als Zeitleiste, ungesäter Math.random(), Date.now() in Zuständen. requestAnimationFrame darf nur die Wiedergabeuhr vorrücken und render(clock) aufrufen. Die Vorlage macht dies bereits.
  • Zufälligkeit: zur Bauzeit aus mulberry32(seed) generieren, niemals innerhalb von render.
  • SVG-Zeichnen benötigt alle drei: pathLength="1", stroke-dasharray="1" und stroke-dashoffset von 1 bis 0. Ohne ein Dasharray erscheint die Linie ab Frame 0 vollständig gezeichnet.
  • inline-block-Wortspannen verschlucken nachfolgende Leerzeichen. Setze den Abstand in margin-right.

4. Bewegungsgrammatik

Fünf Bewegungen, jede mit einer Aufgabe. Wenn eine Bewegung keine davon ist, lösche sie.

  • EINGANG: eine orchestrierte Sequenz pro Seite oder Szene, in Lesereihenfolge, Geschwister mit 60–120ms Versatz. Fade-up in jedem Abschnitt ist das KI-Verratmerkmal.
  • BETONUNG: ein Element nach dem anderen: eine Maßvergrößerung (≤1.2), ein Leuchten oder eine Farbänderung, die Bedeutung trägt.
  • ÜBERGANG: eine Zustandsänderung. Das geänderte Teil bewegt sich; alles andere bleibt still. 0.2–0.6s.
  • KAMERA: eine Maßstabs-/Verschiebung auf Bühnenebene, höchstens einmal pro Szene, 0.8–1.2s, niemals während des Lesens von Text.
  • AUSGANG: 0.3–0.5s, vollständig abgeschlossen. Kein Element überlebt einen Zwischenzustand über eine Szenengrenze hinweg, außer einem bewussten Kontinuitätsanker, der identisch bleibt oder morphiert (dasselbe Objekt ändert seinen Zustand, der stärkste verfügbare Übergang).

Übergänge tragen Bedeutung: harter Schnitt = Kategorienwechsel, Morph = dasselbe ändert sich, Schwenk = Überquerung. Niemals einen überall gleichen Standard-Crossfade. Dauern und Easing-Funktionen sind in references/animation-primitives.md. Nachbarn, die sich zusammen bewegen, erhalten unterschiedliche Dauern oder einen Versatz.

5. Stack-Entscheidung

SituationStack
Seiten-MikrobewegungCSS-Übergänge auf transform/opacity, 0.2–0.6s; Schleifen ≤2s innerhalb @media (prefers-reduced-motion: no-preference)
Video / Motion Graphic / Kinetische TypografieVorlage + Vanilla render(t) (Standard)
>6 versetzte Spuren oder SVG-Morph-OrchestrierungGSAP UMD, eine pausierte Master-Zeitleiste, seek(t) → tl.seek(t)
DiagrammeInline SVG (Standard) oder Chart.js UMD mit animation:false, Hex-Farben (Canvas kann keine CSS-Variablen lesen)
Generative Kunstp5.js mit randomSeed/noiseSeed
3D, nur wenn 3D die Botschaft istThree.js UMD; Kamera in render(t) skripten

Verwende den einfachsten Stack, der zum Ergebnis führt. Externe Skripte müssen exakte, festgepinnte Versionen von cdnjs.cloudflare.com oder cdn.jsdelivr.net sein. Alles andere inline. Jede Schriftart erhält einen echten Fallback-Stack.

6. Technische Basis (nicht verhandelbar)

  1. Einzelne .html-Datei mit CSS und JS inline, unter 16 MB, Bilder/Daten als data:-URIs.
  2. Farben als :root-Token; dunkle Ebene unter @media (prefers-color-scheme: dark) geschützt durch :root:not([data-theme="light"]) und wiederholt unter :root[data-theme="dark"]; expliziter body-Hintergrund.
  3. meta viewport mit viewport-fit=cover; env(safe-area-inset-*)-Padding; height:100% auf html/body, niemals 100vh; breite Blöcke scrollen innerhalb ihres eigenen overflow-x:auto; Raster verwenden minmax(0,1fr).
  4. Angezeigte berechnete Zahlen gehen durch Math.round, toFixed oder Intl.NumberFormat. Count-ups landen exakt auf dem Endwert.
  5. Barrierefreiheit: Kontrast ≥4.5:1 (≥3:1 für ≥24px Text), sichtbarer Fokus, prefers-reduced-motion respektiert (die Vorlage zeigt den eingeschwungenen Endframe).
  6. Lesbare Schrift: in einem 1080p-Videoframe kein Text unter 20px (H/54). Auf mobilen Seiten kein Fließtext unter 14px.
  7. Browserspeicher hält niemals Zeitleistenzustände. Wo Speicher überhaupt verwendet wird, in try/catch verpacken.

7. Vermeide generisches KI-Design

Wo der Brief Freiheit lässt, gib sie niemals für diese Standardeinstellungen aus (qa.mjs markiert mehrere automatisch):

VerratsmerkmalKorrektur
Cremefarben #F4F1EA-ähnlich + Serifen-Display + Terrakotta #D97757-ähnlicher Akzenteine Palette, die aus den eigenen Materialien des Themas stammt
Beinahe-Schwarz + ein saurer Akzent, unabhängig vom Thema verwendetnur erlaubt, wenn die Richtung es schriftlich rechtfertigt
Identische abgerundete Karten, ein Radius überall, derselbe weiche SchattenRadius-Token nach Hierarchie; Karten nur für begrenzte Objekte
Verläufe als Dekoration, lila Verläufe, Glas-Morphismusflache Füllungen; maximal ein Verlauf, nur für eine kontinuierliche physikalische Eigenschaft
GROSSBUCHSTABEN-Augenbrauen mit Tracking, Mittelpunkt-Meta-Strings, "→" auf LinksSatzfall; lösche Labels, die den Inhalt wiederholen
Inter / System-Schriftart als StandardSchriftarten, die für dieses Thema ausgewählt wurden, mit einem Fallback-Stack
Ein einzelnes Wort in einer Überschrift hervorgehobenNUR erlaubt, wenn die Akzentfarbe ein semantischer Token ist, der für dieselbe Bedeutung an anderer Stelle im Stück verwendet wird (z. B. Koralle = Rauschen)
Generischer Hero: Überschrift + Untertitel + CTA + ScreenshotEröffne mit dem charakteristischsten Ding in der Welt des Themas
Alles zentriert, gleicher Rasterrhythmus in jedem Abschnittein Ausrichtungssystem pro Abschnitt; variiere den Rhythmus
Alles gleichzeitig animiert, 300ms überalldie Dauer-Karte + Stagger (§4)

Setze Kühnheit an einer Stelle ein, dann entferne ein Accessoire.

8. Rendern + QA (vor der Auslieferung obligatorisch)

Führe die automatisierte QA aus. Sie rendert die Datei headless und schreibt Nachweise plus ein Urteil. Sie benötigt Node ≥18. Der erste Lauf in einer frischen Kopie des Skills benötigt npm install in $SKILL/scripts (überspringe es, wenn scripts/node_modules existiert).

node "$SKILL/scripts/qa.mjs" path/to/deliverable.html

In DSH unter Windows führe es mit dem pwsh-Tool mit demselben Befehl aus. Optionen: --step 0.25 (ein feineres Raster für schnelle Szenen), --out <dir>, --mode page|video.

Video-Modus (automatisch, wenn DURATION + seek existieren) erfasst einen Frame pro Schritt und prüft: verbotene APIs, Deterministisch bei Wiederholungen in falscher Reihenfolge, eine eingefrorene Zeitleiste, tote Luft, nahezu leere Spannweiten, einen nicht eingeschwungenen Endframe, Textkollisionen, Text über anderen Grafiken, Clipping, Kontrast, minimale Schriftgröße, Dash-Offset-Linien, die nie zeichnen, reduziert-motion-Schleifen, Konsolen-/Seitenfehler und Vorlagen-Verratsmerkmale. Seiten-Modus rendert Desktop 1440, Mobil 390 und dunkles Schema und prüft dieselben Layout-Regeln plus mobilen horizontalen Überlauf.

Die Ausgaben landen in qa-<name>/: report.md (Urteil und Ergebnisse), report.json (Tintendeckung und Änderung pro Frame), contact-sheet.png (jeder Frame in einem Bild), moments.png (jeweils Anfang, Mitte und Ende jeder Szene, aus window.SCENES), key_000..100.png und frames/.

  • Übergib den Signature-Moment und jeden Sync-Punkt explizit: --at 5.4,9.1.
  • Bewusste Überlagerung (kinetische Typografie absichtlich gestapelt, ein Titel über Filmmaterial) wird in ein Element mit data-qa-allow-overlap gesetzt. Das überspringt die Kollisions- und Text-über-Grafiken-Prüfung nur für diesen Teilbaum. Verwende es niemals, um eine versehentliche Kollision zu unterdrücken.
  • Eine font-WARNUNG bedeutet, dass die erste Wahl der Familie nicht geladen wurde und der Text in einem Fallback angezeigt wird. Behebe dies, bevor du das Layout beurteilst, weil jede Breite falsch ist.

Exit-Code 0 = kein FEHLER. FEHLER ist blockierend. Jede WARNUNG wird entweder behoben oder in einer Zeile in deiner Kritik begründet.

9. Kritik-Loop

  1. Wenn dein Modell Bilder lesen kann: öffne contact-sheet.png, dann alle key_*.png, die falsch aussehen. Beurteile die Pixel, nicht deine Absichten.
  2. Wenn dein Modell text-only ist: verwende report.md plus die Pro-Frame-Tabelle in report.json. coverage < 0.015 bedeutet, dass der Frame leer gelesen wird. Ein diff von 0 über eine Szene hinweg bedeutet, dass sich nichts bewegt. Ein Anstieg in diff markiert einen Schnitt. Überprüfe jede Szenenkarten-Zeitstempel gegen diese Zahlen.
  3. Beantworte jede Frage mit einer konkreten Beobachtung, nicht mit „✓“:
    • Komposition: Auf jedem Schlüssel-Frame, wo landet das Auge zuerst? Ist das die Botschaft?
    • Hierarchie: Ist PRIMARY unverkennbar? Gibt es genau eine bewegte Sache, die pro Frame zählt?
    • Mechanismus: Zeigt der Signature-Moment die Idee ohne die Untertitel?
    • Kontinuität: Sind alle Übergaben sauber, nichts im Zwischenzustand an einer Grenze und Anker identisch oder morphing?
    • Timing: Sind Versätze vorhanden, keine Standarddauern und Lesezeit ≥1.2s pro 8 Wörter?
    • Typografie / Kontrast / Dichte: Größen gemäß Plan, ≤5 konkurrierende Elemente pro Frame, im dunklen Modus lesbar?
    • Erzählung: Könnte ein Betrachter die Kernbotschaft nach einem Ansehen wiederholen?
  4. Korrigieren → qa.mjs erneut ausführen → erneut kritisieren. Wiederholen, bis die QA bestanden wird und die Kritik keinen offenen Punkt mehr hat.
  5. Abschließende Frage, ehrlich beantwortet: „Sieht dies absichtlich gestaltet oder lediglich generiert aus?“ Wenn „generiert“: nenne, was generisch ist, überarbeite den Plan (§1) und baue neu auf. Ein erster Render ist fast nie der Liefergegenstand. Erwarte 2–3 Generationen.

10. Audio-Sync (wenn es Musik oder Sprache gibt)

Errate das Timing niemals nach Gehör. Wandle das Audio in Daten um und lass render(t) sie lesen:

node "$SKILL/scripts/audio-data.mjs" music.mp3 --inject composition.html   # schreibt window.AUDIO in das HTML
  • AUDIO.beats (ein gleichmäßig verteiltes Raster im geschätzten Tempo), AUDIO.onsets (Schläge, Noten, Silben) und Pro-Frame AUDIO.rms / AUDIO.low (0..1; low ist das <150 Hz Kick/Bass-Band).
  • Treibe Bewegung mit den Vorlagen-Helfern an: hit(t, AUDIO.beats, 0.2) für einen Beat-Puls (EMPHASIS), audioAt(t, "low") für kick-reaktive Skalierung, since(t, AUDIO.onsets) für Enthüllungen pro Treffer. Setze Szenenschnitte auf Beats: wähle Szenenanfänge aus AUDIO.beats.
  • Sync ist durch Konstruktion frame-exakt: Ein Puls landet auf dem ersten Frame bei oder nach seinem Beat (≤1 Frame, ≤33 ms bei 30 fps). Wenn das Audio später als t=0 beginnt, übergib --offset <s>.
  • Pegel werden überprüft, bevor jemand zuhört. Beschnittene Samples beenden mit Exit-Code 1. Ein Sample-Peak über −1 dBFS warnt, weil AAC-Codierung es beschneiden wird. Lautstärke außerhalb −18..−12 LUFS wird gemeldet (Plattformen normalisieren auf etwa −14).
  • --bpm überschreibt das geschätzte Tempo. Nützlich, wenn das Audio ein gleichmäßiges, aber nicht offensichtliches Tempo hat.
  • Verwende --skip-inject, wenn du nur die JSON-Daten sehen und die Audio-Datei manuell einfügen willst.

Verwandte Skills