A reel is one HTML file (template/reel.html). render(t) draws the frame for time t. Nothing moves
by itself (no CSS transitions), so every frame is exact. template/render.cjs captures the frames with
Playwright and pipes them to ffmpeg together with the music.
What the user likes (keep these unless told otherwise)
- Length: 30 s for an ad (the usual ad length). Do not stretch scenes to fill time. Add a new scene instead.
- Pace: calm and readable, about 87 BPM (one beat about 0.69 s). One idea per scene. Fast cuts only on real music hits.
- Density: many elements where it helps (for example about 120 letters in the intro rain, not 40).
- No showreel HUD: no corner marks, no corner texts, no timecode. Keep only the thin progress bar.
- Layout must fit: labels and pills get the width their text needs (measure with
getComputedTextLength). Lines and arrows never cross illustrations; put them in the gaps. - Brand (InboxMate): emerald
#10b981, ink#0b1410, paper#f6f7f3with a dot grid, SF Pro Display 900 for headlines, Newsreader italic in emerald for the accent word, hand-drawn spot illustrations frompsquared-websites/apps/inboxmate/media/illu/. Short white flash on each cut. - German copy in "Sie", short, no dashes in headlines.
- Ending: logo lockup, then QR code with the logo inside, "Termin buchen" and the URL.
- Always two formats: landscape 1920x1080 and vertical 1080x1920 (
?v=1), 60 fps.
Claims: check before you render
Every product or legal claim in the video must match the website, the privacy policy and the code. Known state (InboxMate, 09/2026):
- OK: "Daten in Frankfurt" (database and storage), "Standard: EU-KI-Modelle" (switch on by default for new accounts), "Auftragsverarbeitungsvertrag (AVV)", "Für DSGVO-konformen Einsatz gebaut".
- Not OK: "Verarbeitung in der EU" as an absolute (US route exists when the switch is off; web research uses a US service), "AI-Act-konform" or any certificate (not verified), "garantiert DSGVO-konform".
- Prices, customer names, partners (Doppler, neverlost) never appear. When unsure, drop the claim or ask the user.
Workflow
- Storyboard on a beat grid. Plan scenes in beats (see the table in
template/reel.html,scenesarray). The template runs at 128 BPM "music time" and is slowed bySLOWto the real tempo. For 87 BPM:SLOW=(60/87)/(60/128),DUR=30/SLOW. - Copy the template to a work folder in the scratchpad:
reel.html,render.cjs,Newsreader-Italic.ttf, the spot images the scenes use. - Music (ElevenLabs, paid plan):
/usr/bin/python3 scripts/elevenlabs_music.py cand 2 87 30(keyELEVENLABS_API_KEYfrompsquared-skills/.env). Measure each candidate:python3 scripts/analyse_music.py cand1.mp3 84 90. Facts learned: the API ignores section timing and length (returns ~31 s), but the tempo is exact. Composition-plan sections must be >= 3000 ms and were followed less than a timestamp prompt. So pick the track with the best groove and a natural ending, then cut it to the grid withscripts/edit_music.py(plan.json: pieces on bar starts, a reverse-swell break, the natural ending at the logo/QR part). Repeat one bar instead of time-stretching. If no API:compose_fallback.pysynthesizes a clean track on the exact grid. - QR code:
scripts/make_qr.sh https://inboxmate.at <workdir>writesqr.json; paste the matrix into theQR=line. Error correction H, logo covers the centre 7x7 modules only. - Preview before the full render:
node render.cjs preview 1.9,6.6,10.7,...(andVERT=1 node render.cjs preview …). Build one contact sheet with ffmpegtile, look at it once, fix everything in one pass. - Render:
node render.cjs video 60andVERT=1 node render.cjs video 60(set the music file, frame countNand output names inrender.cjs). Playwright comes fromagenthub/node_modules/playwright. - Verify: ffprobe length and size, a contact sheet of the final file, and decode the QR code from
a late frame with OpenCV (
cv2.QRCodeDetector). Copy the results to~/Desktop/.
Report
Say what changed per scene, the music source and how it was cut, which claims you checked, and where the files are. Mention that timing of music cuts was checked by measurement, not by ear.