@@ -0,0 +1,157 @@
|
||||
---
|
||||
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
|
||||
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "Remotion Best Practices"
|
||||
short_description: "Guide Remotion rendering changes in this service."
|
||||
default_prompt: "Use $remotion-best-practices when changing Remotion compositions, metadata, or rendering service code."
|
||||
Reference in New Issue
Block a user