Communitygithub.com

Remotion Compose

자연어 동영상 브리프를 완전하고 미리보기 가능한 Remotion 컴포지션으로 변환합니다. 지속 시간, 장면, 브랜드 색상, 종횡비 및 실제 카피를 추출하고 프레임 예산을 계획하며 useCurrentFrame, interpolate, spring, AbsoluteFill, Sequence를 사용하는 데이터 중심 React/TypeScript를 작성합니다.

Remotion Compose란 무엇인가요?

Remotion Compose는 개발자가 자연어로 된 동영상 요청을 완전한 Remotion 컴포지션으로 즉시 변환할 수 있도록 설계된 AI 에이전트 스킬입니다. 이 스킬은 사용자가 '20초 동영상 만들어 줘'와 같은 간단한 프롬프트를 입력하면 자동으로 지속 시간, 장면 목록, 브랜드 색상, 종횡비, 실제 카피를 추출하고, Remotion의 핵심 API(useCurrentFrame, interpolate, spring, Sequence, AbsoluteFill)를 사용하여 완전한 React/TypeScript 컴포넌트를 생성합니다. 생성된 컴포넌트는 `src/compositions/` 폴더에 저장되고 `src/Root.tsx`에 등록되어 Remotion Studio에서 즉시 미리보기 또는 `remotion-render`로 렌더링할 수 있습니다. 이 스킬은 제품 데모, 워크스루, 기능 소개, 마케팅 애니메이션 등 다양한 비디오 유형을 지원하며, 모든 애니메이션 값이 `useCurrentFrame()`의 순수 함수로 계산되도록 보장하여 스크러빙 시 일관된 결과를 제공합니다.

지원 대상~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/SkillMedev/tutorial-video-studio/tree/main/skills/remotion-compose

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Remotion Compose은(는) 무엇을 하나요?

당신은 자연어 브리프를 완전하고 미리보기 가능한 Remotion 컴포지션 - 프레임 기반 애니메이션이 적용된 실제 React/TypeScript 코드로 변환합니다. 출력물은 src/compositions/ 폴더의 .tsx 파일이며 src/Root.tsx에 등록되어 사용자가 즉시 Studio에서 스크러빙하거나 remotion-render에 넘길 수 있습니다.

제품 데모, 워크스루, 기능 소개, 마케팅 애니메이션을 만들거나 생성하거나 애니메이션화하거나 "X를 보여주는 20초 동영상 코드를 작성해줘"와 같은 요청이 있을 때 트리거됩니다.

1단계 - 브리프 추출

아래 정보를 확보하기 전까지 코딩을 시작하지 마세요. 한 번에 간결하게 질문하고, 명백한 공백은 질문을 멈추지 않고 합리적인 기본값으로 채우세요.

  1. 지속 시간(초) 및 fps(기본값 30 - 제품 및 마케팅 동영상의 표준이며 60fps의 렌더링 비용 절반. 미세한 커서 움직임이나 스크롤 UI를 애니메이션화할 때만 60fps를 사용하며, 30fps는 눈에 띄게 끊깁니다.)
  2. 장면 - 순서대로 발생하는 일. "앱 데모"보다 "로고, 세 가지 기능, CTA"와 같은 비트 목록을 요구하세요.
  3. 브랜드 - 기본/강조/배경 헥스 색상 및 글꼴 (@remotion/google-fonts 패밀리 이름).
  4. 종횡비 / 플랫폼 - 16:9 가로(1920×1080), 9:16 세로(1080×1920, 소셜용) 또는 1:1 정사각형(1080×1080).
  5. 카피 - 실제 헤드라인/기능 이름/CTA 텍스트. 제품 주장을 절대 지어내지 말고 실제 단어를 요청하세요.

모든 곳에서 초를 프레임으로 변환하세요: durationInFrames = seconds * fps. 일반적인 총 길이: 소셜/제품 데모는 15-60초, 광고 컷은 6-15초.

2단계 - 장면 계획 수립

동영상당 하나의 <Composition>, 장면당 하나의 컴포넌트, <Sequence>로 타임라인에 연결합니다. 코드를 작성하기 전에 프레임 예산을 계획하세요:

Total: 20s @ 30fps = 600 frames
  Intro (logo)        frames   0-90    (Sequence from=0   durationInFrames=90)
  Feature 1           frames  90-240   (Sequence from=90  durationInFrames=150)
  Feature 2           frames 240-390   (Sequence from=240 durationInFrames=150)
  Feature 3           frames 390-540   (Sequence from=390 durationInFrames=150)
  CTA outro           frames 540-600   (Sequence from=540 durationInFrames=60)

예산 수립 시 페이싱 임계값:

  • 텍스트가 있는 모든 비트는 최소 2초(30fps에서 60프레임)를 확보하세요 - 진입 애니메이션 및 유지 시간 포함. 헤드라인은 단어당 약 150-200ms의 유지 시간이 필요하여 읽을 수 있습니다. 6단어 헤드라인은 도착 후 약 1초의 유지 시간이 필요합니다.
  • 진입 애니메이션: 10-20프레임. 크로스페이드 및 종료: 12-15프레임. 더 길면 느리게, 더 짧으면 결함처럼 보입니다.
  • 의도적인 플래시 컷이 아닌 한 45프레임보다 짧은 장면은 없습니다.

<Sequence from={F}>는 자식의 로컬 시계를 이동시켜 해당 컴포넌트 내부에서 useCurrentFrame()이 0부터 시작하도록 합니다. 각 장면을 프레임 0에서 시작하는 것처럼 애니메이션화하세요.

3단계 - 핵심 API 참조

  • useCurrentFrame() - 현재 프레임(시계). 모든 것은 이것의 함수로 애니메이션화됩니다.
  • useVideoConfig() - { fps, width, height, durationInFrames }.
  • interpolate(frame, [inFrames], [outValues], opts) - 선형 매핑. 진입/종료 시 항상 { extrapolateLeft: "clamp", extrapolateRight: "clamp" }를 전달하여 값이 범위를 벗어나지 않도록 합니다.
  • spring({ frame, fps, config }) - 물리 기반 0→1(약간 오버슈트). 살아있는 느낌이 필요한 모든 것(팝, 슬라이드, 스케일 인)에 사용하세요.
  • AbsoluteFill - 전체 프레임 절대 위치 div; 모든 장면의 기본 레이어.
  • Sequence - 자식의 시간 이동 및 시간 제한(장면 스케줄러).
  • Series / Series.Sequence - from 오프셋을 수동으로 계산하지 않고 연속 장면.
  • Img, staticFile - 6단계 참조.

4단계 - spring() vs interpolate()

spring()을 사용해야 할 때…interpolate()를 사용해야 할 때…
물리적 느낌이 필요한 동작 - 팝, 바운스, 스케일 인, 슬라이드 인정확하고 선형적인 제어가 필요한 경우 - 특정 프레임 간
자연스러운 안정/오버슈트가 필요한 경우페이드(불투명도 0→1), 색상 변화, 진행률 표시줄, 프레임 정확 타이밍이 필요한 모든 것
카드, 로고, 배지의 진입크로스페이드 및 종료 - 오버슈트가 어색하게 보일 수 있는 경우

패턴 - spring으로 변환을, interpolate로 불투명도를 구동합니다:

const { fps } = useVideoConfig();
const frame = useCurrentFrame();
const pop = spring({ frame, fps, config: { damping: 200 } });   // 0 → 1, 활발하게
const opacity = interpolate(frame, [0, 15], [0, 1], { extrapolateRight: "clamp" });
const scale = interpolate(pop, [0, 1], [0.8, 1]);

damping: 200은 작업용 구성입니다 - 빠르게 안정되고 거의 오버슈트가 없습니다. 낮은 damping(~10-20)은 눈에 띄게 바운스됩니다. 바운스가 목적인 경우에만 사용하세요.

5단계 - 표준 제품 데모 구조

브리프에서 달리 명시하지 않는 한 이 형태를 인코딩하세요: 로고/브랜드 소개 → N개 기능 호출 → CTA 아웃트로. 데이터 기반(6단계)으로 만들어 변형이 자유롭게 가능하도록 하세요.

// src/compositions/ProductDemo.tsx
import {
  AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig,
  interpolate, spring,
} from "remotion";
import { loadFont } from "@remotion/google-fonts/Inter";

const { fontFamily } = loadFont();

export type Feature = { title: string; body: string };
export type ProductDemoProps = {
  brand: string;
  colors: { bg: string; fg: string; accent: string };
  logoText: string;
  features: Feature[];
  cta: string;
};

const Intro: React.FC<{ text: string; colors: ProductDemoProps["colors"] }> = ({ text, colors }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const s = spring({ frame, fps, config: { damping: 200 } });
  const scale = interpolate(s, [0, 1], [0.7, 1]);
  const opacity = interpolate(frame, [0, 12], [0, 1], { extrapolateRight: "clamp" });
  return (
    <AbsoluteFill style={{ backgroundColor: colors.bg, justifyContent: "center", alignItems: "center" }}>
      <h1 style={{ fontFamily, fontSize: 120, color: colors.fg, transform: `scale(${scale})`, opacity }}>
        {text}
      </h1>
    </AbsoluteFill>
  );
};

const FeatureCallout: React.FC<{ feature: Feature; colors: ProductDemoProps["colors"] }> = ({ feature, colors }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const slide = spring({ frame, fps, config: { damping: 200 } });
  const x = interpolate(slide, [0, 1], [-60, 0]);
  const opacity = interpolate(frame, [0, 15], [0, 1], { extrapolateRight: "clamp" });
  return (
    <AbsoluteFill style={{ backgroundColor: colors.bg, justifyContent: "center", paddingLeft: 160 }}>
      <div style={{ transform: `translateX(${x}px)`, opacity }}>
        <div style={{ fontFamily, fontSize: 32, color: colors.accent, fontWeight: 700, letterSpacing: 2 }}>
          {feature.title.toUpperCase()}
        </div>
        <div style={{ fontFamily, fontSize: 64, color: colors.fg, maxWidth: 1100, marginTop: 16 }}>
          {feature.body}
        </div>
      </div>
    </AbsoluteFill>
  );
};

const Outro: React.FC<{ cta: string; colors: ProductDemoProps["colors"] }> = ({ cta, colors }) => {
  const frame = useCurrentFrame();
  const opacity = interpolate(frame, [0, 18], [0, 1], { extrapolateRight: "clamp" });
  return (
    <AbsoluteFill style={{ backgroundColor: colors.accent, justifyContent: "center", alignItems: "center" }}>
      <h2 style={{ fontFamily, fontSize: 84, color: colors.bg, opacity }}>{cta}</h2>
    </AbsoluteFill>
  );
};

export const ProductDemo: React.FC<ProductDemoProps> = ({ colors, logoText, features, cta }) => {
  const intro = 90;
  const per = 150;
  const outro = 60;
  return (
    <AbsoluteFill>
      <Sequence durationInFrames={intro}>
        <Intro text={logoText} colors={colors} />
      </Sequence>
      {features.map((f, i) => (
        <Sequence key={i} from={intro + i * per} durationInFrames={per}>
          <FeatureCallout feature={f} colors={colors} />
        </Sequence>
      ))}
      <Sequence from={intro + features.length * per} durationInFrames={outro}>
        <Outro cta={cta} colors={colors} />
      </Sequence>
    </AbsoluteFill>
  );
};

src/Root.tsx에 등록하고, 동일한 숫자로 durationInFrames를 계산하고 defaultProps를 제공하세요:

<Composition
  id="ProductDemo"
  component={ProductDemo}
  durationInFrames={90 + 3 * 150 + 60}
  fps={30}
  width={1920}
  height={1080}
  defaultProps={{
    brand: "Acme",
    colors: { bg: "#0B0B0F", fg: "#FFFFFF", accent: "#6C5CE7" },
    logoText: "Acme",
    features: [
      { title: "Fast", body: "Ship in seconds, not sprints." },
      { title: "Simple", body: "One prompt, one video." },
      { title: "Yours", body: "Your brand, your copy." },
    ],
    cta: "Start free →",
  }}
/>

세로/소셜의 경우 width={1080} height={1920}로 설정하고, 정사각형의 경우 1080×1080으로 설정합니다. 컴포넌트는 동일하게 유지하고 캔버스만 변경됩니다.

6단계 - 데이터 기반 props 및 정적 에셋

위의 컴포지션은 완전히 데이터 기반입니다. 모든 단어와 색상은 prop입니다. 이것이 핵심입니다 - 변형(새로운 카피, 새로운 팔레트, 지역화된 텍스트)은 재프롬프트가 필요 없으며 다른 props를 전달하기만 하면 됩니다 (remotion-render는 배치 처리를 위해 JSON 파일에서 이 작업을 수행합니다).

정적 에셋(로고, 스크린샷, 오디오)은 public/assets/에 있으며 staticFile()로 참조됩니다 - import나 raw 경로를 사용하지 마세요:

import { Img, staticFile } from "remotion";
<Img src={staticFile("assets/logo.png")} />

7단계 - 출력

완성된 파일을 src/compositions/<VideoName>.tsx에 저장하고 src/Root.tsx에 등록한 후 사용자에게 npx remotion studio(http://localhost:3000)로 미리보기를 안내하세요. 그런 다음 인계하세요: "Studio에서 스크러빙해 보세요. 변경할 점이 있으면 말씀해 주세요 - 너무 빠르다, 색상이 잘못되었다, 다른 카피가 필요하다 등 - 그러면 제가 수정하고 다시 렌더링하겠습니다 (remotion-render)."

금지 사항

  • CSS 전환/애니메이션이나 setTimeout/setInterval로 애니메이션화하지 마세요. Remotion은 프레임을 독립적으로 병렬 렌더링합니다. useCurrentFrame()에서 파생되지 않은 것은 브라우저 미리보기에서는 잘 보여도 최종 렌더링에서는 보이지 않거나 일관성이 없습니다.
  • 분산/입자 효과에 Math.random()을 사용하지 마세요 - 각 렌더링 워커가 다른 값을 얻어 프레임이 일치하지 않습니다. 결정론적 의사 난수성을 위해 Remotion의 random(seed)를 사용하세요.
  • delayRender() / continueRender() 없이 데이터를 가져오거나 비동기 작업을 기다리지 마세요 - 렌더러는 데이터가 도착하기 전에 프레임을 캡처합니다.
  • 장면 컴포넌트 내부에 fps, width, height를 하드코딩하지 마세요 - useVideoConfig()에서 읽어서 30↔60fps 또는 가로↔세로 전환이 타이밍과 레이아웃을 깨지 않도록 하세요.
  • 진입/종료 보간에서 extrapolateLeft/Right: "clamp"를 생략하지 마세요 - 불투명도가 1을 초과하고 요소가 범위를 벗어나 화면 밖으로 이동합니다.
  • 헤드라인, 기능 주장 또는 CTA를 지어내지 마세요 - 사용자의 실제 카피를 사용하고, 누락된 경우 물어보세요.

품질 기준

  • 모든 애니메이션 값은 useCurrentFrame()(및 props)의 순수 함수입니다 - Studio에서 뒤로 스크러빙해도 앞으로 재생하는 것과 동일하게 보입니다.
  • 계획의 프레임 예산은 Root.tsx의 durationInFrames와 정확히 일치하며, 텍스트 비트가 읽을 수 있는 최소 시간보다 적게 유지되지 않습니다.
  • 모든 카피와 색상은 defaultProps가 제공된 타입 props를 통해 전달됩니다 - 장면 컴포넌트에 리터럴이 포함되지 않습니다.
  • 에셋은 staticFile()을 통해 로드됩니다. 파일이 깔끔하게 등록되고 Studio에서 콘솔 오류 없이 미리보기가 가능합니다.

Individual skills in this repo

This repo contains 11 individual skills — each has its own dedicated page.

Captions From Transcript

Produce an accurate, properly timed caption track (SRT or WebVTT) from a video

Kinetic Typography

Put text in motion the right way - title cards, animated captions, lower-thirds, callouts, and word-by-word reveals - with a reading-time-per-word budget so copy holds long enough to read, plus enter/exit timing, weight and size transitions, and type hierarchy in motion. Use when someone asks to

Motion Design Principles

The craft layer for motion: pick the right easing (ease-in / ease-out / ease-in-out / spring), get timing and spacing right, build the anticipation→action→follow-through arc, and apply Disney

Narration Script

Write the spoken voiceover for a tutorial or demo - the actual words, phrased for the ear and synced one-instruction-per-action to what is on screen, with a pacing budget and a confident, jargon-checked tone. Use when someone says

Product Demo Director

Direct the craft of putting a real software UI on screen - cursor choreography, zoom/pan/callout language, screen-recording vs recreated-UI, and making state changes legible with highlights, focus pulls, and slow-downs. Use when filming or recreating an app for a product demo, feature walkthrough, onboarding clip, or release reel and asking

Remotion Render

Renders a Remotion composition to MP4 and runs the edit-and-re-render loop - CLI render commands, 1080p/4K/9:16 presets, concurrency tuning, codec selection, batch variants from a JSON data file, and Lambda for cloud rendering. Use when someone says

Remotion Setup

Scaffolds a new Remotion video project wired for Claude Code Agent Skills - Node check, create-video scaffold, skills install, folder conventions, Google Fonts, and a smoke-test render. Use whenever someone wants to start making videos with Remotion and Claude, even just

Screencast Capture

Capture clean raw screen and camera footage for a tutorial or product demo - choosing the recorder (macOS Screenshot toolbar, QuickTime, OBS, Windows Game Bar), setting resolution / frame-rate / cursor / microphone, prepping a distraction-free stage, and recording in retakeable segments. Use when someone says

SkillMedev/tutorial-video-studio

Plan a product demo, feature announcement, or launch video as a beat sheet and shot list BEFORE animating - hook in the first 3s, problem, reveal, proof, CTA - with target duration and pacing per scene type, output as a JSON scene plan that remotion-compose consumes directly. Use when someone says

Social Video Formatter

Reframe and export a finished video for social platforms - 9:16 ↔ 16:9 cropping, burned-in captions, a platform-native first frame, loop design, and per-platform specs (aspect, length, safe areas) for TikTok, Reels, Shorts, X, and LinkedIn. Use when someone says

Sound and Music Sync

Score a video like an editor: beat-match cuts to the music, land SFX on transitions, pace the voiceover so it breathes, source royalty-free tracks safely, and duck the music so the VO sits clearly on top. Use when adding music, sound effects, or voiceover to a video, when asked to

관련 스킬