Communitygithub.com

cdeistopened/skill-stack

Remotion(React)을 사용하여 프로그래매틱 비디오를 제작합니다. 이 스킬은 리소그래프 미학을 활용한 설명형 비디오 제작을 위한 시각 스타일 가이드, 애니메이션 패턴 및 워크플로우를 제공합니다. Skill Stack을 위한 짧은 형식의 동영상 콘텐츠를 만들 때 사용하세요.

skill-stack란 무엇인가요?

이 스킬은 React 컴포넌트를 비디오로 렌더링하는 Remotion 라이브러리를 사용하여 프로그래매틱 비디오를 제작하기 위한 완전한 워크플로우를 제공합니다. Skill Stack의 독특한 리소그래프(risograph) 인쇄 스타일에서 영감을 받은 시각적 미학을 인코딩하여, 버전 관리가 가능하고 재현 가능하며 무한히 편집 가능한 짧은 형식의 동영상(10-60초)을 만드는 데 중점을 둡니다. 색상 팔레트, 타이포그래피, 애니메이션 패턴(페이드 인/아웃, 스프링, 타자기 효과, 계단식 목록), 그레인 오버레이 등이 포함되어 있으며, 9:16(세로), 1:1(정사각형), 16:9(가로) 등 다양한 종횡비를 지원합니다. 이 스킬은 실제 작업 경험에서 얻은 장면 전환 타이밍, 폰트 크기, 그리고 '너무 빠른' 일반적인 함정을 피하는 방법에 대한 실용적인 교훈을 제공하므로, Claude Code, Cursor, Codex와 같은 AI 어시스턴트가 시각적으로 일관되고 매력적인 설명형 동영상 콘텐츠를 만드는 데 이상적입니다. 또한 타사 서비스(Whisper, ZapCap, Submagic)와의 캡션 통합을 위한 지침과 함께 커뮤니티 리소스(Discord, 템플릿, 패키지)도 포함되어 있어 완전한 비디오 제작 솔루션을 제공합니다.

지원 대상✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/cdeistopened/skill-stack/tree/main/.claude/skills/remotion-video

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

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

문서

Remotion 비디오 제작자

Remotion, 즉 React 컴포넌트를 비디오로 렌더링하는 도구를 사용하여 프로그래매틱 비디오를 만듭니다. 이 스킬은 Skill Stack의 시각적 스타일과 설명 콘텐츠 제작 과정에서 얻은 교훈을 인코딩합니다.

목적

독특한 리소그래프에서 영감을 받은 미학으로 Skill Stack 개념을 설명하는 짧은 형식의 비디오 콘텐츠(10-60초)를 제작합니다. 비디오는 코드이므로 버전 관리가 가능하고, 재현 가능하며, 무한히 편집할 수 있습니다.

이 스킬을 사용해야 할 때

  • Skill Stack 개념을 설명하는 설명 비디오 제작
  • 애니메이션 소셜 콘텐츠 제작 (세로 9:16, 정사각형 1:1, 가로 16:9)
  • 기술 워크플로우 또는 점진적 공개 시각화
  • 정확한 타이밍과 타이포그래피가 중요한 비디오

다음의 경우에는 적합하지 않습니다:

  • 실사 영상 편집 (기존 비디오 도구 사용)
  • 복잡한 3D 그래픽 (Remotion은 2D에 중점)
  • 빠른 일회성 그래픽 (Figma 또는 Canva 사용)

프로젝트 설정

빠른 시작

# 새 Remotion 프로젝트 생성
npx create-video@latest my-video

# 의존성 설치
cd my-video && npm install

# Google Fonts 추가
npm install @remotion/google-fonts

# 스튜디오 시작
npm run start  # http://localhost:3000 열림

파일 구조

my-video/
├── src/
│   ├── Root.tsx           # 구성 정의
│   ├── Main.tsx           # 메인 비디오 컴포넌트
│   └── components/        # 재사용 가능한 요소
├── package.json
├── remotion.config.ts
└── out/                   # 렌더링된 비디오

구성 설정 (Root.tsx)

각 비디오에 대해 항상 여러 종횡비를 만듭니다:

import { Composition, Folder } from "remotion";
import { MyVideo } from "./MyVideo";

export const RemotionRoot = () => (
  <>
    <Folder name="MyVideo">
      <Composition
        id="MyVideo-Vertical"
        component={MyVideo}
        durationInFrames={600}  // 30fps에서 20초
        fps={30}
        width={1080}
        height={1920}  // 9:16
      />
      <Composition
        id="MyVideo-Square"
        component={MyVideo}
        durationInFrames={600}
        fps={30}
        width={1080}
        height={1080}  // 1:1
      />
      <Composition
        id="MyVideo-Landscape"
        component={MyVideo}
        durationInFrames={600}
        fps={30}
        width={1920}
        height={1080}  // 16:9
      />
    </Folder>
  </>
);

시각 스타일: Skill Stack 리소그래프

색상 팔레트

const C = {
  paper: "#FAF8F5",    // 따뜻한 오프화이트 배경
  coral: "#D4694A",    // 강조, CTA, 하이라이트
  teal: "#1E4D4D",     // 헤더, 선택된 상태
  ink: "#1C1C1C",      // 본문 텍스트
  muted: "#666666",    // 보조 텍스트
  dimmed: "#AAAAAA",   // 삼차, 비활성화
  white: "#FFFFFF",    // 카드, 컨테이너
};

타이포그래피

import { loadFont as loadInter } from "@remotion/google-fonts/Inter";
import { loadFont as loadPlayfair } from "@remotion/google-fonts/PlayfairDisplay";
import { loadFont as loadJetBrains } from "@remotion/google-fonts/JetBrainsMono";

// 본문 텍스트, UI 레이블
const { fontFamily: inter } = loadInter("normal", {
  weights: ["400", "500", "600"],
  subsets: ["latin"],
});

// 헤드라인, 인용문, 감성 텍스트
const { fontFamily: playfair } = loadPlayfair("normal", {
  weights: ["400", "500", "600", "700"],
  subsets: ["latin"],
});

// 코드, 기술 콘텐츠, 스킬 이름
const { fontFamily: mono } = loadJetBrains("normal", {
  weights: ["400", "500"],
  subsets: ["latin"],
});

글꼴 크기 가이드라인

비디오의 최소 가독 가능 크기:

요소정사각형 (1080)세로 (1080w)가로 (1920w)
헤드라인64-84px64-84px72-96px
스킬 이름36-40px36-40px40-48px
본문 텍스트28-32px28-32px32-36px
레이블24-28px24-28px28-32px
주석22-24px22-24px24-28px

핵심 교훈: 생각보다 항상 더 크게. 비디오는 세부 사항을 압축합니다.

그레인 오버레이

const GrainOverlay: React.FC = () => {
  const frame = useCurrentFrame();

  return (
    <AbsoluteFill
      style={{
        pointerEvents: "none",
        opacity: 0.04,
        mixBlendMode: "multiply",
      }}
    >
      <svg width="100%" height="100%">
        <defs>
          <filter id="grain">
            <feTurbulence
              type="fractalNoise"
              baseFrequency="0.8"
              numOctaves="4"
              seed={Math.floor(frame / 4)}  // 그레인 애니메이션
            />
          </filter>
        </defs>
        <rect width="100%" height="100%" filter="url(#grain)" />
      </svg>
    </AbsoluteFill>
  );
};

애니메이션 패턴

핵심 도구

import {
  useCurrentFrame,
  useVideoConfig,
  AbsoluteFill,
  interpolate,
  spring,
  Sequence,
} from "remotion";

페이드 인/아웃

const fadeIn = interpolate(frame, [0, 30], [0, 1], {
  extrapolateLeft: "clamp",
  extrapolateRight: "clamp",
});

const fadeOut = interpolate(frame, [150, 180], [1, 0], {
  extrapolateLeft: "clamp",
  extrapolateRight: "clamp",
});

// 장면 불투명도 결합
<div style={{ opacity: fadeIn * fadeOut }}>

스프링 애니메이션

const { fps } = useVideoConfig();

// 부드러운 진입
const entrance = spring({
  frame: frame - 20,  // 20프레임 지연
  fps,
  config: { damping: 100 },  // 부드럽게, 바운스 없음
});

// 탄력적인 선택
const selectPulse = spring({
  frame: frame - 15,
  fps,
  config: { damping: 12, stiffness: 100 },  // 바운시
});

// 변환에 적용
<div style={{
  opacity: interpolate(entrance, [0, 1], [0, 1]),
  transform: `translateY(${interpolate(entrance, [0, 1], [20, 0])}px)`,
}}>

타자기 효과

const ScenePrompt: React.FC<{ frame: number }> = ({ frame }) => {
  const text = "여기에 프롬프트 텍스트를 입력하세요";
  const charsToShow = Math.floor(frame / 2);  // 30fps에서 초당 15자
  const visibleText = text.slice(0, charsToShow);
  const isTyping = charsToShow < text.length;
  const cursorBlink = Math.floor(frame / 18) % 2 === 0;

  return (
    <div>
      "{visibleText}
      {(isTyping || cursorBlink) && (
        <span style={{
          backgroundColor: C.coral,
          marginLeft: 4,
          opacity: cursorBlink ? 1 : 0,
        }}>
          {"\u00A0"}
        </span>
      )}
      {!isTyping && '"'}
    </div>
  );
};

계단식 목록 애니메이션

const ITEMS = ["item-1", "item-2", "item-3"];

{ITEMS.map((item, i) => {
  const delay = i * 25;  // 각 항목 사이 25프레임
  const s = spring({
    frame: Math.max(0, frame - delay - 20),
    fps,
    config: { damping: 100 },
  });

  return (
    <div
      key={item}
      style={{
        opacity: interpolate(s, [0, 1], [0, 1]),
        transform: `translateY(${interpolate(s, [0, 1], [20, 0])}px)`,
      }}
    >
      {item}
    </div>
  );
})}

장면 타이밍 가이드라인

지속 시간 계산

  • 30fps = 초당 30프레임
  • 10초 = 300프레임
  • 20초 = 600프레임

페이싱 교훈

너무 빠른 것이 #1 실수입니다. 시청자는 다음을 위해 시간이 필요합니다:

  1. 장면 변경을 알아차리기
  2. 텍스트 읽기
  3. 의미 처리하기
  4. 다음 변경 준비하기

최소 장면 지속 시간:

장면 유형최소편안함
타자기 텍스트3-4초5-6초
목록 나타나기4-5초6-8초
선택/하이라이트3-4초5초
기술 다이어그램4-5초6-8초
핀치라인/CTA2-3초3-4초

장면 중첩 패턴

장면은 하드 컷이 아닌 크로스 페이드되어야 합니다:

// 20초 비디오(600프레임)를 위한 장면 타이밍
{frame < 200 && <ScenePrompt frame={frame} />}
{frame >= 160 && frame < 340 && <SceneScan frame={frame - 160} />}
{frame >= 300 && frame < 460 && <SceneSelect frame={frame - 300} />}
{frame >= 420 && frame < 560 && <SceneLoad frame={frame - 420} />}
{frame >= 520 && <ScenePunchline frame={frame - 520} />}

40프레임의 중첩(1.3초)은 fadeIn/fadeOut 보간과 결합되어 부드러운 크로스 페이드를 만듭니다.


워크플로우

1단계: 스토리보드

코딩 전에 다음을 정의하세요:

  1. 핵심 메시지 - 시청자가 배워야 할 한 가지는 무엇인가요?
  2. 장면 분석 - 각각 하나의 아이디어를 가진 4-6개의 장면
  3. 전체 지속 시간 - 소셜용 10-20초, 설명용 30-60초
  4. 텍스트 콘텐츠 - 각 장면의 정확한 단어

2단계: 기본 구조 만들기

  1. 적절한 지속 시간으로 구성 만들기
  2. 플레이스홀더 콘텐츠로 장면 컴포넌트 구축
  3. 기본 타이밍(장면 범위) 설정
  4. 모든 장면이 나타나는지 테스트

3단계: 스타일링

  1. 색상 팔레트 및 글꼴 적용
  2. 그레인 오버레이 추가
  3. 글꼴 크기가 읽을 수 있는지 확인
  4. 휴대폰(세로)과 데스크탑(가로)에서 테스트

4단계: 애니메이션

  1. 각 장면에 fadeIn/fadeOut 추가
  2. 진입을 위한 스프링 애니메이션 추가
  3. 타이밍 미세 조정 - 거의 항상 더 느리게 해야 함
  4. 전체 재생을 여러 번 테스트

5단계: 렌더링

# 특정 구성 렌더링
npx remotion render MyVideo-Square out/square.mp4

# 모든 형식 렌더링
npx remotion render MyVideo-Vertical out/vertical.mp4
npx remotion render MyVideo-Square out/square.mp4
npx remotion render MyVideo-Landscape out/landscape.mp4

일반적인 실수

❌ 중앙 정렬 문제

문제: 콘텐츠가 왼쪽 상단 모서리에 나타납니다.

해결 방법: position: absolute 대신 flexbox와 함께 AbsoluteFill을 사용하세요.

// ✅ 올바름
<AbsoluteFill style={{
  justifyContent: "center",
  alignItems: "center",
}}>

// ❌ 틀림
<div style={{ position: "absolute", left: "50%", top: "50%" }}>

❌ 작은 글꼴

문제: 스튜디오에서는 텍스트를 읽을 수 있지만 휴대폰에서는 읽기 어렵습니다.

해결 방법: 본문 텍스트는 최소 28px, 헤드라인은 최소 64px.

❌ 너무 빠름

문제: 텍스트가 사라지기 전에 읽을 수 없습니다.

해결 방법: 초기 지속 시간 추정치를 두 배로 늘리세요. 각 장면은 최소 4-8초가 필요합니다.

❌ 하드 컷

문제: 장면 간 전환이 거칠습니다.

해결 방법: 장면을 30-50프레임 겹치고 fadeIn/fadeOut을 사용하세요.

❌ 종횡비 미지원

문제: 비디오가 다른 플랫폼에서 다르게 보입니다.

해결 방법: 처음부터 세 가지 구성(세로, 정사각형, 가로)을 모두 만드세요.


캡션 통합

Remotion은 일급 캡션 지원을 제공합니다. 비용별 세 가지 옵션:

옵션 1: 기본 Whisper (권장 - 무료)

npm install @remotion/captions @remotion/install-whisper-cpp
npx @remotion/install-whisper-cpp --model large-v3-turbo
import { transcribe } from "@remotion/captions";

const result = await transcribe({
  inputPath: "/path/to/audio.mp3",
  model: "large-v3-turbo",
  language: "en",
});
// result.captions = [{ text: "Hello", startTime: 0, endTime: 0.5 }, ...]

옵션 2: ZapCap API ($0.10/분)

로컬 모델 설정 없이 배치 처리를 위한 옵션입니다.

옵션 3: Submagic API ($0.69/분)

미리 스타일이 지정된 "바이럴" 캡션 템플릿이지만 비용이 많이 듭니다.

전체 워크플로우 세부 정보: references/caption-workflow.md 참조


커뮤니티 리소스

디스코드

Remotion 디스코드 - 6,000명 이상의 회원. 활성화된 #help 및 #showcase 채널. 제작자(Jonny Burger)가 직접 응답합니다.

공부할 주요 템플릿

템플릿사용 사례링크
TikTok세로형 소셜 비디오remotion-dev/template-tiktok
Audiogram팟캐스트 클립remotion-dev/template-audiogram
GitHub Unwrapped데이터 기반 비디오remotion-dev/github-unwrapped
claude-remotion-kickstartAI 지원 워크플로우Claude + Remotion용 커뮤니티 스타터

필수 패키지

# 캡션
npm install @remotion/captions @remotion/install-whisper-cpp

# 그래픽
npm install @remotion/skia  # 2D 벡터 그래픽
npm install @remotion/three # Three.js를 사용한 3D
npm install @remotion/lottie # Lottie 애니메이션

# 렌더링
npm install @remotion/lambda  # AWS 서버리스 렌더링
npm install @remotion/player  # 웹 앱에 임베드

전체 리소스 목록: references/community-resources.md 참조


번들 리소스

  • references/what-is-a-skill.tsx - "스킬이란 무엇인가" 비디오의 전체 예제 컴포넌트
  • references/caption-workflow.md - 완전한 캡션 통합 가이드 (Whisper, ZapCap, Submagic)
  • references/community-resources.md - 템플릿, 패키지, 학습 경로

관련 스킬

  • video-caption-creation - 렌더링된 비디오용 캡션 및 해시태그
  • youtube-scriptwriting - 더 긴 설명 비디오 스크립트용
  • social-content-creation - 비디오 개념을 정적 게시물로 재사용

버전 기록

  • v1.1 (2026-01-22): 캡션 및 커뮤니티 통합

    • @remotion/captions를 통한 기본 Whisper 캡션 워크플로우 추가
    • 캡션 스타일 프리셋 추가 (미니멀, 볼드, 가라오케, 브랜드)
    • 커뮤니티 리소스 추가 (디스코드, 템플릿, 패키지)
    • 새 참조 파일: caption-workflow.md, community-resources.md
    • 비용 비교: Whisper (무료) vs ZapCap ($0.10/분) vs Submagic ($0.69/분)
  • v1.0 (2026-01-21): 초기 스킬 생성

    • 리소그래프 시각적 스타일
    • 애니메이션 패턴 (스프링, 보간, 타자기)
    • 타이밍 가이드라인 ("너무 빠름" 반복에서 배움)
    • 장면 중첩 패턴

비디오는 코드입니다. 버전 관리하고, 반복하고, 재사용 가능한 컴포넌트 라이브러리를 구축하세요.

Individual skills in this repo

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

cdeistopened/skill-stack

Create optimized captions and hooks for short-form video (TikTok, Reels, Shorts) using proven hook categories and platform-specific Triple Word Score optimization system.

cdeistopened/skill-stack

When the user is writing the story portion of a launch video or demo and needs the framing where the founder pretends to BE the ICP experiencing the problem, then uses the product on-camera. Also use when the user mentions "demo story", "show don't tell", "day-in-the-life demo", "roleplay demo", "founder as customer", or "first person launch video". This is the story frame, not the full script.

cdeistopened/skill-stack

When the user needs a 3-5 word opening hook for a product launch video — the first second of on-screen text or voice that stops the scroll. Also use when the user mentions "hook for my video", "first second", "opening line", "tagline", "one-liner for launch", or "catchphrase". Produces 10+ hook candidates, not one answer.

cdeistopened/skill-stack

When a user wants to grow an X (Twitter) account from zero before a product launch, or asks how to get first followers, warm up the algorithm, hit ~500-1,000 followers, or prepare an account to make a launch video land. Also use when the user mentions "new X account", "warm up my Twitter", "first 1000 followers", "building in public strategy", "X growth", or "engagement before launch".

cdeistopened/skill-stack

When the user is planning, scripting, or editing a product launch video for X (Twitter) and needs the structure. Also use when the user mentions "launch video", "demo video", "product launch on X", "60 second demo", "how to structure a launch", or "my launch video isn't working". Produces a beat-by-beat timing sheet, not copy.

cdeistopened/skill-stack

When the user has X (Twitter) content that performed well and wants to relay it to LinkedIn 1-2 weeks later with reframing. Also use when the user mentions "repost to LinkedIn", "LinkedIn version of my tweet", "X to LinkedIn", "delayed repost", "LinkedIn for non-tech audience", or "LinkedIn relay". Also use when the user's ICP is non-tech and X is secondary — LinkedIn is the primary channel and this skill produces the content.

cdeistopened/skill-stack

When the user wants to find proven-to-travel post templates in their niche and adapt them to their own product. Also use when the user mentions "what's going viral in my space", "what are competitors posting", "copy a viral post", "trending on X", "post ideas", "template mining", or "what to post this week". This is trend hunting, not plagiarism — the output is a template the user fills with their own assets.

관련 스킬