remotion-best-practices
Best practices for Remotion - Video creation in React
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Best practices for Remotion - Video creation in React
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Create an educational explainer video that teaches a topic in 5 animated scenes with voiceover, animated visuals, and captions.
Create a before/after comparison video showing the old way vs the new way. Dramatic visual contrast with stats.
Create a teaser video for a blog post that drives clicks to read the full article. 4 scenes — hook, key points, standout moment, CTA.
Create an animated data dashboard video from a CSV file or data source. 4-panel layout with charts and KPIs.
Create a promotional video for a product or service by researching its URL. 5 scenes with hook, solution, capabilities, trust, and CTA.
Research a topic, find real data points and stats, then create an animated data visualization video. No CSV needed.
| name | remotion-best-practices |
| description | Best practices for Remotion - Video creation in React |
| metadata | {"tags":"remotion, video, react, animation, composition"} |
Use this skill for the complete video production pipeline — from script writing through rendering and delivery. It includes scaffolding automation, voiceover/caption/music generation scripts, and detailed rule files for every Remotion pattern you'll need.
You need a Remotion project. If you don't have one, create it with npx create-video@latest and select the blank template. The project must have a remotion.config.ts at its root — the scaffold script uses this to locate the project.
Required .env variables in the project root:
ELEVENLABS_API_KEY — for voiceover and background music generationELEVENLABS_VOICE_ID — default voice (optional if set per-project in project.json)KREA_API_KEY — for b-roll generation (if using Krea)On first use, save the Remotion project location to memory so you can find it in future sessions.
Before implementing any scenes, follow this sequence.
API keys (ElevenLabs, Krea, etc.) are loaded from .env by the scripts automatically. NEVER pass API keys on the command line — they will be visible in terminal output. Always use the provided scripts:
npx tsx src/<Name>/generate-voiceover.ts — generates voiceover audio (reads scenes from project.json)npx tsx src/<Name>/generate-captions.ts — transcribes voiceover to captions (reads scene IDs from project.json)npx tsx src/<Name>/generate-background-music.ts — generates background music (reads mood from project.json)npx tsx src/generate-broll.ts --output "public/<name>/broll/" --prompts prompts.json — generates b-roll clipsAll main content (headlines, key text, CTAs, stats, graphics) must be centered vertically and horizontally, building outward from dead center. This is the default unless explicitly overridden.
B-roll, backgrounds, decorative elements, and captions are NOT restricted to the safe zone — they fill the full frame.
If the prompt doesn't specify landscape, default to portrait (9:16).
Portrait (9:16) — 1080x1920 canvas:
Universal cross-platform safe zone (works on TikTok, Reels, and Shorts):
Platform UI is updated frequently — these values are current as of early 2026.
Landscape (16:9): Full frame is usable, no safe zone restriction.
First frame rule: Scene 1's first animation must start at frame 0 with no delay AND start at visible values (e.g. scale 0.8, opacity 0.5). Spring animations start from 0 and take several frames to reach visible values — if starting from scale 0 or opacity 0, the first frames are blank which looks broken as a thumbnail and on autoplay.
Run the scaffold script from the Remotion project root. The script is located in the plugin's scripts/ directory:
python3 <path-to-plugin>/scripts/scaffold.py <CompositionName>
This automatically creates the full composition structure:
src/<Name>/ — index.tsx, Scene1.tsx (placeholder), get-audio-duration.ts, generate-voiceover.ts, generate-captions.ts, generate-background-music.ts, Captions.tsx, project.jsonpublic/<name>/voiceover/, public/<name>/broll/, public/<name>/captions/src/Root.tsxAfter scaffolding, start (or restart) Remotion Studio so it picks up the new composition:
npx remotion studio
The placeholder scene is immediately previewable. Do NOT manually create these files — use the script.
The scaffold creates project.json in the composition directory. This file is the single source of truth — all scripts read from it, and you update it at every step. Every creative decision, every configuration value, every approval status goes into this file.
First, decide how many scenes the video needs (typically 3-5). Then write the voiceover script for all scenes. Audio durations drive scene lengths (not the other way around).
When presenting the script for approval, ALWAYS show for every scene:
After the script, ask the user:
Use these exact values for approval gates: "pending" (wait for approval), "approved" (auto-proceed), "completed" (done). Do not use booleans or yes/no.
Update project.json: Fill in:
branding.company, branding.website, branding.socials — from the user's answersvoice.voice_id — the user's chosen voice ID (empty = use env var)background_music.enabled and background_music.mood — from the user's answerrender — "pending" or "approved"youtube.publish — "pending" or "approved" (only if publishing to YouTube)youtube.links, youtube.tags, youtube.category — only if publishing to YouTubeheadline, voiceover, and visual fieldsIf the scene count changed, duplicate scene entries in the scenes array to match. Also duplicate the placeholder Scene1.tsx for each additional scene (rename the component export to Scene2, Scene3, etc.) and update index.tsx to import all scenes and wire them into the TransitionSeries with fade transitions between each. Load ./rules/compositions.md for composition patterns and ./rules/transitions.md for the TransitionSeries wiring pattern.
The voiceover script reads directly from project.json — no need to edit the script itself. Just make sure the voiceover text is filled in for each scene in project.json (Step 2), then run:
npx tsx src/<Name>/generate-voiceover.ts
After voiceover files are generated, update index.tsx: replace the placeholder calculateMetadata with one that reads actual audio durations using getAudioDuration. The composition duration should be driven by the voiceover audio, not hardcoded frame counts. Load ./rules/voiceover.md for the exact calculateMetadata pattern.
Decide which scenes get b-roll backgrounds. Allocate ~2 b-roll clips per 30 seconds of video. Any scene can have b-roll — it's a background layer independent of the foreground content (text, charts, animated diagrams, anything).
Update project.json: For each scene, fill in broll.type ("image", "video", or "none") and broll.prompt.
Then generate the b-roll clips. Create a prompts JSON file from the project.json b-roll entries and run:
npx tsx src/generate-broll.ts --output "public/<name>/broll/" --prompts prompts.json
The prompts.json format: [{"name": "scene-02", "prompt": "description..."}, ...]
The script submits jobs to Krea.ai, polls until complete, downloads the clips, and extends them to 15s with ffmpeg.
When coding scenes with b-roll, you MUST follow the compositing pattern in ./rules/b-roll.md:
AbsoluteFill with filter: "brightness(0.35)" and overflow: "hidden", OffthreadVideo with Ken Burns bounce zoomAbsoluteFill with safe zone padding and justifyContent: "center"backgroundColor: "rgba(10,10,10,0.7)") for readabilityThe scaffold sets up a basic TransitionSeries. When adding multiple scenes (Step 2), add <TransitionSeries.Transition> elements with fade() between each sequence at 1-1.5 seconds (30-45 frames at 30fps). Define PADDING_FRAMES (silence after voiceover ends) and ensure it is >= TRANSITION_DURATION or voiceovers will overlap during transitions. Audio stays inside TransitionSeries.Sequence — do not separate it into its own layer. Load ./rules/transitions.md for the full transition pattern with code examples.
All videos should have animated subtitles with word highlighting. Follow this sequence:
npx tsx src/<Name>/generate-captions.ts
Output goes to public/<name>/captions/.
2. Proofread (MANDATORY — DO NOT SKIP) — Whisper ALWAYS mangles brand names. This is not optional.
branding.company from project.json. Search every caption file for ANY misspelling of it — Whisper splits words into tokens so check for partial matches too (e.g. "Gar" + "ombo" instead of "Gorombo"). Merge split tokens and correct the spelling. This is the #1 priority.SWITCH_CAPTIONS_EVERY_MS = 1800 gives breathing room after sentences. Lower values (1200ms) feel rushed with no pause after periods. The spacing after punctuation makes a huge difference in how captions read.<Captions captionFile="<name>/captions/scene-01.json" /> at composition level inside each TransitionSeries.Sequence, not inside individual scene components. Each scene gets its own Captions component pointing to its caption JSON file.Load ./rules/subtitles.md for the full Caption component API, transcription details, and display patterns.
If background_music.enabled is true in project.json, generate a background music track:
npx tsx src/<Name>/generate-background-music.ts
The script reads the mood from project.json, measures total voiceover duration, and generates an instrumental track via ElevenLabs Music API. The track saves to public/<name>/background-music.mp3 and plays automatically in the composition at 15% volume. Set hasBackgroundMusic: true in the composition's defaultProps in Root.tsx.
Duration note: The music should cover the FULL video length including padding frames and transitions, not just the voiceover. Add extra seconds to the generated duration to account for this (typically 5-10 seconds beyond total voiceover).
If background music is disabled, skip this step.
Remotion Studio should already be running from Step 1. If not, restart it with npx remotion studio. The user can review the video in the browser and request changes.
Update project.json: Set each completed scene's status to "coded".
Before rendering, verify ALL of the following. Do NOT render until every item is confirmed:
If ANY step was skipped, go back and complete it before rendering.
If render is "approved" in project.json, render automatically when all checklist items pass. Otherwise wait for user approval.
npx remotion render <CompositionId> out/<name>.mp4 --port 3100
After render completes, upload to the user's configured delivery destination (e.g. Google Drive via gws CLI, or another tool). Ask the user where to deliver if not previously specified.
If youtube.publish is "approved" in project.json, generate a YouTube description by:
youtube.linksyoutube.tags and youtube.categorybranding.website and any URLs from branding.socialsyoutube.description_notesThen upload via python3 youtube-upload.py.
Update project.json: Set render to "completed" after successful render. Set youtube.publish to "completed" after successful upload.
For some video operations, such as trimming videos or detecting silence, FFmpeg should be used. Load the ./rules/ffmpeg.md file for more information.
When needing to visualize audio (spectrum bars, waveforms, bass-reactive effects), load the ./rules/audio-visualization.md file for more information.
When needing to use sound effects, load the ./rules/sound-effects.md file for more information.
Read individual rule files for detailed explanations and code examples: