Remotion Best Practices
lyonjs/shortvid.io
Best practices for Remotion - Video creation in React. An agent skill from lyonjs/shortvid.io.
Finds and places b-roll on a talking-head video: classifies each moment, searches suitable sources and returns a short list of candidates for you to pick from.
$ npx skills add louisedesadeleer/b-roll-finder --skill find-broll -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install louisedesadeleer/b-roll-finder find-broll --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
Claude Code skills documentation · loads skills from .claude/skills/
Install the "find-broll" agent skill from https://github.com/louisedesadeleer/b-roll-finder/tree/main into .claude/skills/find-broll/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "find-broll", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add louisedesadeleer/b-roll-finder --skill find-broll -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install louisedesadeleer/b-roll-finder find-broll --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "find-broll" agent skill from https://github.com/louisedesadeleer/b-roll-finder/tree/main into .agents/skills/find-broll/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "find-broll", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add louisedesadeleer/b-roll-finder --skill find-broll -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install louisedesadeleer/b-roll-finder find-broll --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "find-broll" agent skill from https://github.com/louisedesadeleer/b-roll-finder/tree/main into .cursor/skills/find-broll/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "find-broll", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add louisedesadeleer/b-roll-finder --skill find-broll -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install louisedesadeleer/b-roll-finder find-broll --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "find-broll" agent skill from https://github.com/louisedesadeleer/b-roll-finder/tree/main into .gemini/skills/find-broll/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "find-broll", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install louisedesadeleer/b-roll-finder find-brollInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add louisedesadeleer/b-roll-finder --skill find-broll -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "find-broll" agent skill from https://github.com/louisedesadeleer/b-roll-finder/tree/main into .github/skills/find-broll/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "find-broll", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add louisedesadeleer/b-roll-finder --skill find-broll -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install louisedesadeleer/b-roll-finder find-broll --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "find-broll" agent skill from https://github.com/louisedesadeleer/b-roll-finder/tree/main into .opencode/skills/find-broll/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "find-broll", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
find-brollFinds and places b-roll on a talking-head video: classifies each moment, searches suitable sources and returns a short list of candidates for you to pick from.
The skill sources footage, memes and screenshots to lay over a talking-head edit, working from the transcript. For each moment it classifies what kind of cutaway is needed, limits the search to suitable sources, scores what it finds and returns a contact sheet of vetted candidates timed to the spoken word. The agent never makes the final selection; that stays with you.
A taste profile, TASTE.md, is loaded before any sourcing. Unless it begins with a Confirmed-by line carrying a name and date, the agent must ask four onboarding questions out loud and record the answers, and it may not infer them from memory or notes. A ban you state during a run, such as no memes, takes effect at once, is written into the profile's guardrails and is never revisited. Helper scripts ship with it: cdp_capture.py, render_cutaways.py and zoom_still.py.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 36b8a56. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 3 files in scripts/ (Python), which the agent can run.
Shell commands in SKILL.md call:
ffmpegyt-dlpFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
youtube.complatform.twitter.comcdn.syndication.twimg.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
B-Roll Finder loads about 7.1k tokens when it runs. Until then it costs about 70 tokens; SKILL.md has 3,969 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from louisedesadeleer/b-roll-finder at commit 36b8a56, republished under its MIT licence (© louisedesadeleer). 3,969 words, ~7,123 tokens.
.claude/skills/find-broll/SKILL.md (or your agent's skills folder). This skill also uses 7 other files; get the full folder from GitHub.A reusable methodology for sourcing and placing b-roll on talking-head video. Genericized from a working agent skill. Adapt paths and brand tokens to your own setup.
When the user states a preference or ban mid-run ("no memes", "no text cards", "nothing political"), it applies IMMEDIATELY and for the rest of the session, AND gets written into the profile's Guardrails right then — not at the end. A banned category is never sourced again, never proposed again, never "just one candidate to check". Violating a stated ban is the worst failure this skill can make: it tells the user the agent doesn't listen.
Open the profile (TASTE.md or the user's fork). The ONLY thing that skips onboarding is a literal Confirmed-by: <name> (<date>) line at the top of the profile. No line → ask the four onboarding questions (below) out loud, write the answers into the profile, add the line. This is NOT optional and NOT inferable:
The agent NEVER picks the final b-roll. The user does. The right clip is often a taste call. This skill's job is to narrow the funnel — classify each moment, scope the search to trusted/authoritative sources, score candidates, and hand back a tight contact sheet. The user makes the final pick.
Curation is half the skill. Every run starts by loading a taste profile: the b-roll fingerprint (which types, how fast to cut), the trusted-source list tagged by topic, and the guardrails. This repo ships with a working default — TASTE.md, revealed from real published videos — so the skill has good taste out of the box. Use it as-is until the user builds their own (TASTE.md's "Make it yours" section covers the import-then-prune mechanism: pull their YouTube subscriptions via yt-dlp --cookies-from-browser, prune together, then reveal their fingerprint from their own published videos).
When onboarding fires: the shipped TASTE.md is an EXAMPLE profile (the author's), not the user's. On first run, check the profile for a Confirmed-by: line naming the current user. Absent → run onboarding: ask the questions below, write the answers into the user's profile (their fork of TASTE.md), and add Confirmed-by: <user> (<date>) at the top. Present → skip onboarding and just load it. The user can re-trigger anytime with "redo my profile".
Ask these on first run and write the answers into the taste profile (TASTE.md ships with one set of answers; confirm they fit):
ffmpeg -an) or want the clip's sound?off · white · black · auto (contrast-pick per clip). The credit is the source's canonical name + platform ("Vinexposium / YouTube", "Decanter") — short, never a URL. If the footage already carries its own badge bottom-right, move the credit bottom-left for that clip. Note: an on-screen credit is etiquette, not a license — official/authoritative sources remain the real copyright posture.Do NOT ask conversational permission for access or searches while sourcing — running /find-broll already authorizes the skill to act on the user's behalf. Never ask "want me to search/look up/access X?" for:
yt-dlp metadata searches and downloads of public videos/channelsJust do it and show the result. The user's taste checkpoints stay: the plan approval before sourcing and the final pick on taste-route beats. The ONLY things that still warrant a question: publishing/posting anything outward, paid actions, deleting user files, and installing heavy dependencies. Ask-permission friction everywhere else is a bug, not politeness.
The skill earned trust through restraint; heavyweight process makes output WORSE, not better (tested 2026-06-11: a full-funnel run took ~10× longer and shipped worse composition than the lean run). Defaults:
After the plan is approved, cluster beats by where their asset lives, then fetch each source ONCE:
assets/raw/) so re-renders and v2s never re-fetch.Fewer, perfectly-accurate beats beat lots of mediocre ones. The habit to kill is keyword-matching to hit a quota.
| When the narration is… | Source this |
|---|---|
| "people are saying" / discourse | tweets, headlines, posts, search-result screenshots |
| a number / stat ("$24/mo", "750 sign-ups") | the figure ON SCREEN — pricing page, dashboard, chart, stat card |
| growth / "went viral" | a graph going UP, or the viral post itself with its metrics |
| decline / "tanking" | a graph going DOWN, error screens, the failing thing |
| "research shows" / authority | the study/paper headline or the expert on camera |
| a direct quote | the authentic post/blog screenshot (beats a synthetic quote-card), or them saying it |
| an era / "back in the day" | archival/vintage footage of that period |
| a place | establishing shots of that place |
| comparison / "X vs Y" | sequential full-bleed singles — never an agent-built split-screen |
| "how it works" / step-by-step | screen recording or motion graphics of the steps |
| a story with actions ("every morning he'd…") | the PLACES & ACTIONS, evocatively — never a literal reenactment |
| a metaphor ("like a rocket") | the metaphor object ONLY if it lands — metaphors default to SKIP |
| an emotion / reaction beat | propose the moment + register; the user supplies the meme |
| the creator's own content ("my video") | self-source their actual clip/post — not a search |
Genre predicts b-roll TYPE and density better than topic does (style + cadence answers from intake override these):
Classify EVERY moment before searching:
| Route | Trigger | Source |
|---|---|---|
| Receipts | Time-sensitive — drama, news, complaints, a current claim/stat | Tweets / article headlines / reviews, recency-sorted, captured as clean screenshots |
| Entity | A person, a physical product, or a historical moment | The official / authoritative channel — the canonical clip, not a random upload |
| Concept | An abstract idea you'd have to draw (a process, a mental model, a stat) | Custom motion-graphics (e.g. Remotion) in your brand style — the DEFAULT when the profile has a Remotion project path — or real footage from the authoritative source |
⛔ Cards never replace real footage of a literal thing. If the beat names a concrete entity (grape varieties, a product, a place) and real footage exists, a generated text card is a FAIL — even if the user's fingerprint shows they like cards. Cards are for ideas with NO literal footage. (2026-06-11: a "three grapes" beat got a navy text card while the official film had the actual clusters — wrong.) | Cultural / Meme | A creator clip or joke where taste decides | NEVER searched or fetched by the agent. Propose the MOMENT + register ("punchline at 2:31, deadpan") in the plan; the user supplies the meme from their library — or strikes the beat. Agent-found memes have failed every time they've been tried. |
Litmus (in order): Happening now? → Receipts. A person / product / event? → Entity (official source). An abstract idea? → Concept (motion-graphics). A reaction beat? → Meme (user's library).
YouTube's sweet spot is the Entity route (people, products, historical moments). Don't force it onto abstract ideas — those are Concept jobs.
A clip merely containing the person is NOT relevant b-roll (the #1 person-clip failure):
If a plan is >60% website screenshots, it's wrong.
When BOTH a moving and a static version of a source exist, take the moving one: the product's own demo video over its homepage; a real screen-recording of scrolling over a static capture; a live excerpt over a headshot. Stills stay right where READING is the point (a tweet, a headline, a review). Rubric tie-breaker: equal relevance → motion wins.
zoompan is bannedHard-won distinction — the ban is on the METHOD, not the effect:
zoompan / crop-pans / scroll-pans are BANNED, at any speed, with any supersampling. They sample on integer pixel steps, so even a ~1%/sec zoom stutters. Tested exhaustively (4× lanczos supersample → zoompan → downscale): still shaky. Don't burn time re-attempting.img.resize((W,H), Image.LANCZOS, box=<float coords>) — float box coordinates = sub-pixel sampling — piped as rawvideo into x264. ~30 lines of Python.Score 1–5 and drop anything below the bar:
Check time-sensitivity first — a dated tweet from this month beats a years-old YouTube clip for a current story.
yt-dlp "https://www.youtube.com/@<handle>/search?query=<q>" --flat-playlist --print "%(title).75s ||| %(duration_string)s ||| %(id)s" — search INSIDE the official/trusted channel. ytsearchN:<query> is the fallback; fully open results get flagged "⚠️ outside trusted sources".--flat-playlist --print costs seconds; download only the chosen winners (-f "bv*[height<=1080]+ba/b").https://platform.twitter.com/embed/Tweet.html?id=<TWEET_ID> renders a clean card headlessly, no auth (&hideThread=true; capture with scripts/cdp_capture.py). The tweet's real attached media resolves via https://cdn.syndication.twimg.com/tweet-result?id=<ID>&token=a. Verify what the attachment actually shows before shipping it."Login-walled" is a claim you prove by attempting, not a label for punting. Exhaust ALL of these before handing a beat back to the user:
yt-dlp — public profiles/videos usually need NO login.yt-dlp --cookies-from-browser — the user's logged-in cookies beat most walls.--word-timestamps True, one pass during transcription — no extra tooling). Find the keyword's word time and anchor +0.2–0.5s after it. Whisper word-ends run slightly early and embed pauses inside word durations, so bias LATER when unsure — late reads as intentional, early reads as a mistake.scale=W:H:force_original_aspect_ratio=increase,crop=W:H.Across re-renders the #1 failure is silently DROPPING beats the user already approved. Keep a BROLL-MANIFEST.md next to the deliverable: one row per beat (in/out · beat · asset · status incl. which version approved it) plus a "Removed (do not re-add)" list. Before EVERY re-render: read the manifest, verify every approved beat is in the new cut, add the new ones, update statuses. Approved b-roll never disappears without the user explicitly cutting it.
After every render, extract a frame at every beat's midpoint AND every joint (b-roll↔b-roll, b-roll↔face), tile them into a grid, and LOOK at it. Fix and re-verify. A render isn't done until the grid is clean.
Explicit AUTO-REJECT checklist — a frame containing ANY of these fails, no judgment call:
Grade the grid against this list line by line — "looks fine" without the list is how watermarked clips ship.
Proxy FIRST for big sources: if the base video is 4K/HEVC/>500MB, transcode a 1080p working copy before anything (ffmpeg -hwaccel videotoolbox -i src -vf scale=1920:-2 -c:v h264_videotoolbox -b:v 6M -c:a aac proxy.mp4) — every later step (frame scans, renders) runs 5–10× faster against it.
Don't grab low-res pre-merged streams — select a real stream (-f "bv*[height<=1080]+ba/b").
Don't let --download-sections be the final cut (variable framerate stutters) — download the short clip, then trim with a re-encode.
Standard format: constant fps, cover-crop full-bleed, audio stripped:
ffmpeg -ss <in> -t <dur> -i full.mp4 \
-vf "fps=30,scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080,setsar=1" \
-an -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart out.mp4Attribution on → composite the small credit label (PIL-rendered PNG, ~70% opacity) via overlay during formatting (some ffmpeg builds lack drawtext).
yt-dlp (no API key); headless browser + CDP for public-page screenshots (consent walls: click accept in every frame context, verify visually).scripts/zoom_still.py (sub-pixel PIL float-box → x264; --blurfill for portrait/odd aspect; never zoompan).scripts/cdp_capture.py (headless Chrome via CDP — clicks "accept" in every frame context, CMP-iframe aware; CDP_SCALE=2 for crisp receipts).scripts/render_cutaways.py (segment-concat template: base visual replaced per beat window, audio untouched).ffmpeg; ImageMagick for contact sheets.© louisedesadeleer, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 7 other files (scripts) in the repository root of louisedesadeleer/b-roll-finder.
Open the folder on GitHubat commit 36b8a56
B-Roll Finder next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| B-Roll Finder this skilllouisedesadeleer/b-roll-finder | 123 | — | ~7.1k | Automated safety check: Pass | MIT | |
| Remotion Best Practiceslyonjs/shortvid.io | 147 | 32 repos | ~1k | Automated safety check: Pass | MIT | |
| FFmpeg for Video Productiondigitalsamba/claude-code-video-toolkit | 2.2k | 3 repos | ~3.3k | Automated safety check: Pass | MIT | |
| HyperFrames Video Entry Pointheygen-com/hyperframes | 58k | 3 repos | ~5.2k | Automated safety check: Pass | Apache-2.0 | |
| Video Podcast Makerdtsola/xiaoyaosearch | 1k | — | ~3.4k | Automated safety check: Pass | MIT | |
| ShortsAgriciDaniel/claude-shorts | 218 | — | ~3.2k | Automated safety check: Notes | MIT |
lyonjs/shortvid.io
Best practices for Remotion - Video creation in React. An agent skill from lyonjs/shortvid.io.
digitalsamba/claude-code-video-toolkit
Command recipes for converting, resizing, compressing, trimming and extracting audio from video with FFmpeg, including settings for Remotion projects.
heygen-com/hyperframes
Entry point for making, editing and rendering videos from HTML compositions with HyperFrames, routing each request to the right workflow.
dtsola/xiaoyaosearch
Turns a topic into a 4K horizontal video podcast through research, scripting, text-to-speech, Remotion rendering and background music, and can learn styles from references.
AgriciDaniel/claude-shorts
Interactive longform-to-shortform video creator. An agent skill from AgriciDaniel/claude-shorts.
Pluviobyte/video-production-skills
Create reusable black-background white-text opening animations for new videos.
Categories
Finds and places b-roll on a talking-head video: classifies each moment, searches suitable sources and returns a short list of candidates for you to pick from. The skill sources footage, memes and screenshots to lay over a talking-head edit, working from the transcript. For each moment it classifies what kind of cutaway is needed, limits the search to suitable sources, scores what it finds and returns a contact sheet of vetted candidates timed to the spoken word.
B-Roll Finder fits situations like: adding cutaway footage, memes or screenshots over a talking-head video; sourcing b-roll for a podcast or tutorial intro from its transcript; finding clips for each beat of an edit and placing them on the right word.
Run `npx skills add louisedesadeleer/b-roll-finder --skill find-broll -a claude-code`. Or copy the skill folder (the louisedesadeleer/b-roll-finder repository) into .claude/skills/find-broll in your project. Claude Code loads it when a task matches its description.
Run `npx skills add louisedesadeleer/b-roll-finder --skill find-broll -a codex`. Or copy the skill folder (the louisedesadeleer/b-roll-finder repository) into .agents/skills/find-broll in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add louisedesadeleer/b-roll-finder --skill find-broll -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/find-broll, .gemini/skills/find-broll, .github/skills/find-broll and .opencode/skills/find-broll in your project.
Going by SKILL.md and its folder, B-Roll Finder needs Python for the scripts in its folder and the command-line tools its instructions call (ffmpeg and yt-dlp). Our summary lists: A transcript of the video; A taste profile (TASTE.md) confirmed through the onboarding questions.
SKILL.md names 3 domains. In commands or code: youtube.com, platform.twitter.com and cdn.syndication.twimg.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
B-Roll Finder is published under the MIT licence (from the LICENSE file in the skill folder). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.1k tokens (SKILL.md is roughly 28k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with B-Roll Finder: Remotion Best Practices (lyonjs/shortvid.io, 147 stars), FFmpeg for Video Production (digitalsamba/claude-code-video-toolkit, 2.2k stars), HyperFrames Video Entry Point (heygen-com/hyperframes, 58k stars) and Video Podcast Maker (dtsola/xiaoyaosearch, 1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
louisedesadeleer (a GitHub user) maintains it in louisedesadeleer/b-roll-finder, which has 123 GitHub stars. The repository was last updated on June 11, 2026.
Source: louisedesadeleer/b-roll-finder on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.