Communitygithub.com

lyonsv/demo-video-skill

Nehmen Sie mit Playwright und ffmpeg hochwertige, geskriptete Demovideos Ihrer Web-App auf (Produktdemos, Architektur-Animationen, Feature-Segmente) in einem einheitlichen 1440×900 MP4-Format mit Titel- und Endkarten, Beschriftungen und Klickrippeln.

Was ist demo-video-skill?

Dieses Skill ermöglicht es KI-Agenten, geskriptete, polierte Demovideos einer Webanwendung in einem konsistenten, hauseigenen Format aufzunehmen. Es steuert einen headless Chrome-Browser über Playwright und nutzt ffmpeg für die Videokodierung. Die resultierenden MP4-Dateien haben eine Auflösung von 1440×900 Pixeln, 30 fps, H.264-Codec, weiße Titel- und Endkarten, abgerundete, halbdurchsichtige Beschriftungen, violette Klickrippel und sichtbare Tastatureingaben. Wartezeiten werden auf etwa 2 Sekunden komprimiert. Das Skill ist als Tool für Claude Code, Cursor, Codex und andere KI-gesteuerte Entwicklungsumgebungen konzipiert. Der Workflow umfasst Storyboard-Erstellung, Ordnerstruktur im 'demos repo', Preflight der App, Schreiben des Aufnahmeskripts mit der demo-kit-Bibliothek, Aufnahme, Review und Auslieferung. Enthaltene Skripte (record.js, find-demos.js, review.js, concat.js, encode.js, record-scenes.js, demo-kit.js) automatisieren die gesamte Pipeline. Das Skill enthält vollständige Referenzbeispiele (Beispielskript in assets/, funktionierendes Beispiel in examples/sift/) und dokumentiert typische Fallstricke wie Speicherverbrauch und Portkonflikte.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/lyonsv/demo-video-skill/tree/HEAD

In Ihrer bevorzugten KI fragen

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

Dokumentation

Demovideos

Skriptbasierte Produktvorführungen, die von der laufenden Anwendung aufgezeichnet werden. Der Zuschauer sieht das Produkt bei der echten Arbeit; langsame Teile (Modellantworten, Jobs) werden vorgeschnellt, und jeder Abschnitt hat eine kurze Beschriftung, die sagt, worauf zu achten ist. Das gleiche Format wird jedes Mal verwendet, so dass Segmente zu einem Video zusammengefügt werden können.

Das hauseigene Format

Halten Sie diese Punkte exakt ein, damit neue Segmente zu früheren passen:

  • Video: 1440×900, 30fps, H.264 (libx264 -preset slow -crf 18), yuv420p, +faststart, kein Audio.
  • Titel- und Endkarten: vollständig weißer Bildschirm, zentriert: eine optionale kleine, graue Markenzeile in Großbuchstaben (setze brand in kit.start; standardmäßig keine), 46px fette Titelzeile, 20px graue Untertitelzeile. Halten für ca. 2,8s, dann ausblenden. Segmente beginnen mit einer Titelcard; das letzte Segment endet mit einer einzeiligen Takeaway-Karte (z.B. „Idee → Bewertung → Live-Test → Auslieferung“ / „Kein App-Deploy dazwischen“).
  • Beschriftungen: dunkle Tablette (rgba(17,17,17,.88)), weiße 17px halbfette Lato-Schrift, unten zentriert. Eine Idee pro Beschriftung, etwa 60 Zeichen oder weniger, Satzfall, kein abschließender Punkt, Präsens, aus Sicht des Betrachters geschrieben („Ergebnisse öffnen sich als Artefakt neben dem Chat“). Wechseln Sie die Beschriftung, wenn sich der Takt ändert; halten Sie jede für ca. 2,5–4s.
  • Klicks: ein violetter Ripple (rgba(122,71,255,…)) erscheint auf dem Ziel kurz vor jedem Klick.
  • Tippen: sichtbar, Taste für Taste (ca. 25ms pro Taste; 14ms für langen Text).
  • Wartezeiten: alles Langsame läuft innerhalb von ff(), das in etwa 2s abgespielt wird. Alles andere läuft in Echtzeit.
  • Architekturszenen: eine feste 1440×900 weiße Seite mit Szenen (Titel → Vorher → Problem hervorgehoben → Nachher → Metriken hochzählen → Feature-Liste), Lato, Tinte #111, violetter Akzent #6f43d6; „Vorher“-Tags grau, „Nachher“-Tags lila. assets/architecture-example.html ist die Referenz: Verwenden Sie dessen CSS und Struktur wieder und ändern Sie den Inhalt.

Wo Videos leben: das Demos-Repo

Jedes Video hat einen Ordner im Demos-Repo des Teams (standardmäßig ~/src/demos, oder $DEMOS_REPO), der seine Aufzeichnungsskripte und ein demo.json-Manifest enthält. Produkt-Repos bleiben frei von Demo-Code. Aufnahmen werden nie committet; das Manifest gibt mit output an, wohin die MP4-Datei geht.

~/src/demos/
  package.json            playwright-core + ffmpeg-static (einmal npm install)
  <video>/
    demo.json             Manifest
    architecture.html     „Szenen“-Segment (optional)
    record-<part>.js      „Walkthrough“-Segmente, geschrieben auf dem demo-kit
    .build/               MP4s und Frames pro Segment (gitignoriert)

Manifest (demo.json):

{
  "name": "<video-name>",
  "title": "Einzeiler: Was das Video zeigt",
  "description": "Für wen es ist und welche Aussage es trifft",
  "owner": "email",
  "repos": ["Repos, in denen die aufgezeichneten Funktionen leben, mit Branches"],
  "needs": [{ "what": "service", "check": "URL, die mit 2xx/3xx antwortet, wenn sie läuft", "start": "Wie man sie startet" }],
  "reset": "Wie man eine saubere Aufnahme bekommt und was die Aufnahme hinterlässt",
  "segments": [
    { "name": "architecture", "kind": "scenes", "page": "architecture.html", "timeline": "0:3000,1:4500" },
    { "name": "walkthrough", "kind": "walkthrough", "script": "record-walkthrough.js" },
    { "name": "intro", "kind": "video", "file": "~/pfad/zu/existing.mp4" }
  ],
  "output": "~/Downloads/<name>.mp4"
}

Das examples/sift/-Verzeichnis dieses Skills ist ein Referenzordner: ein Zwei-Segment-Video (eine Szenenseite und ein echter Walkthrough) einer kleinen Beispiel-App, die sich im selben Ordner befindet.

Wenn das Demos-Repo noch nicht geklont ist, erstellen Sie es (git init, das obige package.json, und eine .gitignore mit node_modules/, .build/, *.mp4, *.jpg, *.png, *-frames/ und *-timeline.json) und teilen Sie dem Benutzer mit, dass es noch kein Remote hat.

Tools (in scripts/, relativ zu diesem Skill)

SkriptFunktion
find-demos.jsnode find-demos.js [root…] [--json]: Listet jedes Video im Demos-Repo auf, mit Segmenten, Repos, Ausgabe und wann es zuletzt aufgenommen und committet wurde.
record.jsnode record.js <video-dir> [--only <segment>]: Überprüft needs, zeichnet jedes Segment auf und kodiert es in .build/, fügt sie zu output zusammen (das alte Video wird als *.previous.mp4 behalten). Führen Sie es vom Stammverzeichnis des Demos-Repo aus.
demo-kit.jsBibliothek für Walkthrough-Skripte: kit.start() liefert page, title/untitle, caption, tap, type, ff, scroll/scrollTop, ripple, navigate, startCast, finish. Frames werden auf die Festplatte gestreamt.
encode.jsnode encode.js <frames-dir> <timeline.json> <out.mp4>: Erstellt die MP4-Datei und komprimiert ff()-Fenster.
record-scenes.jsnode record-scenes.js <page.html> <out.mp4> "0:3000,1:4500,…": Zeichnet eine Szenenseite auf, die window.step(n) definiert.
concat.jsnode concat.js <out.mp4> <a.mp4> <b.mp4> …: Fügt Segmente zusammen, kodiert sie erneut in das hauseigene Format.
review.jsnode review.js <video.mp4> <out-dir> [stills] [at=s,s,…]: 2×2 Kontaktabzüge von Standbildern zum Rücklesen.

assets/example-walkthrough.js ist ein vollständiges, ausgearbeitetes Beispiel auf dem Kit (und examples/sift/record-walkthrough.js ist ein echtes). Lesen Sie es, bevor Sie einen neuen Walkthrough schreiben; es zeigt die Struktur, einschließlich des Wechselns zwischen Apps während des Videos, vorschneller Jobs und einer Endkarte.

Workflow

0. Finden, was bereits existiert

Führen Sie zuerst find-demos.js aus. Wenn der Benutzer ein Video neu aufnehmen oder erweitern möchte, das bereits einen Ordner hat, arbeiten Sie in diesem Ordner: Nehmen Sie es mit record.js <folder> (oder --only <segment> nach einer UI-Änderung) neu auf oder fügen Sie dem Manifest ein Segment hinzu. Legen Sie keinen zweiten Ordner für dasselbe Video an. Erstellen Sie einen neuen Ordner nur für ein wirklich neues Video, benannt nach diesem (kebab-case).

1. Zuerst ein Storyboard

Bevor Sie Code schreiben, schreiben Sie das Storyboard als nummerierte Liste von Abschnitten, jeweils mit ihren Takten: was auf dem Bildschirm passiert und die Beschriftung. Entscheiden Sie vorab:

  • Was muss echt sein und was kann simuliert werden. Bevorzugen Sie Echt (echte Modellaufrufe, echte Suchen). Wenn Daten simuliert werden müssen (z.B. Wochen von Live-Traffic), sagen Sie das auf dem Bildschirm, sowohl in einer Beschriftung als auch in der App selbst, wenn dies gekennzeichnet werden kann. Zuschauer nehmen eine Demo für bare Münze, daher ist ein simuliertes, als echt präsentiertes Ergebnis irreführend.
  • Worauf darf nicht geklickt werden. Alles, was in gemeinsame Umgebungen schreibt (Boards speichern, E-Mails senden, Käufe). Zeigen Sie die Schaltfläche; drücken Sie sie nicht.
  • Länge: etwa 60–90s pro Segment. Ein 3-minütiges zusammengefügtes Video ist in Ordnung; jedes Segment sollte einen Punkt machen.

Wenn das Ziel des Benutzers aus dem Gespräch klar hervorgeht, teilen Sie das Storyboard in Ihrem Update während der Arbeit mit. Fragen Sie nur, wenn der Zweck des Videos unklar ist.

2. Ordner für das Video einrichten

Erstellen Sie <demos repo>/<video>/ mit einer demo.json (füllen Sie needs mit einer check-URL für jeden Dienst, den das Video berührt, und notieren Sie reset). Führen Sie npm install im Stammverzeichnis des Demos-Repo aus, wenn node_modules fehlt. Das Kit und die Skripte lösen playwright-core und ffmpeg-static aus dem Arbeitsverzeichnis auf, führen Sie also alles vom Repo-Stammverzeichnis aus. Chrome muss installiert sein (channel: 'chrome'; kein Playwright-Browser-Download ist erforderlich).

3. Preflight der App

  • Bestätigen Sie, dass jeder Dienst, den das Video berührt, läuft (curl jede URL), und dass lokales HTTPS funktioniert (das Kit ignoriert selbstsignierte Zertifikate).
  • Setzen Sie den Zustand zurück, damit die Aufnahme sauber beginnt (frische DB, geleertes localStorage), und lassen Sie das Skript sofort abbrechen, wenn der Zustand schmutzig ist. Eine Aufnahme, die nach 3 Minuten fehlschlägt, kostet echte Modellaufrufe und Zeit.
  • Messen Sie die langsamen Endpunkte, die das Video abfragt. Eine 4-Sekunden-Ergebnisabfrage zeigt als Lade-Skeleton auf Kamera; beheben Sie die Abfrage oder warten Sie darauf.
  • Machen Sie einen Screenshot von jedem Schlüsselzustand mit einem kleinen Playwright-Skript und sehen Sie es sich an: Layout, Umbruch, kaputte Bilder, was über dem Fold bei 1440×900 sichtbar ist. Das ist günstiger als eine Aufnahme.

4. Das Aufnahmeskript schreiben

Kopieren Sie die Struktur von assets/example-walkthrough.js:

const kit = require(process.env.DEMO_KIT || `${process.env.HOME}/.claude/skills/demo-video/scripts/demo-kit`);
const demo = await kit.start();                             // record.js liefert die Frame- und Timeline-Pfade
await demo.page.goto(URL, { waitUntil: 'networkidle' });
await demo.title('Feature-Name', 'Was es den Leuten ermöglicht');
await demo.startCast();                                     // Start nachdem der Titel die Seite bedeckt
await demo.sleep(2800); await demo.untitle(); await demo.sleep(900);
await demo.caption('…'); await demo.tap(locator); await demo.type(locator, 'text');
await demo.ff(() => page.waitForFunction(() => /* Antwort beendet */ true, null, { timeout: 180000 }));
await demo.finish();
  • Verwenden Sie stabile Selektoren (aria-label, IDs, data-*) und überprüfen Sie sie am echten DOM.
  • Warten Sie innerhalb von ff() auf echte Abschlussbedingungen, nicht auf feste Schlafzeiten, mit großzügigen Timeouts.
  • Wenn eine Beschriftung über etwas spricht, scrollen Sie es zuerst auf den Bildschirm (demo.scroll(px, 'main') für Apps, deren Inhalt innerhalb eines Elements scrollt).
  • demo.navigate(url) wechselt Seiten oder Apps; es startet die Bildschirmübertragung auf der neuen Seite neu.
  • Erstellen Sie für ein Architektursegment die Szenenseite aus dem Beispiel und nehmen Sie sie mit record-scenes.js auf. Geben Sie ihr auch eine Navigation mit Pfeiltasten und Leertaste (das Beispiel hat sie), damit dieselbe Seite auch bei einer Live-Präsentation funktioniert.

5. Aufnahme

Führen Sie vom Stammverzeichnis des Demos-Repo das gesamte Video (oder ein Segment) im Vordergrund mit einem langen Timeout aus und protokollieren Sie die Ausgabe:

set -o pipefail; node ~/.claude/skills/demo-video/scripts/record.js <video> [--only <segment>] 2>&1 | tee <video>/.build/record.log

Nicht in tail pipen: Es versteckt den Exit-Code des Recorders, und eine fehlgeschlagene Aufnahme sieht wie ein Erfolg aus. Wenn Sie es im Hintergrund ausführen müssen, warten Sie auf die tatsächliche PID (while kill -0 $PID; do sleep 5; done), anstatt auf eine „abgeschlossen“-Benachrichtigung zu vertrauen, die vor dem Ende des Prozesses eintreffen kann.

6. Review

record.js hat bereits alles kodiert und zusammengefügt; es gibt den Review-Befehl aus:

node ~/.claude/skills/demo-video/scripts/review.js <output.mp4> <video>/.build/review 16

Um ein Segment zu betrachten, reviewen Sie <video>/.build/<segment>.mp4.

Lesen Sie jeden Kontaktabzug, bevor Sie das Video als fertig bezeichnen. Überprüfen Sie, dass:

  • jede Beschriftung mit dem übereinstimmt, was zu diesem Zeitpunkt auf dem Bildschirm ist;
  • das, worauf sich eine Beschriftung bezieht, sichtbar ist, nicht unter dem Fold;
  • es keine kaputten Bilder oder Alt-Texte, feststeckende Skelette, Fehler-Toasts, umbrochene oder abgeschnittene Header oder Debug-UI gibt;
  • vorschnelle Wartezeiten wie ein schnelles Verschwimmen des Fortschritts aussehen, nicht wie ein eingefrorener Frame;
  • Titel- und Endkarten vorhanden sind.

Beheben Sie das Skript oder die App (z.B. einen Platzhalter für Bilder, die nicht geladen werden können, eine schnellere Abfrage), setzen Sie den Zustand zurück und nehmen Sie erneut auf. Rechnen Sie mit zwei oder drei Aufnahmen.

7. Auslieferung

  • Überprüfen Sie die Verbindungspunkte: review.js <output> <dir> 0 at=<t-1>,<t+1> an jeder Segmentgrenze.
  • record.js behält die vorherige Version als *.previous.mp4. Überschreiben Sie niemals Videos, die nicht das eigene output dieses Ordners sind: Um zu einem Video eines anderen hinzuzufügen, fügen Sie es als video-Segment eines neuen Ordners hinzu.
  • Teilen Sie dem Benutzer mit, dass der Videoordner bereit ist, im Demos-Repo committed zu werden. Committen Sie nur, wenn er darum bittet.
  • Berichten Sie dem Benutzer: die Dateipfade und -dauern, was jedes Segment zeigt, was echt und was simuliert war, und alle Zustände, die die Aufnahme hinterlassen hat (laufende Dienste, erstellte Datensätze, alles, was noch eingeschaltet ist) mit Anleitung, wie es rückgängig gemacht werden kann.

Bekannte Fallstricke

  • Speicher: Eine CDP-Bildschirmübertragung sendet bis zu 60 Frames pro Sekunde, während etwas animiert wird. Das Puffern von Frames im Speicher für eine mehrminütige Aufnahme führt dazu, dass der Recorder ohne Ausgabe beendet wird. Das Kit streamt Frames auf die Festplatte und verdünnt sie während ff(); behalten Sie es so bei.
  • Uhr: ff()-Fenster und Frame-Zeitstempel verwenden beide Wanduhr-Sekunden, also messen Sie die gesamte Wartezeit (einschließlich Polling) innerhalb eines ff()-Aufrufs.
  • Blockierende Arbeit (z.B. execFileSync für ein Datenskript) innerhalb von ff() ist in Ordnung: Die Frames werden danach fortgesetzt und das Fenster wird trotzdem komprimiert.
  • Ports: Überprüfen Sie, ob ein Port frei ist, bevor Sie einen Dienst für die Demo starten; beenden Sie keine Prozesse, die Sie nicht gestartet haben.
  • Zurückgelassener Zustand: Eine Demo, die mit dem Ausliefern oder Aktivieren von etwas endet, lässt es eingeschaltet. Schalten Sie es danach aus oder informieren Sie den Benutzer.

Verwandte Skills