PTENES
MODULE 1.1

🕐 The Time Engine

In Remotion, there is no "play." There is a question repeated very quickly: "what image to draw on frame N?". Understanding this mental shift is what unlocks all the other 80 templates.

6
Topics
40
Minutes
Basic
Level
Theory
Type
timeline (durationInFrames = 90 · 30fps = 3s) 0 1 2 3 … frame 42 your component draws frame 42 image one video frame Repeat for all 90 frames → the player combines everything into a 3-second video. No frame depends on the previous one — each calculates itself independently.
1

🕐 useCurrentFrame() — the clock

On a web page, you would use requestAnimationFrame or a setInterval and accumulate state. In Remotion, forget all that. You just ask: "what frame am I on right now?" — e useCurrentFrame() returns an integer that grows from 0 to the end of the video.

🎯 The central idea

The frame is the entrance and the image is the output. When the frame changes, everything is recalculated from scratch. This hook is the starting point for practically every template in the library.

  • •Returns a number: 0 at the beginning, then increases by 1 each time.
  • •The component is re-executed for every frame during rendering.
  • •You never “advance” time — Remotion does that for you.
Minimal component MyVideo.tsx
import { useCurrentFrame } from "remotion";

export const MyVideo = () => {
  const frame = useCurrentFrame();   // 0, 1, 2, 3 …
  return <div>Frame atual: {frame}</div>;
};

💡 Practical tip

Want to try it? Open Remotion Studio and drag the timeline. The number that appears is exactly what useCurrentFrame() returns. Seeing the number change as you drag makes the concept concrete.

Return
Integer ≥ 0
Reactivity
Recalculates per frame
No state
Doesn’t accumulate anything
Base of
interpolate, spring
2

⚙️ fps and durationInFrames — the measuring stick

The frame alone does not tell you how much time has passed. The one that sets the scale is the fps (frames per second). At 30fps, frame 30 is "1 second." The durationInFrames tells you how many frames the video has in total—it’s your time limit.

📊 Conversions you’ll use all the time

  • seconds × fps = frames — 2s at 30fps = 60 frames
  • frames ÷ fps = seconds — 90 frames at 30fps = 3s
  • 30fps — web/social standard, lightweight to render
  • 60fps — smoother, doubles render cost

✓ What to DO

  • ✓Set fps and duration in <Composition>.
  • ✓Derive timings from fps (fps * 1.5 for 1.5s).
  • ✓Think of the animation within the durationInFrames window.

✗ What NOT to do

  • ✗Fixing "frame 45" without remembering that it changes if the fps changes.
  • ✗Animate beyond durationInFrames (it disappears in the final render).
  • ✗Mix 30 and 60fps between scenes without converting.
fps
Frames per second
duration
Total in frames
Pattern
30fps
Rule
s × fps = frames
3

📐 useVideoConfig() — dimensions and fps

How do you get the fps inside the component without hardcoding it? And the width, to center something? The useVideoConfig() returns everything: width, height, fps e durationInFrames from the composition being rendered.

Format-responsive Centered.tsx
const { width, height, fps } = useVideoConfig();
const frame = useCurrentFrame();

// "1 segundo" funciona em 30 ou 60fps:
const apareceu = frame > fps;
// centralizar sem saber o tamanho exato:
const cx = width / 2;

💡 Why this matters

The same component can run in 16:9 (1920×1080) and 9:16 (1080×1920) without changing a line—if you read width/height from useVideoConfig() instead of hard-coding numbers. That’s how a template becomes reusable across YouTube and Reels.

width
Width in px
height
Height in px
fps
No hardcoding
Gain
Multiformat
4

🎯 The frame as the source of truth

Here’s the golden rule: the image of a frame depends ONLY on the frame number. No useState accumulating, no timers, no “how long has it been since I clicked.” Each frame is a pure function.

1

The render requests frames out of order

To render quickly, Remotion renders multiple frames in parallel — it may calculate frame 80 before 20. This only works because each one is independent.

2

Real-time state breaks this

A setInterval assumes time runs continuously. That doesn’t happen in rendering — each frame is an isolated calculation. That’s why the animation comes from the frame, not timers.

3

Everything derives from an input

Position, opacity, color, scale — they’re all frame functions. When the frame changes, everything is recalculated. This discipline is what keeps the video consistent.

Pure function
frame → pixels
No timers
No setInterval
Parallelizable
Fast rendering
Predictable
Always the same
5

🔁 Determinism — same frame, same image

Direct consequence of the previous rule: rendering frame 42 today, tomorrow, or on another machine produces exactly the same pixel. This is called determinism — and it has a clear enemy: unseeded randomness.

⚠️ Warning: what destroys determinism

  • ✗Math.random() — returns a different value on each calculation, making particles "blink".
  • ✗Date.now() / new Date() — changes with each run.
  • ✗Any external data that changes between renders.

✅ The solution: seeded random()

Remotion offers random("seed"): given the same seed, it always returns the same number. You get visual “randomness” without losing reproducibility.

import { random } from "remotion";
// mesma seed → mesmo valor, sempre:
const x = random("particula-7") * width;
Determinism
Always reproducible
Villain
unseeded random
Solution
random("seed")
Gain
Parallel rendering OK
6

⏱️ Think in frames, not seconds

The module’s final habit change: your unit of work becomes the frame. “The title comes in within half a second” becomes “the title comes in within 15 frames.” Seconds only appear at the system boundary—when a human types in a value.

✓ Frame mindset

  • ✓"Appears from frame 0 to 15" — straight in the API.
  • ✓Stagger: item N starts at frame N×5.
  • ✓Convert seconds only at the start: 0.5 * fps.

✗ Second mindset

  • ✗Calculate "0.5s" in the middle of the entire animation over and over.
  • ✗Mix seconds and frames in the same calculation.
  • ✗Forgetting that changing the fps rescales everything in seconds.

💡 Rule of thumb

At 30fps: 15 frames = 0.5s, 30 frames = 1s, 45 frames = 1.5s. Memorize these three and you can estimate any timing in your head.

Unit
The frame
Seconds
At the edge only
Conversion
× fps
Decorate
15 / 30 / 45

📌 Module summary

✓
useCurrentFrame() — the current frame number is the only time input that matters.
✓
fps and durationInFrames — convert seconds to frames and define the video window.
✓
useVideoConfig() — provides width/height/fps without hardcoding, making the template multi-format.
✓
Pure function and determinism — each frame calculates itself; use random("seed") for safe randomness.
✓
Think in frames — frame is the unit; seconds only at the boundary.

Next module:

1.2 — interpolate(): transform the frame number into opacity, position, and scale.