
HTML To Video Pipeline
Reliable HTML-to-MP4 rendering via headless browser recording (Playwright/Puppeteer) +...
Install
npx skills add XiaomiMiMo/MiMo-Code --skill html-to-video-pipeline -g -a claude-code -y- Repository
- XiaomiMiMo/MiMo-Code13.7k
- Category
- Design
- Updated
- 3d ago
- License
- MIT
- Context cost
- Mediumabout 3,000 tokens
- Runs scripts
- No, instructions only
What it does
Reliable HTML-to-MP4 rendering via headless browser recording (Playwright/Puppeteer) + ffmpeg, the ordering, gotchas, and verification steps you MUST get right or the output silently rots. Trigger whenever the user is building or debugging any pipeline that turns an HTML/CSS/JS page (single-file, multi-composition, GSAP-driven, or `@keyframes`-driven) into a video file, including headless recording, screen capture of a web page, deterministic frame-by-frame capture, multi-scene concatenation, or engine-mixed video output. Also trigger when the symptom sounds like: font swap flashing in the opening frames (FOUT), the first few seconds of the video are frozen/dead, animations play during page load and get truncated, concatenated segments produce a video whose duration is wildly wrong (e.g., 8s becomes 35s), `file://` loaded HTML fails to fetch its sub-scenes, the exported video is soft/blurry compared to the browser, or playback stutters/looks choppy despite passing a high `-r` fps to ffmpeg. Use even for one-off scripts, the failure modes here are subtle enough that starting from scratch usually reintroduces them.
HTML → Video: the pipeline that actually works
Turning a live HTML page into an MP4 sounds like a one-liner ("Playwright records, ffmpeg encodes") and the first draft always looks fine, until you play back the export and notice text flashing in a fallback font, three dead seconds at the start, or a "10-second" clip that clocks in at 35s. This skill captures the specific ordering, waits, and encoder flags that make the output trustworthy.
Think of the pipeline as five phases with a single invariant between them:
launch → hold @ frame 0 → align capture start with animation start → record → trim & encode
The invariant: no pixel of the animation should render before capture is ready, AND capture must not start before every asset that affects layout has loaded. Every gotcha below is a violation of that invariant.
Quick checklist (each item is expanded below):
viewportmust exactly equalrecordVideo.size, mismatch silently rescales the output soft/blurry.- Freeze CSS animations via
addInitScriptbeforegoto(). gotowithdomcontentloaded, neverload.- Pre-inline
data-composition-srcsub-scenes,file://blocks client-sidefetch. - Font wait = stylesheet
<link>load →face.load()per face →fonts.ready→ 2 rAFs. - Probe duration with infinite-iteration /
repeat: -1guards. - Unfreeze = t=0; trim
leadInMs − 120mswith-ssbefore-i. - Concat: same engine → demuxer
-c copy; mixed engines → concat filter + re-encode. - Verify with ffprobe duration + full decode + sampled frames. Always.
There are two capture modes, and picking the wrong one wastes a day:


