Communitygithub.com

VidTSX 2D 비디오 생성기

샷, 장면 또는 비디오 설명으로부터 VidTSX(Remotion 기반)에서 사용할 프로덕션 준비 완료된 2D TSX 비디오 파일을 생성합니다. 사용자가 VidTSX 비디오, 2D TSX 샷이나 장면, 애니메이션 클립, 타이틀 카드, 렌더링된 모션 그래픽을 만들거나 생성하고 싶을 때마다 사용하세요.

VidTSX 2D 비디오 생성기란 무엇인가요?

이 스킬은 Remotion 기반 비디오 프레임워크인 VidTSX용 2D TSX 비디오 파일을 생성합니다. 사용자가 비디오, 샷 또는 장면을 설명하면, 이 스킬은 Remotion 컴포지션의 엄격한 규칙을 준수하는 프로덕션 준비 완료된 React/TSX 구성 요소를 생성합니다. 이는 useState/useEffect/setTimeout과 같은 상태 저장 또는 시간 기반 React API를 사용하지 않고, 오직 프레임 기반 애니메이션(useCurrentFrame + interpolate)만을 사용합니다. 잘못된 코드는 렌더링 충돌을 일으키므로 정확성이 매우 중요합니다. 이 스킬은 가로/세로/정사각형 화면 형식, 6가지 스타일 프리셋(미니멀리스트, 멤피스, 네오 브루탈리즘, 글래스모피즘, 네온, 코퍼레이트)을 지원하며, Remotion 고유의 제약 조건(단조 증가 interpolate 범위, Easing.bezier 구문, chroma-js 및 @remotion/paths의 올바른 사용법)을 강제합니다. 생성된 파일은 명확한 마크다운 펜스나 설명 없이 순수 TSX 코드만 포함해야 합니다. 이 스킬은 3D/three.js 작업, 일반 React 개발, 또는 기존 비디오 파일 편집에는 사용되지 않습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/gbax316/shorts-director/tree/main/.claude/skills/vidtsx-2d-generator

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

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

문서

VidTSX 2D 비디오 생성기은(는) 무엇을 하나요?

샷 또는 비디오 설명으로부터 VidTSX용 프로덕션 준비 완료된 2D TSX 비디오 파일을 생성합니다. 이 파일들은 VidTSX가 프레임별로 렌더링하는 Remotion 컴포지션입니다. 따라서 독창성보다 정확성이 더 중요합니다. 단일 비단조 interpolate 범위나 잘못된 useState 하나가 렌더를 중단시킬 수 있습니다.

이 스킬은 2D 모션 그래픽을 다룹니다. 3D 작업(@remotion/three / React Three Fiber)은 범위를 벗어납니다.

이 스킬 사용 방법

  1. 명확한 단일 샷 → .tsx 파일을 직접 생성합니다.
  2. 복잡하거나, 여러 샷이 있거나, 시각적으로 모호한 요청 → 먼저 짧은 메시지 하나로 샷 분할이나 시각적 방향을 확인한 후 생성합니다. 지나치게 묻지 않으며, 한 줄 확인으로 충분합니다.
  3. 인라인 코드가 아닌 실제 .tsx 파일로 전달합니다. 이러한 TSX 구성 요소는 항상 20줄을 초과하며, 사용자는 이 파일을 직접 편집합니다. 사용자가 단일 결합 전달물을 요청하지 않는 한, 기본적으로 파일당 하나의 샷 (원자적이고 편집하기 쉬움)으로 제공합니다.
  4. 파일은 컴포넌트 코드만 포함합니다. 아래 구조적 섹션 주석은 환영하지만, 파일 내부에 마크다운 펜스나 산문 설명은 포함하지 않습니다.
  5. 렌더링을 수행하고 완료되었다고 말하기 전에 확인합니다 — 렌더 검증을 참조하세요. 추론만 한 샷은 완료된 것이 아닙니다. 스틸 이미지(그리고 공개/스크롤의 경우 각 큐에서의 프레임)가 기준입니다.

출력 사양

화면 비율 프리셋

형식너비높이사용 사례
가로19201080YouTube, 프레젠테이션
세로10801920TikTok, Reels, Shorts
정사각형10801080Instagram 피드

기본값

  • 형식: 가로 (1920×1080)
  • 길이: 5초
  • FPS: 30
  • 스타일: 미니멀리스트 (references/style-presets.md 참조)

필수 파일 구조

모든 생성된 파일은 다음 골격을 따릅니다. 레이블이 지정된 섹션 주석은 의도적인 것으로, 대용량 파일을 탐색 가능하게 유지합니다.

import React from 'react';
import {
  useCurrentFrame,
  useVideoConfig,
  interpolate,
  Easing,
  AbsoluteFill,
  Sequence,
} from 'remotion';

// =============================================================================
// 컴포지션 설정
// =============================================================================
export const compositionConfig = {
  id: 'ComponentName', // PascalCase만 — 하이픈이나 밑줄 없음
  durationInSeconds: 5,
  fps: 30,
  width: 1920,
  height: 1080,
};

// =============================================================================
// 스타일 상수
// =============================================================================
const COLORS = {
  primary: '#6366f1',
  secondary: '#8b5cf6',
  accent: '#06b6d4',
  background: '#0f0f23',
  text: '#ffffff',
} as const;

const TYPOGRAPHY = {
  fontFamily: 'Inter, system-ui, sans-serif',
} as const;

const EASINGS = {
  easeOut: Easing.bezier(0.33, 1, 0.68, 1),
  easeIn: Easing.bezier(0.32, 0, 0.67, 0),
  easeInOut: Easing.bezier(0.37, 0, 0.63, 1),
  overshoot: Easing.bezier(0.34, 1.56, 0.64, 1),
} as const;

// =============================================================================
// 사전 생성 데이터 (모듈 수준에서 한 번 계산, 렌더 중에는 계산 안 함)
// =============================================================================
const seededRandom = (seed: number): number => {
  const x = Math.sin(seed * 9999) * 10000;
  return x - Math.floor(x);
};

// =============================================================================
// 메인 컴포넌트
// =============================================================================
const ComponentName: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps, durationInFrames, width, height } = useVideoConfig();

  return (
    <AbsoluteFill style={{ backgroundColor: COLORS.background }}>
      {/* 콘텐츠 */}
    </AbsoluteFill>
  );
};

export default ComponentName;

ComponentName을 샷을 설명하는 PascalCase 이름으로 바꾸고, 선택한 스타일 프리셋에서 COLORS 블록을 설정하고, 요청에 따라 width/height/durationInSeconds/fps를 설정합니다.


정확성 규칙

이것들은 스타일 선호도가 아닙니다. 렌더가 성공하도록 하는 요소입니다. VidTSX(Remotion을 통해)는 각 프레임을 고정된 프레임 번호에서 컴포넌트를 호출하여 렌더링합니다. 이벤트 루프, 프레임 간 지속성, 또는 벽시계 시간이 없습니다. 이러한 것을 가정하는 모든 것은 실패합니다.

애니메이션은 항상 프레임 기반입니다.

  • 모든 모션을 useCurrentFrame() + interpolate()로 구동합니다.
  • useState, useEffect, setTimeout, setInterval 또는 CSS 애니메이션/전환을 절대 사용하지 마세요. 이들은 프레임별 모델에 맞지 않으며 깨지거나 비결정적인 출력을 생성합니다.
  • 무작위 또는 절차적 작업에는 seededRandom(또는 이와 동등한 시드 함수)을 사용하여 주어진 프레임의 모든 렌더가 동일하도록 합니다. 파티클/랜덤 배열을 모듈 수준에서 사전 생성하고, 렌더 함수 내부에서는 절대 생성하지 마십시오. 프레임당 재계산하면 깜빡임이 발생합니다.
  • 요소가 한꺼번에 나타나는 대신 순차적으로 들어오도록 애니메이션 간격을 조정하세요. 더 좋게 보이며 예상되는 모양입니다.

interpolate — 입력 범위는 반드시 엄격하게 증가해야 함

interpolate의 입력 범위는 엄격하게 단조 증가해야 합니다. 중복되거나 내림차순 값은 런타임에 오류를 발생시킵니다.

// ✅ 올바름
interpolate(frame, [0, 30, 60], [0, 1, 0]);

// ❌ 오류 발생 — 입력 범위가 내림차순
interpolate(frame, [60, 30, 0], [0, 1, 0]);

매핑을 반전시키려면 입력 범위가 아닌 출력 범위를 뒤집으세요:

// ✅ 올바름 — 0→100, 1→0 매핑
interpolate(value, [0, 1], [100, 0]);

// ❌ 잘못됨
interpolate(value, [1, 0], [100, 0]);

인덱스 기반 타이밍의 경우 startFrame < endFrame인지 확인하고 항상 클램프하세요:

const startFrame = index * 30;
const endFrame = startFrame + 30;
interpolate(frame, [startFrame, endFrame], [0, 1], {
  extrapolateLeft: 'clamp',
  extrapolateRight: 'clamp',
});

항상 바인딩되지 않은 값이 정말로 필요한 경우가 아니라면 extrapolateLeft: 'clamp' 및 extrapolateRight: 'clamp'를 전달하세요. 이 값이 없으면 값이 키프레임 전후에 범위를 벗어납니다.

Easing — Easing.bezier()를 사용하고 래퍼 구문을 사용하지 마세요

Easing.out(Easing.cubic)과 같은 래퍼 형식은 충돌을 일으킵니다. 명명된 베지어를 한 번 정의하고(골격의 EASINGS 블록 참조) 참조하세요:

// ❌ 충돌
Easing.out(Easing.cubic);
Easing.in(Easing.quad);

// ✅ 올바름
interpolate(frame, [0, 30], [0, 1], {
  easing: EASINGS.easeOut,
  extrapolateRight: 'clamp',
});

chroma-js — 네임스페이스 가져오기만 가능

// ✅ 올바름
import * as chroma from 'chroma-js';
const color = chroma('#00bfff').brighten(0.5).hex();

// ❌ 잘못됨 — "chroma is not a function"
import chroma from 'chroma-js';

@remotion/paths — 실제 함수만 존재함

다음 헬퍼는 존재하지 않으며 절대 사용해서는 안 됩니다: makeCircle(), makeRect(), makeTriangle(), makeLine(), makePie(), makePolygon(), makeEllipse(), makeStar().

다음 가져오기만 유효합니다:

import { evolvePath, getLength, getPointAtLength, getTangentAtLength } from '@remotion/paths';

SVG 경로 문자열을 직접 작성하고 evolvePath로 애니메이션화하세요:

const circlePath = 'M 50 10 A 40 40 0 1 1 49.99 10 Z';
const rectPath = 'M 0 0 L 100 0 L 100 50 L 0 50 Z';
const linePath = 'M 0 0 L 100 100';

const { strokeDasharray, strokeDashoffset } = evolvePath(progress, rectPath);

컴포지션 ID

compositionConfig.id는 PascalCase만 가능합니다 — 하이픈이나 밑줄 없음 (예: ProductReveal, product-reveal 또는 product_reveal 안 됨).


레이아웃

안전 영역

  • 상단 10%: 플랫폼 UI용으로 예약.
  • 하단 15%: 캡션/버튼용으로 예약.
  • 기본 콘텐츠는 세로로 25%–75% 사이에 유지하세요.

중앙 정렬 헬퍼

const centered: React.CSSProperties = {
  position: 'absolute',
  top: '50%',
  left: '50%',
  transform: 'translate(-50%, -50%)',
};

타이포그래피

요소크기두께
제목72–120px700–900
부제목36–48px500–700
본문28–36px400–500

텍스트 요소에는 항상 margin: 0을 설정하세요. 브라우저 기본값이 레이아웃을 중앙에서 벗어나게 밀어냅니다.


스타일 프리셋

이 저장소에서 기본값은 브랜드 스타일이며 프리셋이 아닙니다. 샷은 골격의 로컬 COLORS/TYPOGRAPHY 블록 대신 remotion/src/brand.ts에서 COLORS, GRADIENT, RADIUS, SHADOW, EASINGS를 가져오고 remotion/src/fonts.ts에서 FONT_HEADLINE, FONT_DISPLAY, FONT_BODY, FONT_MONO를 가져오며 brand.md를 따릅니다. FONT_HEADLINE(Instrument Serif)에는 한 가지 두께만 있습니다. 절대 fontWeight를 주지 마세요. 샷은 compositionConfig에 ground: 'night'라고 명시되지 않는 한 낮 바탕에 위치합니다. 키트 구성 요소(lib/shorts.tsx, BrandBg)는 여기서 색상을 가져오므로, 직접 설정하는 모든 색상에 대해 brand.ts에서 useGround()를 읽으세요.

사용자가 스타일을 지정하면 references/style-presets.md 에서 해당 팔레트와 특성을 로드하고 COLORS 객체를 골격에 넣습니다. 여섯 가지 프리셋은: 미니멀리스트, 멤피스, 네오 브루탈리즘, 글래스모피즘, 네온/사이버펑크, 코퍼레이트입니다. 스타일이 지정되지 않은 경우 위의 브랜드 스타일을 사용하세요.


렌더 검증 (건너뛰지 마세요)

샷은 직접 확인하기 전까지 완료된 것이 아닙니다. .tsx를 작성한 후 적어도 하나의 스틸 이미지를 렌더링하고 열어보세요. 추론만 한 샷은 절대 전달하지 마십시오. 렌더링이 성공하고 숫자가 올바르게 보이지만 텍스트가 카드를 넘치거나, 이미지가 잘못된 크롭으로 잘리거나, 요소가 화면 밖에 있거나, 두 요소가 겹칠 수 있습니다. 스크린샷만이 이러한 문제를 잡아냅니다.

  • 스틸 이미지 렌더링(예: node scripts/render-all.mjs --still --scale=1 <ShotId>)하고 PNG를 읽으세요.
  • 시간 기반 공개(큐에 들어오는 요소, 스크롤, 단계적 페이즈)의 경우, 단일 지속 시간의 60% 스틸 이미지로는 충분하지 않습니다. 전체 클립을 렌더링하고 각 주요 순간에서 프레임을 추출하거나(ffmpeg -ss <t> -i out/<id>.mp4 -frames:v 1 f.jpg), 여러 오프셋에서 스틸 이미지를 렌더링하세요. 하나의 프레임이 아닌 각 큐에서의 상태를 확인하세요.
  • 특히 다음을 확인하세요: 이미지가 슬롯에 맞는지(중요한 콘텐츠가 잘리지 않았는지; 이질적인 실제 이미지의 경우 일치하는 배경에 objectFit: contain 선호), 텍스트가 잘리거나 넘치지 않는지, 안전 영역을 벗어난 것이 없는지, 각 애니메이션 요소가 표시되어야 할 때 실제로 보이는지.
  • 다른 푸티지 위에 합성된 경우, 고립된 샷뿐만 아니라 최종 출력 프레임도 교차 확인하세요.

스크린샷이 드러내는 것을 수정한 후 다시 렌더링하고 다시 확인하세요. "렌더링했고 올바르게 보입니다" — 표시된 프레임과 함께 — 를 완료 기준으로 삼으세요.


최종 출력

완전한 .tsx 파일과 그 외에는 아무것도 생성하지 마세요. 파일 자체에 마크다운을 감싸거나 코드 앞뒤에 설명을 넣지 마십시오. 파일을 전달할 때 채팅에 짧은 한 줄 메모를 남기는 것은 괜찮습니다.

Individual skills in this repo

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

gbax316/make-ai-short

Build a GENERATIVE-pixels vertical short (1080×1920, ~35-40s) end-to-end — a recurring locked character animated by a fal video model (Seedance 1.5 Pro default) under a philosophical/story VO, composited in Remotion with word-synced captions, SFX audition, seamless frame-0==last-frame loop. Use when the user wants to "make an AI video short", "make an ai short", "make a blue-man video", or any short where the pixels come from a VIDEO MODEL — not TSX animation (that is make-short) and not layered collage (that is make-vox). Defers model choice re-litigating to ai-shorts/IDEAS.md, TSX crash rules to vidtsx-2d-generator, SFX taste to suggest-sfx + brand §7. For a NEW short (writers' room, dialogue skits, documentaries, mixed render paths), start with shorts-director, which calls this track as an engine.

gbax316/shorts-director

Directs a faceless vertical short from idea to finished, mastered file, and gets better with every run. Picks a format, writes the episode in a writers' room (three premises judged as the buyer), voices it, gates on an animatic, then decides beat by beat how each moment is made: drawn in code in Remotion, a cut-out from a generated still, a generated clip, or one of the engine tracks. Modes: series, writers-room, produce, sound, finish, bakeoff, effects (/effects), improve (the learning loop after every short). Formats so far: character skit with dialogue and synced mouths, photoreal mini documentary with sourced figures. Triggers on "make a short", "next episode", "make a video about X", "faceless video", "reel for this offer". Do NOT trigger for editing an existing video file, for a pure code-drawn explainer with no writers' room (make-short), or for collage (make-vox).

관련 스킬