wikis / Remotion / wiki / concepts / animation.md view as markdown
Animation: Frames, Interpolation & Springs
Definition
Animation in Remotion is a pure function of the frame number: useCurrentFrame() gives the current frame, and you derive every animated property from it. Two helpers do most of the work — interpolate() maps a value range to an output range (with easing and clamping), and spring() runs a physics simulation from 0 to 1. Because frames render concurrently across multiple headless browser tabs, anything time- or randomness-dependent must be deterministic per frame.
How It Works
The frame-driven model
A fade-in is just math on the frame: const opacity = Math.min(1, frame / 60);. The cardinal rule: always animate using useCurrentFrame() — CSS transitions and other wall-clock animations cause flickering during rendering because frames are captured out of order.
interpolate(input, inputRange, outputRange, options?)
const opacity = interpolate(frame, [0, 60], [0, 1], {
extrapolateRight: "clamp",
});
- Multiple keyframes:
interpolate(frame, [0, 20, durationInFrames - 20, durationInFrames], [0, 1, 1, 0])fades in and out (durationInFramesfromuseVideoConfig()). - Any driver, not just time: feed a spring into it —
interpolate(driver, [0, 1], [0, 200])maps a 0→1 spring to 0→200px. - Extrapolation:
extrapolateLeft/extrapolateRightacceptextend(default),clamp,wrap,identity. E.g.interpolate(1.5, [0, 1], [0, 2], {extrapolateRight: 'clamp'}) // 2. - Easing:
easing: Easing.bezier(0.8, 0.22, 0.96, 0.65)curves the progress within the active segment; from v4.0.462 pass an array with one easing per segment, e.g.[Easing.out(Easing.cubic), Easing.in(Easing.cubic)]for a 3-keyframe range (length must beinputRange.length - 1). - Posterize (v4.0.470+):
posterize: 3quantizes the input so frames 0–2 share frame 0's value — a stop-motion/sampled look. - CSS transform strings (v4.0.472+): output ranges may be
scale,translate,rotate, ortransformOriginstrings, e.g.translate: interpolate(frame, [0, 30], ['0px 0px', '100px 50px']). Units must match per component. - Numeric tuples (v4.0.473+): output range entries can be same-length number tuples.
- Input and output ranges must have equal length; single-value ranges work from v4.0.469.
spring() and measureSpring()
const value = spring({
frame,
fps,
config: {
stiffness: 100,
},
});
Animates from: 0 to to: 1 by default; pass fps from useVideoConfig(). Config knobs: mass (default 1, lower = faster), damping (default 10, higher = less bounce), stiffness (default 100, bounciness), overshootClamping (default false, caps at to). Timing knobs: durationInFrames stretches the curve to an exact length, delay holds the initial value for n frames, reverse plays backwards. Order of operations: stretch → reverse → delay. Delay can also be done manually via frame - 20 as the frame argument.
measureSpring({fps, config}) returns how many frames a spring needs to settle (e.g. measureSpring({fps: 30, config: {damping: 200}}) // => 23); threshold (default 0.005) defines "settled" — lower threshold, longer measured duration. Use it to size sequences around a spring.
Animation math
Spring values are plain numbers, so combine them arithmetically. The enter/exit idiom:
const enter = spring({fps, frame, config: {damping: 200}});
const exit = spring({fps, frame, config: {damping: 200}, durationInFrames: 20, delay: durationInFrames - 20});
const scale = enter - exit;
enter rises 0→1 at the start; exit rises 0→1 in the last 20 frames; their difference scales the element in and back out with one expression.
Colors: interpolateColors()
interpolateColors(frame, [0, 20], ['red', 'yellow']) returns an rgba() string (e.g. rgba(255, 128, 0, 1)). Accepts hex, rgb/rgba, hsl/hsla, CSS color names, and (v4.0.439+) oklch, oklab, lab, lch, hwb with optional / alpha. Options: easing (v4.0.475+, single function or per-segment array) and posterize (v4.0.470+).
Noise and deterministic randomness
@remotion/noiseprovidesnoise3D(seed, x, y, z)— use two dimensions for space and the third for time (frame * speed) to get organic motion like a floating dot grid; map its[-1, 1]output withinterpolate().random(seed)fromremotionreturns a deterministic pseudorandom number in[0, 1)for anumberorstringseed:random(1) // 0.07301638228818774, always. Seed per element (random(random-x-${i})) for stable particle layouts.Math.random()triggers an ESLint warning because each render thread would see different values; if you truly want non-determinism,random(null)bypasses the warning.
Key Parameters
interpolate()options:extrapolateLeft,extrapolateRight,easing,posterize. TypesExtrapolateTypeandInterpolateOptionsexported since v3.3.77.spring()args:frame,fps,from,to,reverse,delay,durationInFrames,durationRestThreshold,config: {mass, damping, stiffness, overshootClamping}.measureSpring()args:fps,threshold,config,from,to.random()arg:number | string | null.
When To Use
- Linear/keyframed property changes →
interpolate()withclamp. - Natural, bouncy entrances and scale pops →
spring(); flatten the bounce withdamping: 200. - Combined enter/exit on one element → animation math (
enter - exit). - Animated color shifts →
interpolateColors(). - Organic wobble, particles, generative art →
@remotion/noise+random(seed).
Risks & Pitfalls
- CSS transitions/animations flicker in renders — never animate outside
useCurrentFrame(). - Forgetting
extrapolateRight: 'clamp'lets values run past the output range (scale 2 at frame 40 for a[0, 20] → [0, 1]mapping). Math.random()differs per render thread — userandom(seed).- Springs overshoot by design — values can exceed
tobriefly; useovershootClamping: trueif that breaks layout. - Hardcoding spring length — a spring's natural settle time depends on config and fps; measure with
measureSpring()instead of guessing. - Per-segment easing array of wrong length errors — must be
inputRange.length - 1.
Related Concepts
- compositions fundamentals —
<Sequence>shifts the frame that drives these helpers - transitions — packaged scene-to-scene animations
- audio — driving animation from audio data
- performance recipes — keeping per-frame work cheap
Sources
- raw/github_doc-packages-docs-docs-animating-properties-mdx.md — frame-driven model, flickering warning
- raw/github_doc-packages-docs-docs-interpolate-mdx.md —
interpolate()full API incl. easing, posterize, CSS transforms - raw/github_doc-packages-docs-docs-spring-mdx.md / -measure-spring-mdx.md — spring API and measurement
- raw/github_doc-packages-docs-docs-animation-math-mdx.md — enter/exit composition
- raw/github_doc-packages-docs-docs-interpolate-colors-mdx.md — color interpolation
- raw/github_doc-packages-docs-docs-noise-visualization-mdx.md —
noise3D()technique - raw/github_doc-packages-docs-docs-random-mdx.md — deterministic randomness
