Velxio Promo-Video-Pipeline
Drei Phasen, alle in diesem Repository (velxio_docs; /home/dave/velxio_docs auf der Entwickler-Box):
- Aufnahme —
scripts/promo-record.mjssteuert das echte Produkt auf Staging End-to-End (leeres Projekt -> ESP32 auswählen -> 220R + LED hinzufügen -> Widerstand drehen -> per Pin-Klicken verdrahten -> Sketch schreiben -> Ausführen -> LED blinkt), mit einem eingeblendeten sichtbaren Cursor + Klick-Wellen. Jeder Schritt protokolliert{t, x, y, label}inscripts/promo-events.json; das Rohvideo landet inscripts/promo-raw.webm. - Beat-Gitter —
scripts/detect-beats.py(librosa) wandelt den Soundtrack inpromo/src/beats.jsonum (BPM, Beats, Kicks, Snares). - Postproduktion —
promo/ist ein Remotion-Projekt.prepare.mjskopiert die Aufnahme, trimmt den Pre-Modal-Boot, schneidet die Kompilier-Wartezeit heraus und gibtsrc/data.jsonaus.src/Promo.tsxrendert die Kamera (Zooms zentriert auf jedem Beat, jeder Punch wird auf den nächsten musikalischen Beat innerhalb von 0,34 s GESNAPPT), Untertitel-Bläschen, eine SOLIDE Intro-Karte, das velxio.dev-Outro und die Musikspur mit Ein- und Ausblendungen.
Befehle
cd /home/dave/velxio_docs
VELXIO_SHOTS_EMAIL='[email protected]' VELXIO_SHOTS_PASSWORD='<see memory vstaging-test-user>' \
node scripts/promo-record.mjs # Aufnahme (~2-4 Min. inkl. Kompilieren)
python3 scripts/detect-beats.py promo/public/soundtrack.mp3 --fps 30 \
--out promo/src/beats.json # nur, wenn sich der Track ändert
cd promo && node prepare.mjs
CHROME=$(ls -d $HOME/.cache/ms-playwright/chromium-*/chrome-linux*/chrome | sort | tail -1)
npx remotion render src/index.ts promo out/velxio-demo.mp4 --codec h264 --browser-executable "$CHROME"
Veröffentlichte Kopie für die GitHub-Ansicht: media/velxio-demo.mp4 (eingecheckt;
überschreiben + pushen, um dieselbe URL zu aktualisieren). promo/out/ ist gitignoriert.
Überprüfungsverfahren (NICHT überspringen)
Test-Frames ZU DEN BEAT-ZEITEN aus promo/src/data.json (ct-Feld) verwenden,
nicht zu erratenen Zeiten – Beats verschieben sich zwischen Aufnahmen:
ffmpeg -y -ss <ct> -i out/velxio-demo.mp4 -vframes 1 /tmp/beat.png
Prüfen: Intro lesbar, jeder Zoom zeigt sein Motiv vollständig, Untertitel passen zum Bildschirminhalt, Cursor verdeckt nichts Wichtiges, letzte LED leuchtet.
Galerie-Demovideos (einfacher Modus)
Ein kurzes Video pro Galerie-Beispiel – es öffnen, ausführen, funktionierend filmen – mit einer geteilten Intro-Karte (Logo + Titel + Board links, der gesamte Schaltkreis rechts), einem unteren Drittel, dem Outro und dem Soundtrack.
node scripts/gallery-scan.mjs # den 406-Beispiel-Index aktualisieren
node scripts/gallery-record.mjs [slug ...] # 1080p-Aufnahmen (bereits erstellte überspringen)
node scripts/gallery-bbox.mjs [slug ...] # messen, wo der Schaltkreis sitzt
node scripts/gallery-render.mjs [slug ...] # ein mp4 pro Aufnahme
- Das kuratierte Demo-Set befindet sich in
GALLERYam Anfang vongallery-record.mjs; Slugs stammen ausscripts/gallery-index.json(Thumbnail-Dateiname = Slug). - Standbilder werden mit
deviceScaleFactor: 2aufgenommen und auf den Schaltkreis-Beschnittbereich zugeschnitten: scharf genug, um die Hälfte eines 1080p-Frames zu füllen. Zoomen Sie die App NICHT, um einen kleinen Schaltkreis zu vergrößern – der Canvas-Anker zoomt auf seine Mitte und treibt den Schaltkreis aus dem Bild; setzen Sie stattdessen die Ansicht zurück. - Der Beschnittbereichs-Durchlauf benötigt einen FRISCHEN KONTEXT pro Beispiel: ein zweites clientseitiges Laden des Editors hinterlässt einen leeren Canvas und misst nichts.
- Beispiele ohne Board (Kategorien Digital / Analog) kompilieren nie: Ausführen bleibt deaktiviert und die SPICE-Engine treibt sie von Anfang an.
- Backend-QEMU-Boards (STM32, Raspberry Pi) geben keine „In-Browser“-Konsolenzeile aus. STM32 läuft zusätzlich überhaupt nicht auf Staging (libqemu-arm ist ein optionales Asset, das dort nicht bereitgestellt wird) – kompiliert in 3 s, startet nie.
- Rohaufnahmen (
promo/public/gallery/*.webm, ~3 MB pro Datei) sind gitignoriert; die Schaltkreis-Standbilder und die JSON pro Aufnahme werden eingecheckt, sodass ein erneutes Rendern nur die Aufnahmen benötigt.
Musik
promo/public/soundtrack.mp3 = Mixkit „House Vibez“ von Lily J
(assets.mixkit.co/music/745/745.mp3), Mixkit Stock Music Free License –
kostenlos für kommerzielle Nutzung, keine Namensnennung erforderlich. 123 BPM. Datei
austauschen und detect-beats.py erneut ausführen, um Tracks zu wechseln; den Lizenzhinweis in
promo/public/ATTRIBUTION.md aktuell halten.
Der Track beginnt mit ~8 s Intro: AUDIO_START in Promo.tsx ist der
erste erkannte Beat, sodass das Audio von dort startet und die Komposition
t=0 auf einem Downbeat landet. Die Lautstärke beträgt 0,55 mit einer 0,9 s Einblendung und einer
2,2 s Ausblendung über das Outro.
Style-Regeln (aus Davids Review – beibehalten)
- Das Video startet IM Editor mit dem bereits geöffneten Board-Template-Modal
und dem bereits minimierten AI-Chat. Keine Startseite, kein Laden, kein
sichtbarer Minimieren-Klick (der Recorder erledigt dies programmatisch vor dem Start;
prepare.mjs trimmt auf die
start-Markierung). - Intro-Titel auf einer SOLIDEN dunklen Karte – niemals durchscheinend über der UI.
- Zooms MÜSSEN ihr Motiv ZENTRIEREN: translate+scale mit Kantenbegrenzungen
(
Promo.tsx), niemals transformOrigin-at-Point (lässt das Motiv an einer Grenze zurück und schneidet es ab, z. B. die ESP32-Karte). - Add-Part-Beats verwenden eine KURZE Haltezeit (~0,5 s), damit der Zoom rechtzeitig loslässt, um ZU SEHEN, wo das Teil gelandet ist.
- Der Code-Beat zentriert den GESAMTEN Editor-Bereich (fx/fy überschreibt 357,280) – niemals einen beschnittenen Editor, während Code geschrieben wird.
- Nach dem Klicken auf Ausführen den Cursor WEGBEWEGEN (der Recorder bewegt sich auf 700,620), damit der Button-Spinner sichtbar ist; der Ausführen-Beat zoomt auf das Kompilieren/Ausführen-Cluster mit moderatem Maßstab (1,8).
- Den Widerstand nach dem Platzieren horizontal drehen (vertikale Standardausrichtung überlappt auf Kamera seine eigenen Drähte).
- Der Zeiger ist ein macOS-ähnlicher PFEIL, kein Punkt. Hotspot-Mathematik (aus dem saas-product-demo-Skill): die Spitze sitzt bei (4,3) in einem 24x24 viewBox, also ist das Element bei Render-Breite W um (-4W/24, -3W/24) versetzt – ohne das liest jeder Klick ~6-8 px vom Ziel entfernt.
- Zoom-Punches landen auf musikalischen Beats (siehe Musik oben); lassen Sie niemals einen Punch mehr als ~0,3 s von seinem Klick abweichen, nur um einen Beat zu treffen.
- Beats, deren MODAL BEIM KLICK SCHLIESST (choose-blank, add-*), benötigen
lead: 0,45: Die Spitze muss VOR dem Klick landen, damit der Frame die Karte noch offen zeigt, und das Loslassen zeigt dann, wo das Teil gelandet ist. Eine Spitze auf dem Klick selbst lässt den Zoom auf einem bereits geschlossenen Dialog parken.
Fallen (jede hat eine kaputte Aufnahme verursacht – alle werden in den Skripten behandelt)
/ist die Marketing-Landingpage, auch wenn eingeloggt; der Editor ist/editor. Vorher via fetch POST/api/auth/loginauf der Seite anmelden.- Auf einem frischen
/editoröffnet sich der „Start a new project“-Overlay automatisch (.new-project-overlay) und fängt alle externen Zeigerklicks ab. Zuerst damit interagieren oder programmatische Klicks auslösen. - Das Suchfeld des Picker BEHÄLT die vorherige Abfrage – mit Strg+A + Rücktaste löschen, bevor Sie tippen, sonst suchen Sie „esp32led“.
- Picker-Karten: genauen Titel gegen
.component-picker-modal .card-nameabgleichen (generische Text-Engines treffen auf Monaco-Token hinter dem Modal). Ergebnisse sind entprellt – bis zu 5 s abfragen. Kartennamen sind exakt („Resistor 220 Ω“ mit U+2126-ähnlichem Zeichen, nicht „Resistor“; in/components-metadata.jsonprüfen). - Boards werden NICHT von ihrem Körper gezogen – das Board dort lassen, wo der Picker es ablegt (nahe der rechten Kante des Canvas) und kleine Teile RELATIV zu seinem Live-BoundingBox LINKS davon platzieren, wo der Platz ist.
- Pin-Klicks: die eigenen
[data-pin-overlay="true"][title=<pin>]divs der App verwenden und den Kandidaten wählen, der dem Host-Element am nächsten ist (Titel kollidieren: Board-Pin „2“ vs. Widerstand-Pin „2“). Die Berechnung auspinInfo-Offsets bricht bei gedrehten Teilen. ESP32-Pins heißen '2','4','GND' (nicht D2). - Jede Drahtverbindung durch Zählen von
path[stroke="#1a1a1a"]verifizieren (jeder Draht-Umriss-Pfad; Drähte haben keine Klasse/Daten-Attribute). Einmal wiederholen via Escape + erneutes Klicken. - Der Schaltkreis-Verifizierer BLOCKIERT Ausführen für eine LED ohne Vorwiderstand (3.9e12 A-Fehler). Das Demo muss GPIO2 -> 220R -> LED A, GND -> LED C verdrahten. Niemals eine Aufnahme ausliefern, die „Trotzdem ausführen“ benötigt hat.
- Die Blank-Vorlage enthält einen Standardsketch – Strg+A vor dem Tippen des
On-Camera-Kommentars, dann den vollständigen Sketch via
monaco.editor.getModels()[0].setValue(...)setzen (buchstäbliches Tippen kämpft mit Monacos automatisch schließenden Klammern). - Der „Enjoying Velxio? / Star on GitHub“-Toast photobombt Aufnahmen länger als ~5 Min. – der eingefügte Cleaner entfernt ihn jede Sekunde.
- Playwright zeichnet keinen OS-Cursor auf: der eingefügte
#vx-cursordiv + Mousedown-Welle (context.addInitScript) ist der sichtbare Zeiger. - Die Kompilier-Wartezeit ist real (30 s warm - 5 min kalt): der Recorder protokolliert
runundsim-started; prepare.mjs schneidet diesen Bereich heraus. Der Sim-Start wird durch eine „In-Browser“-Konsolenzeile erkannt; „guest crashed“ = Abbruch. - Remotion rendert mit dem Playwright-Chromium via
--browser-executable(kein gebündelter Browser-Download auf dieser Box).
Referenz-Repositories (am 2026-08-15 untersucht)
Zwei Claude-Code-Skills für dasselbe Genre, anderer Ansatz: sie KOMPONIEREN Filme aus Screenshots/schematischen UIs mit einem synthetischen Cursor – unsere ZEICHNET das echte Produkt AUF. Klonen Sie sie zum Weiterentwickeln:
github.com/noamdorr/saas-product-demo-video– 20-45 s beat-synchrone Marketingfilme in Remotion. Stehlen: Soundtrack BEAT-SYNC (librosadetect-beats.py: Szenenschnitte auf Snares, Szeneninterne Ereignisse auf Kicks – unser Video ist stumm, das Hinzufügen von Musik + das Ausrichten der Zoom-Beats ist das größte verfügbare Upgrade), Cursor-Hotspot-Mathematik (SVG-Pfeilspitze ist bei 4,3 einer 24-Box – wichtig, wenn wir unseren Punkt-Cursor gegen einen Pfeil tauschen), Tipp-Budget-Prüfung, Iterations-Playbook.github.com/Vincentwei1021/video-shotcraft– 152 Shot-Rezeptkarten mit Demo-Quellen + Galerie (vincentwei1021.github.io/video-shotcraft), einer genehmigten Vorlage (Ink Press), 2.5D-Kamerabewegungen, Sounddesign und drei Betriebsmodi (Vorlage / autonom / gemeinsam erstellt). Stehlen: das direktionale Shot-Vokabular und seine endgültige Review-Checkliste; es installiert auch als Plugin, falls jemals ein voller Kinofilm gewünscht wird.
Verwandte
- Screenshot-Pipeline:
scripts/shots.mjs(gleiches Repo) – Szenen mit dem AI-Panel minimiert, außer wenn es das Motiv ist. - GIFs: ein Segment aufzeichnen (Playwright recordVideo) und mit
ffmpeg Zwei-Pass-Palette konvertieren; siehe
scripts/weather-media.mjsfür das Zoom+Zuschneide-Muster (Zuschneidebereich aus dem boundingBox des Elements). - Staging-Testbenutzer: memory
vstaging-test-user(s3-tester, pro). - Kaputtes Showcase-Projekt (Wetterstation) wird in
project/docs-portal-2026-08/STATUS.mdin velxio-prod verfolgt.