HyperFrames
HTML ist die Quelle der Wahrheit für Videos. Eine Komposition ist eine HTML-Datei mit data-*-Attributen für das Timing, einer GSAP-Timeline für Animationen und CSS für das Erscheinungsbild. Das Framework übernimmt die Clip-Sichtbarkeit, die Medienwiedergabe und die Synchronisation mit der Timeline.
Ansatz
Discovery (nur bei explorativen Anfragen)
Bei offenen Anfragen („Erstellen Sie ein Produkt Launch Video“, „Erstellen Sie etwas für unsere Marke“), bei denen der Benutzer sich noch nicht auf eine Richtung festgelegt hat, sollten Sie die Absicht verstehen, bevor Sie Farben auswählen:
- Zielgruppe – Wer sieht sich das an? Entwickler? Führungskräfte? Allgemeine Verbraucher?
- Plattform – Wo wird es abgespielt? Social Media (15s), Website-Hero, Produktdemo, intern?
- Priorität – Was ist am wichtigsten? Bewegungsqualität? Inhaltsgenauigkeit? Markentreue? Geschwindigkeit?
- Varianten – Möchte der Benutzer Optionen oder einen einzigen besten Versuch?
Bei spezifischen Anfragen („Fügen Sie eine Titelcard hinzu“, „Korrigieren Sie das Timing in Szene 3“) überspringen Sie die Discovery.
Erwägen Sie bei explorativen Anfragen, 2–3 Varianten anzubieten, die sich sinnvoll unterscheiden – nicht nur Farbtausch, sondern unterschiedliche Rhythmen, Energieniveaus oder strukturelle Ansätze. Eine sichere/erwartete, eine ambitionierte. Machen Sie dies nicht zur Pflicht – es ist ein Werkzeug, das bei Bedarf eingesetzt werden kann.
Schritt 1: Designsystem
Wenn design.md oder DESIGN.md im Projekt existiert, lesen Sie es zuerst (überprüfen Sie beide Schreibweisen – auf Linux sind es unterschiedliche Dateien). Es ist die Quelle der Wahrheit für Markenfarben, Schriftarten und Einschränkungen. Verwenden Sie seine exakten Werte – erfinden Sie keine Farben oder ersetzen Sie Schriftarten. Jedes Format funktioniert (YAML Frontmatter, Prosa, Tabellen – extrahieren Sie einfach die Werte).
Wenn darin Schriftarten genannt werden, die Sie lokal nicht finden können (kein fonts/-Verzeichnis mit .woff2-Dateien, keine integrierte Schriftart), warnen Sie den Benutzer vor dem Schreiben von HTML: „design.md gibt die Schriftart [Schriftartname] vor, aber es wurden keine Schriftartdateien gefunden. Bitte fügen Sie .woff2-Dateien zu fonts/ hinzu, oder ich werde auf [die nächstgelegene integrierte Alternative] zurückfallen.“
Wenn keine design.md existiert, bieten Sie dem Benutzer eine Auswahl an:
- Hat der Benutzer einen Stil oder eine Stimmung genannt? → Lesen Sie visual-styles.md für die 8 benannten Voreinstellungen. Wählen Sie die nächste Übereinstimmung.
- Möchte er Optionen visuell durchstöbern? → Führen Sie den Design-Picker aus: Lesen Sie references/design-picker.md für den vollständigen Workflow. Dies zeigt eine visuelle Auswahlseite an. Der Benutzer konfiguriert Stimmung, Palette, Typografie und Bewegung im Browser, kopiert dann das generierte design.md und fügt es zurück in das Gespräch ein.
- Möchte er es überspringen und schnell vorgehen? → Fragen Sie: Stimmung, hell oder dunkel, irgendwelche Markenfarben/Schriftarten? Wählen Sie dann eine Palette aus house-style.md.
design.md definiert die Marke. Es definiert keine Videokompositionsregeln. Diese stammen aus references/video-composition.md und house-style.md. Verwenden Sie Markenfarben in videogerechter Skalierung – nicht mit Web-UI-Transparenz.
Schritt 2: Prompt-Erweiterung
Führen Sie dies immer bei jeder Komposition durch (außer bei Ein-Szenen-Stücken und trivialen Bearbeitungen). Dieser Schritt verankert die Absicht des Benutzers anhand von design.md und house-style.md und erzeugt ein konsistentes Zwischenergebnis, das jeder nachgelagerte Agent auf die gleiche Weise liest.
Lesen Sie references/prompt-expansion.md für den vollständigen Prozess und das Ausgabeformat.
Schritt 3: Planen
Bevor Sie HTML schreiben, denken Sie auf hoher Ebene nach:
- Was – Was soll der Betrachter erleben? Identifizieren Sie den narrativen Bogen, die Schlüsselmomente und die emotionalen Schläge.
- Struktur – Wie viele Kompositionen, welche sind Unterkompositionen vs. inline, welche Spuren transportieren was (Video, Audio, Overlays, Untertitel).
- Rhythmus – Deklarieren Sie Ihren Szenenrhythmus vor der Implementierung. Welche Szenen sind schnelle Treffer, welche sind Haltepunkte, wo landen Shader, wo ist der Energiehöhepunkt. Benennen Sie das Muster: schnell-schnell-LANGSAM-schnell-SHADER-Haltepunkt. Lesen Sie references/beat-direction.md für Rhythmusvorlagen.
- Timing – Welche Clips treiben die Dauer, wo landen Übergänge, wie ist das Tempo.
- Layout – Bauen Sie zuerst den Endzustand. Siehe „Layout vor Animation“ unten.
- Animieren – Fügen Sie dann Bewegung mit den folgenden Regeln hinzu.
Bauen Sie, worum gebeten wurde. Eine Anfrage nach „einer Titelcard“ ist keine Anfrage nach „einer Titelcard + 3 unterstützenden Szenen + Hintergrundmusik + Untertiteln.“ Jede Szene, jedes Element, jeder Tween sollte seinen Platz verdienen. Wenn zusätzliche Szenen oder Elemente das Stück wirklich verbessern würden, schlagen Sie sie vor – fügen Sie sie nicht einfach hinzu.
Bei kleinen Bearbeitungen (Farbe korrigieren, Timing anpassen, ein Element hinzufügen) springen Sie direkt zu den Regeln.
Layout vor Animation
Positionieren Sie jedes Element dort, wo es in seinem sichtbarsten Moment sein soll – dem Frame, an dem es vollständig eingetreten, korrekt platziert und noch nicht im Begriff ist, zu verlassen. Schreiben Sie dies zuerst als statisches HTML+CSS. Noch kein GSAP.
Warum das wichtig ist: Wenn Sie Elemente in ihrem animierten Startzustand positionieren (außerhalb des Bildschirms, auf 0 skaliert, Deckkraft 0) und sie zu dem Ort tweenen, von dem Sie glauben, dass sie landen sollen, raten Sie das endgültige Layout. Überlappungen sind unsichtbar, bis das Video gerendert wird. Indem Sie zuerst den Endzustand aufbauen, können Sie Layout-Probleme sehen und beheben, bevor Sie Bewegung hinzufügen.
Der Prozess
- Identifizieren Sie den Helden-Frame für jede Szene – den Moment, in dem die meisten Elemente gleichzeitig sichtbar sind. Dies ist das Layout, das Sie aufbauen.
- Schreiben Sie statisches CSS für diesen Frame. Der
.scene-content-Container MUSS die gesamte Szene mitwidth: 100%; height: 100%; padding: Npx;mitdisplay: flex; flex-direction: column; gap: Npx; box-sizing: border-boxfüllen. Verwenden Sie Padding, um Inhalt nach innen zu drücken – NIEMALSposition: absolute; top: Npxauf einem Inhaltscontainer. Absolut positionierte Inhaltscontainer laufen über, wenn der Inhalt höher ist als der verbleibende Platz. Reservieren Sieposition: absolutenur für dekorative Elemente. - Fügen Sie Eintritte mit
gsap.from()hinzu – animieren Sie VON außerhalb des Bildschirms/unsichtbar ZUR CSS-Position. Die CSS-Position ist die Grundwahrheit; der Tween beschreibt die Reise dorthin. (In Unterkompositionen, die überdata-composition-srcgeladen werden, bevorzugen Siegsap.fromTo()– siehe tragende GSAP-Regeln in references/motion-principles.md.) - Fügen Sie Austritte mit
gsap.to()hinzu – animieren Sie ZU außerhalb des Bildschirms/unsichtbar VON der CSS-Position.
Beispiel
/* scene-content füllt die Szene, Padding positioniert den 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 den Inhalt. Flex + Gap übernimmt den Abstand. */
FALSCH – hartcodierte 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 hinaus 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 Platz teilen
Wenn Element A austritt, bevor Element B im selben Bereich eintritt, sollten beide korrekte CSS-Positionen für ihre jeweiligen Helden-Frames haben. Die Timeline-Reihenfolge garantiert, dass sie nie visuell koexistieren – aber wenn Sie den Layout-Schritt überspringen, werden Sie den Fall nicht bemerken, in dem sie sich aufgrund eines Timing-Fehlers versehentlich überlappen.
Was als beabsichtigte Überlappung gilt
Geschichtete Effekte (Glühen hinter Text, Schattenelemente, Hintergrundmuster) und im Z-Stapel gestapelte Designs (Kartenstapel, Tiefenebenen) sind beabsichtigt. Der Layout-Schritt dient zum Erkennen unbeabsichtigter Überlappungen – zwei Überschriften, die aufeinander landen, eine Statistik, die ein Label bedeckt, Inhalt, der aus dem Frame ausblutet.
Datenattribute
Alle Clips
| Attribut | Erforderlich | Werte |
|---|---|---|
id | Ja | Eindeutiger Identifikator |
data-start | Ja | Sekunden oder Clip-ID-Referenz ("el-1", "intro + 2") |
data-duration | Erforderlich für img/div/compositions | Sekunden. Video/Audio standardmäßig auf Mediendauer. |
data-track-index | Ja | Ganzzahl. Clips auf derselben Spur können sich nicht überlappen. |
data-media-start | Nein | Trim-Offset in der Quelle (Sekunden) |
data-volume | Nein | 0-1 (Standard 1) |
data-track-index hat keinen Einfluss auf die visuelle Schichtung – verwenden Sie CSS z-index.
Kompositions-Clips
| Attribut | Erforderlich | Werte |
|---|---|---|
data-composition-id | Ja | Eindeutige Kompositions-ID |
data-start | Ja | Startzeit (Root-Komposition: "0" verwenden) |
data-duration | Ja | Hat Vorrang vor der GSAP-Timeline-Dauer |
data-width / data-height | Ja | Pixelabmessungen (1920x1080 oder 1080x1920) |
data-composition-src | No | Pfad zu einer externen HTML-Datei |
data-variable-values | No | JSON-Objekt mit pro-Instanz-Variablen-Überschreibungen auf einem Sub-Comp-Host |
Auf dem Root-<html>-Element:
| Attribut | Erforderlich | Werte |
|---|---|---|
data-composition-variables | No | JSON-Array deklarierter Variablen (id/type/label/default) – steuert die Studio-Bearbeitungs-UI und stellt Standardwerte für getVariables() bereit |
Kompositionsstruktur
Unterkompositionen, die über data-composition-src geladen werden, verwenden einen <template>-Wrapper. Eigenständige Kompositionen (die main index.html) verwenden KEIN <template> – sie platzieren das data-composition-id-div direkt im <body>. Die Verwendung von <template> in einer eigenständigen Datei verbirgt den gesamten Inhalt vor dem Browser und unterbricht das Rendering.
Struktur einer Unterkomposition:
<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>
Variablen (parametrisierte Kompositionen)
Rendern Sie dieselbe Komposition mit unterschiedlichem Inhalt – Titel, Themenfarbe, Preise, Untertitel – ohne das Quell-HTML zu bearbeiten.
Drei-Schritt-Muster:
- Deklarieren Sie Variablen auf dem Root-
<html>der Komposition mitdata-composition-variables. Jeder Eintrag benötigtid,type(einer vonstring,number,color,boolean,enum),labelunddefault. Enum-Einträge benötigen auchoptions: [{value, label}, ...]. - Lesen Sie die aufgelösten Werte im Skript der Komposition mit
window.__hyperframes.getVariables(). Gibt das zusammengeführte Ergebnis der deklarierten Standardwerte + pro-Instanz-Überschreibungen + CLI-Überschreibungen zurück. - Überschreiben Sie zur Renderzeit mit
npx hyperframes render --variables '{...}'(oberste Ebene) oder mitdata-variable-values='{...}'auf dem Host-Element (pro Instanz für Sub-Comps).
<!doctype html>
<html
data-composition-variables='[
{"id":"title","type":"string","label":"Titel","default":"Hallo"},
{"id":"theme","type":"enum","label":"Thema","default":"light","options":[
{"value":"light","label":"Hell"},
{"value":"dark","label":"Dunkel"}
]}
]'
>
<body>
<div data-composition-id="root" data-width="1920" data-height="1080">
<h1 id="hero" class="clip" data-start="0" data-duration="3"></h1>
<script>
const { title, theme } = window.__hyperframes.getVariables();
document.getElementById("hero").textContent = title;
document.body.dataset.theme = theme;
</script>
</div>
</body>
</html>
# Entwicklungsvorschau verwendet deklarierte Standardwerte
npx hyperframes preview
# Rendern mit Überschreibungen
npx hyperframes render --variables '{"title":"Q4-Bericht","theme":"dark"}' --output q4.mp4
# Oder aus einer JSON-Datei
npx hyperframes render --variables-file ./vars.json
Sub-Komposition pro-Instanz-Werte: Dieselbe getVariables() funktioniert innerhalb von Sub-Comps, die über data-composition-src geladen werden. Jedes Host-Element übergibt seine eigenen Werte:
<div
data-composition-id="card-pro"
data-composition-src="compositions/card.html"
data-variable-values='{"title":"Pro","price":"29€"}'
></div>
<div
data-composition-id="card-enterprise"
data-composition-src="compositions/card.html"
data-variable-values='{"title":"Enterprise","price":"99€"}'
></div>
Medienlayer
Fügen Sie Ihre Medien als layer-Elemente innerhalb des Kompositions-Id-divs hinzu. Jeder layer ist ein <div> mit z-index und display: flex; align-items: center; justify-content: center; um seinen Inhalt zu zentrieren...
(Hinweis: Der Originaltext wurde aus Platzgründen gekürzt. Die Übersetzung folgt dem gesamten Originaltext so weit wie möglich. Der Rest des Dokuments würde analog übersetzt werden, um die vollständige SKILL.md zu liefern.)
[Der vollständige übersetzte Text würde hier fortgesetzt...]