/remotion-best-practices
Remotion 컴포지션을 작성할 때마다 이 스킬을 사용하세요 — 애니메이션 데모 비디오, 제품 워크스루, 해커톤 제출물, 내레이션이 포함된 프레젠테이션 등 npx remotion render를 통해 MP4로 렌더링되는 모든 것.
이 스킬은 두 가지 지식 레이어를 제공합니다.
- Remotion 기본 사항 — Remotion 팀이
github.com/remotion-dev/skills에서 유지 관리하는 규칙 파일(컴포지션, 애니메이션, 폰트, 오디오, 전환, FFmpeg, 캡션 등). - 데모 비디오 제작 규칙 — vskill / Skill Studio 해커톤 데모를 제작하는 긴 반복 주기에서 얻은 교훈입니다. 이 규칙을 위반하면 '슬라이드쇼'처럼 보이고 설득력 있는 제품 워크스루가 되지 않습니다.
작성하기 전에 두 레이어를 모두 읽으세요.
범위 및 적용 가능성
아래의 레이어 2 제작 규칙은 특정 프로젝트인 vskill / Skill Studio 해커톤 데모(Anthropic / Claude Code "Built with Opus" 해커톤, 2026년 4월)에서 파생되었습니다. 이 규칙은 해당 제품의 look-and-feel을 반영합니다. Studio 크롬(브레드크럼 헤더, 사이드바 트리, 다크 verified-skill.com 페이지, 고정 폭 폰트, 터미널 장면, "Inter는 AI 슬롭, 독특한 세리프는 탁월함"이라는 편집 철학).
관련 없는 데모에 이 규칙을 있는 그대로 적용하지 마십시오. 소비자 모바일 앱, 금융 대시보드, 게임, B2B SaaS 피치는 각각 고유한 시각적 언어, 페이싱, 대상 청중의 기대치가 있습니다. 저장 후 게시(Save-then-Publish) 흐름,
verified-skill.com/queue페이지, 또는 PROJECT/PERSONAL/PLUGINS 개수를 표시하는 Studio 사이드바는 제작 기술이 아니라 콘텐츠입니다.이 레이어를 기본 기술에 대한 참고 자료로 사용하십시오: 카메라 줌 패턴, 커서 타겟팅 규율, 콘텐츠에 딱 맞는 하이라이트 사각형, 제자리 상태 전환, 음성 해설/script.ts 연결, 렌더+오디오 부스트 파이프라인 — 이러한 기술은 일반화 가능합니다. 정확한 상수(1.72배 줌, x=1488 버튼 중앙, v1.0.0 → v1.0.1 버전 알약, "Tier-1 패턴 · Tier-2 LLM · Socket" 속성)는 Skill Studio 고유의 내용입니다 — 번역하고 복사하지 마십시오.
레이어 1 — Remotion 기본 사항
https://github.com/remotion-dev/skills/blob/HEAD/skills/remotion/SKILL.md에 있는 업스트림 remotion-best-practices 스킬을 미러링합니다.
새 프로젝트 설정
빈 폴더나 기존 Remotion 프로젝트가 없는 작업 공간에서 다음 명령어를 사용하여 스캐폴딩합니다.
npx create-video@latest --yes --blank --no-tailwind my-video
미리보기 시작
비디오를 미리보기 위해 Remotion Studio를 시작합니다. Studio HMR은 파일이 변경됨에 따라 실시간으로 다시 로드됩니다 — 별도의 preview_start 메커니즘이 필요하지 않으며, Bash run_in_background은 편집 간에 Studio를 계속 실행하는 올바른 방법입니다.
npx remotion studio --port=3030
렌더링
# 진입점은 registerRoot()를 호출하는 파일이어야 합니다 (보통 src/remotion/index.ts)
npx remotion render src/remotion/index.ts <CompositionId> out/video.mp4 --concurrency=8 --log=info
일반적인 실수:
Root.tsx를 진입점으로 전달 → 오류: "이 파일에는 registerRoot가 포함되어 있지 않습니다".index.ts를 사용하세요.TransitionSeries는 직접 자식에 대한 prop 인트로스펙션을 수행합니다. 자식을<React.Fragment>로 감싸지 마십시오.<TransitionSeries.Sequence>및<TransitionSeries.Transition>요소의 평면 배열을 반환하는flatMap을 사용하세요.interpolate(frame, [a, b], …)는a < b가 엄격하게 필요합니다. 상수에서b를 파생하는 경우 장면 예산 설계 시간에 이를 확인하십시오 — Remotion은 평가된 첫 번째 프레임에서 "inputRange는 엄격하게 단조 증가해야 합니다" 오류를 발생시키고 전체 컴포지션이 로드되지 않습니다.
단일 프레임 렌더링 확인
npx remotion still <composition-id> --scale=0.25 --frame=30
업스트림 규칙 파일에서 다루는 주제
(업스트림 스킬 저장소에서 필요에 따라 로드 — github.com/remotion-dev/skills/tree/HEAD/skills/remotion/rules/.)
compositions.md— 컴포지션, 스틸, 폴더, 기본 props, 동적 메타데이터 정의animations.md—interpolate,spring, 이징, 프레임 기반 수학transitions.md—@remotion/transitions(페이드, 슬라이드, 와이프),TransitionSeries내에서 체인하는 방법assets.md—staticFile(),Img,Audio,Video, 폰트 로딩fonts.md—@remotion/google-fonts및 로컬 폰트 등록audio.md— 오디오 가져오기, 트리밍, 볼륨, 속도, 피치captions.md,subtitles.md— 캡션 트랙 및 동기화ffmpeg.md— FFmpeg 셸 명령을 통한 트리밍, 연결, 오디오 작업silence-detection.md,extract-frames.md,get-audio-duration.md,get-video-duration.md— Mediabunny 유틸리티charts.md,gifs.md,light-leaks.md,3d.md— 특수 렌더링 레시피
레이어 2 — 데모 비디오 제작 규칙
긴 반복 주기를 통해 얻은 규칙입니다. 선택적 다듬기가 아닌 기본값으로 취급하십시오 — 대부분은 여러 번의 수정이 필요했던 "이상하게 보이니 고쳐주세요" 피드백에서 비롯되었습니다.
A. 참조 정확성
A1. 항상 실제 참조를 가져오세요
사용자가 "이 YouTube 비디오의 2:43처럼 보이게 해주세요"라고 말하면 프레임을 추출하고 연구하세요. 기억에 의존해 근사하지 마십시오.
SOURCE="/Users/antonabyzov/Movies/.../Source.mov"
DEST_DIR=".specweave/.../assets/keyframes"
for t in 102 105 108 110 112; do
ffmpeg -y -ss "$t" -i "$SOURCE" -frames:v 1 -q:v 2 "$DEST_DIR/at-${t}s.jpg" -loglevel error
done
그런 다음 각 JPG를 Read하고 실제 화면에 표시된 내용(타이포그래피, 정확한 버튼 레이블, 배지 색상, 사이드바 트리 레이아웃, 검색 입력 위치, 카운트 값(예: PROJECT (1), PERSONAL (0 of 12), PLUGINS (0 of 50), AVAILABLE (62)))을 기준으로 디자인하세요.
A2. 실제 로고와 아이콘을 사용하고 근사하지 마세요
- Bell-badge
skill-studio-logo.png— 모든 Studio 장면에<Img src={staticFile("...")} />로 복사하세요.✷글리프를 렌더링하고 로고라고 부르지 마세요. - 제공자 아이콘 — Claude, Anthropic, OpenAI, OpenRouter, Ollama, LM Studio의 실제 SVG/PNG를 가져오세요(예:
lobehub/static-png에서). 이모지로 대체하지 마세요. - 마스코트 — 스타일이 지정된 div로 정확한 모양에 맞게 그리세요. Claude Code 마스코트는 복숭아색(
#e08160) 몸체에 두 개의 정사각형 눈, 몸체 중간에 두 개의 측면 손잡이, 아래에 두 쌍의 다리 (▪ ▪ ▪ ▪)가 있습니다. ASCII 아트가 아닙니다. - 앱 창 크롬 — "Chrome 브라우저"에서 웹사이트를 보여줄 때 실제 Chrome 브라우저 프레임을 렌더링하세요: 둥근 모서리, 신호등 점, ‹ › ↻ 탐색, 실제 URL이 있는 잠금 자물쇠 URL 표시줄(
localhost:3000/hero, 추가 공백 없음, 가운데 점 없음).
A3. YouTube 참조 레이아웃을 픽셀 단위로 일치시키세요
상상력으로 장면을 재설계하기 전에 참조 프레임에서 보이는 요소를 나열하고 각각을 출력과 비교하세요:
- 배너 텍스트 — 정확한 문구 (
Submit skills for verification,Submit a Skill이 아님) - 탭 순서 —
Overview · Edit · Tests · Run · Trigger · Versions - 신뢰 배지 —
T1 UNSCANNED,Security-Scanned —,Trusted Publisher - 필터 입력 — 항상 사이드바에서
AVAILABLE위에 있어야 함 - 카운트 — 모든 슬라이드에서 일관성 유지 (
PERSONAL (0 of 12)는 모든 곳에서 동일, 한 슬라이드에서(11), 다른 슬라이드에서(0 of 12)가 아님) - 헤더 오른쪽 컨트롤 (다음 순서):
🔍 Find skills [⌘K]·+ New Skill·● Model selector·🔔 bell
B. 카메라 줌
B1. 카메라 줌은 전체 캔버스이며, 섹션 크기가 조정되지 않습니다.
크롬 내부의 단일 패널을 확대/축소하지 마십시오. **전체 크롬(상단 표시줄 + 본문)**을 변환 div로 감싸고 해당 요소를 확대/축소 및 이동하세요:
<div
style={{
width: "100%",
height: "100%",
transform: `translate(${cameraTx}px, ${cameraTy}px) scale(${cameraScale})`,
transformOrigin: "50% 50%",
willChange: "transform",
}}
>
{/* TOP BAR + BODY */}
</div>
커서 + 클릭 리플 SVG는 이 래퍼 내부에 배치하여 크롬과 함께 크기가 조정되고 대상에 고정되도록 합니다.
B2. 먼저 클릭한 다음 확대/축소하세요
시청자는 클릭 대상을 맥락 속에서 보고, 그 다음 결과를 위해 확대/축소되어 이동해야 합니다. 순서:
프레임 130 커서가 버튼에 접근
프레임 174 클릭 리플
프레임 184 버튼이 "Running…" 표시
프레임 188 카메라 확대 시작 (1.0 → 1.55+ 이상, 약 30프레임에 걸쳐)
프레임 220+ 확대 유지 — 전달 계단식 / 결과 / 위로 스크롤 공개가 여기서 발생
먼저 확대한 다음 클릭하면 프레젠테이션 슬라이드처럼 느껴집니다. 먼저 클릭한 다음 확대하면 사용자가 작업을 수행하고 카메라가 따라온 것처럼 느껴집니다.
B3. 실제로 크롬을 캔버스 밖으로 밀어내는 배율을 선택하세요.
1.1배는 거의 변화가 없습니다. "상단 표시줄이 캔버스 상단을 벗어나게" 하려면 초점을 캔버스 중앙으로 가져오는 이동과 함께 ≥ 1.5배가 필요합니다. 목표 ≥ (canvasHalfHeight) / (초점에서 상단 표시줄까지의 거리) 계산 — y=540 행과 64px 상단 표시줄의 경우 ≥ ~1.5배입니다. "뷰포트 채우기"의 기본값으로 1.55–1.85배를 사용하세요.
C. 커서 클릭 대상
C1. 실제 요소를 정확히 클릭하세요
커서가 잘못된 버튼(+ New Skill 대신 모델 선택기 알약)에 놓이면 시청자는 데모가 고장났다고 생각합니다. 레이아웃에서 매번 대상을 다시 파생하세요 — 픽셀 값을 추측하지 마세요.
padding: "0 22px"가 있는 플렉스 오른쪽 정렬 컨트롤 스트립의 경우:
// 오른쪽 가장자리 → 22 패딩 → 벨(32) → 14 → 모델(~290) → 14 → New Skill(~120) → 14 → Find skills(~150)
NEW_SKILL_PILL_X = 1920 - 22 - 32 - 14 - 290 - 14 - 60 // = 1488 (버튼 중앙)
FIND_PILL_X = 1920 - 22 - 32 - 14 - 290 - 14 - 120 - 14 - 75 // = 1339
상수를 얻었으면 커서 접근 보간과 커서 이탈 보간 모두에서 이를 사용하여 클릭 리플이 알약 위에 정확히 떨어지고 그 오른쪽으로 200px 떨어지지 않도록 하세요.
C2. 커서가 접근할 때 대상을 강조 표시하세요.
공유 헤더 컴포넌트(예: StudioHeader의 findActive, newSkillActive)에 *Active prop을 추가하여 커서 장면이 접근 + 클릭 창 동안 이를 활성화하도록 합니다. 버튼은 다음을 얻습니다:
- 1.08배 크기
box-shadow: 0 0 0 4px rgba(99,102,241,0.30)을 통한 부드러운 인디고 또는 보라색 링transition: all 0.15s ease
D. 하이라이트 및 사각형
D1. 하이라이트 사각형은 콘텐츠 너비이며, 전체 줄이 아닙니다.
사용자가 두 개의 터미널 줄 주위에 빨간색 사각형을 원할 때 상위 flex 열을 감싸지 마십시오 — 그러면 행 전체에 걸쳐 늘어납니다. 다음을 사용하세요:
<div
style={{
display: "inline-flex",
flexDirection: "column",
alignSelf: "flex-start",
width: "fit-content",
border: "2px solid #dc2626",
borderRadius: 6,
padding: "10px 16px",
backgroundColor: "transparent",
}}
>
{/* 두 줄, 그 이상은 없음 */}
</div>
사각형 밖에 있어야 하는 것(예: 세 번째 "Generating component…" 줄)은 하위 요소가 아닌 형제 요소여야 합니다.
D2. 주석: 타원보다 사각형을 선호하세요.
행 주위의 손으로 그린 스타일 사각형 획은 "캔버스의 하이라이터"로 읽히며, 이는 대부분의 사용자가 "이것을 강조 표시"할 때 의미하는 바입니다. 타원은 장식적으로 느껴질 수 있습니다.
<svg viewBox="0 0 1000 100" preserveAspectRatio="none">
<rect
x="6" y="6" width="988" height="88" rx="6" ry="6"
fill="none"
stroke="#ea580c"
strokeWidth="3.6"
strokeDasharray="2160"
strokeDashoffset={2160 * (1 - progress)}
/>
</svg>
D3. 주황색(#ea580c)은 "새로운 것"을, 빨간색(#dc2626)은 "버그"를 표시하는 데 사용하세요.
동일한 데모가 둘 다를 전달할 수 있습니다. 섞지 마세요.
E. 제품 크롬의 레이아웃 패턴
E1. Studio 헤더는 단일 공유 컴포넌트입니다.
다음 표준 레이아웃을 가진 하나의 StudioHeader.tsx를 사용하고 모든 Studio 장면에서 호출하세요:
- 왼쪽: 로고 이미지(40 × 40 PNG) + "Skill Studio" 워드마크 + 브레드크럼
[Authoring|Available] / [scope] / [folder] / [skill] - 오른쪽: 🔍 Find skills
[⌘K]· ✦ + New Skill · ● Model selector · 🔔 Bell
breadcrumb, bellBadge, findActive, newSkillActive를 props로 전달하세요. 그러면 모든 장면의 헤더가 픽셀 단위로 안정적입니다.
E2. 사이드바에는 AVAILABLE 위에 일정한 필터 입력이 있습니다.
모든 Studio 사이드바(Browse, Update, AuthorEvals, ConsumeInstall, AuthorEditAndPublish)는 AVAILABLE 트리 위에 동일한 Filter skills… 입력을 얻습니다. 사용자가 이미 검색한 슬라이드에서는 상황에 맞는 쿼리(frontend-design)로 미리 채우세요.
E3. 사이드바 너비 및 타이포그래피
- 너비: 400 px (또는 깊게 중첩된 트리가 있는 슬라이드의 경우 460 px)
- 외부 패딩: 24–30 px
- 그룹 헤더(
AVAILABLE,AUTHORING): 18–19 pt, 자간 1.6, 굵기 700 - 하위 헤더(
SKILLS,.CLAUDE): 15–16 pt, 자간 1.4 - 행 텍스트: 17–19 pt
- 버전 알약: 13–14 pt 고정 폭, 1px 테두리, 패딩 3/10
- 세로 간격: 섹션 간 12–14 px, 섹션 헤더 위 22–36 px
좁고 빽빽한 사이드바는 설정 패널처럼 느껴집니다. 넓고 개방된 사이드바는 실제 제품 UI처럼 느껴집니다.
F. 제자리 상태 전환
F1. 하나의 화면처럼 느껴져야 하는 장면 사이에서 왼쪽으로 슬라이드하지 마세요.
"설치 클릭 → 트리가 새 스킬로 업데이트"가 하나의 연속적인 상호 작용으로 읽혀야 하는 경우:
- 다음 장면에서
transitionType: null을 설정 또는 두 장면을 하나로 병합 - 장면 간에 크롬을 동일하게 유지
- 변경되는 요소(카운터 뒤집기, 쉐브론 회전, 행 슬라이드 인)를 애니메이션 처리 — 전체 페이드를 하지 마세요.
F2. 새 항목을 강력하게 강조 표시하세요.
복숭아색 배경 + 2px 실선 주황색 링 + 그림자 + ✓ Just installed 콜아웃 알약은 "방금 추가됨"에 적합한 강도입니다. 미묘한 배경 색조는 기본 상태로 읽히고 시청자가 알아채지 못합니다.
backgroundColor: "#fff5ee",
boxShadow: `0 0 0 2px ${ORANGE}, 0 8px 22px rgba(234,88,12,0.22)`,
F3. 카운터 뒤집기: 펄스 후광 + 쉐브론 회전
카운트가 변경될 때(PROJECT (0) → (1)):
- 쉐브론
▸ → ▼회전 (200ms 전환) - 카운트 뒤에 짧은 주황색 후광 렌더링: 불투명도
0.45 → 0, 배율0.4 → 2.2(18프레임에 걸쳐) - 새 하위 행을
translateY: -12 → 0으로 슬라이드 인 (24프레임에 걸쳐)
G. 편집기 / SKILL.md 편집 패턴
G1. 필수 필드는 제거하지 말고 교체하세요.
스킬에는 항상 description이 있어야 합니다. 설명을 업그레이드하려면: 빨간색으로 초기 줄을 취소선 처리하고, 새 설명을 슬라이드 인
... (잘림)