Remotion Best Practices
Build Remotion output as a deterministic function of the frame, input props, and declared assets. Preserve user edits and the project's existing package manager, architecture, and style unless the task requires a change.
Start with evidence
- Read repository instructions and inspect
package.json, the lockfile, Remotion config, entry point, registered compositions, and nearby tests. - On an existing project, run
node <skill-directory>/scripts/audit-remotion-project.mjs <project-root>. Treat its output as evidence, not permission to upgrade. - Record the installed Remotion version before choosing APIs. Keep all
remotionand@remotion/*packages on the same exact version. Do not add a second lockfile. - Identify whether the deliverable is a video, a single still, a frame sampled from a video, or a batch of store screenshots.
- Define composition ID, dimensions, FPS, duration, props, output path, and required assets before implementation.
Load only the relevant reference
- For
<Composition>,<Still>,useCurrentFrame(),interpolate(),spring(),<Sequence>, or<Series>, read composition-and-timing.md. - For
staticFile(), media, fonts, network data,useDelayRender(),delayRender(), orcalculateMetadata(), read assets-and-async.md. - For CLI,
renderStill(), server-side rendering, or Remotion Lambda, read rendering-and-lambda.md. - For slow renders, high memory use, nondeterminism, or verification strategy, read performance-and-testing.md.
- For App Store or Google Play images, including 1284×2778 output delegated by
screenshot-studio, read store-stills.md. - When an API or platform rule may have changed, consult the live primary source linked in sources.md before coding.
Non-negotiable implementation rules
- Derive time from
useCurrentFrame()anduseVideoConfig(). Do not use CSS transitions, CSS keyframe animations, wall-clock timers, or unseeded randomness for rendered motion. - Clamp finite animations unless extrapolation is intentional. Express timings in seconds multiplied by
fpswhen they represent time, and centralize shared scene durations. - Remember that
useCurrentFrame()is relative inside a timed component. Pass an absolute frame from the composition root only when global synchronization is intentional. - Use
<Sequence>for explicit placement on the parent timeline and<Series>for contiguous scenes. Give every scene an explicit duration. - Put local assets in
public/and resolve them withstaticFile(). Use Remotion media components rather than raw HTML tags so rendering waits for media correctly. - Prefer
useDelayRender()inside components. Create a handle once, clear it exactly once, and callcancelRender(error)on failure. PrefercalculateMetadata()for data needed to determine props or metadata once per render. - Keep render-time code free of browser-only assumptions that are unavailable in headless Chromium or Lambda. Never expose AWS credentials or other secrets to the browser bundle.
- Validate dimensions, file format, alpha-channel policy, and platform-specific rules independently for each store target. Never assume one portrait size is accepted by both Apple and Google.
Work in a tight render loop
- Type-check and run focused tests.
- Render representative still frames: the start, each scene boundary, a motion midpoint, and the last frame.
- Inspect the actual pixels, not just the Studio preview. Check clipping, text wrapping, safe margins, missing assets, and transparent backgrounds.
- Render a short frame range or low-scale draft before a full expensive video.
- Benchmark concurrency on the deployment machine instead of maximizing it blindly.
- Render the final artifact with an explicit composition ID, props, output path, dimensions, and format.
- Verify exit status, file existence, pixel dimensions, duration/frame count where relevant, and a final visual sample.
Make changes conservatively
- Do not upgrade Remotion, rewrite project structure, or replace media components unless required by the task or approved by the user.
- Gate newer APIs behind the installed version; provide a compatible fallback when practical.
- Do not hide render failures with arbitrary timeout increases. First identify the unresolved handle, network request, asset, font, or media decode.
- Do not claim a performance improvement without measurements from comparable renders.