Teaser-Video
Produziere einen Launch-fähigen Teaser (~30-45 s) einer laufenden App: Erstelle ein Storyboard, filme ihn durch die Steuerung der echten UI, schneide ihn mit ffmpeg und gib ein MP4 plus ein GIF für die README zurück.
Das Ergebnis muss wie ein Produktvideo aussehen, nicht wie eine Bildschirmaufnahme. Der Unterschied liegt in der Regie – Inszenierung, Bildausschnitt und Rhythmus – nicht in der Auflösung.
Referenzimplementierungen befinden sich in reference/; sie sind funktionierende ESM-Module, kein Pseudocode. Richte sie in einem Scratch-Verzeichnis ein – niemals innerhalb des Projekts:
cp -r <skill>/reference/* "$SCRATCH/" && cd "$SCRATCH" && npm install
export TEASER_BASE_URL="https://the-app.example.com"
reference/package.json deklariert "type": "module" und die drei Abhängigkeiten. Jedes Skript liest TEASER_BASE_URL, sodass nichts auf eine App hartcodiert ist.
Vor allem anderen: die zwei harten Regeln
1. Niemals echte Nebenwirkungen auslösen ohne ausdrückliche, aufgelistete Zustimmung.
Das Filmen einer echten App bedeutet, echte Buttons zu klicken. Einige davon senden E-Mails, veröffentlichen öffentlich, kosten Geld oder senden Formulare an Dritte. Bevor du die App berührst:
- Liste jede Aktion in deinem Storyboard auf, die den Rechner verlässt.
- Teile dem Benutzer genau mit, was jede Aktion tut und wie oft, und hole dir Zustimmung zur Anzahl.
- Bevorzuge einen Modus, der vor dem irreversiblen Schritt stoppt (eine Vorschau, ein Trockenlauf, ein Bestätigungs-Gate, das du filmen und dann ablehnen kannst).
Es gibt keine schreibgeschützte Sonde gegen ein Live-System. Ein „diagnostischer“ Klick, der in einer bereits laufenden Session landet, feuert wirklich. Wenn du debuggen musst, warum eine Aktion nicht funktioniert hat, nimm an, dass dein nächster Klick funktionieren wird, und sei bereit dafür.
Wenn etwas auslöst, das du nicht beabsichtigt hast: Stoppe den Prozess sofort an seiner Quelle (beende die Session/Worker, nicht nur den UI-Button, der möglicherweise nicht wirkt), überprüfe den gestoppten Zustand durch Rücklesen und teile dem Benutzer klar in deiner abschließenden Nachricht mit – inklusive Anzahl.
2. Gehe davon aus, dass jeder Frame öffentlich und voller PII ist.
Echte Konten enthalten Namen, E-Mails, Adressen und Dokumente. Lege die Richtlinie vorher mit dem Benutzer fest:
- Rahme es ein (Standard) – komponiere Aufnahmen, die Identität ausschließen. Entferne persistente UI-Elemente (Seitenleisten, Avatare, Kontomenüs) im ffmpeg-Schritt.
- Verstecke vor der Aufnahme –
page.evaluate, umvisibility: hiddenauf störenden Karten zu setzen, bevor die Kamera läuft. Niemals filmen und hoffen, drumherum schneiden zu können. - Verwende ein gesätes Demo-Konto – am saubersten, wenn eines existiert.
Überprüfe jeden Frame des finalen Schnitts in voller Auflösung, bevor du ihn auslieferst. Nicht das Kontaktblatt – die Frames.
Arbeitsablauf
1. Erkunden und Storyboard
Mache zuerst authentifizierte Screenshots von jedem Kandidatenbildschirm (reference/scout.js). Sieh sie dir an. Schreibe dann eine Storyboard-Tabelle: Beat, Aufnahme, was der Betrachter fühlen soll, und Länge. Eine Aufnahme ohne zugewiesenen Job wird herausgeschnitten, bevor sie gefilmt wird.
Ein Bogen, der funktioniert: Spannung (das Problem) → Enthüllung (das Produkt) → Beweis (es macht wirklich das Ding) → Skalierung (die Ergebnisse) → Vertrauen (wo es läuft) → Abschluss.
Vermerke im Storyboard, welche Bildschirme PII enthalten und welche sicher sind.
2. Den Set vorbereiten
Kümmere dich vor der Aufnahme um die Gestaltung, niemals danach:
- Wähle Ansichten, in denen die Daten am besten aussehen – vollständige Diagramme, aktive Listen, erkennbare Namen, Werte ungleich Null. Niemals einen Spinner, einen leeren Zustand oder ein halb gerendertes Diagramm filmen.
- Setze den UI-Zustand bewusst (Panelbreiten, zugeklappt/aufgeklappt, Filter, Scrollposition) über
localStoragein einem Initialisierungsskript oder einempage.evaluatevor der Aufnahme. - Entferne Toasts, Banner und Cookie-Banner aus dem Sichtfeld.
- Lasse Daten zur Ruhe kommen:
networkidleplus ein paar Sekunden.
3. Filmen
Verwende CDP Screencast (Page.startScreencast), nicht Bildschirmaufnahme. Es erfasst die Seite außerhalb des Bildschirms mit ~100fps, sodass nichts, was der Benutzer tut, im Bild erscheint und der Rechner nutzbar bleibt. Playwright steuert; CDP filmt. reference/rig.js implementiert es.
- Ein Motiv pro Aufnahme. Rahme die Sache ein, nicht „die ganze App“.
- Kamerabewegungen erfolgen über skriptgesteuertes erleichtertes Scrollen innerhalb der Seite (
cameraScroll), niemals über einen Filter. Siehe die zoompan-Warnung unten. - Der Cursor ist ein Schauspieler: Verwende den injizierten SVG-Cursor (
cursorClick), der mit Erleichterung gleitet und beim Drücken eintaucht, oder verstecke ihn. Kein zielloses Treiben. - Probiere jede Einstellung aus, extrahiere Frames, sieh sie dir an, passe an, dann filme richtig.
Filmen eines externen Fensters (ein Browser, den die App selbst öffnet, eine Desktop-App) erfordert Betriebssystem-Erfassung – gdigrab/x11grab/avfoundation (recordDesktop im Rig). Dies erfasst alles auf dem Bildschirm, einschließlich der eigenen Arbeit des Benutzers. Warne den Benutzer, bitte ihn, zurückzutreten, und überprüfe das Ergebnis Frame für Frame; lösche es, wenn es etwas Privates eingefangen hat.
4. Titelcards
Animiertes HTML/CSS, das im Browser gefilmt wird, keine statischen Bilder. Injiziere das Card-Markup in eine leere Seite auf dem eigenen Ursprung der App, damit ihre Webschriftarten und Palette aufgelöst werden, und screencaste sie dann. Ziehe die tatsächliche Anzeigeschriftart von der Live-Seite (getComputedStyle) und pinne einen bekannt guten Mono-Stack an, anstatt einen zu ermitteln.
Passe an die Bewegungssprache der App an (ihre eigenen Easing-Kurven und Dauern). Lade das frontend-design-Skill, bevor du sie entwirfst, wenn das Projekt keinen etablierten Card-Stil hat.
5. Schneiden
reference/build.js normalisiert jedes Segment auf eine gemeinsame Größe/Bildrate und blendet dann die Kette über. Halte Schnitte alle ~2,5-4 s. Gib dem Höhepunktmoment Raum bei normaler Geschwindigkeit, während du das Routine drumherum komprimierst.
6. Überprüfen, dann ausliefern
- Erstelle ein Kontaktblatt und vollauflösende Frames pro Sekunde.
- Lese die Frames auf PII, abgeschnittene Paneele und unlesbaren Text.
- Überprüfe Dauer und Abmessungen mit einer Sonde.
- Liefere ein MP4 plus, für READMEs, ein palette-optimiertes GIF (GitHub wird ein committes MP4 nicht inline abspielen). Halte das GIF unter ~10 MB.
- Lasse es still, es sei denn, du wirst darum gebeten; du kannst keine Musik lizenzieren. Sage das.
Hart erkämpfte Details
Verwende niemals zoompan für Push-Ins. Es berechnet den Zoom pro Frame neu und rundet das Ausschneidefenster auf ganze Pixel, wodurch das Bild hin- und herschnappt – es wirkt wie ein Erdbeben. Verwende statische Aufnahmen plus echtes In-Page-Scrollen. Wenn du unbedingt ein Push-In brauchst, skaliere die Quelle zuerst 4x vor und überprüfe mit einer Frame-Delta-Messung (reference/jitter.js): Eine statische, festgestellte Aufnahme sollte einen mittleren Delta deutlich unter 1,0 messen; sichtbares Wackeln liegt bei 3+.
Screencast hört auf, Frames auszugeben, wenn die Animation zur Ruhe kommt. Eine Karte, deren Animation nach 1,2 s endet, ergibt einen 1,2 s Clip. Füge mit tpad=stop_mode=clone:stop_duration=N Polster hinzu und schneide auf die gewünschte Länge mit -t.
Baue Frames mit Zeitstempeln zusammen, nicht mit fester Rate. Screencast-Frames kommen mit metadata.timestamp an; schreibe eine ffmpeg-Concat-Liste mit den tatsächlichen Dauern pro Frame und taste dann auf konstante 60fps um. Eine Annahme eines festen Intervalls führt zu Ruckeln.
ffmpeg-static als Entwicklungsabhängigkeit, aufgelöst über den Modulpfad. Verlasse dich niemals darauf, dass ffmpeg im PATH ist. (ffprobe ist nicht in diesem Paket – parsiere stattdessen ffmpeg -i stderr.)
Authentifizierte Aufnahme: Melde dich einmal angemeldet an, speichere storageState, verwende es für jede Einstellung (reference/login.js). Sessions laufen ab – beende das Filmen am selben Tag oder führe es erneut aus. Säe dort auch alle localStorage UI-Präferenzen.
Localhost von einer bereitgestellten Ursprungsadresse aus wird blockiert durch Chromes Richtlinie zum lokalen Netzwerkzugriff. Wenn die Seite einen lokalen Dienst erreichen muss, starte mit --disable-features=LocalNetworkAccessChecks,PrivateNetworkAccessChecks,BlockInsecurePrivateNetworkRequests.
Beschneide persistente UI-Elemente mit einem festen Versatz. Filme mit Viewport-Breite 1920 + railWidth, dann crop=1920:1080:railWidth:0, um die Seitenleiste zu entfernen und genau auf 1080p zu landen.
Liefergegenstände
Berichte den Pfad, die Dauer und die Abmessungen; lege klar dar, was noch vom Benutzer benötigt wird (Musik, ein GitHub-natives Video-Upload); und lege alles offen, was während des Filmens passiert ist, das der Benutzer wissen sollte.