vid-sizzle-reel
Erzeugt einen energiegeladenen Sizzle Reel oder ein Hype-Video aus Marken-Assets und Kernbotschaften. Pipeline: HyperFrames HTML-Komposition (GSAP-Timelines) → Headless Chromium → FFmpeg H.264 MP4. Kein Runway. Kein Pika. Keine KI-Video-APIs. Keine Laufzeitkosten außer Node.js + FFmpeg.
Abgrenzung zu vid-product-launch:
vid-product-launcherzählt eine narrative Geschichte – eine aufbauende Enthüllung, fünf Abschnitte, Spannungsbogen.vid-sizzle-reelerzeugt Energie und Begeisterung – schnelle Schnitte, Musik-zentriert, keine einzelne Storyline.
Kritische Regeln (vor jeder Erstellung lesen)
-
Schreibe die Kernbotschaften selbst – oder bitte den Benutzer, sie zu schreiben. Das sind die genauen Phrasen, die auf dem Bildschirm erscheinen. „Die KI wird das schon irgendwie regeln” produziert Füllmaterial. 3-5 prägnante Zeilen sind der gesamte Inhalt eines Sizzle Reels.
-
Der Markenname erscheint NUR in der Land-Sektion. Cold Open und Build erzeugen Spannung, ohne die Marke zu nennen. Die Land-Sektion ist der Höhepunkt.
-
Deklariere das Rhythmusmuster in einem Kommentar am Anfang des Skripts, bevor du HTML schreibst. Format:
// RHYTHM: flash-sequence | Cold[0-5s]: stat | Build[5-40s]: msg(1.5s)|flash|... | Peak[40-55s]: ... | Land[55-60s]: logo+CTA. Jede Timing-Entscheidung wird daran gemessen. -
Erstelle zuerst den Endzustand des Layouts in CSS – noch kein GSAP. Positioniere jedes Element in seinem sichtbarsten Moment im statischen CSS. Füge dann GSAP-Entrances mit
gsap.from()und Exits mitgsap.to()hinzu. Positioniere niemals im animierten Startzustand. -
class="clip"auf jedem zeitgesteuerten Element. Von HyperFrames benötigt. Ohne dies ist das Element für den Player unsichtbar. -
data-start,data-duration,data-track-indexauf jedem Clip. Keine Ausnahmen. Clips auf demselben Track dürfen sich nicht überlappen – verwende verschiedene Track-Indizes. -
Kein
Math.random(). HyperFrames benötigt deterministische Kompositionen. Verwende einen seed-basierten PRNG (mulberry32) für alle Pseudo-Zufallswerte. -
Alle GSAP-Timelines starten mit
{ paused: true }und registrieren sich unterwindow.__timelines["comp-id"]. Der HyperFrames-Player steuert die Wiedergabe – rufe niemalstl.play()auf. -
Verwende niemals
position: absoluteauf.scene-content-Containern. Nutzewidth:100%; height:100%; padding:Npx; display:flex. Behalteposition:absoluteausschließlich für dekorative Elemente vor. -
Musik: Separat
<audio>-Element mitdata-track-index. Das Video mussmuted playsinlinesein. Platziere Audio niemals in einem<video>-Element. -
Lies
references/cut-patterns.mdUNDreferences/tone-presets.md, bevor du HTML generierst. -
Gib HTML niemals im Chat aus. Speichere es in einer Datei. Zeige nur die Zusammenfassung.
Schritt 1: Aufnahme
Erforderlich:
key_messages– 3-5 prägnante Zeilen, die auf dem Bildschirm erscheinen (der Benutzer muss diese schreiben)
Optionale Parameter und Standardwerte:
| Parameter | Standard | Beschreibung |
|---|---|---|
| brand_assets | keine | Logo-URL/-Pfad, Markenfarben (Hex), wichtige Screenshots |
| tone | energetic | energetic / cinematic / emotional / professional |
| music | keine | Dateipfad oder BPM/Genre-String (z. B. "128bpm electronic") |
| duration | 60 | 30 / 60 / 90 Sekunden |
| aspect_ratio | 9:16 | 9:16 (1080x1920) / 16:9 (1920x1080) |
| cut_style | auto | fast (1-2s) / cinematic (3-5s) – auto leitet vom Ton ab |
| end_card | auto | Logo + Slogan + CTA-URL für Land-Sektion |
cut_style-Auto-Standards: energetic → fast; professional → fast (2s); cinematic → cinematic; emotional → mixed
Wenn key_messages fehlt, frage genau so:
„Um den Sizzle Reel zu generieren, brauche ich deine Kernbotschaften – die genauen Phrasen, die auf dem Bildschirm erscheinen. Gib mir 3-5 prägnante Zeilen. Das ist das Wichtigste, was du für dieses Video schreibst.
Beispiele: ‚Genutzt von 500+ Wachstumsteams‘ / ‚Von Tagen zu Minuten‘ / ‚Funktioniert mit Claude, Codex, Gemini‘
Ebenfalls hilfreich: Ton (energetic/cinematic/emotional/professional), Dauer (30/60/90s), Markenfarben oder Logo-URL."
Wenn key_messages vorhanden sind → gehe sofort zu Schritt 2.
Schritt 2: HyperFrames installieren
HyperFrames-Fähigkeiten installieren (nur beim ersten Mal – überspringen, falls bereits installiert):
npx skills add heygen-com/hyperframes
Umgebung überprüfen:
node --version # muss >= 22 sein
ffmpeg --version # muss vorhanden sein
Projekt vorbereiten:
npx hyperframes init sizzle-[slug] --example kinetic-type --non-interactive
cd sizzle-[slug]
Slug: Kebab-Case aus dem Markennamen von end_card oder der ersten key_message, max. 25 Zeichen.
Schritt 3: Interne Architektur (wird dem Benutzer nie gezeigt)
1. Schnittpunkt-Timing aus duration + cut_style ableiten:
| Sektion | 30s | 60s | 90s |
|---|---|---|---|
| Cold Open | 0-5s | 0-5s | 0-8s |
| Build | 5-25s | 5-40s | 8-65s |
| Peak | 25-28s | 40-55s | 65-80s |
| Land | 28-30s | 55-60s | 80-90s |
Wandle jede Grenze in Millisekunden um. Berechne die Dauer pro Szene aus cut_style:
fast: 1,2s-1,8s pro Nachricht (Standard 1,5s)cinematic: 3,5s-5,0s pro Nachricht (Standard 4,0s)mixed: 2,0s-4,0s, variierend nach Sektionsenergie
2. key_messages auf Szenen abbilden:
- Cold Open (1 Szene): eine Impact-Statistik oder Frage – KEIN Markenname, baut Spannung auf
- Build: eine Szene pro key_message
- Peak: Wiederhole die stärkste Nachricht in doppelter Größe oder kombiniere 2 Nachrichten in schnellem Wechsel
- Land: Markenname + Slogan + CTA-URL
3. Beat-Sync erkennen, falls Musik bereitgestellt:
npx hyperframes tts --analyze-beats [Musikdatei]
Falls nicht verfügbar, aus BPM berechnen: beat_ms = 60000 / BPM. Schnitte auf jeden 2. Beat ausrichten.
4. Ton-Voreinstellung auswählen – lies references/tone-presets.md für CSS-Tokens.
5. Rhythmusmuster deklarieren – schreibe Kommentar am Anfang des Skripts:
// RHYTHM: flash-sequence
// Cold Open [0-5000ms]: stat
// Build [5000-40000ms]: msg-1(1500ms)|flash|msg-2(1500ms)|flash|msg-3(1500ms)|flash|msg-4(1500ms)|flash|build-accum(10000ms)
// Peak [40000-55000ms]: msg-strongest(1200ms)|flash|msg-2nd(1200ms)|flash|HOLD(5600ms)
// Land [55000-60000ms]: logo+tagline+cta
6. Pixelabmessungen bestimmen:
9:16→ B=1080, H=1920 (Standard – Instagram Reels, TikTok, YouTube Shorts)16:9→ B=1920, H=1080
Schritt 4: HyperFrames HTML-Komposition
Lies references/cut-patterns.md und die HyperFrames-Fähigkeit (/hyperframes), bevor du Code schreibst.
Erforderliches HTML-Grundgerüst:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
[font CDN link from tone preset]
<style>
:root {
[alle CSS-Tokens aus der Ton-Voreinstellung]
}
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
</style>
</head>
<body>
<div
data-composition-id="sizzle-[slug]"
data-width="[W]"
data-height="[H]"
style="position:relative;width:[W]px;height:[H]px;overflow:hidden;background:var(--bg)"
>
[if cut-flash: true]
<div id="cut-flash"
style="position:absolute;inset:0;background:var(--cut-flash-bg);opacity:0;pointer-events:none;z-index:200"></div>
[end if]
[if film-grain: true]
<canvas id="grain-overlay"
width="240" height="135"
style="position:absolute;inset:0;width:[W]px;height:[H]px;pointer-events:none;opacity:0.022;mix-blend-mode:overlay;z-index:50"></canvas>
[end if]
[if vignette: true]
<div id="vignette-overlay"
style="position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 35%,rgba(0,0,0,0.65) 100%);pointer-events:none;z-index:51"></div>
[end if]
<!-- Szenen – ein div pro Szene -->
<div id="scene-cold"
class="clip"
data-start="0"
data-duration="5"
data-track-index="0"
style="position:absolute;inset:0;opacity:0"
>
<div class="scene-content" style="width:100%;height:100%;padding:120px;display:flex;flex-direction:column;align-items:center;justify-content:center;box-sizing:border-box">
[Cold Open Inhalt – eine Statistik oder Impact-Phrase, kein Markenname]
</div>
</div>
[ein div pro Build-Szene, data-start inkrementiert um Schnittdauer]
[Peak Szene(n)]
[Land Szene – Markenname + Slogan + CTA]
[if music bereitgestellt]
<audio id="music"
class="clip"
data-start="0"
data-duration="[Gesamtdauer]"
data-track-index="10"
data-volume="0.85"
src="[Musikpfad]"
></audio>
[end if]
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<script>
// ── RHYTHMUS-DEKLARATION ──────────────────────────────────────────────────────
// RHYTHM: [flash-sequence | cinematic-hold | beat-sync | mixed]
// Cold Open [0-Nms]: ...
// Build [N-Nms]: ...
// Peak [N-Nms]: ...
// Land [N-Nms]: ...
// ── SEEDED PRNG (nur für Korn – keine anderen Zufallswerte) ───────────────────
function mulberry32(seed) {
return function() {
seed |= 0; seed = seed + 0x6D2B79F5 | 0;
let t = Math.imul(seed ^ seed >>> 15, 1 | seed);
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
return ((t ^ t >>> 14) >>> 0) / 4294967296;
};
}
[if film-grain: true]
// ── FILMKORN (nur filmisch/emotional) ───────────────────────────────────
const grainCanvas = document.getElementById('grain-overlay');
const grainCtx = grainCanvas ? grainCanvas.getContext('2d') : null;
// Korn aktualisiert durch GSAP-Ticker (kein Frame-Einfang – HyperFrames übernimmt das)
[end if]
// ── GSAP TIMELINE ───────────────────────────────────────────────────────────
const tl = gsap.timeline({ paused: true });
// ── COLD OPEN ───────────────────────────────────────────────────────────────
[Cold Open Entrance- und Exit-Tweens – siehe cut-patterns.md für genaues Muster]
// ── BUILD-SEKTION ───────────────────────────────────────────────────────────
[Pro-Nachricht-Tweens – flash-sequence oder cinematic-hold aus cut-patterns.md]
// ── PEAK-SEKTION ─────────────────────────────────────────────────────────────
[Peak-Tweens – gleiches Muster wie Build, aber engeres Timing]
// ── LAND-SEKTION ─────────────────────────────────────────────────────────────
[Land-Entrances – Logo, Slogan, CTA. Kein Exit – hält bis zum Ende]
// ── TIMELINE-REGISTRIERUNG ────────────────────────────────────────────────────
window.__timelines = window.__timelines || {};
window.__timelines["sizzle-[slug]"] = tl;
</script>
</div>
</body>
</html>
Regeln zur Designqualität:
- Cold Open Statistik: ≥160px Schriftgröße für 16:9, ≥100px für 9:16
- Kernbotschaften: ≥80px Schriftgröße – auf einen Blick lesbar
- Markenname in Land-Sektion: ≥120px für 16:9
- Alle Farben aus Variablen der Voreinstellung – keine freien Hex-Codes außer
var(--accent)-Literal-Hex innerhalb von CanvasfillStyle scene-contentverwendet immerpadding + flex– niemalsposition:absoluteauf dem Inhaltscontainerclass="clip"auf jedem Element mitdata-start
Schritt 5: Selbst-QA (behebe jeden Fehler vor Schritt 6)
Inhalt:
-
key_messages– jede Phrase erscheint genau einmal, keine Duplikate - Markenname erscheint NUR in der Land-Sektion (nicht Cold Open, nicht Build, nicht Peak)
- Cold Open enthält KEINEN Markennamen und KEINEN Produktnamen – nur Statistik oder Impact-Phrase
- Land-Sektion hat: Markenname + Slogan + CTA-URL (mindestens drei Elemente)
- end_card CTA-URL auf dem letzten Frame vorhanden
HyperFrames-Vertrag:
-
class="clip"auf jedem Element mitdata-start -
data-start,data-duration,data-track-indexauf jedem Clip -
data-composition-idauf dem Root-Kompositions-div -
window.__timelines["sizzle-[slug]"] = tlregistriert - Alle Timelines starten mit
{ paused: true } - Kein
Math.random()– nur seed-basierter PRNG - Keine
tl.play()- odertl.resume()-Aufrufe
GSAP / Layout:
-
gsap.from()für alle Entrances (VON außerhalb DES BILDSCHIRMS ZUR CSS-Position) -
gsap.to()für alle Exits (VON CSS-Position AUSSERHALB DES BILDSCHIRMS) - Kein
position:absoluteauf.scene-content-Containern - Rhythmusmuster in Kommentar am Anfang des Skripts deklariert
Schnitt-Timing:
-
fast-Ton: durchschnittliche Schnittdauer ≤ 2,0s -
cinematic-Ton: durchschnittliche Schnittdauer ≥ 3,0s - Schnittblitz feuert bei jeder Schnittgrenze für
energetic-Ton (60ms, Opacity 0→1→0) - Clips auf demselben Track überlappen sich NICHT (überprüfe alle
data-track-index-Gruppierungen)
SFX:
-
window.__sfxTimelinevorhanden und vor der Timeline-Registrierung platziert -
word-hit-Ereignis pro Kernbotschaft -
whooshbeim Build → Peak-Übergang -
cta-chimebeim Land-Start - Kein SFX feuert vor 500ms
Schritt 6: Linten, Rendern, Ausgabe
npx hyperframes lint
npx hyperframes inspect --json
Behebe alle Lint-Fehler. Behebe alle Inspect-Fehler (Textüberläufe, Clips, die Container verlassen). Dann rendern:
npx hyperframes render --output sizzle/[slug]/sizzle-reel.mp4
Ausgabe:
## Sizzle Reel: [Markenname aus end_card]
Ton: [tone] | Dauer: [N]s | Schnittstil: [cut_style] | Seitenverhältnis: [ratio]
Rhythmus: [deklariertes Muster]
Sektionen
Cold Open [0-Ns]: [Impact-Statistik oder Phrase]
Build [N-Ns]: [N Kernbotschaften aufgelistet]
Peak [N-Ns]: [stärkste Nachricht in maximaler Größe]
Land [N-Ns]: [Markenname] + "[Slogan]" + [CTA-URL]
Dateien
Quelle: sizzle/[slug]/index.html
Ausgabe: sizzle/[slug]/sizzle-reel.mp4
SFX-Timeline (in jede Komposition einbetten)
Das gleiche FFmpeg-synthetisierte SFX-System wie bei vid-product-launch. Platziere window.__sfxTimeline unmittelbar vor der GSAP-Timeline-Registrierung.
Referenz der SFX-Typen für Sizzle Reel:
| Typ | Sound | Dauer | Platzierung |
|---|---|---|---|
word-hit | Sub-Punch (50Hz) + transienter Klick (2,2kHz) + Noise-Burst | 180ms | Einer pro Start einer key_message-Szene |
whoosh | Zwei-Band-Noise-Sweep (1,1kHz Körper + 4-8kHz Luft) | 700ms | Beim Build → Peak-Übergang |
cta-chime | A-Dur-Akkord (440+554+659+880Hz) + Nachhall-Glöckchen | 1,2s | Exakt beim Land-Start |
window.__sfxTimeline = [
// ein word-hit pro key_message (berechnet aus den Startzeiten der Szene)
{ ms: MSG_1_START_MS, sfx: 'word-hit', vol: 0.50 },
{ ms: MSG_2_START_MS, sfx: 'word-hit', vol: 0.50 },
{ ms: MSG_3_START_MS, sfx: 'word-hit', vol: 0.50 },
// ... wiederhole für jede Nachricht
{ ms: PEAK_START_MS - 700, sfx: 'whoosh', vol: 0.55 },
{ ms: LAND_START_MS, sfx: 'cta-chime', vol: 0.65 },
];
Berechne alle ms-Werte aus den deklarierten Sektionsstartzeiten.
Referenzen
references/cut-patterns.md
Inhalt:
- flash-sequence: Jede Szene blendet ein (opacity 0→1 über 200ms), hält für Nms (siehe
cut_style), blendet aus (opacity 1→0 über 150ms). Schnittblitz feuert bei jeder Grenze (60ms weißer Frame). Alle Szenen auf aufsteigendemdata-track-index. - cinematic-hold: Jede Szene blendet ein (opacity 0→1 über 400ms), hält für Nms (siehe
cut_style), blendet aus (opacity 1→0 über 500ms). Kein Schnittblitz. Szenen können auf demselbendata-track-indexliegen, solange sie sich nicht überschneiden. - beat-sync: Wie flash-sequence, aber Schnittblitze sind auf jeden 2. Beat ausgerichtet.
data-durationmuss ein Vielfaches vonbeat_ms * 2sein. - mixed: Cold Open + Land: cinematic-hold. Build + Peak: flash-sequence, aber mit 300ms Überblendungen statt Schnittblitzen.
references/tone-presets.md
Inhalt:
/* energetic */
:root {
--bg: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
--text: #ffffff;
--accent: #ff3366;
--accent2: #33ccff;
--cut-flash-bg: rgba(255,255,255,0.85);
--shadow: rgba(0,0,0,0.5);
--font: 'Poppins', sans-serif;
--bold-weight: 800;
}
/* cinematic */
:root {
--bg: #1a1a1a;
--text: #f0e6d3;
--accent: #c9a96e;
--accent2: #8b7355;
--cut-flash-bg: transparent;
--shadow: rgba(0,0,0,0.7);
--font: 'Playfair Display', serif;
--bold-weight: 700;
}
/* emotional */
:root {
--bg: #2d1b2e;
--text: #fce4ec;
--accent: #e91e63;
--accent2: #f06292;
--cut-flash-bg: transparent;
--shadow: rgba(0,0,0,0.6);
--font: 'Lato', sans-serif;
--bold-weight: 300;
}
/* professional */
:root {
--bg: #0d1117;
--text: #c9d1d9;
--accent: #58a6ff;
--accent2: #30363d;
--cut-flash-bg: rgba(88,166,255,0.15);
--shadow: rgba(0,0,0,0.4);
--font: 'Inter', sans-serif;
--bold-weight: 600;
}