← ClaudeAtlas

smooth-renderlisted

Render an HTML/CSS animation to a smooth, sharp MP4 at native resolution (up to 2K/4K) without choppy motion. Use when a CSS/JS animation (especially glassy/blur/backdrop-filter, gradient, or continuous-motion scenes) renders JANKY or stuttery via screenshot/screencast capture, when you need per-frame-accurate logical-time output with no wall-clock drift, or when muxing audio onto a rendered animation. Triggers: "render my animation to video", "the capture is choppy/stuttering", "export this HTML animation as MP4", "2K render of my web animation", "frames are dropping when I record the page".
JagZ999/explainer-video · ★ 1 · Web & Frontend · score 74
Install: claude install-skill JagZ999/explainer-video
# Smooth Render Capture an HTML/CSS animation to a crisp MP4 where motion is **buttery, not choppy** — even for the cases that normally stutter: `backdrop-filter`/blur, glassy cards, gradients, and always-on continuous animations. ## Why naive capture is choppy Chrome's CDP screencast (and most "screenshot every frame" loops) **coalesces** gradual changes — a smooth CSS transition emits far fewer frames than it should, and the result judders. Slowing the *output* fps doesn't fix the missing frames. ## The fix (two tricks, in `scripts/render.js`) 1. **Slow logical clock** — the page advances its own time `t` by `dt * window.__RATE` (e.g. RATE=0.7). Each logical second now spans more wall-clock time, so the screencast emits **more frames per logical second**. Every captured frame is tagged with the page's logical `t`, then remapped on the way out → exact timing, **no drift**. 2. **Heartbeat** — a 1px corner dot mutated every `requestAnimationFrame` so the screencast never sees a "still" region and keeps emitting at a uniform high rate. Output is per-frame JPEGs + `frames.json` (per-frame logical timestamps). `scripts/assemble.js` turns that into an ffmpeg concat list with **per-frame durations** (= logical-time diffs), so the final encode is perfectly timed regardless of capture jitter. ## Wiring your page (required) The page must expose globals `t` (logical seconds), `TOTAL`, `seek(t)`, `play()`, and in its rAF loop advance time by the rate: ```js function tick(now){ if(!