런칭 비디오 생성기
30~60초 모션 그래픽 런칭 비디오를 <YOUR_BRAND> 제품 또는 기능을 위해 처음부터 끝까지 제작합니다.
- Remotion 4 React 구성으로 MP4 (1920×1080 + 1080×1080) 렌더링
- ElevenLabs AI 내레이션 (기본 Bill 음성), 이벤트별 사운드 효과 및 배경 음악
- 비트 기반 타이밍: 모든 시각적 단계가
script.timings.json의 측정된 오디오 길이를 기준으로 시작 프레임을 읽습니다. 카피를 편집하고 오디오를 재생성하면 모든 시각 요소가 자동으로 이동합니다. 수동 프레임 조정이 필요 없습니다. - 브랜드에 모션 서브시스템 (글래스/커서/툴-필 컴포넌트)이 있다면 이를 상속받으세요. 아래 설명된 참조 패턴은 하나의 유효한 시스템입니다: 깨끗한 흰색 테이블 시스템(결과 테이블, 대시보드, 트레이스) 위에 레이어링된 글래스모픽 모션 서브시스템(채팅 셸, 커서, 툴 필)입니다.
저장소에 참조 Remotion 프로젝트가 있다면 이 스킬을 해당 프로젝트에 연결하세요. 그렇지 않으면 아래 설명된 패턴이 독립적으로 작동합니다. 소스 저장소의 참조 구현 경로: <YOUR_REFERENCE_VIDEO_PATH>.
사용 시기
다음과 같은 경우에 사용합니다:
- "X에 대한 런칭 비디오 생성"
- "런칭 비디오 / 제품 비디오 / 기능 공개 비디오 제작"
- "[기능]에 대한 비디오 렌더링"
- 사용자가 명시적으로
/launch-video입력
다음과 같은 경우에는 건너뜁니다:
- 정적 소셜 그래픽 →
/graphics-designer - 슬라이드 데크 / 웨비나 → 데크 파이프라인 사용
- 8초 미만의 짧은 광고 클립 → 일반적으로 단일 Remotion 스틸 또는 단일 씬 구성으로 충분하며, 이 스킬의 전체 파이프라인은 과하다고 볼 수 있습니다.
- 원녹화 영상 (토킹 헤드, 웨비나 녹화, 창업자 비디오, 고객 인터뷰, 화면 캡처 데모) → 대신
/video-use스킬을 사용하세요. 해당 스킬은 Scribe 트랜스크립트에서 단어 경계를 기준으로 편집하고, 필러 단어를 제거하며, 컬러 그레이딩과 자막을 추가합니다. 이 스킬은 Remotion에서 처음부터 제작하는 합성 모션 그래픽을 위한 것입니다. 두 스킬은 함께 구성될 수 있습니다:/video-use편집은 브랜드 애니메이션 삽입을 위해 Remotion 오버레이 슬롯을 생성할 수 있지만, 편집 자체는/video-use에서 수행됩니다.
아키텍처 개요
motion/<video-name>/
├── package.json # remotion 4 + react 19 + tsx + dotenv + mp3-duration
├── remotion.config.ts # publicDir → ../../brand/motion (단일 에셋 소스)
├── tsconfig.json
├── SCRIPT.md # 사람이 읽을 수 있는 내레이션 스크립트 (비트별)
├── .env # ELEVENLABS_API_KEY (gitignored!)
├── .env.example
├── generate-audio.ts # ElevenLabs 내레이션 실행기, 비트별 해시 캐시
├── generate-sfx.ts # ElevenLabs 음향 효과 실행기, 해시 캐시
├── generate-music.ts # ElevenLabs 음악 실행기 + 앞부분 무음 제거
├── script.timings.json # 내레이션 길이 (생성됨)
├── sfx.timings.json # SFX 길이 (생성됨)
├── music.timings.json # 음악 길이 (생성됨)
└── src/
├── Root.tsx # registerRoot
├── Video.tsx # 구성 레지스트리 + LaunchVideoComposition 래퍼
├── theme.ts # fps + 지속 시간 + 색상 (<YOUR_BRAND_TOKENS_PATH> 미러링)
├── script.ts # 내레이션 비트 (id, phase, text)
├── timings.ts # script.timings.json 로더 + beatStartFrame()
├── sfx.ts # SFX 클립 정의 (프레임에 고정)
├── music.ts # 음악 프롬프트 + 볼륨
├── Narration.tsx # 내레이션 전용 Sequence 트랙
├── SoundDesign.tsx # 내레이션 + SFX + 음악 결합
└── scenes/
├── HeroBackground.tsx # 반복 재생 /video/hero-bg.mp4
├── OpeningScene.tsx # 오케스트레이션 씬 (모든 단계 고정)
├── GlassCursor.tsx # 멀티플레이어 스타일 "you" 커서
├── CompanyTable.tsx # 데이터 테이블 채우기 + 컬럼 공개
├── AgentDashboard.tsx # Google 캘린더 주간 보기
├── AgentRunDetail.tsx # 도구 호출 추적 보기
├── MemoryPanel.tsx # 통계 + 스파크라인 대시보드
├── Confetti.tsx # 파티클 버스트
└── ClosingCard.tsx # 종료 채팅 콜백 ("Inviting" 패턴)
에셋은 brand/motion/에 있습니다:
video/hero-bg.mp4+ 포스터 (브랜드 히어로 배경 루프, 예:brand/motion/video/hero-bg.mp4의 앰비언트 비디오)logos/{models,tools,companies,sequencers}/— 타사 브랜드 마크audio/{launch-narration,sfx,music}/— 생성된 mp3 파일 (재현 가능한 렌더링을 위해 커밋됨)components/HeroChatMockup.tsx— 프레임워크 독립적인 채팅 셸
새 런칭 비디오 워크플로우
1. 브리핑
사용자로부터 다음 정보를 얻습니다:
- 대상: 누구를 위한 것인가? (GTM 팀? 엔지니어? 투자자?)
- 재생 시간: 목표 초 (기본 30-45초, 60초 이상은 hype 영상에 긴 느낌)
- 핵심 메시지: 전달할 4-8가지 사항, 내러티브 순서로
- 출력 형식: 랜드스케이프 (웹/LinkedIn), 스퀘어 (IG/피드), 또는 둘 다
2. 비트 아웃라인
각 비트 = 하나의 시각적 단계 동안 재생되는 하나의 내레이션 문장입니다. 일반적으로 6-8개 비트. 비트 오디오 길이의 합 = 전체 재생 시간. 비트 길이는 각각 3-7초를 목표로 합니다.
각 비트에 대해 다음을 기록합니다: id, phase (한 줄 시각적 설명), text (음성 대사, 10-20단어).
3. SCRIPT.md 작성
인간 검토를 위해 스크립트를 package.json과 같은 위치에 저장합니다. 형식:
## 비트 N — 단계 이름
**프레임** ~시작~끝 (초) · **목표 ~N단어**
> "음성 대사."
**시각적 동기화:** 화면에 표시되는 내용.
4. src/script.ts 빌드
SCRIPT.md를 데이터로 미러링합니다. 내레이션 생성기와 구성 모두 SCRIPT를 가져옵니다. 여기에는 Remotion 가져오기를 사용하지 않습니다 (생성기가 일반 Node에서 실행될 수 있도록).
export interface Beat { id: string; phase: string; text: string; }
export const SCRIPT: Beat[] = [...];
export const AUDIO_SUBDIR = "audio/launch-narration";
export function audioPath(id: string) { return `${AUDIO_SUBDIR}/${id}.mp3`; }
5. 내레이션 생성
cd motion/<video-name>
cp .env.example .env # ELEVENLABS_API_KEY 붙여넣기
npm install
npm run generate-audio
그러면 brand/motion/audio/launch-narration/{beat-id}.mp3가 생성되고 script.timings.json에 길이가 기록됩니다. 비트 텍스트로 해시되므로 변경되지 않은 비트는 후속 실행에서 건너뜁니다 (저렴한 반복).
6. 시각적 씬 빌드
OpeningScene.tsx에서:
- 모듈 로드 시 비트 시작 시간 계산:
const HERO_BEAT = beatStart("hero", 0); // → 0 const DATABASE_BEAT = beatStart("database", 0); // → 171 (hero 종료 후) // ... 등 - 모든 애니메이션 프레임을
BEAT_X + offset으로 표현:const BADGE_IN = HERO_BEAT + 6; const TYPE_START = HERO_BEAT + 38; const TOOLS_START = HERO_BEAT + 115; // "GTM stack" 가사와 동기화 const CURSOR_PRESS = HERO_BEAT + 165; - 단계 씬 사이를 비트당 불투명도 게이트를 사용하여 크로스페이드합니다.
7. SFX 생성 (선택 사항이지만 효과적)
src/sfx.ts에서 클릭/전환 순간을 정의합니다. 각 클립을 동일한 beatStartFrame() 헬퍼를 사용하여 특정 fromFrame에 고정합니다. 효과적인 예시 클립:
- 프롬프트 애니메이션 아래 타이핑 텍스처
- 커서 누름 시 선명한 클릭
- "enroll" / 완료 순간에 축하 팝
- 종료 카드 공개 시 미묘한 팽창
npm run generate-sfx
8. 음악 생성
src/music.ts에서 하나의 프롬프트 + 지속 시간을 정의합니다. generate-music.ts는 앞부분 무음을 자동으로 제거합니다 (ElevenLabs 음악은 종종 내레이션과 비교하여 "음악 없음"으로 읽히는 조용한 마디로 시작합니다).
npm run generate-music
9. 렌더링으로 반복
npm run render:landscape
렌더링에는 약 30~90초가 소요됩니다. QuickTime 호환성을 위해 출력을 항상 yuv420p TV 범위로 다시 인코딩하십시오 — 배경 비디오는 yuvj420p (JPEG 범위)이며 전파로 인해 일부 플레이어에서 재생이 중단될 수 있습니다:
ffmpeg -y -i out/launch-landscape.mp4 \
-c:v libx264 -profile:v high -level:v 4.0 \
-pix_fmt yuv420p -color_range tv -crf 18 -c:a copy \
out/launch-landscape-fixed.mp4
mv out/launch-landscape-fixed.mp4 out/launch-landscape.mp4
ffmpeg -ss N -i ... -frames:v 1 /tmp/check.jpg를 사용하여 전체 렌더링을 보지 않고 특정 타임스탬프를 스팟 체크할 수 있습니다.
디자인 규칙
음성 (시각적 + 음성)
- 절대 엠 대시를 사용하지 마십시오. 마침표, 쉼표, 콜론, 괄호, 중간점만 사용합니다.
- 어디에서나 금지된 단어:
활용,시너지,견고한,세계적 수준의,매끄러운,직관적인,강력한,혁신적인. - 숫자가 형용사보다 낫습니다 ("많은 도구" 대신 "8개 도구").
- 간결하고 구체적입니다. 모호한 표현은 금지합니다.
- 마무리: 브랜드 주도이며, "축하합니다."가 아닙니다. 여기서 발견된 가장 강력한 마무리 패턴은: "Inviting" 키커 → 새 프롬프트가 입력된 채팅 입력 → URL 서명입니다. 시작 비트로의 채팅 콜백은 매번 축하 효과를 냅니다.
색상 (예시 토큰 · 브랜드에 맞게 조정)
밝고 중립적입니다. 하나의 강조색만 사용하며, 의미가 있는 곳(라이브 도트, 하이라이트, 성공 상태)에서만 씬당 한 번 사용합니다.
| 토큰 | Hex | 용도 |
|---|---|---|
--bg | #fafafa | 페이지 배경 |
--surface | #ffffff | 카드, 대시보드 |
--ink | #0a0a0a | 기본 텍스트 + 숫자 |
--muted | #71717a | 보조 텍스트 |
--line | #e4e4e7 | 테두리 |
--accent | #10b981 | 단일 강조색 |
타이포그래피
- 스택:
'Helvetica Neue', Helvetica, Arial, sans-serif - 모노 (키커, 코드, 레이블):
ui-monospace, 'SFMono-Regular', Menlo - 히어로 타이포그래피: 두께 450, 좁은 자간 (
-0.05em) - 모노 키커 스타일: 11-14px, 대문자, 자간
0.16-0.18em, 색상#71717a또는#a1a1aa - 회색 본문 텍스트의 굵은/중간 부분은 브랜드 패턴을 미러링합니다: 주변
#71717a텍스트와 달리<span style={{ color: "#0a0a0a", fontWeight: 500 }}>굵게</span>.
두 가지 시각적 모드
씬당 하나를 선택하십시오. 혼합하지 마십시오:
- 글래스모픽 / 제품 내 — 채팅 셸, 커서, 툴 필, 히어로 배경 비디오 위에.
backdrop-filter: blur(28px),rgba(255,255,255,0.45)를 사용한 흰색 글래스. - 깨끗한 흰색 / 표 형식 — 테이블, 대시보드, 트레이스, 메모리 패널.
bg #ffffff,1px solid #e4e4e7, 미묘한 그림자.
모드 간 배경 페이드 전환은 가장 영화적인 순간 중 하나입니다. 약 20~30프레임을 할당하고 부드러움을 위해 Easing.bezier(0.4, 0, 0.2, 1) (머티어리얼 표준)을 사용하십시오.
애니메이션 규칙
- 스프링의 감쇠 22-28. 20 미만에서는 아마추어로 읽히는 바운스가 발생합니다. 의도적으로 "팝" 효과를 원할 때만 14-18을 사용하십시오.
- 느리게 하는 것보다 타이트한 스태거가 낫습니다. 첫 번째 본능은 항상 속도를 늦추는 것입니다. 두 번째 패스는 일반적으로 스태거를 절반으로 줄이는 것을 포함합니다. 계단식 항목 간 기본 스태거: 3-6프레임.
- 중요한 곳에서 시각 자료를 가사에 동기화하십시오. 내레이션이 "GTM stack"이라고 말하면 툴 필은 그 단어에 맞춰 날아와야 합니다. 3초 전이 아닙니다. 단어 수준 동기화를 위해 ElevenLabs의
with_timestamps를 사용하거나, 근사치로 충분하다면 비트 길이/단어 수를 기준으로 추정하십시오. - 행 높이를 예약하십시오. 테이블/카드에 텍스트가 애니메이션될 때 행의
minHeight는 콘텐츠가 채워짐에 따라 레이아웃이 튀는 것을 방지합니다. 캐스케이드 중에 행이 커지면 지저분해 보입니다. - 높고 빈 사각형을 생성하는 경우 0 불투명도보다 조건부 렌더링을 사용하십시오. 아직 공개를 시작하지 않은 카드는 공간을 차지하지 않아야 합니다.
- 씬 모드 간 하드 컷 대신 크로스페이드하십시오. 각 주요 씬은
interpolate+ 이즈 곡선을 통해 애니메이션되는opacity게이트를 얻습니다.
ElevenLabs 주의 사항
- 기본 음성 + 모델:
generate-audio.ts는 기본적으로 Bill (pqHfZKP75CvOlQylNhV4)을eleven_multilingual_v2모델로 사용합니다. Bill은 ElevenLabs 라이브러리에서advertisement사용 사례 목소리입니다: 현명하고, 성숙하며, 선명합니다. 실제 광고 음성 해설처럼 읽히며, "소셜 미디어의 AI 남자"처럼 읽히지 않습니다.multilingual_v2는 프로덕션 내레이션을 위한 가장 안정적이고 생생한 모델입니다. 런칭 비디오에eleven_turbo_v2_5를 사용하지 마십시오 — 빠르고 저렴한 모델이며 히어로 배경 비디오와 비교하면 그 차이가 들립니다. Turbo는 미리보기 / SFX 타이밍 확인에는 괜찮지만 최종 렌더링에는 적합하지 않습니다. - 음성 설정이 스크립트에 포함되어 있습니다:
stability 0.40,similarity_boost 0.75,style 0.30,use_speaker_boost true. ElevenLabs 모범 사례에 따르면: 안정성이 0.30 미만이면 불안정하고, 0.60 이상이면 단조롭습니다. 유사도 0.75는 문서상 최적 지점이며, 스타일 0.20–0.40은 드리프트 없이 표현력을 더합니다. 눈에 띄는 억양 변화를 원하지 않는 한 스타일을 0.4 이상으로 올리지 마십시오. - 음성 캐시 키에는 음성 + 모델 + 설정이 포함됩니다. 이 중 하나를 변경하거나 (또는 비트 텍스트 편집) 캐시된 MP3가 무효화되고 비트가 다시 렌더링됩니다.
.env(VOICE_ID=...MODEL_ID=...) 또는generate-audio.ts를 편집하고npm run generate-audio를 다시 실행하기만 하면 됩니다. - 기타 내레이션 등급 음성 (Bill이 적합하지 않은 경우):
- Eric
cjVigY5qzO86Huf0OWal— 부드럽고, 신뢰할 수 있으며, 현대적인 SaaS 느낌 - Chuck Miller
HIGUfNOdjuWQwwapnTRW— 프로 클론, 깊고 거친, 영화적 - George
JBFqnCBsd6RMkjVDRZzb— 영국식 스토리텔러, 내러티브 스토리 - Logan
jD4PjnscE4XmlzgsuqY0— 프로 클론, 젊은 스토리텔러 - Brian
nPczCjzI2devNBz1zQrb— 레거시 기본값;social_media로 레이블 지정; Bill보다 "AI"처럼 읽힙니다. - 결정하기 전에 참조 Remotion 프로젝트에서 이들을 A/B 샘플링하십시오.
- Eric
- 음성 목록을 보려면
voices_read권한이 필요합니다. 일부 키에는 이 권한이 없습니다.GET /v1/voices를 사용할 수 없으면 알려진 ID로 대체하십시오. - 음악 API는 프롬프트에서 브랜드 이름을 거부합니다. "Apple keynote", "Linear launch trailer" 등은 TOS 위반을 트리거합니다. 브랜드 이름을 지정하지 않고 분위기를 설명하십시오 ("현대 기술 런칭 트레일러를 위한 영화적 악기", "아르페지오 신디사이저 멜로디가 있는 펄스 일렉트로닉 비트").
- 음악은 기본적으로 앞부분 무음 (~1-2초)으로 시작합니다. 생성기의
silenceremoveffmpeg 패스가 이를 제거하여 재생이 프레임 0에서 시작되도록 합니다. 해당 필터를 유지하십시오. - 음향 효과 최소 지속 시간은 0.5초입니다. 그 이하에서는 API가 오류를 반환합니다. 반올림하십시오.
- 음악 볼륨:
0.10은 내레이션 아래에서 무음으로 읽힙니다.0.15-0.18이 최적 지점입니다 — 분명히 들리지만 음성과 충돌하지 않습니다.
피해야 할 함정
<Sequence>없이<Audio>추가: 전체 재생 시간 동안 오디오가 재생됩니다. 항상<Sequence>로 감싸서 시작 프레임과 지속 시간을 지정하십시오.
// 나쁜 예
<Audio src={narrationSrc} />
// 좋은 예
<Sequence from={narrationStartFrame} durationInFrames={narrationDuration}>
<Audio src={narrationSrc} />
</Sequence>
-
하드코딩된 프레임 값:
magicConstants.ts에서 프레임을 정의하지 않으면 오디오 길이가 변경될 때마다 수동 조정이 필요합니다.beatStartFrame()을 고수하십시오. -
배경 비디오를 별도로 처리하는 것을 잊음:
hero-bg.mp4는 yuvj420p (JPEG 범위)입니다. 항상 최종 출력을 yuv420p TV 범위로 다시 인코딩하십시오. -
렌더링 전에 SFX 타이밍 확인 건너뛰기: 사운드 디자인 파일은 시각 자료와 일치해야 합니다. 프레임 그래버로 분할된 렌더링을 사용하여 각 SFX가 정확한 프레임에서 트리거되는지 확인하십시오.
-
오디오 길이 측정 실패:
mp3-duration패키지에 의존하십시오. 수동 추정은 종종 수 초 차이가 나며 전체 타이밍을 망칠 수 있습니다. -
긴 폴링 방치: 스킬이 완료될 때까지 기다리는 것은 비효율적입니다. 로그에 알림이 표시되도록 구성하고 다른 작업을 진행하십시오.
랜드스케이프 + 스퀘어 이중 렌더링
npm run render:all
두 가지 출력을 생성합니다:
out/launch-landscape.mp4(1920×1080, h264, yuv420p, 30fps)out/launch-square.mp4(1080×1080, h264, yuv420p, 30fps)
구성된 :
// src/Video.tsx
export const LANDSCAPE_ID = "launch-landscape";
export const SQUARE_ID = "launch-square";
export const LANDSCAPE_COMP = new Composition({
id: LANDSCAPE_ID,
component: LaunchVideoComposition,
durationInFrames,
fps: 30,
width: 1920,
height: 1080,
});
export const SQUARE_COMP = new Composition({
id: SQUARE_ID,
component: LaunchVideoComposition,
durationInFrames,
fps: 30,
width: 1080,
height: 1080,
});
스퀘어 비디오는 시각적 요소를 다시 배치하기 위해 약간의 조정이 필요할 수 있습니다. useVideoConfig()로 감지하고 그에 따라 조건부로 배치하십시오.
const { width, height } = useVideoConfig();
const isSquare = width === 1080 && height === 1080;
예: 간단한 실행
# 1. 저장소 복제 및 프로젝트로 이동
cd my-project
# 2. 런칭 비디오 생성 요청 (스킬 트리거)
> /launch-video My New Feature
# 3. 스킬이 motion/my-new-feature/ 디렉토리 생성
# 기본 템플릿 파일 포함
# 4. 브리핑에 따라 SCRIPT.md 편집
# (또는 스킬이 대화형으로 안내)
# 5. API 키 설정 및 오디오 생성
cd motion/my-new-feature
cp .env.example .env
# .env에 ELEVENLABS_API_KEY 추가
npm install
npm run generate-audio
# 6. 선택 사항: SFX 및 음악 생성
npm run generate-sfx
npm run generate-music
# 7. 사전 렌더링 확인을 위해 단일 프레임 렌더링
ffmpeg -ss 3 -i out/launch-landscape.mp4 -frames:v 1 /tmp/check.jpg
# 8. 최종 비디오 렌더링
npm run render:all
# 9. QuickTime 호환성을 위해 다시 인코딩
npm run fix-renders
이렇게 하면 재생 준비가 완료된 두 개의 MP4 파일 (out/launch-landscape.mp4 및 out/launch-square.mp4)이 생성됩니다.
권장 도구
이 스킬 외에도 전체 비디오 파이프라인을 위해 다음 스킬을 설치하는 것을 고려하십시오:
/video-use: 녹화된 영상 (토킹 헤드, 데모, 웨비나) — 단어 경계 편집, 필러 단어 제거, 컬러 그레이딩, 자막./graphics-designer: 정적 소셜 그래픽, 배너, 썸네일./slides: 슬라이드 데크 생성./brand-guidelines: 브랜드 가이드라인 질의.