Communitygithub.com

ilya-makarov-dev/Reframe

Erstelle Videokompositionen, Animationen, Titelcards, Overlays, Untertitel, Voiceovers, audio-reaktive Visuals und Szenenübergänge in HyperFrames HTML.

Was ist Reframe?

Reframe ist ein KI-Agenten-Skill zur Erstellung von HTML-basierten Videokompositionen mit HyperFrames. Es ermöglicht die Erstellung kompletter Videoproduktionen – von animierten Titelcards und Overlays über Untertitel, Text-to-Speech, audio-reaktive Animationen (Beat-Sync, Glow, Pulse) bis hin zu Szenenübergängen (Crossfades, Wipes, Reveals). Der Skill folgt einem strikten, deterministischen Workflow: Visuelle Identität vor Code (DESIGN.md oder visuelle Vorgaben), Layout vor Animation (Endzustand zuerst als statisches CSS), dann GSAP-Timelines für Ein- und Ausgänge. Die Plattform unterstützt Sub-Kompositionen, Video+Audio-Separation, Font-Einbettung und wird über CLI-Befehle (init, lint, preview, render) gesteuert – diese sind jedoch Teil eines separaten hyperframes-cli-Skills. Besonders wichtig: Keine Exit-Animationen vor Szenenübergängen (außer in der letzten Szene), keine zufälligen oder asynchronen Timeline-Konstruktionen, und immer finite Wiederholungen (`repeat: -1` ist verboten).

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ilya-makarov-dev/Reframe/tree/HEAD/.claude/skills/hyperframes

In Ihrer bevorzugten KI fragen

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

Vorschau

Aus dem Skill-README

Dokumentation

HyperFrames

HTML ist die Quelle der Wahrheit für Video. Eine Komposition ist eine HTML-Datei mit data-*-Attributen für das Timing, einer GSAP-Timeline für Animationen und CSS für das Aussehen. Das Framework kümmert sich um Clip-Sichtbarkeit, Medienwiedergabe und Timeline-Synchronisation.

Ansatz

Bevor HTML geschrieben wird, denke auf hoher Ebene nach:

  1. Was – Was soll der Betrachter erleben? Identifiziere den narrativen Bogen, Schlüsselmomente und emotionale Höhepunkte.
  2. Struktur – Wie viele Kompositionen, welche davon Sub-Kompositionen vs. Inline, welche Spuren transportieren was (Video, Audio, Overlays, Untertitel).
  3. Timing – Welche Clips bestimmen die Dauer, wo liegen die Übergänge, wie ist das Tempo.
  4. Layout – Baue zuerst den Endzustand. Siehe „Layout vor Animation“ unten.
  5. Animieren – Füge dann Bewegung mit den folgenden Regeln hinzu.

Bei kleinen Änderungen (Farbe korrigieren, Timing anpassen, ein Element hinzufügen) springe direkt zu den Regeln.

Visuelle Identität – Torwächter

Prüfe in dieser Reihenfolge:

  1. Existiert DESIGN.md im Projekt? → Lies es. Verwende seine genauen Farben, Schriftarten, Bewegungsregeln und „Was NICHT zu tun“-Einschränkungen.
  2. Existiert visual-style.md? → Lies es. Übernimm dessen style_prompt_full und strukturierte Felder. (Hinweis: visual-style.md ist eine projektspezifische Datei. visual-styles.md ist die Stilbibliothek mit 8 benannten Vorlagen – unterschiedliche Dateien.)
  3. Hat der Benutzer einen Stil genannt (z.B. „Swiss Pulse“, „dunkel und technisch“, „Luxusmarke“)? → Lies visual-styles.md für die 8 benannten Vorlagen. Erstelle eine minimale DESIGN.md mit: ## Style Prompt (ein Absatz), ## Colors (3-5 Hex-Werte mit Rollen), ## Typography (1-2 Schriftfamilien), ## What NOT to Do (3-5 Anti-Patterns).
  4. Nichts davon? → Stelle 3 Fragen, bevor HTML geschrieben wird:
    • Welche Stimmung? (explosiv / filmisch / fließend / technisch / chaotisch / warm)
    • Heller oder dunkler Hintergrund?
    • Gibt es bestimmte Markenfarben, Schriftarten oder visuelle Referenzen? Erstelle dann eine minimale DESIGN.md aus den Antworten.

Jede Komposition muss ihre Palette und Typografie auf eine DESIGN.md, visual-style.md oder explizite Benutzeranweisung zurückführen. Wenn du nach #333, #3b82f6 oder „Roboto“ greifst – hast du diesen Schritt übersprungen.

Bewegungsvorgaben, Größen, Eintrittsmuster und Easing folgen house-style.md. Der Hausstil regelt, WIE sich Dinge bewegen. Die DESIGN.md regelt, WIE Dinge aussehen.

Layout vor Animation

Positioniere jedes Element dort, wo es in seinem sichtbarsten Moment sein soll – der Frame, in dem es vollständig eingetreten, korrekt platziert und noch nicht wieder austretend ist. Schreibe dies zuerst als statisches HTML+CSS. Noch kein GSAP.

Warum das wichtig ist: Wenn du Elemente in ihrem animierten Startzustand positionierst (außerhalb des Bildschirms, skaliert auf 0, Deckkraft 0) und sie dorthin bewegst, wo du denkst, dass sie landen sollen, rätst du das endgültige Layout. Überlappungen bleiben unsichtbar, bis das Video gerendert wird. Indem du zuerst den Endzustand baust, kannst du Layout-Probleme sehen und beheben, BEVOR du Bewegung hinzufügst.

Der Prozess

  1. Identifiziere den Hero-Frame für jede Szene – den Moment, in dem die meisten Elemente gleichzeitig sichtbar sind. Dies ist das Layout, das du baust.
  2. Schreibe statisches CSS für diesen Frame. Der .scene-content-Container MUSS die gesamte Szene mit width: 100%; height: 100%; padding: Npx; füllen, mit display: flex; flex-direction: column; gap: Npx; box-sizing: border-box. Verwende Padding, um Inhalt nach innen zu verschieben – NIEMALS position: absolute; top: Npx auf einem Inhaltscontainer. Absolut positionierte Inhaltscontainer laufen über, wenn der Inhalt höher ist als der verbleibende Platz. Reserviere position: absolute nur für Dekorationen.
  3. Füge Eintritte mit gsap.from() hinzu – animiere VON außerhalb/unsichtbar ZUR CSS-Position. Die CSS-Position ist die Grundwahrheit; der Tween beschreibt die Reise dorthin.
  4. Füge Austritte mit gsap.to() hinzu – animiere ZU außerhalb/unsichtbar VON der CSS-Position.

Beispiel

/* scene-content füllt die Szene, Padding positioniert Inhalt */
.scene-content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 120px 160px;
  gap: 24px;
  box-sizing: border-box;
}
.title {
  font-size: 120px;
}
.subtitle {
  font-size: 42px;
}
/* Container füllt jede Szenengröße (1920x1080, 1080x1920, usw.).
   Padding positioniert Inhalt. Flex + Gap handhabt Abstände. */

FALSCH – fest codierte Abmessungen und absolute Positionierung:

.scene-content {
  position: absolute;
  top: 200px;
  left: 160px;
  width: 1920px;
  height: 1080px;
  display: flex; /* ... */
}
// Schritt 3: In diese Positionen hinein animieren
tl.from(".title", { y: 60, opacity: 0, duration: 0.6, ease: "power3.out" }, 0);
tl.from(".subtitle", { y: 40, opacity: 0, duration: 0.5, ease: "power3.out" }, 0.2);
tl.from(".logo", { scale: 0.8, opacity: 0, duration: 0.4, ease: "power2.out" }, 0.3);

// Schritt 4: Aus diesen Positionen heraus animieren
tl.to(".title", { y: -40, opacity: 0, duration: 0.4, ease: "power2.in" }, 3);
tl.to(".subtitle", { y: -30, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.1);
tl.to(".logo", { scale: 0.9, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.2);

Wenn Elemente sich im Laufe der Zeit den Raum teilen

Wenn Element A austritt, bevor Element B im selben Bereich eintritt, sollten beide korrekte CSS-Positionen für ihre jeweiligen Hero-Frames haben. Die Timeline-Reihenfolge garantiert, dass sie nie gleichzeitig sichtbar sind – aber wenn du den Layout-Schritt auslässt, wirst du den Fall nicht erkennen, in dem sie aufgrund eines Timing-Fehlers versehentlich überlappen.

Was als beabsichtigte Überlappung gilt

Geschichtete Effekte (Glühen hinter Text, Schattenelemente, Hintergrundmuster) und Z-Stack-Designs (Kartenstapel, Tiefenschichten) sind beabsichtigt. Beim Layout-Schritt geht es darum, unbeabsichtigte Überlappungen zu erkennen – zwei Überschriften, die aufeinander landen, eine Statistik, die ein Label verdeckt, Inhalt, der aus dem Frame läuft.

Datenattribute

Alle Clips

AttributErforderlichWerte
idJaEindeutige Kennung
data-startJaSekunden oder Clip-ID-Referenz ("el-1", "intro + 2")
data-durationErforderlich für img/div/compositionsSekunden. Video/Audio standardmäßig Medien-Dauer.
data-track-indexJaGanze Zahl. Clips auf derselben Spur können sich nicht überlappen.
data-media-startNeinVersatz in die Quelle kürzen (Sekunden)
data-volumeNein0-1 (Standard 1)

data-track-index beeinflusst NICHT die visuelle Schichtung – verwende CSS z-index.

Kompositions-Clips

AttributErforderlichWerte
data-composition-idJaEindeutige Kompositions-ID
data-startJaStartzeit (root composition: "0" verwenden)
data-durationJaHat Vorrang vor GSAP-Timeline-Dauer
data-width / data-heightJaPixelmaße (1920x1080 oder 1080x1920)
data-composition-srcNeinPfad zur externen HTML-Datei

Kompositionsstruktur

Sub-Kompositionen, die über data-composition-src geladen werden, verwenden einen <template>-Wrapper. Eigenständige Kompositionen (die Haupt-index.html) verwenden KEIN <template> – sie setzen das data-composition-id-div direkt in <body>. Die Verwendung von <template> in einer eigenständigen Datei verbirgt den gesamten Inhalt vor dem Browser und unterbricht das Rendering.

Sub-Kompositionsstruktur:

<template id="my-comp-template">
  <div data-composition-id="my-comp" data-width="1920" data-height="1080">
    <!-- Inhalt -->
    <style>
      [data-composition-id="my-comp"] {
        /* Bereichsbezogene Stile */
      }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
    <script>
      window.__timelines = window.__timelines || {};
      const tl = gsap.timeline({ paused: true });
      // Tweens...
      window.__timelines["my-comp"] = tl;
    </script>
  </div>
</template>

Laden im Root: <div id="el-1" data-composition-id="my-comp" data-composition-src="compositions/my-comp.html" data-start="0" data-duration="10" data-track-index="1"></div>

Video und Audio

Video muss muted playsinline sein. Audio ist immer ein separates <audio>-Element:

<video
  id="el-v"
  data-start="0"
  data-duration="30"
  data-track-index="0"
  src="video.mp4"
  muted
  playsinline
></video>
<audio
  id="el-a"
  data-start="0"
  data-duration="30"
  data-track-index="2"
  src="video.mp4"
  data-volume="1"
></audio>

Timeline-Vertrag

  • Alle Timelines starten { paused: true } – der Player steuert die Wiedergabe
  • Jede Timeline registrieren: window.__timelines["<zusammensetzungs-id>"] = tl
  • Das Framework verschachtelt Sub-Timelines automatisch – NICHT manuell hinzufügen
  • Die Dauer stammt von data-duration, nicht von der GSAP-Timeline-Länge
  • Niemals leere Tweens erstellen, um die Dauer festzulegen

Regeln (Nicht verhandelbar)

Deterministisch: Kein Math.random(), Date.now() oder zeitbasierte Logik. Verwende einen gesetzten PRNG, wenn Pseudo-Zufallswerte benötigt werden (z.B. mulberry32).

GSAP: Nur visuelle Eigenschaften animieren (opacity, x, y, scale, rotation, color, backgroundColor, borderRadius, Transformationen). NICHT visibility, display animieren oder video.play()/audio.play() aufrufen.

Animationskonflikte: Niemals dieselbe Eigenschaft am selben Element von mehreren Timelines gleichzeitig animieren.

Kein repeat: -1: Unendlich wiederholte Timelines zerstören die Aufnahme-Engine. Berechne die genaue Wiederholungszahl aus der Kompositionsdauer: repeat: Math.ceil(duration / cycleDuration) - 1.

Synchrone Timeline-Erstellung: Baue Timelines niemals innerhalb von async/await, setTimeout oder Promises. Die Aufnahme-Engine liest window.__timelines synchron nach dem Laden der Seite. Schriftarten werden vom Compiler eingebettet, daher sind sie sofort verfügbar – kein Warten auf Schriftladen nötig.

NIEMALS tun:

  1. window.__timelines-Registrierung vergessen
  2. Video für Audio verwenden – immer stummgeschaltetes Video + separates <audio>
  3. Video in ein zeitgesteuertes div verschachteln – einen nicht zeitgesteuerten Wrapper verwenden
  4. data-layer verwenden (data-track-index verwenden) oder data-end (für data-duration)
  5. Video-Element-Abmessungen animieren – einen Wrapper-div animieren
  6. Play/Pause/Seek bei Medien aufrufen – das Framework besitzt die Wiedergabe
  7. Einen Container auf oberster Ebene ohne data-composition-id erstellen
  8. repeat: -1 in irgendeiner Timeline oder Tween verwenden – immer endliche Wiederholungen
  9. Timelines asynchron bauen (innerhalb von async, setTimeout, Promise)
  10. gsap.set() auf Clip-Elemente aus späteren Szenen anwenden – sie existieren zum Zeitpunkt des Seitenladens nicht im DOM. Verwende stattdessen tl.set(selector, vars, timePosition) innerhalb der Timeline zum oder nach dem data-start-Zeitpunkt des Clips.
  11. <br> im Inhaltstext verwenden – erzwungene Zeilenumbrüche berücksichtigen nicht die tatsächliche gerenderte Schriftbreite. Text, der natürlich umbricht + ein <br> erzeugt einen zusätzlichen unerwünschten Umbruch, der zu Überlappungen führt. Lass Text stattdessen über max-width umbrechen. Ausnahme: Kurze Anzeigetitel, bei denen jedes Wort bewusst in einer eigenen Zeile steht (z.B. „DAS\nUNSTERBLICHE\nSPIEL" bei 130px).

Szenenübergänge (Nicht verhandelbar)

Jede Multi-Szenen-Komposition MUSS ALLE diese Regeln befolgen. Ein Verstoß gegen eine einzige davon ist eine defekte Komposition.

  1. IMMER Übergänge zwischen Szenen verwenden. Keine harten Schnitte. Keine Ausnahmen.
  2. IMMER Eintrittsanimationen in jeder Szene verwenden. Jedes Element animiert über gsap.from() herein. Kein Element darf vollständig geformt erscheinen. Wenn eine Szene 5 Elemente hat, braucht sie 5 Eintritts-Tweens.
  3. NIEMALS Austrittsanimationen verwenden, außer in der letzten Szene. Das bedeutet: KEIN gsap.to(), das die Deckkraft auf 0 animiert, y außerhalb des Bildschirms, Skalierung auf 0 oder irgendeine andere „Aus“-Animation, bevor ein Übergang ausgelöst wird. Der Übergang IST der Ausgang. Der Inhalt der ausgehenden Szene MUSS im Moment des Übergangsstarts vollständig sichtbar sein.
  4. Nur letzte Szene: Die letzte Szene kann Elemente ausblenden (z. B. Überblendung zu Schwarz). Dies ist die EINZIGE Szene, in der gsap.to(..., { opacity: 0 }) erlaubt ist.

FALSCH – Austrittsanimation vor dem Übergang:

// VERBOTEN – dies leert die Szene, bevor der Übergang sie verwenden kann
tl.to("#s1-title", { opacity: 0, y: -40, duration: 0.4 }, 6.5);
tl.to("#s1-subtitle", { opacity: 0, duration: 0.3 }, 6.7);
// Übergang feuert auf leerem Frame

RICHTIG – nur Eintritt, Übergang übernimmt Austritt:

// Szenen-1-Eintrittsanimationen
tl.from("#s1-title", { y: 50, opacity: 0, duration: 0.7, ease: "power3.out" }, 0.3);
tl.from("#s1-subtitle", { y: 30, opacity: 0, duration: 0.5, ease: "power2.out" }, 0.6);
// KEINE Austritts-Tweens – Übergang bei 7.2s übernimmt den Szenenwechsel
// Szenen-2-Eintrittsanimationen
tl.from("#s2-heading", { x: -40, opacity: 0, duration: 0.6, ease: "expo.out" }, 8.0);

Animationsleitplanken

  • Erste Animation um 0,1-0,3 s versetzen (nicht t=0)
  • Eases über Eintritts-Tweens variieren – verwende mindestens 3 verschiedene Eases pro Szene
  • Wiederhole kein Eintrittsmuster innerhalb einer Szene
  • Vermeide Vollbild-lineare Farbverläufe auf dunklen Hintergründen (H.264-Banding – verwende radial oder einfarbig + lokales Glühen)
  • 60px+ Überschriften, 20px+ Fließtext, 16px+ Datenbeschriftungen für gerendertes Video
  • font-variant-numeric: tabular-nums bei Zahlenspalten

Wenn kein visual-style.md oder keine Animationsanweisung gegeben ist, folge house-style.md für ästhetische Vorgaben.

Typografie und Assets

  • Schriftarten: Schreibe einfach die gewünschte font-family in CSS – der Compiler bettet unterstützte Schriftarten automatisch ein. Wenn eine Schriftart nicht unterstützt wird, warnt der Compiler.
  • Füge crossorigin="anonymous" zu externen Medien hinzu
  • Für …

[gekürzt für die Übersetzung]

Verwandte Skills