Official비디오 & 애니메이션github.com

remotion-markup

콘텐츠, 애니메이션 및 효과 모범 사례

remotion-markup란 무엇인가요?

이 스킬은 Remotion을 사용한 React 기반 비디오 마크업 작성에 관한 포괄적인 지침을 제공합니다. 개발자가 비디오 컴포지션 내에서 애니메이션, 타이밍, 미디어 에셋, 효과를 올바르게 구현할 수 있도록 돕습니다. `useCurrentFrame()`과 `interpolate()`를 사용한 애니메이션 구동 방법, 미디어 프리마운트 최적화, 스튜디오 편집을 고려한 대화형 컴포넌트 구조화, `Effects`를 통한 비주얼 이펙트 적용 등을 다룹니다. Claude Code, Cursor, Codex 등 다양한 AI 에이전트 플랫폼에서 사용할 수 있으며, Remotion의 공식 모범 사례를 기반으로 잘못된 CSS 트랜지션 사용이나 비인라인 트랜스폼과 같은 일반적인 함정을 피할 수 있도록 안내합니다. 단일 씬, 멀티 씬 비디오, 연결된 컴포지션, 텍스트 강조, 보이스오버, 지도, 전환 및 모션 블러까지 모든 Remotion 프로젝트 유형에 필요한 세부 지침이 포함되어 있습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/remotion-dev/skills/tree/main/skills/remotion-markup

Installed? Explore more 비디오 & 애니메이션 skills: steipete/video-frames, steipete/summarize, openclaw/openclaw · View all 6 →

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

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

미리보기

스킬 README에서

문서

이는 Remotion React 마크업 작성을 위한 지침입니다. 이 지침이 적절하지 않다면 대신 Remotion 모범 사례를 참조하세요.

사용자 변경 사항 유지

사용자는 대화 외부에서 코드를 편집할 수 있습니다.

해당 사이에 예상치 못한 변경 사항이 발견되면 덮어쓰지 말고 의도적인 것으로 간주하거나 확인을 요청하세요.

일반 규칙

컴포지션 또는 씬 컴포넌트 내에서 useVideoConfig()에서 fps를 가져와 from, trimBefore, durationInFrames, premountFor와 같은 타이밍 속성을 포함한 모든 초-프레임 계산에 사용하세요. JSX 노드에 표현식을 유지하면(예: trimBefore={4 * fps}) 스튜디오에서 타이밍을 편집할 수 있으며 컴포지션 프레임 속도가 변경되어도 올바르게 유지됩니다.

useCurrentFrame()과 interpolate()를 사용하여 애니메이션을 구동하세요. CSS transition 또는 animation은 올바르게 렌더링되지 않으므로 리팩터링해야 합니다. Tailwind 애니메이션 클래스는 올바르게 렌더링되지 않으므로 리팩터링해야 합니다.

Easing.bezier() 및 Easing.spring()을 사용하여 타이밍을 사용자 정의하세요.

Remotion 상호작용 모범 사례에 따라 마크업을 구조화하세요. 편집 가능한 속성이 있는 씬에는 Interactive.withSchema({wrapInSequence: true, layout: 'absolute-fill'})를 선호하세요. 내부 마크업은 프래그먼트를 반환할 수 있으며, 래퍼가 레이아웃과 인스턴스 스타일을 처리합니다. 로어 써드와 같은 크기가 지정된 요소는 기본 레이아웃을 유지하고 style을 자체 루트에 전달할 수 있습니다. 재사용 가능한 씬을 연결된 컴포지션으로 등록하세요. 타이밍을 지원하는 컴포넌트에 직접 타이밍을 배치하고, 불필요한 <Sequence> 래퍼를 피하세요. premountFor를 지원하는 모든 타이밍 컴포넌트에 1초의 프리마운트를 제공하세요. premountFor={fps} (여기서 fps는 useVideoConfig()에서 가져옴). 미디어, 상호작용 컴포넌트, <Sequence>, <TransitionSeries.Sequence>, 및 <TransitionSeries.Overlay>에 적용하세요. 여기에는 씬 내부에 중첩된 타이밍 컴포넌트도 포함됩니다. 중첩된 항목이 부모가 시작되기 전에 마운트되어야 하는 경우 부모 타임라인 항목도 프리마운트하세요. <TransitionSeries.Transition>과 같이 premountFor가 없는 컴포넌트는 대체가 필요하지 않습니다.

스튜디오는 항목을 생성한 JSX 소스 노드를 편집합니다. 모든 컴포지션 등록, 클립, 씬, 레이어 및 시퀀스를 자체 JSX 노드로 작성하고 편집 가능한 속성을 인라인으로 포함하세요. 프로그래매틱 루프는 생성된 인스턴스가 의도적으로 하나의 소스 템플릿으로 제어되는 경우에 적합하며, 사용자가 인스턴스를 개별적으로 편집해야 하는 경우에는 적합하지 않습니다.

import { useCurrentFrame, useVideoConfig, Easing, interpolate, Interactive } from "remotion";

export const FadeIn = () => {
  const frame = useCurrentFrame();
  const {fps} = useVideoConfig();

  return (
    <Interactive.Div
      name="Title"
      premountFor={fps}
      style={{
        opacity: interpolate(frame, [0, 2 * fps], [0, 1], {
          extrapolateRight: "clamp",
          extrapolateLeft: "clamp",
          easing: Easing.bezier(0.16, 1, 0.3, 1),
        }),
      }}
    >
      Hello World!
    </Interactive.Div>
  );
};

interpolate() 호출을 style 속성에 인라인으로 유지하세요. transform 대신 scale, translate, rotate CSS 속성을 사용하세요.

// 👍 인라인 편집 가능한 키프레임 및 트랜스폼 단축키
style={{
  scale: interpolate(frame, [0, 100], [0, 1], {
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
    easing: Easing.spring({damping: 200}),
    output: 'perceptual-scale' // `scale` 애니메이션의 경우 "output: 'perceptual-scale'" 사용
  }),
  translate: interpolate(frame, [0, 100], ["0px 0px", "100px 100px"], {
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
    easing: Easing.spring({damping: 200}),
  }),
  rotate: interpolate(frame, [0, 100], ["20deg", "90deg"], {
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
    easing: Easing.spring({damping: 200}),
  }),
}}

// 👎 인라인이 아닌 값과 트랜스폼 문자열은 스튜디오에서 편집하기 어려워짐
const scale = interpolate(frame, [0, 100], [0, 1]);

style={{
  transform: `scale(${scale})`,
}}

에셋

프로젝트 루트의 public/ 폴더에 에셋을 배치하세요. public/ 폴더의 파일을 참조하려면 staticFile()을 사용하세요.

미디어 컴포넌트

@remotion/media에서 <Video> 및 <Audio>를 사용하여 비디오와 오디오를 추가하세요. <CanvasImage> 컴포넌트를 사용하여 이미지를 추가하세요. <AnimatedImage>를 사용하여 애니메이션 GIF, APNG, WebP 또는 AVIF 이미지를 추가하고, Chrome을 사용하지 않는 경우 @remotion/gif를 사용하세요. public/의 파일에 대해서는 staticFile()을 사용하거나 원격 URL을 직접 전달하세요:

import { Audio, Video } from "@remotion/media";
import { staticFile, CanvasImage, AnimatedImage, useVideoConfig } from "remotion";

export const MyComposition = () => {
  const {fps} = useVideoConfig();

  return (
    <>
      <Video src={staticFile("video.mp4")} premountFor={fps} style={{ opacity: 0.5 }} />
      <Audio src={staticFile("audio.mp3")} premountFor={fps} />
      <CanvasImage
        src={staticFile("logo.png")}
        premountFor={fps}
        style={{ width: 100, height: 100 }}
      />
      <Video src="https://remotion.media/video.mp4" premountFor={fps} />
      <AnimatedImage src={staticFile('nyancat.gif')} premountFor={fps} />
    </>
  );
};

컴포지션이 주로 비디오 또는 오디오 클립의 타임라인인 경우, 소스 구조를 선택하기 전에 video-editing.md를 읽으세요.

예제 씬

배경 비디오와 로어 써드가 있는 씬입니다. 로어 써드는 자체 타임라인을 가진 상호작용 컴포넌트이며, 연결된 컴포지션으로 등록됩니다. 그 텍스트는 children으로 전달되고 accentColor는 편집 가능한 속성입니다. 페이드 인은 호출 위치에서 인라인으로 키프레임이 적용됩니다.

// MyScene.tsx
import { Video } from "@remotion/media";
import { Easing, interpolate, useCurrentFrame, useVideoConfig } from "remotion";
import { LowerThird } from "./LowerThird";

export const MyScene = () => {
  const { fps } = useVideoConfig();
  const frame = useCurrentFrame();

  return (
    <>
      <Video
        name="Background"
        src="https://remotion.media/video.mp4"
        premountFor={fps}
        objectFit="cover"
        style={{
          position: "absolute",
          width: "100%",
          height: "100%",
        }}
      />
      <LowerThird
        name="Lower third"
        from={1 * fps}
        premountFor={fps}
        accentColor="#0b84f3"
        style={{
          opacity: interpolate(frame, [1 * fps, 2 * fps], [0, 1], {
            extrapolateRight: "clamp",
            extrapolateLeft: "clamp",
            easing: Easing.bezier(0.16, 1, 0.3, 1),
          }),
        }}
      >
        Jane Doe, Product Designer
      </LowerThird>
    </>
  );
};
// LowerThird.tsx
import type React from "react";
import { Interactive, type InteractivitySchema } from "remotion";

type LowerThirdProps = {
  readonly children: React.ReactNode;
  readonly accentColor: string;
  readonly style?: React.CSSProperties;
};

const LowerThirdInner: React.FC<LowerThirdProps> = ({
  children,
  accentColor,
  style,
}) => {
  return (
    <Interactive.Div
      style={{
        position: "absolute",
        left: 80,
        bottom: 80,
        display: "flex",
        alignItems: "center",
        gap: 20,
        backgroundColor: "white",
        borderRadius: 16,
        padding: "20px 32px",
        color: "black",
        fontFamily: "Helvetica, Arial, sans-serif",
        fontSize: 48,
        fontWeight: 600,
        ...style,
      }}
    >
      <div
        style={{
          width: 8,
          alignSelf: "stretch",
          borderRadius: 4,
          backgroundColor: accentColor,
        }}
      />
      {children}
    </Interactive.Div>
  );
};

const lowerThirdSchema = {
  ...Interactive.childrenSchema,
  accentColor: {
    type: "color",
    default: "#0b84f3",
    description: "강조 색상",
  },
} as const satisfies InteractivitySchema;

export const LowerThird = Interactive.withSchema({
  Component: LowerThirdInner,
  componentName: "LowerThird",
  schema: lowerThirdSchema,
  wrapInSequence: true,
});
import { Composition } from "remotion";
import { LowerThird } from "./LowerThird";
import { MyScene } from "./MyScene";

export const RemotionRoot: React.FC = () => {
  return (
    <>
      <Composition
        id="MyScene"
        component={MyScene}
        durationInFrames={60}
        fps={30}
        width={1280}
        height={720}
      />
      <Composition
        id="LowerThird"
        component={LowerThird}
        durationInFrames={30}
        fps={30}
        width={1280}
        height={720}
        defaultProps={{
          children: "Jane Doe, Product Designer",
          accentColor: "#0b84f3",
        }}
      />
    </>
  );
};

지연 및 트리밍

지원되는 컴포넌트에 직접 타이밍을 배치하세요. 지원되는 속성, 예제 및 연산 순서는 타이밍 속성을 참조하세요.

지도

비디오에 지도를 포함하려면 Remotion 지도를 참조하세요.

텍스트 강조 및 주석

텍스트 강조(하이라이트 마커), 원, 밑줄, 취소선, 크로스아웃 텍스트, 상자에 대한 내용은 text-highlights.md를 참조하세요.

멀티 씬 비디오

여러 개의 연속된 씬이 있는 비디오를 계획 중이라면 multi-scene-video.md를 참조하세요.

연결된 컴포지션

씬 또는 레이어 그룹에 자체 편집 가능한 타임라인이 필요한 경우 connected-compositions.md를 따르세요. 멀티 씬 비디오에서 중요한 씬에 대해 이 구조를 선호하세요.

사전 컴포즈 작업

Pre-compose Ambient glow (src/BarChart.tsx:134)와 같은 스튜디오 요청의 경우, 주어진 위치에서 선택된 시퀀스 마크업을 찾으세요. connected-compositions.md에 따라 연결된 컴포지션을 만드세요: 마크업을 명명된 컴포넌트로 추출하고, 가능하면 Interactive.withSchema({wrapInSequence: true})로 상호작용하게 만든 후, 동일한 내보내진 컴포넌트 참조를 루트에 고유한 <Composition>으로 등록하세요. 상호작용 컴포넌트를 타이밍 속성과 함께 직접 렌더링하거나, 해당 래퍼에 목적이 있을 때 시퀀스의 유일한 자식으로 렌더링하세요. 선택된 노드가 이미 시퀀스인 경우 해당 속성을 유지하고 자식을 추출하세요. 등록에는 부모 사용과 동등한 defaultProps와 함께 차원, fps, duration이 필요합니다. 등록된 컴포지션 없이 컴포넌트를 추출하는 것은 사전 컴포즈 요청을 완료하지 않습니다.

fontFamily 및 글꼴 로딩과 같은 상속된 스타일을 추출된 컴포넌트로 가져오세요. 부모 독립성을 참조하세요.

음성 해설

Remotion 컴포지션에 ElevenLabs TTS를 사용한 AI 생성 음성 해설을 추가하려면 voiceover.md를 참조하세요.

비디오 임베딩

트리밍, 볼륨, 속도, 루핑, 피치와 같은 비디오 임베딩에 대한 고급 지식은 embedding-videos.md를 참조하세요.

오디오 임베딩

트리밍, 볼륨, 속도, 피치와 같은 고급 오디오 기능은 audio.md를 참조하세요.

크롭

컴포넌트의 가시적인 사각형을 크롭해야 하는 경우 cropping.md를 참조하세요.

전환

씬 전환 패턴은 transitions.md를 참조하세요.

모션 블러

모션 블러 또는 움직임 흔적을 추가할 때는 선호되는 HTML-in-canvas 접근 방식, 미리보기 요구 사항 및 대안에 대해 motion-blur.md를 읽으세요.

시각 및 픽셀 효과

시각 효과를 추가할 때는 먼저 영향을 받을 요소 또는 그룹을 식별하세요. 대상 컴포넌트가 effects를 지원하고 아래 내장 효과가 요청과 일치하는 경우, CSS 근사치보다 해당 효과를 선호하세요. 예를 들어, 비네트 효과가 해당 비디오에 영향을 주어야 할 때 <Video>의 effects 속성에 직접 vignette()을 적용하세요.

다음 컴포넌트는 직접 effects를 허용합니다:

Import fromComponents
remotion<Img>, <CanvasImage>, <AnimatedImage>, <Solid>, <HtmlInCanvas>
@remotion/media<Video>
@remotion/gif<Gif>
@remotion/rive<RemotionRiveCanvas>
@remotion/shapes<Arrow>, <Callout>, <Circle>, <Ellipse>, <Heart>, <Pie>, <Polygon>, <Rect>, <Spark>, <Star>, <Triangle>

일반 HTML 요소, <Interactive.*> DOM 래퍼, <AbsoluteFill> 및 <Sequence>는 직접 effects를 허용하지 않습니다. 해당 콘텐츠에 효과를 적용하려면 <HtmlInCanvas>로 감싸고 래퍼에 effects 속성을 배치하세요.

다른 요소의 경우 적절한 경우 일반 HTML 및 CSS를 선호하세요. 전체 그룹을 후처리하는 것이 적절하고 환경이 지원하는 경우 그룹을 <HtmlInCanvas>로 감싸는 것을 고려하세요.

효과를 적용하기 전에 가져오기, 매개변수 및 설정에 대해 effects.md를 읽으세요. 또한 일치하는 내장 효과가 없을 때 createEffect()를 사용한 재사용 가능한 사용자 정의 효과를 다룹니다.

사용 가능한 효과

@remotion/effects의 내장 효과:

  • 색상 및 톤: brightness(), colorCorrection(), colorKey(), contrast(), duotone(), exposure(), grayscale(), hue(), invert(), levels(), linearGradient(), linearGradientTint(), lut(), saturation(), shadowsHighlights(), thermalVision(), tint(), vibrance(), whiteBalance().
  • 블러 및 흔적: blur(), lightTrail(), linearProgressiveBlur(), radialProgressiveBlur(), regionBlur(), radialBlur(), motionBlur(), directionalBlur(), zoomBlur(), trail().
  • 광학 및 렌즈: chromaticAberration(), depthOfField(), lensDistortion(), lensFlare(), vignette(), glow().
  • 스타일화: displacement(), emboss(), glitch(), noise(), pixelate(), posterize(), sepia(), sketch(), watercolor(), crt().
  • 에지 및 디테일: edges(), sharpen(), sobel(), canny().
  • 텍스처 및 오버레이: chromaKey(), lumaKey(), overlay(), pattern(), checkerboard(), gradientMap(), colorOverlay(), texture(), bumpMap(), normalMap(), displacementMap().
  • 블렌드 모드: blend(), multiply(), screen(), overlay(), darken(), lighten(), colorDodge(), colorBurn(), hardLight(), softLight(), difference(), exclusion().
  • 변환: flip(), flop(), mirror(), tile(), repeat(), wrap().
  • 매트 및 마스크: matteChroma(), matteLuma(), mask(), erase().
  • 사용자 정의: createEffect()로 자체 효과를 만드세요.

Individual skills in this repo

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

관련 스킬