158 lines
8.3 KiB
Markdown
158 lines
8.3 KiB
Markdown
---
|
|
name: remotion-best-practices
|
|
description: Use when writing, reviewing, or refactoring Remotion code in this repository, including compositions, dynamic metadata, @remotion/media video/audio, CLI or renderer rendering, Docker/Chromium settings, queue progress/cancellation, or render performance.
|
|
---
|
|
|
|
# Remotion Best Practices
|
|
|
|
## Overview
|
|
|
|
Apply current Remotion guidance to this Bun rendering service without losing the
|
|
project-specific details that make renders reliable: dynamic metadata, S3 input
|
|
URLs, BullMQ progress, Docker Chromium, and cleanup of generated artifacts.
|
|
|
|
## Workflow
|
|
|
|
1. Fetch current Remotion docs first with Context7. This repo pins Remotion
|
|
packages at `4.0.435`, so compare docs version badges against that version
|
|
before using newer API options.
|
|
2. Identify the layer being changed:
|
|
- Composition UI: `src/components/Composition.tsx`, `src/components/Captions.tsx`
|
|
- Composition registration and metadata: `src/components/Root.tsx`,
|
|
`src/hooks/useVideoMeta.ts`
|
|
- Render orchestration: `server/services/render_video.ts`,
|
|
`server/services/render_queue.ts`
|
|
- Runtime config: `remotion.config.ts`, `Dockerfile`, `.env.example`,
|
|
`server/config.ts`
|
|
3. Keep render behavior deterministic. A frame should be a pure function of
|
|
props, frame number, and explicitly loaded assets.
|
|
4. Verify with `bun run lint` and a focused smoke test: Remotion Studio,
|
|
`bun run render` with valid props, or the API/queue path when server behavior
|
|
changed.
|
|
|
|
## Project Map
|
|
|
|
- Runtime: Bun, React 19, Remotion `4.0.435`.
|
|
- Entry point: `src/index.ts` registers `RemotionRoot`.
|
|
- Main composition: `CaptionedVideo` in `src/components/Root.tsx`.
|
|
- Metadata: `getVideoMeta()` uses `calculateMetadata` plus
|
|
`@remotion/media-parser` `parseMedia()` to set duration, dimensions, and fps
|
|
from the input video.
|
|
- Media rendering: `CaptionsComposition` uses `@remotion/media` `Video`, with
|
|
captions overlaid in `AbsoluteFill`.
|
|
- Server rendering: `renderCaptionedVideo()` writes props JSON into `out/`,
|
|
runs `./node_modules/.bin/remotion render src/index.ts ... --props`, parses
|
|
CLI progress output, and deletes the props file in `finally`.
|
|
- Queue wrapper: BullMQ controls job concurrency through
|
|
`MAX_CONCURRENT_RENDERS`, uploads finished files to S3, sends webhooks, and
|
|
stores cancellation flags in Redis.
|
|
- Docker: Chromium and FFmpeg are installed in the image; Remotion browser
|
|
download is skipped; sandboxing is disabled through env.
|
|
|
|
## Composition Rules
|
|
|
|
- Animate with `useCurrentFrame()`, `useVideoConfig()`, `interpolate()`,
|
|
`spring()`, and `Sequence`. Do not use CSS animations, CSS transitions,
|
|
timers, or wall-clock time for render-critical motion.
|
|
- Keep props JSON-serializable. When adding composition input fields, update
|
|
`src/types/captions_composition.d.ts`, `src/components/Root.tsx`
|
|
`defaultProps`, and the server-side props object together.
|
|
- Avoid fetches or expensive async work inside frame-rendering components.
|
|
Prefer server preprocessing or `calculateMetadata()` for data that changes
|
|
duration, dimensions, fps, or props.
|
|
- Use `delayRender()` only for assets that must block a frame, such as dynamic
|
|
CSS/font loading. In new code prefer `useDelayRender()` where practical, and
|
|
always clear or cancel every handle on success and failure.
|
|
- Use `AbsoluteFill` for full-frame layers and `Sequence` for frame-based
|
|
timing. Convert seconds with the active `fps`, not a hardcoded 30 unless the
|
|
composition contract really is fixed at 30 fps.
|
|
|
|
## Metadata
|
|
|
|
- Keep dynamic duration and dimensions in `calculateMetadata`, not component
|
|
`useEffect()`. In Remotion v4, `useEffect()` can run again for render workers
|
|
and multiply API calls.
|
|
- For this repo, preserve the existing `parseMedia()` path unless deliberately
|
|
upgrading. Current Remotion docs are moving media metadata toward Mediabunny,
|
|
so check docs before adding new metadata helpers.
|
|
- Use `Math.ceil(durationInSeconds * fps)` and keep the existing minimum of one
|
|
frame so zero-length or partially unreadable metadata cannot produce invalid
|
|
compositions.
|
|
- If metadata fetching starts using `fetch()`, pass Remotion's `abortSignal` so
|
|
cancelled metadata calculations stop promptly.
|
|
- When migrating from the CLI to `@remotion/renderer`, pass the same
|
|
`inputProps` to both `selectComposition()` and `renderMedia()` so
|
|
`calculateMetadata()` and the actual render resolve the same composition.
|
|
|
|
## Media And Assets
|
|
|
|
- Local reusable assets belong in `public/` and should be referenced with
|
|
`staticFile()`. The `public/` folder must stay beside the project
|
|
`package.json`.
|
|
- Remote video URLs from S3/MinIO are valid, but they must be accessible from
|
|
the Chromium process inside Docker. Prefer presigned URLs with enough TTL for
|
|
queue wait time plus render time.
|
|
- This repo currently uses `@remotion/media` `Video`. It is frame-perfect and
|
|
fast, but respect version badges: options introduced after `4.0.435` require
|
|
a package upgrade before use.
|
|
- Do not use `objectFit` on `@remotion/media` `Video` while the project remains
|
|
on `4.0.435`; the docs mark it as `4.0.442`. Use sizing wrappers or upgrade
|
|
Remotion intentionally.
|
|
- Do not use `credentials` on `@remotion/media` `Video` while on `4.0.435`; the
|
|
docs mark it as `4.0.437`. Prefer signed public URLs for protected videos in
|
|
this version.
|
|
- Keep `Config.setVideoImageFormat("jpeg")` for regular opaque videos. Switch
|
|
to `png` only when transparency or color-accuracy requirements justify the
|
|
slower render and larger intermediate frames.
|
|
- For unsupported media, HLS, looping, alpha channels, pitch shifts, or
|
|
frame-manipulation callbacks, re-check the current docs for `@remotion/media`
|
|
`Video`, `OffthreadVideo`, and their fallback behavior before changing code.
|
|
|
|
## Render Service Rules
|
|
|
|
- The current CLI path means `remotion.config.ts` applies. If switching to
|
|
Node/Bun APIs, move needed options into `bundle()`, `selectComposition()`, or
|
|
`renderMedia()` because Remotion config is not automatically applied there.
|
|
- Keep the two concurrency knobs separate:
|
|
- BullMQ `MAX_CONCURRENT_RENDERS` controls simultaneous videos.
|
|
- Remotion render concurrency controls frame workers inside one video.
|
|
Tune both against Docker CPU and memory limits; a 4 GB / 2 CPU container can
|
|
run out of memory quickly with multiple video jobs.
|
|
- Prefer renderer callbacks (`onStart`, `onProgress`, `onBrowserLog`,
|
|
`onDownload`) if moving to `@remotion/renderer`. Keep CLI progress parsing
|
|
tolerant because CLI log text can change.
|
|
- If moving to `@remotion/renderer`, use `makeCancelSignal()` instead of only
|
|
killing a process. Keep Redis cancellation and upload abort behavior aligned.
|
|
- Preserve bounded stdout/stderr capture. Render failures should include enough
|
|
tail output for debugging without logging full user media paths or huge logs.
|
|
- Keep generated files under `out/`, remove props JSON in `finally`, and remove
|
|
rendered files after upload. Never commit render outputs or real `.env`
|
|
values.
|
|
- In Docker, keep Chromium, FFmpeg, emoji fonts, and Linux browser libraries in
|
|
sync with Remotion requirements. If browser detection changes, configure an
|
|
explicit browser executable or Remotion renderer option instead of relying on
|
|
accidental host state.
|
|
|
|
## Validation
|
|
|
|
- Always run `bun run lint` after TypeScript or Remotion changes.
|
|
- For composition/caption layout changes, run Remotion Studio or a short render
|
|
using valid props with an accessible `videoSrc`.
|
|
- For API, queue, cancellation, or upload changes, run `bun run server` and
|
|
smoke the affected `/api/render` flow, including callback/progress behavior
|
|
when touched.
|
|
- For Docker/browser/render-performance changes, smoke through
|
|
`docker compose up --build remotion` when feasible because local host Chrome
|
|
behavior is not enough evidence.
|
|
|
|
## Source Anchors
|
|
|
|
- Remotion render APIs: https://www.remotion.dev/docs/renderer/render-media
|
|
- Dynamic metadata: https://www.remotion.dev/docs/dynamic-metadata
|
|
- `delayRender()` / `useDelayRender()`: https://www.remotion.dev/docs/delay-render
|
|
- Video tag comparison: https://www.remotion.dev/docs/video-tags
|
|
- `@remotion/media` `Video`: https://www.remotion.dev/docs/media/video
|
|
- `staticFile()`: https://www.remotion.dev/docs/staticfile
|
|
- Server-side rendering and Docker links: https://www.remotion.dev/docs/ssr
|
|
- Official Remotion agent skills: https://www.remotion.dev/docs/ai/skills
|