릴 빌더(reel builder)
엔진: $(reelsmith root)/engine/ (build.py, template.html, music.py, pull_vo.py, capcut.py, fonts/). 릴당 한 폴더: <reel-dir>/reel.json → <reel-dir>/out/reel.mp4. reelsmith가 설정되지 않았다고 표시되면 reelsmith setup을 한 번 실행하세요.
reelsmith new reels/my-reel # src/, vo/ 폴더와 템플릿 reel.json 생성
reelsmith sheet reels/my-reel/src/* # 콘택트 시트 → 각 세그먼트에 대해 `ss` 선택
reelsmith build reels/my-reel --stills # ~1분: 프레임, 단어 타이밍, 자막, out/qa_sheet.jpg
reelsmith stills reels/my-reel 0.5,7.8,21.3 # 추가 확인 프레임
reelsmith build reels/my-reel # 전체 렌더링 (~60초 기준 4~5분)
항상 --stills를 먼저 실행하세요: 출력된 자막 목록을 읽고 out/qa_sheet.jpg를 확인하세요 (빨간 영역 = Reels/TikTok UI 영역; 중요한 것은 빨간 영역에 있으면 안 됩니다). reel.json을 수정한 후 빌드하세요. 마지막에 출력된 음량 수치(−14 LUFS ±1, 최고점 ≤ −1 dB)를 확인하세요. 그런 다음 최종 MP4의 효과와 전환 주변 프레임을 꼭 확인한 후 전달하세요.
워크플로우 (크리에이터 시간 ≈ 릴당 10분)
- 스크립트:
reel-script스킬 → 크리에이터 승인. 악센트 단어는<em>…</em>로 표시하세요; 표시용 숫자는 그대로 유지하세요. - 보이스: 크리에이터가 직접 녹음한 파일(
vo/vo.mp3) 또는 ElevenLabs (docs/voice.md참조): TTS 텍스트 = 태그 없는 스크립트, 숫자는 철자로 표기, 브랜드명은 발음대로 표기. 무료 플랜은 ElevenLabs 웹 UI에서 생성 (Claude(Chrome)로 구동 가능), 그런 다음reelsmith voice <reel-dir>로 가장 최신 2개 테이크를vo/에 가져와 길이를 확인합니다. 둘 다 받아쓰고, 더 깨끗한 쪽을vo/vo.mp3로 유지합니다. 느린 목소리:vo에"speed": 1.07추가. - 푸티지:
footage-scout스킬 — 신규 클립만 사용 (used_footage.md확인), 콘택트 시트, 개인정보 검사. 세그먼트 지속시간의 합이 보이스 종료 시점 + 약 2초가 되어야 합니다. - 편집 계획:
reel-director스킬이 이 스토리에 맞는 3~5개 효과와 전환 위치를 선정합니다. - reel.json 작성 →
--stills→ 수정 → 빌드 →out/reel.mp4+out/cover.jpg+out/caption.txt전달. - (선택) CapCut에서 사운드 패스:
reel-capcut스킬 (라이브러리 사운드 효과 + 귀로 고른 음악).
reel.json
{
"vo": {"file": "vo/vo.mp3", "offset": 0.25, "speed": 1.07, "gaps": [[5.73, 0.8]]},
"script": "I've been rewriting my guide for three months and yesterday I changed the cover font <em>for the fourth time</em>. …",
"hook": {"tag": "the eternal-draft scenario", "lines": ["the guide is almost ready.", "<em>for three months now</em>"], "out": 5.55},
"end": {"from": 55.6, "lines": ["how long has", "<em>yours been waiting?</em>"], "lines_at": [55.75, 56.6],
"sub": "tell me in the comments", "sub_at": "@comments", "handle": "@yourhandle", "handle_at": 58.6},
"cover": {"from": 0, "to": 4.35, "title": "DRAFT", "left": "No.4 · October", "right": "@yourhandle", "top": 330},
"cover_t": 2.0,
"stamps": [{"seg": ["I", "J"], "text": "tanya · 2 years in drafts"}],
"punch": [[3.02, 4.4], ["@thousand", 9.0]],
"segments": [
{"id": "A", "clip": "src/night_desk.mp4", "ss": 9.5, "dur": 2.5, "crop": [0, 0.196, 0.75], "cut": true},
{"id": "B", "clip": "src/keys.mp4", "ss": 1.3, "dur": 1.9, "move": "none"},
{"id": "E", "clip": "src/phone_walk.mov", "ss": 0.8, "dur": 4.5, "cut": true, "in": "zoom"},
{"id": "I", "clip": "src/cafe.mp4", "ss": 0.3, "dur": 3.2, "look": "bw"},
{"id": "K", "clip": "src/walk.mov", "ss": 14.0, "dur": 4.95, "look": "burst"},
{"id": "N", "clip": "src/breakfast.mov", "ss": 0.0, "dur": 3.45, "rate": 0.4},
{"id": "Q", "clip": "src/meadow.mov", "ss": 13.2, "dur": 9.1, "move": "pull-out", "in": "zoom"}
],
"caption": "…",
"music": "synth"
}
완전한 실제 예제 (우크라이나어, 61초, 17개 세그먼트, 아래 모든 효과 포함)는 $(reelsmith root)/examples/chernetka/reel.json에 있습니다; 최소 예제는 examples/template/reel.json에 있습니다.
보이스 및 자막
- lang: 보이스오버의 Whisper 언어 (
"uk","en", …); 생략 시 자동 감지 (또는REELSMITH_LANG사용). - vo.gaps
[vo_time, extra_s]: (속도 조정된) 보이스의 해당 시점 근처 가장 조용한 지점에 숨 쉬는 간격을 삽입 — 포토 몽타주 공간 확보용. vo.speed: atempo 계수. - "@word" 앵커: hook / end / doodles / glass / checklist / cover / orbit / wall / punch / subs_skip 의 모든 시간은
"@thousand"(해당 스크립트 단어 시작점; 정확히 일치 우선, 없으면 접두사),"@again#2"(두 번째 등장),"@twice+0.3"형식으로 지정 가능. Whisper가 잘못 들은 단어는 보간된 시간을 사용하므로 초 단위로 지정하세요.--stills실행 후out/words.json에 실제 타이밍이 있습니다. - subs / punch: 생략 시
script+ 단어 타이밍에서 자동 생성 (57단어, 12줄, 악센트 단어는 이탤릭 악센트 색상, 마침표 없음, 줄 끝이 "and/in/of…"로 끝나지 않음; 펀치인은 3초 이상 간격의 악센트 구절 최대 4개). 재정의하려면"subs": [[a, b, "html"]],"punch": [[a, b]]사용. 자막은 후크 카드가 표시되는 동안, 유리 타이틀 및 체크리스트 아래, 엔드 카드가 시작되면 숨겨집니다 (subs_from/subs_until/subs_skip [[a, b]]로 조정 가능).
카드 및 텍스트
- hook: 프레임 0부터 보이는 종이 카드 (
at: [t…]는 줄을 하나씩 표시,size,top). end:from부터 시작하는 카드,lines_at에 줄 표시,sub,handle. - stamps: 나열된 세그먼트 위 왼쪽 상단 모노 필 (장소, 날짜, 캐릭터 이름).
- cover (커버 스토리 + 프레임 브레이크): 너비에 맞춰진 매거진 마스트헤드, 글자가 떨어져 들어옴;
"cut": true인 세그먼트에서는 인물이 타이틀 앞에 서 있습니다. 머리 위쪽이 마스트헤드 상단보다 40~80px 아래에 있는 샷을 선택/크롭하세요 — 절대 눈을 가로지르지 않게. 마스트헤드의color, 위치를top으로 조정.cover_t≈ 2 로 설정하면out/cover.jpg에 완성된 커버가 표시됩니다. - glass (유리 타입):
{"from", "to", "lines", "at", "top"}프로스트 유리 타이틀. - checklist:
{"from", "to", "title", "items": [{"text", "sub", "at", "sub_at"}]}항목별로 커지는 카드,at시점에 체크 표시. - wall (헤드라인 월):
{"from", "to", "items": [...], "every": 0.06}파일명/헤드라인 타일이 쌓이는 효과; 위에 유리 타이틀을 올리세요. - orbit:
{"from", "to", "seg", "text": "1000 FOLLOWERS · ", "speed", "scale", "tilt", "lift"}cut세그먼트의 머리 주위를 도는 텍스트 링; 뒷부분은 인물 뒤로 지나갑니다. 가까운 셀카에 가장 적합. - doodles (낙서 애니메이션):
{"kind": "text"|"circle"|"underline"|"strike"|"arrow", "at", "to", "x", "y", …}— text:text, size, rot, write; circle/strike:w, h(striken지그재그; 3이면 단어 읽기 가능); underline:w; arrow:x2, y2, bend;color,width. 크림색 후광이 있는 악센트 잉크, 왼쪽→오른쪽으로 쓰여지며 3프레임마다 흔들림. 후크 카드가 올라와 있는 동안에는 y ≈ 1000 위에, 얼굴 위에는 두지 마세요.
세그먼트
- 경로: 릴 폴더 기준 상대 경로, 그 다음 현재 디렉터리, 그 다음 저장소.
img로 HEIC/JPG 사진도 가능합니다. ss클립 내 시작 시간,dur초;pos0~1 가로 프레이밍 (와이드 소스용);crop [x, y, size]= 세로 프레임의 펀치인 크롭 (4K에서 선명 유지);rate< 1 = 슬로우 모션 (짧은 부분만 사용 가능할 때).- cut:
true= 이 세그먼트에 대해 macOS Vision 인물 마스크 사용 (reelsmith masks, 약 0.2초/프레임, 캐시됨). cover와 orbit에 필요합니다. - in:
"zoom"(나가는 샷이 블러와 함께 빠르게 들어오고 새 샷이 줌에서 착지) 또는"whip"(빠른 블러 슬라이드, 검은 가장자리 없음). 모든 컷이 아닌 4~6개의 주요 컷에 사용하세요. - look:
""웜 필름 ·"memory"페이드된 확대비행 효과 (포토 몽타주용,date는 주황색 카메라 날짜 스탬프 추가) ·"bw""흑백 (음악이 약해짐) ·"burst"회색→컬러로 피어오름 (음악이 열림). - move:
push(기본 느린 푸시인) ·tilt-up·pull-out·none.
사운드 및 색상
- music:
"synth"(룩에 따라 생성된 로파이 배경음 — 플레이스홀더로 충분, 크리에이터는 실제 트랙을 선호하는 경향), 사용 권한이 있는 오디오 파일 경로, 또는null. 원본 클립 사운드는 절대 사용되지 않습니다. - music_gain: 기본 0.16 (보이스 아래, 사이드체인 덕킹).
- colors:
{"accent": "#D4573A", "cream": "#F4EFE6", "ink": "#1F1A17"}(기본값: 베이지 / 테라코타).
실제 피드백에서 나온 규칙
- 효과는 첫 시청 시 폰 화면에서도 읽혀야 합니다: 크고, 악센트 색상이며, 애니메이션 처리. 작은 크림색 낙서와 희미한 유리 패널은 "효과가 어디 있나요?"라는 반응을 불러일으켰습니다.
- 컷에서 반복되는 흰색 플래시 금지. 원본 클립 사운드는 음소거. 릴당 3~5개 기법, 모두 사용하지는 마세요.
- 텍스트, 카드 또는 낙서를 절대 눈 위에 두지 마세요; 카드를 이동하거나 샷을 다시 구성하세요.
- 클립의 화면과 배경을 전체 해상도로 확인하세요: 타인의 메시지, 자동차 번호판, 거리 이름, 개인 대시보드 → 해당 초는 건너뛰세요.
- 매 릴마다 신규 푸티지 사용 (
used_footage.md). 타인의 얼굴이 있는 샷은 사용 전에 물어보세요.
트러블슈팅
- pip install 실패: Python 3.10+이 설치되어 있는지 확인하고
pip install --upgrade pip를 실행한 후 다시 시도하세요. - ffmpeg 관련 오류:
ffmpeg가 시스템 PATH에 있는지 확인하세요. macOS:brew install ffmpeg, Ubuntu:sudo apt install ffmpeg. - "reelsmith: command not found":
reelsmith setup을 실행하거나$(reelsmith root)/engine/이 PATH에 추가되었는지 확인하세요. - 자막 싱크 불일치:
--stills단계에서out/words.json을 확인하고subs또는punch에서 직접 시간을 조정하세요. - 렌더링 속도가 느림:
rate값을 확인하고(0.4 권장) 불필요한cut: true를 피하세요. - 메모리 부족: 세그먼트 수를 줄이거나 해상도를 낮추세요.