When to use: Any time you want a value to change over the course of the video.
How: Read useCurrentFrame() inside a component, then derive styles/values from it with interpolate() (linear/eased mapping) or spring() (physics-based). Never use setState/timers/CSS animations for video content — everything must be a pure function of the frame, or a render at frame N won't match a render at frame N done in isolation (as happens during parallelized/distributed rendering).
Trade-offs: Pure frame-derived rendering is what makes Remotion's server-side and distributed rendering deterministic; anything stateful or time-based (Date.now(), setInterval) breaks that guarantee.
When to use: Structuring a video into a timeline of distinct scenes/clips.
How: One <Composition> per renderable video; inside it, wrap each scene in a <Sequence from={...} durationInFrames={...}> (or use <Series> for back-to-back sequences without manual offset math) so each scene's useCurrentFrame() is relative to its own start.
Trade-offs: Nesting sequences is normal and expected — a sub-component doesn't need to know its absolute position in the parent timeline.
When to use: When a video's duration, dimensions, or fps depend on external data (a fetched dataset, an uploaded file, a CMS entry) rather than being fixed at code time.
How: Pass a calculateMetadata callback to <Composition>; it can fetch data and return an updated durationInFrames/width/height/fps/defaultProps before rendering starts.
Trade-offs: This runs before the render begins (not per-frame), so it's the right place for one-time async setup, not frame-by-frame logic.
When to use: A component needs to wait on an async task (font load, remote data fetch, image dimension probe) before it's safe to capture a frame.
How: Call delayRender() to get a handle, do the async work, then call continueRender(handle). Has no effect in Studio/Player preview — only matters for actual rendering.
Trade-offs: Overusing this to gate large amounts of work slows down rendering, since Remotion waits per-component; prefer resolving data once via calculateMetadata when possible instead of delaying every instance.
When to use: Referencing any local file (image, audio, video, font, JSON) from inside a composition.
How: Put the file in the project's public/ folder and reference it via staticFile('/my-file.ext') instead of a relative import or hardcoded path — this resolves correctly both in Studio preview and in a rendered/bundled context.
Trade-offs: Files not in public/ and not loaded via staticFile() may work in dev but break once bundled for rendering.
When to use: Going from "renders fine locally" to "needs to render reliably in production."
How: renderMedia() (local/server, @remotion/renderer) for full control and self-hosting; Lambda (@remotion/lambda) for the fastest, most scalable managed option; Cloud Run (@remotion/cloudrun) as the GCP-native alternative when the team is already on Google Cloud.
Trade-offs: Lambda/Cloud Run trade infra control for scalability and cold-start behavior; self-hosted renderMedia() gives full control over the machine (codecs, GPU, caching) at the cost of managing that infra yourself.
When to use: Anything that behaves differently in Studio/Player than in an actual render (video frame extraction, delayRender, browser-only APIs).
How: Treat Studio and Player as approximations of the real thing — <OffthreadVideo> exists specifically because <Video>'s frame extraction isn't rendering-accurate; always do a real render (or at least renderStill) before trusting frame-exact output.
Trade-offs: Optimizing purely for a smooth Studio preview can hide bugs that only show up in the actual rendered output.
When to use: Deciding how end users interact with a Remotion video.
How: Use @remotion/player (<Player>) to let users scrub/watch a composition live inside a web app without rendering anything; use the renderer/Lambda/Cloud Run pipeline only when you need an actual output file (mp4, gif, still image, etc.).
Trade-offs: The Player re-runs the composition's React code in the browser at interactive framerate — it's not a substitute for verifying real rendered output.