make-video은(는) 무엇을 하나요?
아이디어를 렌더링되고 검증된 MP4로 변환합니다. 무료 로컬 도구만 사용합니다. 이 스킬로 만든 프로젝트는 AGENTS.md에 자체 규칙이 있으므로 이를 따라야 합니다(애니메이션 순수성, useScale, sec(), 폴더 레이아웃).
0. 비디오 프로젝트 설정 (최초 한 번)
현재 폴더에 tools/make-story.sh가 없으면 아직 비디오 프로젝트가 아닙니다:
-
작업 전에 먼저 기계를 확인하세요:
uname -sm(Darwin arm64 필요),node --version(20+),brew --version,df -h ~(약 8 GB 여유 공간). 다른 OS에서는 무엇이 작동하지 않는지 설명하세요(Chatterbox와 테이크 체커는 Apple GPU에서 실행됨). Node나 Homebrew가 없으면 사용자에게 설치 명령어 하나를 알려주고 기다리세요. -
사용자에게 다운로드될 내용을 알리고 승인을 기다리세요. 승인 없이 다운로드를 시작하지 마세요. 다음 표를 보여주세요(모두 무료, 공식 소스):
다운로드 크기 용도 위치 npm 패키지 (Remotion 등) ~500 MB 렌더링 node_modules/ffmpeg, uv, FluidSynth (Homebrew, 없을 때만) ~150 MB 오디오/비디오 도구 Homebrew Python 패키지 (PyTorch, Chatterbox…) ~1.5 GB 음성, QA .venv/GeneralUser GS 사운드폰트 ~30 MB 음악 tools/soundfonts/Chatterbox 가중치 ~3 GB 음성 Hugging Face 캐시 ( ~/.cache/huggingface), 모든 프로젝트에서 공유Whisper small.en ~590 MB 자막 tools/models/Whisper large-v3-turbo (선택 사항 테이크 체커) ~1.6 GB 불명확한 대사 재녹음 Hugging Face 캐시 총 약 6 GB, 10-20분 소요. 더 가벼운 옵션을 제공하세요:
SKIP_TAKE_CHECK=1은 테이크 체커를 건너뜁니다(총 4.4 GB). 프로젝트를 생성할 위치를 물어보세요(기본값~/videos). -
승인을 받으면, 이 SKILL.md 옆에 있는
template/폴더를 프로젝트로 복사하세요(점 파일 포함,cp -R <skill dir>/template/. <dest>/). 그런 다음git init. -
백그라운드에서
tools/setup.sh를 실행하고 사용자에게 진행 상황을 알리세요: 현재 단계를 말해주고(▶줄 출력), 큰 다운로드 중에는 진행률을 보여주세요(du -shL ~/.cache/huggingface/hub/models--ResembleAI--chatterbox, 목표 ~3 GB). 재실행해도 안전합니다: 완료된 단계는 건너뛰고 중단된 다운로드는 재개됩니다. 다운로드가 중단되면(5분 동안 크기 증가 없음) 중지하고 setup을 다시 실행하세요. 실패하면 오류를 읽고 원인(누락된 도구, 디스크 공간, 네트워크)을 해결한 후 다시 실행하세요. 누락된 모델을 우회하지 마세요. -
작동을 확인하세요:
tools/make-story.sh stories/fridge-drama FridgeDrama는 약 4분 만에 33초 예제(냉장고에서 세 야채가 논쟁)를 만듭니다. 사용자에게out/FridgeDrama.mp4를 보여준 다음, 무엇을 만들고 싶은지 물어보세요.
도구는 스스로 모델을 찾습니다(Chatterbox와 테이크 체커는 Hugging Face 캐시에서, 자막은 tools/models/에서). 따라서 설정 후에는 아무것도 구성할 필요가 없습니다. 두 번째 프로젝트는 캐시된 가중치를 재사용하므로 설정이 훨씬 빠릅니다.
1. 브리핑 확정 (누락된 경우에만 질문)
| 필드 | 기본값 |
|---|---|
| 플랫폼 / 형식 | 릴/쇼츠: 1080×1920, 30 fps · YouTube: 1920×1080, 30 fps · 피드 포스트: 1080×1350 |
| 길이 | 릴/쇼츠: 15-45초 · YouTube: 3-10분 |
| 종류 | 스토리(캐릭터가 말함, §3B 사용) 또는 모션 그래픽(텍스트, 데이터, 다이어그램, §3A 사용) |
| 주제 + 하나의 핵심 메시지 | 시청자가 기억해야 할 한 가지 |
| 오디오 | 음성(Chatterbox), 음악 + SFX (tools/music.py), 또는 음악만 |
| 음성 | Chatterbox 내장 음성, 또는 사용자 자신의 녹음을 복제한 음성(§3B). 동의 없이 다른 사람의 목소리를 복제하지 마세요. |
2. 코드보다 먼저 스크립트 작성
길이 예산: Chatterbox 속도의 영어 음성은 약 2.6 단어/초입니다. 목표 시간 ≈ 단어 수 ÷ 2.6 + Σ 일시 정지 + 아웃트로. 생성 전에 확인하세요. (냉장고 드라마: 62단어 + 6.4초 일시 정지 + 3초 아웃트로 = 33초.)
세로형 쇼트 폼 페이싱 규칙:
- 프레임 0부터 화면과 오디오로 후크를 걸어야 합니다. 처음 1.5초가 시청 유지율을 결정하며, 프레임 0은 종종 썸네일이므로 빈 프레임이나 페이드 인으로 시작하지 마세요.
- 각 줄은 ≤ 12 단어. 자막은 한 번에 ≤ 3 단어를 표시합니다.
- 매초 무언가 움직여야 합니다.
- 1080×1920 안전 영역: y=220 위나 y=1540 아래(플랫폼 UI)에는 중요한 것을 배치하지 말고, y≈1000 아래 x≈940 오른쪽에는 배치하지 마세요: 좋아요/댓글/공유 버튼이 오른쪽 가장자리를 따라 있습니다(
tools/qa.py --layout에서 실패). 발표자는 왼쪽 아래에 배치하세요. - 페이오프나 punchline으로 끝내고, 2-3초짜리 클릭 유도 문구 카드를 추가하세요.
설명 영상 템플릿 ("작동 원리" 및 개발 팁 릴, 45-60초, 120-160단어):
- 후크(≤ 3초): 놀라운 사실 또는 결과.
- "실제 작동 방식은 이렇습니다": 설명을 여는 한 줄.
- 2-4개의 비트, 각각 하나의 숫자 + 하나의 비유 ("비디오는 초당 30장의 사진, 마치 플립북과 같습니다").
- "하지만 여기에 함정이 있습니다": 반전, 함정 또는 흔한 실수.
- 한 줄의 페이오프, 명확한 클릭 유도 문구하나(저장, 공유 또는 팔로우).
그런 다음 스크립트 아래에 모든 사실 주장과 출처 링크를 나열하고, 확인할 수 없는 것은 표시한 후 음성 생성 전에 수정하거나 삭제하세요. 숫자나 주장이 나올 때 화면에 출처를 표시하세요(작게, 카드 하단).
쇼츠/릴 제작 체크리스트:
- 눈에 보이는 진행. 단계별 비디오는
<StepCard steps={[{at: 0, title: "다운로드"}, …]} />(src/components/StepCard.tsx)를 사용하세요: "STEP 2/4" 알약과 분할 막대. - 노래방 자막(선택 스타일).
<Karaoke words={captions} keywords={["무료"]} style={{left: 60, right: 140, top: 1180}} />(src/components/Karaoke.tsx): 2-5단어 덩어리가 화면에 표시되고, 말하는 단어는 진하게, 다가올 단어는 회색, 키워드와 강조 단어는 강조 색상으로 표시되어 음소거 자동 재생에서도 시청자가 앞서 읽을 수 있습니다.background는 밝은 카드 느낌을 줍니다. 레이아웃 검사가 볼 수 있도록qa를 전달하세요. - 시리즈 칩. 왼쪽 상단의 에피소드 표시("PART 2")는 게시물을 연속 시청하게 만듭니다.
- 대비 표시. 전후 비교 또는 "우리 대 그들"은 말로 설명하는 것보다 두 열 카드로 더 효과적입니다.
- 목록보다 스토리 비트. "시도 1 실패 → 시도 2 실패 → 효과가 있었던 것"은 기능 목록보다 주의를 더 잘 잡습니다.
- CTA 전에 punchline. 하나의 인간적인 줄, 그 다음 클릭 유도 문구.
- 진짜 보상(가이드, 프롬프트, 저장소)이 있는 경우에만 "KEYWORD로 댓글 달면 DM 드립니다"를 약속하세요.
TTS 작성을 위한 팁:
- 줄을 "…"으로 시작하지 마세요: Chatterbox가 임시 채움 단어를 improvise합니다.
- 줄을 숫자 단어로 시작하지 마세요("Two. The face"는 "to the face"로 나옴). "Second, …"로 작성하세요.
- 숫자와 특이한 이름은 발음되는 대로 쓰고("five point six", "X Z"), 실제 텍스트는 줄의
caption필드에 넣으세요. - 큰 숫자는 반올림하세요("over 600"): TTS는 "646"과 "87,000"을 왜곡합니다.
- 후크의 짧은 단어는 흐려집니다("This repo"는 "The three"로 들림). 테이크 체커가 정확히 들을 때까지 다시 작성하세요.
- 여러 음성이 같은 짧은 단어를 함께 외치지 마세요. 혼합이 번집니다.
- 구두점이 전달을 지시합니다: "?"는 상승, "."는 하강, CAPS는 강조를 추가합니다.
3A. 모션 그래픽 비디오
src/compositions/_Template→src/compositions/<Name>으로 복사하고, 비트 유형(후크, 포인트, 통계, 목록, CTA)별로 하나의 컴포넌트를 만듭니다.getSampleIntroDuration이 하는 것처럼 스크립트(비트 합계 - 전환)에서 지속 시간을 계산합니다.- 인라인
defaultProps와 함께src/Root.tsx에 등록합니다. - 음악만:
totalMs,outroStartMs및events가 있는 타임라인 JSON을 작성한 다음tools/music.py를 실행합니다.
3B. 음성 스토리 (캐릭터 + 자막 + 음악)
stories/<slug>/script.json을 생성하세요(stories/fridge-drama/script.json 복사):
characters:color,exaggeration(0.3 차분 → 0.9 극적), 선택적으로refVoice: 복제할tools/voices/의 깨끗한 10-30초 WAV. 없으면 Chatterbox의 내장 음성이 사용됩니다. 사용자 목소리를 복제하려면: 조용한 방에서 60-90초 동안 자연스럽게 말하게 한 다음, 음악이나 에코가 없는 깨끗한 10-15초 조각을 자릅니다(ffmpeg -ss <start> -t 12 -i note.m4a -af highpass=f=80,loudnorm=I=-18 -ar 24000 tools/voices/me.wav).lines:speaker,text,pauseAfter(초), 선택적event+eventAt: "start"로 스토리 비트(문 열림, 숨기…)를 표시하여 애니메이션과 음악 모두가 참조합니다.- 줄당 선택적 음성 지시:
emotion(calm|neutral|warm|excited|dramatic|whisper),pace(slow|normal|fast),emphasis(자막에서 CAPS로 말하고 강조되는 단어),pauseBefore(초)."pace": "slow"와 0.4초 일시 정지는 모든 단어를 명확하게 만듭니다.
그런 다음 하나의 명령어를 실행하세요:
tools/make-story.sh stories/<slug> <CompositionId> # 음성 → 자막 → 음악/SFX → lint → 렌더링 → 마스터 → QA
SKIP_VOICE=1 tools/make-story.sh … # 비주얼만 반복
SAMPLE=15 tools/make-story.sh … # 처음 15초만 렌더링하여 승인 받고 중지
| 도구 | 출력 |
|---|---|
tools/voice.py | public/<slug>/lines/*.wav (텍스트 + 음성 설정으로 캐시됨), public/<slug>/voice.wav, stories/<slug>/timeline.json (라인 타이밍, 이벤트, 프레임별 입 모양). 테이크 체커가 설치된 경우 Whisper가 모든 문장을 듣고 불명확한 문장을 재녹음합니다(VOICE_TAKES, 기본값 3). |
tools/captions.mjs | public/<slug>/captions.json (Whisper의 단어 타이밍, 스크립트의 철자), stories/<slug>/captions-report.json (단어 오류율 및 줄당 일치 단어, Whisper가 놓친 "채워진" 부분, 전체 matchRate) |
tools/music.py | public/<slug>/music.wav (MIDI → FluidSynth, 컷에 맞춤), public/<slug>/sfx.wav |
tools/qa.py | stories/<slug>/qa/report.md: PASS / FIX / FAIL |
timeline.json / captions.json에서 컴포지션을 빌드하세요(src/compositions/FridgeDrama/data.ts 참조). mouthOpen()으로 입을 움직이고, 활성 화자를 향해 시선을 돌리며, timeline.events.*를 통해 이벤트를 처리하고, timeline.durationInFrames에서 지속 시간을 가져옵니다.
타이밍 변경(텍스트 또는 일시 정지)은 자막을 다시 생성해야 합니다. 자막 시간은 절대적이므로 그렇지 않으면 표류합니다. make-story.sh는 항상 자막을 다시 실행합니다.
4. 확인 (완료하기 전에 항상)
tools/make-story.sh는 tools/qa.py로 끝나며 FAIL 시 0이 아닌 종료 코드를 반환합니다. 파일, 음량(-14 ±1 LUFS, true peak ≤ -1), 자막 정확도, 비트에 맞는 컷(≤ 120ms), 정지 구간(≤ 3초), 시각적 다양성(가장 긴 유사 구간 ≤ 5초), 화면 텍스트를 반복하는 자막을 확인합니다. LAYOUT=<CompId>는 또한 데드 존과 얼굴에 대한 자막을 확인합니다(컴포지션에는 자막 #FF00FF과 얼굴 #00FFFF를 윤곽선으로 표시하는 qa prop이 필요합니다). stories/<slug>/qa/report.md를 읽고 모든 FAIL과 FIX를 수정하세요.
그런 다음 눈으로 확인하세요:
npm run lint.- WER > 0.2인
stories/<slug>/captions-report.json의 줄은 아마 중얼거린 것입니다: 다시 작성하고 재생성하세요(캐시 덕분에 저렴함). Whisper가 놓친 단어는 간격의 음성 부분 위에만 배치되며, 긴 단어가 더 많은 시간을 받고filled아래에 나열됩니다: 해당 지점을 들어보세요.matchRate가 70% 미만이면 스크립트와 오디오가 다르므로 계속하기 전에 음성을 다시 생성하세요. - 주요 비트(후크, 각 화자, 각 이벤트, 아웃트로)에서 스틸을 렌더링하고, 하나의 접촉 시트로 결합한 후 실제로 살펴보세요:
캐릭터 크기, 안전 영역, 캐릭터를 가리는 오버레이, 아웃트로 뒤의 잔해, 자막 동기화, 텍스트 크기(칩 ≥ 28px, 본문 ≥ 54px, 1080 너비 기준)를 확인하세요.npx remotion still <Id> out/stills/f<N>.png --frame=<N> --scale=0.4 ffmpeg -i a.png -i b.png … -filter_complex hstack=inputs=K out/stills/contact.png - 최종 MP4에서 4-5프레임을 추출하여 살펴보세요.
- 중요한 내용은 맥락 없이 접촉 시트를 비판하도록 새로운 하위 에이전트에게 요청하세요. 새로운 시각은 제작자가 놓친 문제를 찾습니다.
5. 전달
사용자에게 MP4, 제목, 캡션, 3-5개의 해시태그 및 썸네일 프레임을 제공하세요. 명시적 승인 없이는 게시하거나 업로드하지 마세요. 복제된 음성이나 AI 얼굴이 사용된 경우 YouTube의 "변경 또는 합성 콘텐츠" 레이블을 체크하도록 상기시키세요.
시간을 절약하는 규칙
- 한 번에 하나의 렌더링. 여러 Remotion 렌더링을 동시에 실행하면 기계가 몇 시간 동안 과부하됩니다. 파이프라인은 이미
--timeout=180000 --concurrency=2를 전달합니다. - Remotion 패키지는
npx remotion add <pkg>로 추가하고 절대 일반npm i를 사용하지 마세요. 버전이 일치해야 합니다. - 음량: 대화 −16 LUFS, 배경 음악 약 −24, 최종 마스터 −14(2패스, 이미
make-story.sh에 있음). 음성이 음악보다 최소 10dB 이상 크게 유지하세요. - Studio는
defaultProps가Root.tsx의 인라인 객체인 경우에만 prop 편집을 저장할 수 있습니다. - 행에 대한 zsh 루프는
for x in "a b c"가 깨지므로while read -r a b c; do …; done <<EOF로 작성하세요.
더 많은 교훈과 직접 추가하는 방법: reference/lessons.md.
측정된 비용 (M1 Max, 64 GB)
| 단계 | 시간 |
|---|---|
| Chatterbox 모델 로드 | 실행당 ~20초 (모든 줄이 캐시된 경우 건너뜀) |
| 음성 생성 | 첫 줄 ~55초 (워밍업), 그 후 ~3× 실제 시간 |
| 테이크 확인 | 재녹음이 필요한 문장당 ~20-30초 |
| 자막 (Whisper small.en, WebGPU) | 11줄 기준 ~10초 |
| 음악 + SFX | 2-5초 |
| 1080×1920, 33초 렌더링 | ~97초 (비디오 1초당 ~3초) |
| 전체 파이프라인 | 음성 캐시 시 ~2분; 처음부터 ~4분 |
make-video는 TheNoumanDev](https://github.com/TheNoumanDev)가 zero-dollar-studio에서 만들었습니다. @0x45.dev YouTube 채널의 파이프라인입니다.