Vanilla JavaScript · HTML/CSS

HTML Reel

The hook of a talking-head reel, drawn in HTML from one clock. Every frame is draw(t), with t the scratch voice's seconds, so each word rises on its word and the zoom lands on “in.” When the real take comes in, the same scene re-renders at t = W(τ), straight lines between the words both takes share, and follows the creator's delivery frame for frame. Animate it with CSS timelines or timers and it can't follow: every new take means animating it again, and stretching the render to fit judders.

Timed to
Scratch voice · t 0.00 s
Your take · τ 0.00 s
Lines join each word the takes share (“but” has none). Orange: the playhead, t = W(τ). Dashes: the end.

How it was made

  1. A scratch voice read the script (ElevenLabs). Its word times are the constants at the top of the scene, and the scene is animated to them.
  2. One draw(t) sets every part from t: each word through its mask, the camera, the window's layers, the tags and the light. HTMLReel.scene({ dur: 8.6, draw }) puts it on window.__frame.
  3. The creator recorded the lines. Their words were matched to the scratch's: 23 anchors, [τ, t]. anchors turns them into W, straight lines between them, and the hook plays 7.77 s instead of 8.6 s.
  4. The renderer opens ?frame (or ?frame&take), calls __frame(τ) once a frame at 540 × 960 and screenshots; __bounds() keeps the data-safe titles inside the 3:4 safe area.
  5. No video, canvas or WebGL: the window is HTML, so the 4.4× zoom is drawn at that size, not enlarged.