Skip to content
motion lab

05 Video in code

A video is a function of the frame number. Scrub it frame by frame.

Floor
05 of 09
Demos
Frame-accurate timeline

A video is a function

In a video editor you move clips and keyframes by hand. In code, a video is a function: frame number in, picture out. Frame 42 always looks the same, no matter what came before it or how fast your machine is.

That one property unlocks everything else on this floor. You can scrub to any frame instantly, render frames in parallel across many machines, change one line of copy and re-render without re-animating, and check a specific frame in review (“at frame 84 the logo overlaps the caption”).

Frame-accurate timeline

A three-second title sequence where every property is computed from the frame number. Drag the playhead, step one frame at a time, and watch the values change.

Frame
021 / 89
Timecode
00:00:00:21
Seconds
0.700
Frame
01530456075
BackgroundTitleAccent barSubtitleLogo
Values at frame 21
LayerPropertyValue
Backgroundopacity1.000
Titley0.0px
Titleopacity1.000
Accent barscaleX0.019
Accent baropacity1.000
Subtitley12.0px
Subtitleopacity0.000
Logoscale0.000

Red values changed since the previous frame.

Frame rate
Playback speed

Same three seconds, 90 frames. Changing the frame rate keeps the moment; only the frame number changes.

export const Title = () => {
  const frame = useCurrentFrame(); // 21
  const { fps } = useVideoConfig(); // 30

  const y = interpolate(frame, [6, 24], [40, 0], {
    easing: Easing.bezier(0.16, 1, 0.3, 1),
    extrapolateLeft: "clamp",
    extrapolateRight: "clamp",
  });
  // At frame 21: y = 0.0px, opacity = 1.00

  return <h1 style={{ transform: `translateY(${y}px)` }}>Motion, on brand.</h1>;
};

Frames, not seconds

Video runs at a fixed frame rate, so every timing decision eventually becomes a whole number of frames. At 30 fps a 0.6-second move is 18 frames; at 24 fps it is 14.4, which has to round to 14 or 15. Plan in seconds if you like, but review in frames, because that is what renders.

Remotion gives you the frame directly: useCurrentFrame() inside React components, with interpolate() and spring() to turn it into values. HyperFrames works from HTML: you write a paused GSAP timeline, and the renderer seeks it to each frame’s time. Different authoring styles, same deterministic model.

Rules of thumb

  • Never read the clock (Date.now(), timers) inside a composition. Everything derives from the frame.
  • Name keyframes by frame in reviews and briefs: “f18 title settled”, not “around half a second”.
  • Pick the frame rate first. Changing it later shifts every rounded keyframe.
  • Clamp interpolations so values hold steady before and after their range.
  • Step frame by frame through every transition before you render. Problems hide between frames.