Reel — 스플릿 편집(화자 위 45% 패널)
영상 상단에 크림색 고정 패널(1080 × split.panel_height, 기본값 864 = 45%)을 채우고, UI 스타일 위젯(카드, 미터, 토글, 터미널, 칩 등)으로 현재 말하는 내용을 시각화합니다. 화자는 하단에 스케일 1로 위치하며 절대 움직이지 않습니다. 끝에는 댓글 키워드를 크게 표시한 후, 팔로우 카드가 나타납니다. 실제 예제: examples/split/ (Claude 스킬 5개에 관한 100초 분량 실제 영상의 계획 + 장면 모듈).
인수: $ARGUMENTS
기본값(사용자가 변경하라고 하지 않는 한 그대로 사용)
먼저 reel.config.json을 읽고, 없으면 reel.config.example.json을 사용합니다.
| 항목 | 기본값 |
|---|---|
| 분할 | "split": split.panel_height (864 → 패널 45%, 화자 55%; 960 = 50/50) |
| 화자 | 스케일 1, 확대/축소 없음, 이동 없음; 얼굴이 화자 영역 중앙에 위치 (speaker_y) |
| 안전 영역 | "safe": split.safe = [64, 160, 64, 32] → 장면 콘텐츠는 위에서 160px 아래 952 × 672 영역에 위치 (인스타그램 헤더/폰 상태바가 상단을 가림) |
| 자막 / SFX / 음악 | 추가하지 않음. 오디오 = 촬영본 자체 믹스를 사용하며, finish.py에서 리먹싱 |
| 촬영본 | 이미 컷, 그레이딩, 음악이 추가되었다고 가정 → 그대로 사용. Raw/미편집본은 먼저 확인 요청 |
| CTA | 댓글 키워드(단어 또는 숫자)를 말풍선 카드에 크게 표시; 팔로우 카드는 "handle": creator.handle, 텍스트만, 얼굴 크롭 없음 |
| 팔레트 | split_palette: 크림 패널, 잉크 텍스트, 악센트 채움; 크림 위 텍스트는 accent_deep(대비) 사용 |
입력값
촬영본 이름과 주제는 인수로 받습니다. 한 번에 하나의 메시지로, 부족한 정보만 물어봅니다: 촬영본이 이미 컷/그레이딩/음악 작업되었는지; 댓글 키워드; Whisper가 잘못 들을 수 있는 이름이나 전문 용어(도구 및 제품 이름).
파이프라인
PY = .venv/Scripts/python.exe -X utf8 (Windows) 또는 .venv/bin/python -X utf8 (macOS/Linux). 긴 단계는 백그라운드에서 실행.
| # | 단계 | 명령/동작 | 확인 |
|---|---|---|---|
| 1 | 확인 | ffprobe; 접촉 시트 ffmpeg -i raw/<take> -vf fps=1/5,scale=216:384,tile=9x2 -frames:v 1 work/<take>/sheet.jpg 및 시각 확인 | 머리 위 빈 벽? 이미 편집됨? |
| 2 | 전사 | $PY tools/transcribe.py <take> --prompt "<이름, 전문용어>" | 도구 이름 교정; 3초 이상 간격 → 다시 전사 창 |
| 3 | 얼굴 | $PY tools/face_track.py <take> --split <panel_height> | speaker_y 출력 |
| 4 | 비트 계획 | 하나의 아이디어당 하나의 장면, 일반적으로 3~7초, 각 위젯은 말한 단어에 고정됨(cue = 단어 시작). 장면은 콘텐츠만 변경, 레이아웃 변경 없음 | |
| 5 | 계획 파일 | work/<take>/showcase.json (examples/split/showcase.json 기반): video ("../../raw/<파일>"), split, speaker_y, safe, scenes_module, scenes[] {kind, start, end, cue{...}}, 팔로우 장면의 handle; _note에 얼굴 번호 기록 | |
| 6 | 장면 | tools/scenes_<슬러그>.py (examples/split/scenes_5skills.py 기반): 각 종류별 sc_<종류>(i, s) -> (html, js), RENDER 딕셔너리, 선택적 CSS/JS. 안전 영역 내 좌표(952 너비); id는 s{i}-*; 큐 시간은 절대값. sc_comment, sc_follow는 CTA | |
| 7 | 빌드 | $PY tools/showcase_build.py <take>; work/<take>/sc에서: npx hyperframes lint public → 0 오류; npx hyperframes snapshot public -o ../snaps --no-end --describe false --at <각 장면 중간>; 시트 확인 후 수정 | 텍스트가 패널 내부에 있고, 헤더 아래에 없음 |
| 8 | 빠른 렌더링 | $PY tools/finish.py <take> --seconds 12; work/<take>/sc/quick_sheet.jpg 확인 | |
| 9 | 전체 렌더링 | $PY tools/finish.py <take> (백그라운드) → final/<take>/, 확인, qa/sheet.jpg | 시트 확인 |
| 10 | 보고 | 경로, 길이, 장면, 확인 결과. 새로운 내용을 배웠으면 이 스킬에 추가 |
패널 규칙
- 위젯은 현재 말하고 있는 문장을 보여줍니다: 저장소 이름을 말할 때 저장소 카드, 비교할 때 미터, "이건 아니야"라고 말할 때 취소선.
- 각 장면은 다음 장면으로 0.25초 전에 페이드 아웃됩니다(빌더가 처리); 장면 내에서 요소는 큐 단어에 따라 등장합니다.
- 화면에 표시되는 숫자는 촬영본의 실제 개수여야 합니다.
showcase_build.py에 내장된 장면 종류(hook,repo,cta, …)는 45% 안전 영역 이전에 만들어져 영역을 넘을 수 있습니다. 대신examples/split/scenes_5skills.py를 기반으로tools/scenes_<슬러그>.py에 종류를 작성하세요.- 페르시아어/아랍어 텍스트:
.fa클래스(요소에 RTL 적용,<html>에dir="rtl"사용하지 않음),letter-spacing: 0, 숫자는fa()사용, 큰 숫자 0은 라틴어 '0'. - 하나의 속성에 중복 트윈 없음,
Math.random/from:"random"사용 금지, 슬라이드 인은 from 상태에autoAlpha:0포함. - 소스 클립이 HDR(HLG)인 경우 먼저 톤 매핑(
tools/story_assets.py의TONEMAP) —finish.py는 "HDR 자동 승격"에서 중단됩니다. hyperframes snapshot은 렌더링의 증거가 아닙니다 — 8단계가 증거입니다.