Communitygithub.com

HusseinRagab/motion-reels

Erstelle 9:16 Bewegtgrafiken (1080×1920) für eine Interior-Design-Seite mit code-basierter Animation – Headlines, Pläne, Vorher/Nachher-Wipes, Photo-Push-Ins, Materialmuster – Frame für Frame gerendert mit Playwright und ffmpeg. Verwende dies, wenn jemand ein Reel, einen Short oder ein vertikales Bewegtvideo erstellen, storyboarden, rendern oder reparieren möchte.

Was ist motion-reels?

Dieses Skill ermöglicht es, hochwertige, vertikale Bewegtgrafiken (9:16 im Reel-Format) vollständig über Code zu erstellen – Frame für Frame gerendert mit Playwright und ffmpeg. Es ist speziell für Interior-Design-Seiten konzipiert und unterstützt Headlines, sich zeichnende Grundrisse, Vorher/Nachher-Wipes, langsame Photo-Push-Ins und Materialmuster. Ein Reel besteht aus mehreren Blöcken (in JavaScript), die festlegen, welche Elemente wann erscheinen. Der gesamte Workflow ist stark automatisiert: vom Briefing über das Beat-Sheet bis zum finalen Render und der Fehlerprüfung. Das Skill läuft auf Windows, macOS und Linux und integriert Sprachausgabe (über TTS oder Aufnahmen) sowie Hintergrundmusik. Alle Prüfungen (z. B. auf Sicherheitszonen, Überlappungen und Fehler) sind strikt und müssen bestanden werden, bevor das Reel ausgeliefert wird. Das Skill unterstützt auch arabische Reels von rechts nach links.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/HusseinRagab/reel-motion-kit/tree/HEAD/motion-reels

In Ihrer bevorzugten KI fragen

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

Dokumentation

Was macht motion-reels?

Code-basierte Bewegtgrafiken für vertikale Reels. Jedes Reel besteht aus einem oder mehreren Blöcken. Ein Block ist eine kleine JavaScript-Datei, die Headlines, Zeichnungen, Fotos und Muster in einer Welt platziert und angibt, wann jedes Element erscheint. Jeder Zeitpunkt stammt aus einem Timeline von Wörtern: entweder einem Beat-Sheet (ohne Stimme) oder den Wortzeitpunkten einer Sprachaufnahme. Die Engine rendert jeden Frame in einer eigenen frischen Browser-Seite, überprüft das Layout und setzt das Ergebnis mit Stimme und/oder Musik zusammen.

Die Person, der die Seite gehört, entscheidet über das Aussehen, die Wörter und was veröffentlicht wird. Claude veröffentlicht niemals etwas.

Einrichtung (einmalig)

  • Python 3.10+ und ffmpeg/ffprobe im PATH. Dann das setup.ps1 (Windows) oder setup.sh (macOS/Linux) des Repos, oder pip install -r requirements.txt + python -m playwright install chromium (oder env MG_CHROME = eine vorhandene Chrome-Installation).
  • Nur Stimme: pip install -r requirements-voice.txt (faster-whisper; der erste Lauf lädt das Spracherkennungsmodell herunter).
  • Test: python engine/selftest.py muss SELFTEST OK ausgeben (prüft die Beispiele, negative Tests schlagen wie erwartet fehl, arabische Untertitel werden richtig getrennt und ein kurzer Render + Fehlerscan + Assembly erreicht -14 LUFS). --quick überspringt den Render.

Engine-Dateien (alle in engine/): render.py (Prüfung / Storyboard / Standbilder / Video), beats.py, words.py, frames.py, faultscan.py, assemble.py, storyboard_sheet.py, make_grain.py, templates/ (Shell, reel.js, reel.css, Schriftarten).

Ein Ordner pro Reel

<Reel-Name>/
  brief.md          wofür das Reel ist, die eine Idee, der Call-to-Action, verfügbare Fotos
  beats.txt         die Wörter auf dem Bildschirm, ein Beat pro Zeile (oder script.txt + take.wav bei Sprachaufnahme)
  words.json        Timeline (aus beats.py oder words.py)
  photos/           die Fotos des Eigentümers (nur solche, an denen er die Rechte hat)
  A.js, B.js ...    Blöcke
  build/            Prüf-JSON, Storyboard-Standbilder, Block-Videos, render.json-Dateien, Kontaktabzüge
  <Reel>_REV01_<Datum>.mp4   das ausgelieferte Reel; ein späterer Fix wird als _REV02 ausgeliefert, niemals überschrieben

Gates (niemals überspringen oder umordnen; bei jedem ⛔ für das OK des Eigentümers anhalten)

  1. Briefing. Eine Idee pro Reel (eine Raum-Präsentation, eine Material-Geschichte, eine Grundriss-Änderung, ein Tipp). Fotos und den Handle anfragen. Auflisten, was jedes Foto zeigt. In den ersten 2 Sekunden einen Haken setzen.
  2. Beat-Sheet (beats.txt): die genauen Wörter auf dem Bildschirm, in der richtigen Reihenfolge, ein Beat pro Zeile. Halte einen Beat kurz (2–7 Wörter). Setze jedes Element einer Liste in eine eigene Zeile, damit jedes Zeit zum Wirken hat. ⛔ Eigentümer unterschreibt die Wörter. Nach der Freigabe bedeutet eine Wortänderung eine Neujustierung des Zeitplans (und bei Sprachaufnahmen eine Neuaufnahme): weise vor jeder Änderung darauf hin.
  3. Timeline.
    • Ohne Stimme: python engine/beats.py beats.txt words.json (Standardgeschwindigkeit 2,6 Wörter/s + 0,7 s nach jedem Beat; [+1.5] am Ende einer Zeile hält länger; [pause 2] hält ohne Neues).
    • Mit Stimme (jeder TTS oder eine Aufnahme, ein Take pro Block, niemals bearbeitet): python engine/words.py take.wav words.json, dann das Transkript Wort für Wort mit dem Skript vergleichen. Das Bild wird an den Take angepasst, niemals umgekehrt.
  4. ⛔ Storyboard-Standbilder. Baue die Block-Layouts (nur Positionen reichen aus), führe check aus, dann render.py A.js words.json storyboard build/sb und storyboard_sheet.py build/storyboard.png build/sb. Überprüfe das Blatt selbst (Liste unten), dann sende es. Nichts wird animiert, bevor der Eigentümer das Layout freigegeben hat.
  5. Bewegung bauen. Jedes Element auf dem Wort einblenden, das es benennt (Regeln unten). Nach jeder Änderung check ausführen.
  6. Rendern. render.py A.js words.json video build/A.mp4 --workers 4 pro Block (niemals --draft für das, was ausgeliefert wird). Jedes build/A.mp4.render.json muss "capture": "fresh" und denselben Browser wie die anderen Blöcke angeben; wenn der Browser gewechselt hat, alle Blöcke neu rendern.
  7. Fehlerscan. faultscan.py build/A.mp4 --sheet build/A_contact.png für jeden Block, dann für das endgültige Reel. Jeden markierten Zeitpunkt überprüfen. Ein schwarzer Balken oder ein Ein-Frame-Blitzen ist ein Fehler: anhalten und beheben. Dunkler Fotoinhalt ist in Ordnung.
  8. Assemblierung. assemble.py blocks.json <Reel>_REV01_<Datum>.mp4 [--music bed.mp3]. Das Skript gibt die gemessene Lautstärke aus; sie muss dem Zielwert entsprechen (Standard -14 LUFS) und der True Peak bei oder unter -1,5 dBTP liegen.
  9. ⛔ Prüfung. Sende das Reel und seinen Kontaktabzug. Nur bildbezogene Korrekturen rendern nur die geänderten Blöcke neu und werden als nächste _REV ausgeliefert. Der Eigentümer veröffentlicht das Reel.

Bewegungsregeln (warum: ein ruhiger, erstklassiger Eindruck; nichts zuckt, nichts ist schwer lesbar)

  • Wörter bewegen sich nie. Ein Wort blendet ein (0,28 s) und bleibt dann stehen. Kein Schieben, Skalieren, Hüpfen oder Verlaufen von Text.
  • Headlines: hl(el, text, cue(...)) blendet jedes Wort zu seinem eigenen Zeitpunkt in der Timeline ein. Wenn eine Headline eine Sprachaufnahme paraphrasiert, verwende {stream:true}: Wörter erscheinen von links nach rechts, 0,1 s auseinander, ab dem Cue.
  • Kamera: völlig still, während eine Einstellung gehalten wird; sie gleitet nur (0,8 s, ease-in-out) zwischen den Einstellungen. Im 9:16-Format die Einstellungen vertikal in der Welt stapeln (Einstellung 2 bei y 1920, Einstellung 3 bei y 3840) und nach unten gleiten: SHOTS=[[t,540,960,1],[t2,540,2880,1],...].
  • Fotos dürfen langsam hineinzoomen: push:[1,1.04] = konstante Geschwindigkeit, niemals mehr als +6 % (MOTION.PUSH_MAX; die Engine lehnt mehr ab). Kein Push bei einem Foto, das Text trägt.
  • Zeichnungen zeichnen sich ein, während sie benannt werden, zuerst Referenzlinien: Wände vor dem Fenster und der Tür darin, die Grundlinie vor den Höhen, die von ihr aus gemessen werden. at('#walls', cue('Walls'), null, 'draw', 0.9); 0,6–1,0 s pro Element.
  • Maße einheitlich skalieren. Wenn ein Plan zwei Maße zeigt, verwenden beide denselben Maßstab.
  • Beschriften, was die Wörter benennen; jede Zahl benennt ihre Einheit ("3,2 m", niemals eine reine "3,2").
  • Kein Bounce, Überschwingen, elastisches oder Federeasing an irgendeiner Stelle. Jedes Timing stammt von MOTION in reel.js; ändere es dort, niemals als Literal in einem Block.
  • Ein bloßes gestricheltes SVG-Element, das an at() übergeben wird, erscheint vor seinem Cue: wickele es in ein <g>.

Timing-Token (MOTION in reel.js)

TokenWertVerwendung
WORD_FADE / WORD_LEAD0.28 s / 0.08 sEinblenden von Wörtern; beginnt kurz vor dem Wort
STREAM0.10 sAbstand der Wörter bei Stream-Headlines
REVEAL / EXIT0.5 s / 0.4 sBlöcke, Chips, Muster, Fotos ein/aus
draw (at(...,'draw',dur))0.6–1.0 spro gezeichnetem Element
CAM_SLIDE / CAM_LEAD0.8 s / 0.35 sKamerafahrt; beginnt vor dem Cue der Einstellung
PUSH_MAX0.06Grenze für Fotozoome
WIPE1.2 sVorher/Nachher-Wipe
Easing: ease-out cubic für Einblendungen, ease-in-out cubic für Fahrten, Zeichnungen und Wipes.

Layout und die Prüfung

  • Sicherheitszone (SAFE in reel.js): Text, Beschriftungen und Untertitel bleiben innerhalb x 65–1015, y 269–1248 des 1080×1920-Frames (oben 14 %, unten 35 %, seitlich 6 %). Diese Werte sind weit verbreitete Drittanbieter-Richtlinien für Reels, keine von Meta veröffentlichte Regel für organische Beiträge: miss erneut von einem Handy-Screenshot eines veröffentlichten Reels und setze safeZone({...}), wenn sich die App ändert. Fotos und Zeichnungen dürfen darüber hinausragen; Text nicht.
  • render.py <block> words.json check build/<block>.check.json ist vor jedem Render Pflicht. Es tastet alle 0,25 s ab und schlägt bei jeder Überlappung von 0,5 s oder mehr zwischen separaten Elementen (Text, Zeichnungen, Chips, Muster, Fotos, Untertitel) und bei jedem Text außerhalb der Sicherheitszone fehl, während die Kamera hält. Ein Fehlschlag bedeutet das Layout reparieren, niemals rendern. Beweise eine neue Regel mit einem negativen Test (führe einen bekannten Fehler wieder ein; die Prüfung muss fehlschlagen).
  • Text, der zu einem Foto gehört, muss innerhalb des Elements des Fotos platziert werden (parent: photoDiv) mit einem scrim() dahinter, oder das Foto ist ein Hintergrund (bg:true). Andernfalls meldet die Prüfung Text über Foto, was so gewünscht ist.
  • Die Prüfung erkennt nicht, was am Rand des Frames abgeschnitten ist: die Selbstprüfung tut das.

Blöcke bauen (reel.js)

boot(()=>{                                   // jeder Block beginnt mit boot(...)
  handle('@yourstudio');                     // kleiner Handle am oberen Rand der Sicherheitszone
  $('world').insertAdjacentHTML('beforeend', `<div id="h1" class="abs serif" style="left:90px;top:360px;width:900px;font-size:104px"></div>`);
  hl('h1', 'Ein kleiner Raum, *umgeplant.*', cue('Ein kleiner'));          // *...* = Akzent kursiv; ~wort = nicht in der Timeline
  at('#walls', cue('Walls'), null, 'draw', 0.9);                          // fx: 'fade' | 'pop' | 'wipe' | 'draw'
  photo({src:rel('photos/living.jpg'), x:0, y:1920, w:1080, h:1350, a:cue('Light'), push:[1,1.04]});
  beforeAfter({before:rel('photos/before.jpg'), after:rel('photos/after.jpg'), x:90, y:2440, w:900, h:900, a:cue('Before'), t:cue('after')});
  swatch({name:'Eiche', note:'Boden', color:'#B08A62', x:90, y:4480, size:270, a:cue('Eiche')});   // oder src: rel('photos/eiche.jpg')
  clip({dir:rel('clips/walk'), n:240, x:0, y:5760, w:1080, h:1920, a:cue('Walk'), t0:cue('Walk')}); // Frames aus frames.py
  captions(1120, 3);                         // eingebrannte Untertitel aus der Timeline (vertonte Reels)
  SHOTS=[[0,540,960,1],[cue('Light'),540,2880,1]];
});

rel(path) löst eine Datei relativ zum Block auf. cue('words', after) wirft einen Fehler, wenn die Wörter nicht in der Timeline sind, daher schlägt ein Tippfehler lautstark fehl. Vollständiges Beispiel: examples/demo/demo.js.

Arabische und andere Reels von rechts nach links

  • Rufe rtl() als erstes in boot() auf. Headlines verwenden Noto Naskh Arabic, Text IBM Plex Sans Arabic (OFL); Lateinische Schrift fällt auf die Standardschriften zurück. Keine Kursivierung, Buchstabenabstände oder Großschreibung im Arabischen (Buchstaben müssen verbunden bleiben); Akzentwörter ändern nur die Farbe.
  • Textboxen behalten left + width; Text wird rechtsbündig ausgerichtet. Layouts von rechts nach links anordnen (zuerst genannter = ganz rechts).
  • Cues ignorieren diakritische Zeichen, Tatweel, Alef/Yaa/Taa-Marbuta-Varianten und konvertieren Arabisch-Indische Ziffern; ein Cue ohne Buchstaben wirft einen Fehler. ة und ه gelten als ein Buchstabe, daher einen längeren Satz als Cue verwenden, wenn sich zwei Wörter nur dort unterscheiden. Zahlenwörter nur auf Englisch abgleichen: auf Arabisch entweder die Ziffer oder das Wort wie transkribiert als Cue angeben (words.py --lang ar wählt das mehrsprachige Modell).
  • Untertitel werden an ، ؛ ؟ und lateinischer Interpunktion getrennt und diese nicht angezeigt.
  • Beispiel: examples/arabic/.

Look

Das Theme lebt nur in engine/templates/reel.css (Farben als CSS-Variablen, Schriften) und den Schriftdateien. Standard "warm minimal": Papier #F4EFE8, Tinte #2B2622, Akzent #9C6B4E, Cormorant Garamond für Headlines + Jost für Text (beide SIL OFL 1.1). Um das Aussehen zu ändern: die Variablen bearbeiten, oder OFL-Schriften zu engine/fonts/ hinzufügen mit ihrer Lizenzdatei und sie in fonts.css und window.FONTS (reel.js) auflisten. Fordere 3–5 Screenshots des Rasters vom Eigentümer an und passe es an.

Selbstprüfung (Claude, vor dem Senden von Blättern oder Rendern)

  1. Jedes Element beginnt mit seinem Wort; Referenzlinien werden zuerst gezeichnet.
  2. Wörter stehen still, sobald sie angekommen sind; Kamera still, während gehalten wird; kein Sprung am Ende eines Schiebens.
  3. Nichts am Rand des Frames abgeschnitten; aller Text innerhalb der Sicherheitszone; nichts Wichtiges unter den unteren 35 %.
  4. Maße einheitlich skaliert; jede Zahl hat ihre Einheit; Rechtschreibung stimmt mit dem unterschriebenen Beat-Sheet überein.
  5. Prüfung bei jedem Block BESTANDEN; render.json sagt capture: fresh, gleicher Browser für alle Blöcke.
  6. Fehlerscan sauber, oder jeder markierte Zeitpunkt überprüft und erklärt.
  7. Lautstärke und True Peak von assemble.py gedruckt im Zielbereich.

Rechte und Privatsphäre

  • Nur Fotos des Eigentümers, oder solche, an denen er die Rechte hat. Kundenwohnungen: keine Gesichter, Adressen oder Dokumente ohne Einwilligung.
  • Musik: nur Titel, für die der Eigentümer eine Lizenz hat, oder die plattformeigene Bibliothek, die beim Posten in der App hinzugefügt wird.
  • Keine Behauptungen, die der Eigentümer nicht aufgestellt hat (Preise, Zeitpläne, Auszeichnungen).

Fehlerbehebung

  • cue not found: "...": die Wörter sind nicht in dieser Reihenfolge in words.json; korrigiere das Beat-Sheet oder den Cue.
  • ERR reqfail:file:///...jpg: ein Foto- oder Clip-Pfad ist falsch; verwende rel() und überprüfe den Dateinamen.
  • Geisterkopien früherer Zeichnungen oder ein schwarzer Balken: du hast mit --draft gerendert. Neu rendern ohne.
  • Langsame Render: --workers 4 (bis zu 8) auf einem Rechner mit entsprechend vielen Kernen; Prüfung und Storyboard sind schnell, Video nicht.

Verwandte Skills