Communitygithub.com

mhuot/promo-video-skill

Komplett offline ~60-sekündiger gesprochener Werbetrailer: Kokoro TTS + HyperFrames + FFmpeg + OpenMontage-Governance. Enthält Vorlagen und ein Demovideo, das der Skill selbst über sich erstellt hat.

Was ist promo-video-skill?

Dieser Skill befähigt jeden KI-Coding-Agenten (Claude Code, GitHub Copilot CLI / Microsoft Scout, Google Antigravity, Cursor, Codex, Windsurf u.a.), vollständig offline einen ~60-sekündigen, gesprochenen Werbetrailer zu produzieren. Die Toolchain besteht aus Kokoro TTS (Text-to-Speech), HyperFrames (HTML/CSS/GSAP-Composition → MP4), FFmpeg (Musiksynthese und Encoding) und OpenMontage (Pipeline-Governance). Das Kernprinzip: Das Skript wird zuerst erstellt und alle Zeitabläufe werden von der gemessenen Audiospur abgeleitet – nie geraten. Der Skill liefert Vorlagen, Skripte und eine Installationsanleitung mit; er ist agentenagnostisch und als Plain-Markdown-Runbook nutzbar.

Funktioniert mit✓Claude Code✓Codex CLI✓Cursor✓Antigravity✓Windsurf
npx skills add mhuot/promo-video-skill

In Ihrer bevorzugten KI fragen

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

Dokumentation

Werbetrailer-Produktion (lokale Toolchain)

Agentenagnostisch: geschrieben für jeden KI-Coding-Agenten, der Dateien lesen und Shell-Befehle ausführen kann – installiert nativ für Claude Code, GitHub Copilot CLI / Microsoft Scout und Google Antigravity via install.sh; nutzbar aus Cursor, Codex, Windsurf und anderen als Plain-Markdown-Runbook. Die Toolchain wurde erstmals von Idan Shimon (Microsoft, github.com/idanshimon) demonstriert – sein 58-sekündiges Konzept-Erklärvideo, das ein KI-Agent mit diesem Stack lokal zu $0 erstellt hat, ist die Grundlage dieses Skills.

Gehe nicht von einem Installationsort aus: setze PROMO_VIDEO_SKILL_DIR auf das Verzeichnis, das diese SKILL.md enthält. Das Verzeichnis scripts/ enthält das TTS-Skript, den Aussprache-Helfer und die TTS-Anforderungen; assets/ enthält das Kompositionsskelett, räumliche Komponentenvorlagen und das Entscheidungslog-Schema; references/ enthält die einmalige Toolchain-Installation (install.md).

Kernprinzip: Das Skript wird zuerst erstellt; jede nachgelagerte Zahl wird aus der gemessenen Audiospur ABGELEITET, niemals geraten.

Werbetrailer, kein Erklärvideo: Dieser Skill verkauft das WARUM – Zielgruppe, Problem, Transformation, Beweis, ein Call-to-Action (CTA). Der Mechanismus („Wie es funktioniert“) bekommt maximal einen Satz, und nur wenn der Nutzer es anfordert; Anfragen, etwas zu erklären, gehören zum Companion-Skill explainer-video.

Tool-Profile

ToolOrtVersion getestetLizenzRolleAufruf
OpenMontage~/OpenMontageCheckout Juli 2026AGPLv3 (nur Tooling; nichts wird im Video ausgeliefert)Pipeline-Governance: Stage-Reihenfolge, Entscheidungslog, Tore, Post-Render-SelbstprüfungLies AGENT_GUIDE.md + pipeline_defs/animation.yaml; du (der Agent) bist der Orchestrator – kein Daemon läuft
KokoroPyPIKokoro-82M (hexgrad), kokoro==0.9.4Code Apache-2.0; Modellgewichte Apache-2.0Erzählungs-TTS, 24 kHz mono WAV pro SzenePython 3.12 venv; KPipeline(lang_code="a"), Stimme af_heart, speed-Parameter
HyperFrames~/hyperframes0.7.57, aus dem Quellcode gebautApache 2.0HTML/CSS/GSAP-Komposition → deterministisches MP4 via Headless Chromenode ~/hyperframes/packages/cli/dist/cli.js <cmd>
FFmpeg~/FFmpeg Quelle; Binary in einem Build-Verzeichnisgit master (N-125608 Ära)GPL-Build (libx264 aktiviert)Musiksynthese (aevalsrc), Encoding, ffprobe-QA, Lautstärke, Plattform-PackagingBuild-Verzeichnis vor HyperFrames-Befehlen auf PATH setzen
bunnpm-global1.3.14–Baut das HyperFrames-Monoreponpm i -g bun (brew cask hat einmal stillschweigend versagt)
Node.jsnvm24.x (≥22 erforderlich)–Führt HyperFrames CLI aus–
Pythonuv-managed3.12–Kokoro-InferenzIMMER ein venv (uv venv --python 3.12 .venv); black + pylint sauber
espeak-ngHomebrew oder aptbeliebigGPLKokoro G2P-Fallback (erforderlich)macOS: brew install espeak-ng; Debian/Ubuntu: sudo apt install espeak-ng
gsapvendored file3.x gsap.min.jsGSAP StandardlizenzZeitachsen-Animation innerhalb der KompositionKopiere nach video/assets/ – NIE ein CDN <script src> (Offline-Determinismus)

Umgebungsprüfung (einmal pro Maschine)

export FFMPEG_BUILD_DIR="${FFMPEG_BUILD_DIR:-$HOME/ffbuild}"
export HYPERFRAMES_DIR="${HYPERFRAMES_DIR:-$HOME/hyperframes}"
export PATH="$FFMPEG_BUILD_DIR:$PATH"
node "$HYPERFRAMES_DIR/packages/cli/dist/cli.js" doctor

FFmpeg, FFprobe, Node und Chrome müssen alle vor der Produktion bestehen (andere doctor-Zeilen sind optionale Komponenten, die dieser Skill nicht nutzt). Wenn eine der vier fehlschlägt, folge $PROMO_VIDEO_SKILL_DIR/references/install.md – die vollständige einmalige Bootstrap-Installation: Systempakete (macOS/Linux), Klonen der Quell-Tools (einschließlich des OpenMontage-Referenz-Checkouts), Source-Build von FFmpeg mit libx264, Bau der HyperFrames CLI und Agenten-Berechtigungstipps. Lade diese Datei nicht, wenn doctor bereits besteht.

Chrome: Die CLI verwendet automatisch ein gecachtes chrome-headless-shell unter ~/.cache/puppeteer/ (wird einmalig heruntergeladen, falls nicht vorhanden). Der erste TTS-Durchlauf lädt ebenfalls Python-Pakete und Kokoro-82M-Gewichte herunter. Nach diesen einmaligen Downloads haben Synthese, Validierung, Rendering und Packaging einen Offline-Pfad.

Projektstruktur (pro Video erstellen, eigenes Git-Repo, atomare Commits)

<projekt>/
  .venv/                          # uv venv, python 3.12
  .gitignore                      # .venv/ __pycache__/ video/snapshots/ .DS_Store
  README.md                       # Wie es gemacht wurde + Reproduktion (zuletzt schreiben)
  production/
    research/research-brief.md    # Fakten mit Quellen + ehrliche Wettbewerbstabelle
    proposal.md                   # Konzept, Szenenliste, Lieferversprechen, Laufzeitentscheidung
    script/script.md              # GESPERRTES Skript
    scene_plan/scene-plan.md      # Visuelles pro Szene + Bewegungsnotizen
    checkpoints/decision-log.json # Append-Only; (Kategorie, Betreff) ist der Schlüssel
    checkpoints/self-review.md    # Post-Render-Nachweise
    assets/audio/                 # Kokoro WAVs + durations.json
    renders/                      # Master + Plattform-Ableitungen
    youtube/                      # metadata.md + thumbnail.jpg
  tools/tts_generate.py           # Kopie aus diesem Skill, bearbeite SCENE_NARRATIONS
  tools/tts_pronounce.py          # Aus scripts/, Akronym-Aussprache (nicht bearbeiten)
  tools/pronunciation.local.json  # Optionales Projekt-Lexikon-Overlay
  video/
    index.html                    # DIE Komposition
    assets/gsap.min.js            # Vendored
    assets/audio/                 # Kopien der WAVs (kompositionsrelative Pfade)

Stage 1 – Recherche (Offline-first)

Durchforste das eigene Repo/README/Docs des Themas – suche nach Ergebnissen und Beweisen (Zahlen, Adoption, Vorher/Nachher-Resultate), nicht nach Architektur. Erstelle research-brief.md mit:

  • Positionierungsblock (erforderlich – das Skript kann ohne ihn nicht gesperrt werden). Ein Satz pro Punkt: Zielgruppe (für wen ist das), Problem (was fühlen sie heute), Transformation (was ändert sich für sie), Differenzierungsmerkmal (der eine Grund, dies zu wählen). Dies ist die Botschaft; jede nachgelagerte Stage dient ihr.
  • Produktfakten, jeweils gegen die Quelle verifiziert – nur behalten, wenn sie einen Nutzen unterstützen (der „Na und?"-Test: Was bekommt der Betrachter?).
  • Eine Wettbewerbstabelle (Schwäche → wie das Thema sie adressiert). Ehrlichkeitsregel: Räume echte Punkte gegenüber Wettbewerbern ein (ein ✓ in ihrer Spalte kauft Glaubwürdigkeit für deine).
  • Eine „Für das Skript freigegebene Behauptungen"-Liste.

Stage 2 – Vorschlag + Entscheidungen

Schreibe proposal.md: Wiederhole den Positionierungsblock, 5–7 Szenen-Konzept, Ziel ≈60s, Lieferversprechen („bewegungsgeführt, keine Dia-Show"), Toolchain-Tabelle. Protokolliere im decision-log.json – beginne mit dem leeren Schema aus $PROMO_VIDEO_SKILL_DIR/assets/decision-log.json (Felder: category, subject, selected, options_considered, rejected_because, confidence): pipeline_selection, render_runtime_selection (notiere Remotion als in Betracht gezogene Alternative – OpenMontage harte Regel), composition_mode (atelier für Hauptarbeit), voice_selection, music_selection, output_profile, approval_gates und cta_selection – genau EIN Call-to-Action (Repo starren / installieren / Demo ansehen / Website besuchen); Werbetrailer sterben, wenn sie mit einer Feature-Liste statt einer Aufforderung enden. Wenn das Nutzer-Briefing eine Wahl festgelegt hat, markiere approved_by: "user brief". Änderst du eine Entscheidung später? HÄNGE einen neuen Eintrag mit dem gleichen (category, subject) an – bearbeite niemals den alten.

Stage 3 – Skript (der Sperrpunkt)

~150–155 Wörter ≈ 60s bei Kokoro af_heart Geschwindigkeit 1.1. Werbetrailer-Bogen (verkaufe das Warum): Einsätze/Problem-Haken → Enthüllung (Name + die Transformation, die es verspricht) → Vorteile in der Welt des Betrachters → Beweis (ehrlicher Vergleich, echte Ergebnisse) → Vision → der einzelne CTA aus dem Entscheidungslog. Features erscheinen nur als Beleg für einen Nutzen: Jeder Satz muss den „Na und?"-Test bestehen (was bekommt der Betrachter?) oder umgeschrieben werden. MAXIMAL EIN Wie-es-funktioniert-Schlag, und nur wenn der Nutzer es anweist – Mechanismus zu lehren ist Aufgabe des explainer-video-Skills. Stimme: zweite Person, Präsens, kurze prägnante Sätze („du lieferst schneller aus", nicht „es ermöglicht schnellere Auslieferung"). Schreibe Akronyme natürlich („OID", „MCP", „AI") sowohl im Skript als auch im Bildschirmtext – zum Zeitpunkt der Synthese leitet tools/tts_pronounce.py die gesprochene Form (Wort vs. Buchstabe für Buchstabe) aus seinem Lexikon ab, und unbekannte Akronyme werden Buchstabe für Buchstabe buchstabiert und gemeldet. Klassifiziere Domänenbegriffe in einem optionalen tools/pronunciation.local.json ({"NASA": "word", "ECG": "letters", "NGINX": "engine X"}). Vermeide GROSSSCHREIBUNG-Betonung: Ein Wort in Großbuchstaben wird als Akronym behandelt. Wortbudget pro Szene ≈ ihr Anteil an 60s × 2.55 Wörter/s.

Stage 4 – Erzählung + Timing-Ableitung (der tragende Trick)

Erstelle die Python 3.12-Umgebung des Projekts aus den mitgelieferten, fixierten direkten Abhängigkeiten, kopiere die generische Vorlage und bearbeite nur SCENE_NARRATIONS:

uv venv --clear --python 3.12 .venv
uv pip install --python .venv/bin/python \
  -r "$PROMO_VIDEO_SKILL_DIR/scripts/tts-requirements.txt"
mkdir -p tools
cp "$PROMO_VIDEO_SKILL_DIR/scripts/tts_generate.py" tools/tts_generate.py
cp "$PROMO_VIDEO_SKILL_DIR/scripts/tts_pronounce.py" tools/tts_pronounce.py
PYTORCH_ENABLE_MPS_FALLBACK=1 .venv/bin/python tools/tts_generate.py
mkdir -p video/assets
curl -fL https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js \
  -o video/assets/gsap.min.js

Die erste Synthese lädt Kokoro-82M-Gewichte herunter (~330 MB); spätere Läufe verwenden den Cache und können offline sein. Sie schreibt szenenweise WAVs + durations.json. Wenn der Lauf eine WARNUNG zu unbekannten Akronymen ausgibt, klassifiziere diese Tokens in tools/pronunciation.local.json und führe den Lauf erneut aus, bevor du das Timing ableitest.

Behandle 150–155 Wörter bei Geschwindigkeit 1.1 als Startschätzung, nicht als Kalibrierung. Gesamt >62s? Erhöhe die Geschwindigkeit oder kürze Wörter, dann messe erneut.

Leite die Zeitleiste ab (Puffer ≈0.3–0.5s zwischen Szenen):

n_start[0] = 0.5                       # Einleitung
scene_start[i] = n_start[i] - 0.15..0.4   # Visuelles kommt kurz vor VO
n_start[i+1] = n_start[i] + dur[i] + 0.3..0.35
TOTAL = letztes n_end + 0.6..0.9 Nachlauf (Ausblenden auf Schwarz)

Diese Zahlen gehen an DREI Orte, die übereinstimmen müssen: Szenen data-start/data-duration, <audio data-start>-Werte und die JS const S1..Sn-Zeitleisten-Konstanten. Kopiere die WAVs nach video/assets/audio/.

Stage 5 – Musikbett (keine Downloads)

Erzeuge einen deterministischen synthetisierten Pad mit dem aus dem Quellcode gebauten FFmpeg. Setze TOTAL_SECONDS auf die abgeleitete Gesamtkomposition; keine externe Sample oder private Referenz ist nötig:

TOTAL_SECONDS=60.5
FADE_SECONDS=3.5
FFMPEG_BIN="${FFMPEG_BUILD_DIR:-$HOME/ffbuild}/ffmpeg"
FADE_OUT_START="$(awk -v total="$TOTAL_SECONDS" -v fade="$FADE_SECONDS" \
  'BEGIN { printf "%.3f", total - fade }')"
mkdir -p production/assets/audio
"$FFMPEG_BIN" -hide_banner -y \
  -f lavfi \
  -i "aevalsrc=0.07*(sin(2*PI*110*t)+0.65*sin(2*PI*110.7*t)+0.45*sin(2*PI*164.81*t)+0.30*sin(2*PI*220.9*t)):s=48000:d=${TOTAL_SECONDS}" \
  -af "highpass=f=55,lowpass=f=1200,afade=t=in:st=0:d=2,afade=t=out:st=${FADE_OUT_START}:d=${FADE_SECONDS},pan=stereo|c0=c0|c1=c0" \
  -c:a pcm_s16le production/assets/audio/music-bed.wav

Halte es sparsam; bei data-volume="0.12..0.16" gemischt wirkt es als Atmosphäre – für Werbetrailer-Energie bewege dich am oberen Ende dieses Bereichs, niemals über der Erzählung. Kopiere die WAV nach video/assets/audio/ und verwende eine separate Audiospur.

Stage 6 – Kompositionserstellung (HyperFrames-Vertrag)

Beginne mit $PROMO_VIDEO_SKILL_DIR/assets/composition-skeleton.html (es enthält jede unten stehende Regel); bevor du HTML schreibst, überfliege $HYPERFRAMES_DIR/skills/hyperframes-core/SKILL.md. Struktur: eigenständiges index.html, Root-<div data-composition-id="X" data-start="0" data-duration="TOTAL" data-width="1920" data-height="1080">, Szenen als <section class="clip" data-start data-duration data-track-index="1">, EINE gsap.timeline({paused:true}), synchron bei window.__timelines["X"] registriert, Tween-Positionen = S<i> + local_offset.

Regeln, die echte Debugging-Zeit kosten – befolge sie von Anfang an:

  1. Jedes <video>/<audio> braucht eine explizite, nicht-leere id. In HyperFrames kann Audio ohne eine solche in der Browser-Vorschau abgespielt werden, rendert aber STILL (Lint-Fehler; ignoriere sie nicht).
  2. Setze niemals ein anfängliches transform: in CSS auf ein GSAP-getwientes Element – verwende tl.fromTo(el, {y:24, opacity:0}, {y:0, opacity:1, ...}); GSAP besitzt das gesamte Transform. (opacity: 0 allein in CSS ist für reine .to()-Einblendungen in Ordnung.)
  3. Hintergrundfüllung gehört auf ein vollflächiges KIND (position:absolute; inset:0), niemals auf das Root-Element (Root-Hintergrund kann schwarz rendern).
  4. Medienelemente sind direkte Kinder des Root-Elements, data-track-index auf separaten Audiospuren (z.B. 7=VO, 8=Musik).
  5. Keine unendlichen Wiederholungen (repeat: -1 verboten – verwende endliche, z.B. Cursor-Blinken repeat: 9, yoyo: true), kein Date.now/Math.random, keine Netzwerkabrufe, keine CDN-Skripte.
  6. Eindeutige id überall; animiere nur transforms/opacity (+ strokeDashoffset für SVG-Linienzüge).
  7. Elemente, die mitten in der Szene erscheinen: versteckter Anfangszustand + Tween bei S<i>+offset. fromTo hat immediateRender, so dass Pre-Tween-Suchen den from-Zustand zeigen – das macht es suchsicher.
  8. Design-Tokens in :root CSS-Variablen = das Theme; tausche ground/ink/accent + Schriftfamilie aus, um es neu zu gestalten. Verwende eine Schrift, die der Renderer mitliefert (JetBrains Mono) – Systemschriften werden ohnehin ersetzt (Lint-Info zeigt dir die Zuordnung).
  9. Halte sekundären Text ≥ WCAG AA auf der Ground-Farbe – check FAILT Builds bei Kontrast und gibt die konforme Farbe zur Verwendung aus.
  10. Absichtliche Überlappungen/Scroll-Unterschreitungen: markiere mit data-layout-allow-overflow/-overlap/-occlusion, anstatt Funde unerklärt zu lassen.

Szenen-Motiv-Ratschläge: Zeige den ERGEBNIS-Zustand – die verbesserte Welt des Betrachters (Vorher/Nachher-Kontrast, das verschwundene Problem, das Ergebnis auf dem Bildschirm). Ziehe unterstützende Einblicke aus der tatsächlichen UI/Domäne des Themas (gefälschte Suchpalette, Terminal, Baum, Tabelle) als Beleg für einen Nutzen, nicht als Mechanismus-Rundgang. Die Narrationsbögen sind Vorlagen; die Motive dürfen es nicht sein. $PROMO_VIDEO_SKILL_DIR/assets/composition-skeleton.html hat Platzhalter für "Hero"-Szene, "Pain"-Szene usw. – passe die data-start/data-duration in <section> an deine abgeleitete Zeitleiste an.

Verwandte Skills