8.3 KiB
8.3 KiB
name, description
| name | description |
|---|---|
| remotion-best-practices | 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
- 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. - 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
- Composition UI:
- Keep render behavior deterministic. A frame should be a pure function of props, frame number, and explicitly loaded assets.
- Verify with
bun run lintand a focused smoke test: Remotion Studio,bun run renderwith 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.tsregistersRemotionRoot. - Main composition:
CaptionedVideoinsrc/components/Root.tsx. - Metadata:
getVideoMeta()usescalculateMetadataplus@remotion/media-parserparseMedia()to set duration, dimensions, and fps from the input video. - Media rendering:
CaptionsCompositionuses@remotion/mediaVideo, with captions overlaid inAbsoluteFill. - Server rendering:
renderCaptionedVideo()writes props JSON intoout/, runs./node_modules/.bin/remotion render src/index.ts ... --props, parses CLI progress output, and deletes the props file infinally. - 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(), andSequence. 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.tsxdefaultProps, 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 preferuseDelayRender()where practical, and always clear or cancel every handle on success and failure. - Use
AbsoluteFillfor full-frame layers andSequencefor frame-based timing. Convert seconds with the activefps, not a hardcoded 30 unless the composition contract really is fixed at 30 fps.
Metadata
- Keep dynamic duration and dimensions in
calculateMetadata, not componentuseEffect(). 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'sabortSignalso cancelled metadata calculations stop promptly. - When migrating from the CLI to
@remotion/renderer, pass the sameinputPropsto bothselectComposition()andrenderMedia()socalculateMetadata()and the actual render resolve the same composition.
Media And Assets
- Local reusable assets belong in
public/and should be referenced withstaticFile(). Thepublic/folder must stay beside the projectpackage.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/mediaVideo. It is frame-perfect and fast, but respect version badges: options introduced after4.0.435require a package upgrade before use. - Do not use
objectFiton@remotion/mediaVideowhile the project remains on4.0.435; the docs mark it as4.0.442. Use sizing wrappers or upgrade Remotion intentionally. - Do not use
credentialson@remotion/mediaVideowhile on4.0.435; the docs mark it as4.0.437. Prefer signed public URLs for protected videos in this version. - Keep
Config.setVideoImageFormat("jpeg")for regular opaque videos. Switch topngonly 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/mediaVideo,OffthreadVideo, and their fallback behavior before changing code.
Render Service Rules
- The current CLI path means
remotion.config.tsapplies. If switching to Node/Bun APIs, move needed options intobundle(),selectComposition(), orrenderMedia()because Remotion config is not automatically applied there. - Keep the two concurrency knobs separate:
- BullMQ
MAX_CONCURRENT_RENDERScontrols 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.
- BullMQ
- 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, usemakeCancelSignal()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 infinally, and remove rendered files after upload. Never commit render outputs or real.envvalues. - 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 lintafter 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 serverand smoke the affected/api/renderflow, including callback/progress behavior when touched. - For Docker/browser/render-performance changes, smoke through
docker compose up --build remotionwhen 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/mediaVideo: https://www.remotion.dev/docs/media/videostaticFile(): 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