세로 릴스(9:16) 자동 제작 — 주제·영상을 주면 파이프라인 6종(나레이션 몽타주·토킹헤드 자막·BGM+타이포·앱 데모·제품·리액션) 중 자동 판별해 대본→자막→합성까지. 실제 발행작으로 검증한 제작 프리셋 4종(모티베이션 몽타주+프리즈 오프너·롱테이크 브이로그·인물 인서트·화면 전용 설명편) 포함. "릴스 만들어줘", "/reel <주제>", 영상 파일 + 릴스 요청 시 사용.
Installs into .claude/skills of the current project.
Are you the author of reel?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/lvupcrm-reel)
---
name: reel
description: 세로 릴스(9:16) 자동 제작 — 주제·영상을 주면 파이프라인 6종(나레이션 몽타주·토킹헤드 자막·BGM+타이포·앱 데모·제품·리액션) 중 자동 판별해 대본→자막→합성까지. 실제 발행작으로 검증한 제작 프리셋 4종(모티베이션 몽타주+프리즈 오프너·롱테이크 브이로그·인물 인서트·화면 전용 설명편) 포함. "릴스 만들어줘", "/reel <주제>", 영상 파일 + 릴스 요청 시 사용.
---
# /reel — 릴스 파이프라인 (v2.0 · 파이프라인 6종 + 제작 프리셋 4종 + 컷 레이아웃 6종)
주제 또는 영상 파일을 받아 **판별 → 대본·컷시트 → (사용자 OK) → 렌더 → 전달**. 업로드(인스타 게시)는 이 스킬의 범위 밖 — 파일 생성까지만 한다.
## 워크플로 게이트
1. **판별**: 입력 영상 분석 → 파이프라인 선정 + 근거 한 줄 보고
2. **대본·컷시트 제시**: 대본(또는 전사문·텍스트 스토리) + 컷 구성을 먼저 보여주고
3. **사용자 OK 후 렌더** — 렌더는 오래 걸린다. 대본 단계에서 고칠 것을 다 고쳐 재작업 낭비를 막는다.
## 파이프라인 판별 라우터
영상 파일을 받으면 아래 3단계로 판별한다 (주제만 받으면 P1, "기능 소개" 주제면 P4, 제품 사진·영상이면 P5):
```bash
# ① 메타: 해상도·회전·길이·오디오 유무·HDR (color_transfer=arib-std-b67이면 HLG)
ffprobe -v error -show_entries stream=width,height,duration,color_transfer,codec_type:stream_side_data=rotation -of json input.mp4
# ② 말소리: 앞 20초 오디오 추출 → whisper 전사 (유의미한 한국어 문장이 나오면 말소리 있음)
ffmpeg -y -t 20 -i input.mp4 -vn -ac 1 -ar 16000 probe.wav && (mlx_whisper 전사)
# ③ 내용: 프레임 피크 3장(10%·50%·90% 지점) 추출해 Read로 확인 — 인물/현장/화면녹화 판별
ffmpeg -y -ss <t> -i input.mp4 -frames:v 1 peek_N.jpg
```
이 6종은 **음성 방식과 기본 화면의 프리셋**이다 — "무엇이 화면의 주인공인가"로 나뉜다.
⚠️ **프리셋이 영상 전체의 화면을 고정하지 않는다.** 레퍼런스 88편을 보면 한 편 안에서
인물 풀 → 상하분할 → 자료 풀 → 타이포로 계속 갈아탄다.
**음성 방식만 전체에 고정되고, 화면 배치는 컷마다 고른다** → `references/layouts.md` (레이아웃 6종)
| 판별 결과 | 파이프라인 | 문서 |
|---|---|---|
| 말소리 있음 + 화자가 카메라 향해 말함 | **P2 토킹헤드 자막형** (사람이 주인공) | `references/p2-talking.md` |
| 말소리 없음 + 실사 + 전달할 주제 있음 | **P1 나레이션 몽타주형** (현장이 주인공) | `references/p1-narration.md` |
| 말소리 없음 + 실사 + 주제 없이 분위기 소재 | **P3 BGM+타이포형** (분위기가 주인공) | `references/p3-bgm-typo.md` |
| 화면 녹화 / 기능 소개·사용법 주제 | **P4 앱 데모 튜토리얼형** (화면이 주인공) | `references/p4-demo.md` |
| 실물 제품·음식·공간이 화면 중심 | **P5 제품 등장형** (물건이 주인공) | `references/p5-product.md` |
| **원본 콘텐츠 + 내 반응 영상, 소스 둘** | **P6 리액션형** (원본과 반응이 함께 주인공) | `references/p6-reaction.md` |
애매하면(예: 말소리 있는데 현장 스케치) 판별 보고 때 2안 병기하고 추천 1개 제시. **해당 파이프라인 문서만 읽고 진행** — 전부 읽지 않는다.
입력이 **두 소스**(남의 원본 + 내 반응)면 P6이다 — 이때만 음성이 믹스가 되며, **저작권 확인을 먼저 한다**.
## 제작 프리셋 4종 — 실제로 발행해 반응까지 본 구조 (v2.0)
파이프라인이 "무엇을 찍었나"로 나눈 분류라면, 제작 프리셋은 **그대로 복사해 값만 바꾸면 같은 완성도가 나오는 검증된 레시피**다.
스크립트가 딸린 것은 작업 폴더 `reel_<슬러그>/`에 폴더째 복사해 쓴다. 해당 문서만 읽는다.
| | 제작 프리셋 | 언제 (트리거) | 문서 · 스크립트 |
|---|---|---|---|
| A | **모티베이션 몽타주 + 프리즈 오프너** | 그룹 운동·현장 클립 여러 개 + 취지/카피. "모티베이션 영상처럼", "리듬감 있게", "멈췄다가 소개 나오는 거" | `references/preset-motivation.md` · `scripts/preset_motivation/` |
| B | **롱테이크·일상 브이로그** | 폰 생활 클립 1~3개 + 그날 있었던 일. 육아·반려동물·가게 일상. "이 레퍼처럼 담백하게" | `references/preset-longtake.md` · `scripts/preset_longtake/` |
| C | **인물 인서트** (토킹·인터뷰) | 사람이 나오는 영상 + 설명할 내용. 단어별 자막·키워드 팝·흐린 배경 위 모션그래픽. 녹음 원음(인터뷰·반응)을 증거로 끼우는 편 포함 | `references/preset-talk-insert.md` · `word_subs.py` · `mg_kit.py` |
| D | **화면 전용 설명편** | 용어·개념·도구 설명. 얼굴 없이 화면 카드만. "촬영 없이" | `references/preset-screen-only.md` · `screen_cards.py` |
- A·B는 **무음/현장음** 계열(나레이션 없음), C·D는 **나레이션·원음** 계열이다.
- 판별 라우터로 P1~P6을 고른 뒤, 위 트리거에 맞으면 해당 제작 프리셋으로 간다(P3 → A·B, P2 → C, P4 → D).
- **수정 요청**("이 문구만 바꿔줘")·목소리가 어색함·렌더 이상은 `references/craft-notes.md`부터 연다.
제품·음식이 화면 중심이면 P5인데, 나레이션 없이 갈지(P3) 얹을지(P5)는 사용자에게 한 번 물어본다.
⚠️ **whisper 환청 주의**: 무음·배경음만 있는 클립을 전사하면 "다음 영상에서 만나요", "시청해주셔서 감사합니다" 같은 문장이 나온다. 이건 **말소리가 아니라 환청**이다 — 여러 클립에서 같은 문장이 반복되면 무음으로 판정한다.
## 전제 (모두 로컬·무료 / macOS·Windows)
- 도구: `ffmpeg`·`ffprobe`(**libass·zscale 포함 필수**) · `uv`
- 파이썬 도구: 작업 폴더의 `.venv`
| | macOS (Apple Silicon) | Windows |
|---|---|---|
| 세팅 | `bash ~/.claude/skills/reel/scripts/setup.sh ~/reels` | `powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\skills\reel\scripts\setup.ps1"` |
| ffmpeg | osxexperts arm64 정적 빌드 → `~/.local/bin` | gyan.dev essentials → `%USERPROFILE%\.local\bin` |
| 자막 엔진 | `mlx-whisper` | `faster-whisper` (CPU int8 / CUDA 있으면 float16) |
| venv 파이썬 | `.venv/bin/python` | `.venv\Scripts\python.exe` |
| 기본 한글 폰트 | Apple SD Gothic Neo | 맑은 고딕 (malgunbd.ttf) |
- **환경이 없거나 깨졌으면 위 세팅 스크립트를 실행한다** — 관리자 권한 없이 사용자 폴더 안에만 설치한다.
- ⚠️ **Homebrew·winget은 쓰지 않는다.** 설치 중 비밀번호·확인 입력을 요구하는데 Bash 도구는 표준 입력을 넘길 수 없어 반드시 실패한다. 게다가 **Homebrew 코어 ffmpeg에는 libass·zimg가 빠져 있다**(2026-08 확인) — 자막이 안 붙고 HDR 색이 바랜다. 정적 빌드를 내려받아 쓴다.
- 빌드 검증은 `--enable-libass` 문자열이 아니라 **`ffmpeg -filters`에 `ass`·`zscale`이 실제로 있는지**로 판정한다(빌드마다 표기가 다르다).
- `ffmpeg`를 못 찾으면 PATH 미반영이다 — 맥은 `export PATH="$HOME/.local/bin:$PATH"`, 윈도우는 앱을 재시작하거나 전체 경로로 호출한다.
- 스크립트 실행 시 파이썬은 **작업 폴더의 venv 파이썬**을 쓴다(위 표 참조).
- 모델: Qwen3-TTS-12Hz-1.7B-Base(목소리 클론) · mlx_whisper large-v3-turbo(자막) — 첫 실행 시 자동 다운로드
- 목소리 클론 레퍼런스(P1·P4에서 사용): 사용자 녹음 wav + **정확 일치 대본**. 작업 폴더 `voice/ref.wav` + `voice/voice.json`(`{"ref_audio": "ref.wav", "ref_text": "..."}`)에 등록한다 — `tts_chunks.py`가 자동으로 찾는다. 스크립트 파일에 적지 않는다.
- ⚠️ TTS 청크 서두에 "요" 같은 군더더기 음절이 붙을 때가 있다(특정 첫 단어에서 재현). 재전사로 잡히면 ①첫 단어를 바꿔 재생성("전송이나"→"다만 결제나")이 정석, ②트림할 땐 whisper 타임스탬프를 믿지 말고 **10ms RMS 프로파일로 실제 무음 지점**을 찾아 자른다. 최종 합본 재전사 필수.
- ⚠️ ref_text가 실제 발화와 한 단어라도 다르면 옹알이가 생성된다 — 클론 실패의 최다 원인.
- 레퍼런스가 없으면 **맥 마이크로 바로 녹음**한다(폰·AirDrop 불필요). 내가 대본을 주고 사용자가 읽게 하면 대본이 자동으로 일치한다 → `references/p1-narration.md` §1-b.
## 사용자 데이터는 작업 폴더에 — 스킬 폴더는 업데이트로 덮인다
스킬 폴더(`~/.claude/skills/reel`)는 `git pull`이나 새 버전 설치로 통째로 바뀐다. 사용자 것은 전부 **작업 폴더**(예: `~/reels`)에 둔다.
| 사용자 데이터 | 위치 |
|---|---|
| 프로필·목표 | `PROFILE.md` · `GOALS.md` |
| "규칙으로 적어둬" 한 편집 규칙 | **`MY_RULES.md`** — 작업 시작 때 PROFILE·GOALS와 함께 읽는다. 스킬 규칙과 부딪히면 MY_RULES가 이긴다 |
| 목소리 | `voice/ref.wav` + `voice/voice.json` |
| 컷시트·작업 파일 | `reel_<슬러그>/` |
- 사용자가 "앞으로 계속 그렇게 해 — 규칙으로 적어둬"라고 해도 **SKILL.md·references·scripts는 고치지 않는다.** `MY_RULES.md`에 날짜와 함께 한 줄로 적는다.
- 직접 넣은 폰트(잘난체 등)는 `assets/fonts/`에 둔다 — git이 추적하지 않는 파일이라 `git pull`에 안전하다. zip으로 다시 설치할 때만 옮겨야 한다.
## 업데이트 요청 ("릴스 스킬 업데이트해줘")
- **git으로 설치한 경우**(`~/.claude/skills/reel/.git`이 있음): `git -C ~/.claude/skills/reel pull` → 세팅 스크립트 재실행(이미 설치된 건 건너뛰고 새 의존성만 추가) → `CHANGELOG.md`에서 바뀐 점을 요약해 보고.
- **zip이나 v2.0 이전 버전으로 설치한 경우** — 예전엔 사용자 것이 스킬 폴더 안에 있었다. 덮어쓰기 전에 옮긴다:
1. 현재 스킬 폴더를 작업 폴더의 `_skill_backup/reel_<날짜>/`로 복사한다. ⚠️ `~/.claude/skills/` 안에 백업하지 않는다 — 같은 이름 스킬이 둘이 되어 충돌한다.
2. `scripts/tts_chunks.py`의 `REF_AUDIO`·`REF_TEXT` → 작업 폴더 `voice/voice.json`(+ wav를 `voice/`로 복사).
3. 사용자가 SKILL.md·references에 추가한 규칙(새 버전에 없는 문단 — 예전 원본 zip이 있으면 diff로 가려낸다) → `MY_RULES.md`. 애매하면 목록을 보여주고 묻는다.
4. `assets/fonts`·`assets/sfx`에 직접 넣은 파일 → 새 버전의 같은 위치로.
5. 새 버전 설치 → 세팅 재실행 → 옮긴 항목 목록 보고. 백업은 사용자가 확인하기 전까지 지우지 않는다.
## 사용자 프로필·목표 (선택 — 있으면 대본 품질이 크게 올라감)
작업 폴더에 `PROFILE.md`가 있으면 대본 작성 전에 읽는다(`MY_RULES.md`가 있으면 그것도 — 사용자가 쌓은 편집 규칙). 없으면 첫 릴스 제작 시 아래를 물어 만들어 둔다.
- 누구인가(업종·역할) · 누구에게 말하는가(타깃) · 무엇을 파는가 · 말투(존댓말/반말, 구어체 정도) · 금기(쓰지 않을 표현·과장 수위·노출 원치 않는 수치)
`GOALS.md`(목표 워크북)가 있으면 함께 읽는다. 요청받으면 아래를 물어 만든다.
- 릴스로 이루려는 것(예약·판매·팔로워) · 시청자가 했으면 하는 행동(CTA의 근거) · 업로드 빈도 · 찍을 수 있는 소재 / 찍기 어려운 소재
**세팅 직후 자동 인터뷰**: 세팅 스크립트가 성공하면(출력에 `NEXT_STEP=PROFILE_INTERVIEW` 또는 "세팅 완료"), 사용자가 따로 요청하지 않아도 **곧바로 인터뷰를 시작한다.**
"세팅이 끝났습니다! 릴스 대본 품질을 위해 몇 가지만 여쭤볼게요"라고 알린 뒤 프로필 질문(업종·타깃·파는 것·말투·금기) → 목표 질문(이루려는 것·시청자 행동·빈도·소재)을 순서대로 묻고 `PROFILE.md`·`GOALS.md`를 만든다. 두 파일이 이미 있으면 건너뛰고 첫 릴스 안내로 넘어간다.
## 기획 요청 — 주제 추천·콘티 (플레이북)
촬영 전 기획을 요청받으면 아래 절차로 처리한다. 기획 없이 영상만 와도 기존 판별 흐름 그대로 진행한다(기획은 선택).
**주제 추천** ("주제 추천해줘")
1. `PROFILE.md`+`GOALS.md`를 읽는다 (없으면 먼저 만들자고 제안).
2. 주제 5개를 제안한다 — 각 주제에 ①어울리는 대본 유형 ②훅 공식 계열의 첫 문장 1줄을 붙인다.
3. 시의성 있는 소재(계절·시즌 이벤트·최근 이슈)를 우선한다 — 주제 선정·시의성이 성과를 좌우한다.
4. 목표(GOALS)와 연결되지 않는 주제는 제안하지 않는다 — "조회수만 나오는 주제"는 목적지가 없다.
**콘티 (촬영 리스트)** ("콘티 짜줘")
1. 주제를 확정하고 **대본 3청크 초안을 먼저** 쓴다 (훅 공식 + 대본 유형 적용, 나레이션 기준 25~35초).
2. 대본의 각 문장에 필요한 그림을 역산해 **컷 단위 촬영 리스트 표**를 만든다:
| 컷 | 찍을 것 | 구도·앵글 | 목표 길이 | 주의점 |
3. 촬영 리스트 규칙:
- 세로(9:16) 고정 · 컷당 실사용은 2~5초지만 **촬영은 10초 이상 여유 있게** (트림은 AI 몫이라고 안내)
- 훅 컷(첫 3초용)은 인물·움직임·표정 우선 — 정적인 화면으로 시작하지 않는다
- 같은 구도가 3컷 연속되지 않게 클로즈업·와이드·손·화면을 섞는다
- 찍기 어려운 소재(`GOALS.md`)는 리스트에 넣지 않는다
4. 콘티는 작업 폴더에 `콘티_<주제슬러그>.md`로 저장하고, 채팅에는 표로 보여준다 (폰으로 보며 찍도록).
5. 이후 촬영본이 `input`에 오면 **그 콘티를 컷시트 초안으로 사용**한다 — 컷 매칭이 끝나 있으므로 판별·배치가 빨라진다. 콘티에 없는 컷이 섞여 있어도 거부하지 말고 흡수한다.
## 레퍼런스 모사 요청 ("이 릴스처럼 만들어줘: <URL|파일>")
1. **영상 확보** — 파일이면 그대로 쓴다. URL(인스타·유튜브·틱톡 등)이면 `.venv/bin/yt-dlp -o ref.%(ext)s "<URL>"`로 내려받는다(윈도우 `.venv\Scripts\yt-dlp.exe`, setup이 설치). 비공개·다운로드 실패 시 사용자에게 화면 녹화로 제공해달라고 안내한다.
2. **자동 계측 — `scripts/ref_profile.py <레퍼런스> --out ref_profile.json`**
눈대중 금지. 이 도구가 아래를 실측해 JSON으로 준다. **여기서 나온 숫자를 그대로 쓴다.**
| 계측 항목 | 어디에 쓰나 |
|---|---|
| 컷 길이 중앙값·최단·최장 | 컷시트의 컷 길이 배분 |
| 텍스트 밴드 위치(화면 %) | 자막 MarginV · 타이틀 overlay y |
| 글자 높이 보통/최대(화면 %) | 자막 크기 · 강조 확대 배수 |
| 글자색 / 외곽선색 | ASS PrimaryColour / OutlineColour |
| 풀스크린 카드 구간 | 데모·타이포 카드를 넣을 자리 |
| 발화 비율 | 나레이션형인지 무음형인지 |
⚠️ **자막 위치를 우리 정본(MarginV 758)으로 덮어쓰지 않는다** — 모사 요청에서는 레퍼 계측값이 우선이다.
추가로 프레임 9~12장을 눈으로 보고(장면 구성·손동작·자료 화면), 오디오를 전사해 대본 구조와 환청 여부를 확인한다.
폰트는 후보 3~4종을 **같은 문구·같은 스타일로 렌더해 레퍼와 나란히 대조**한 뒤 고른다(획 굵기·둥근 정도).
3. **문법 추출 보고** — 편집 시스템(P1~P6)·훅 계열·컷 리듬·화면 장치(박스 카드·라벨·목업·데코)를 표로 정리해 보여주고, 사용자 주제·소재에 맞춘 콘티를 제안한다(새로 찍을 컷 명시).
4. **재현 제작** — 사용자 소재로 콘티→제작 흐름 그대로. 완성 후 레퍼런스와 side-by-side 비교로 검증한 뒤 완료를 선언한다.
⚠️ **저작권 가드**: 모사 대상은 구성·문법·스타일이다. **원본의 영상 프레임·대본 문장·음원을 결과물에 복사해 넣지 않는다.** 내려받은 레퍼런스 파일은 분석용으로만 쓰고 작업 폴더 밖으로 배포하지 않는다.
## 편집 스타일 프리셋 10종 (화면의 옷)
파이프라인(P1~P6)이 **무엇을 찍었나**라면, 프리셋은 **어떻게 보이게 할까**다. 둘은 독립이라 자유롭게 조합한다.
| # | 이름 | # | 이름 |
|---|---|---|---|
| 01 | 네온 하이라이트(기본) | 06 | 브루탈 네온 |
| 02 | 키네틱 타이포 | 07 | 뉴스 자막바 |
| 03 | 박스 라벨 튜토리얼 | 08 | 타이포 카드 리스트 |
| 04 | BGM 감성 타이포 | 09 | 스플릿 스크린 |
| 05 | 미니멀 화이트 | 10 | 줌 펀치 |
- 사용자가 번호·이름을 말하면 **`references/presets.md`의 해당 항목만 읽고** 그 값(자막 스펙·오버레이·필터·컷 리듬)을 적용한다.
- 지정이 없으면 소재·주제에 맞는 프리셋 **2개를 추천**하고 고르게 한다. 기본값은 01.
- 컷시트를 제시할 때 어떤 프리셋인지 한 줄로 알린다.
## 공통 규약 (모든 파이프라인)
### 대본·카피
- `PROFILE.md`가 있으면 그 톤·타깃·금기를 따른다.
- **훅은 "벽"이 먼저다** (개인 계정 릴스 5편 실측): 댓글 400~1,900개가 달린 3편은 ①다들 막히는 **구체적인 벽**을 먼저 박고
②그 벽을 넘는 **화면 증거**를 보여주고 ③**댓글 키워드 CTA**로 끝났다. 30~65개에 그친 2편은 벽 없이 **내 성과**나 **내 일상**으로 시작했다.
도구·제품 이름이 먼저가 아니다. 주어가 나여도 **내가 겪은 벽**이면 살고 **내 자랑**이면 죽는다.
→ 기획 첫 질문은 "이번 편이 짚을 벽이 뭔가"다. 벽이 안 나오면 소재를 바꾼다.
- 대본으로 쓴 말은 주장이지만 **실제로 누군가 뱉은 말은 증거**다 — 녹음 원음·실사용 장면을 끼울 수 있으면 끼운다(프리셋 C).
- 제3자 목소리·얼굴을 쓸 땐 **발행 전 본인 동의**를 받고, 인물이 특정되는 문장·금액은 빼거나 뭉갠다.
- 기본 금기: 과장·공포 소구·미검증 수치. 확인되지 않은 숫자는 아예 쓰지 않는다.
- TTS용 숫자는 한글 표기("오 분에서 십 분") — 아라비아 숫자는 오독된다.
### 폰트·타이포 (레퍼런스 픽셀 대조로 검증된 스타일)
- **폰트는 `assets/fonts/`에 39종 동봉** (카테고리: 제목·자막 / 본문·자막 / 손글씨·개성 / 명조·감성 + licenses). 전부 OFL — 상업 이용 무조건.
기본은 **가석원체(Gasoek One)** — 자동으로 잡힌다. 사용자가 "OO 폰트로 바꿔줘"라고 하면 `REEL_FONT=이름일부` 환경변수로 넘긴다.
여기어때 잘난체는 저작권 정책상 동봉하지 않는다 — 사용자가 공식 페이지에서 직접 받아 `assets/fonts/`에 넣으면(세팅가이드 안내) 최우선으로 잡힌다.
ASS 자막 폰트도 같은 폴더에서 자동 선택된다(`make_subs.py`가 폰트 내부 이름을 읽어 Fontname에 기입하고, 쓴 폰트를 작업 폴더 `_fonts/`에 모은다 → 합성 시 `fontsdir=_fonts`).
- 용도 가이드: 자막·타이틀은 **제목·자막** 카테고리(가석원·도현·검은고딕 등), 감성 컷은 명조·감성, 포인트 한 컷만 손글씨.
**한 편에 폰트는 1종**(타이틀+자막 동일)이 원칙 — 섞으면 산만해진다.
- 폰트가 하나도 없어도 진행한다 — OS 기본 한글 폰트(맥 Apple SD Gothic Neo / 윈도우 맑은 고딕)로 폴백.
- **타이포 카드**: 그라디언트 단색 카드 금지, `drawtext` 직접 사용 금지(위 공백 문제) — `scripts/make_typo.py`로 투명 PNG 렌더 후 `overlay=0:0`.
강조=노랑 #FCED00+검정 외곽선+드롭섀도, 보조=흰+검정 외곽선, 배경 `eq=brightness=-0.05`.
- **타이틀은 인트로 3.2초만**("썸네일에만"): `make_typo.py title "수식 문구" "메인 타이틀" title.png` → `-loop 1 -t 3.2 -i title.png` + `fade=out:st=2.6:d=0.5:alpha=1` + `overlay=0:227:eof_action=pass`.
전 구간 고정 금지. 수식=빨강 필 #FC0000+흰 글자 / 메인=박스 없음, 흰 글자+근검정 외곽선 #140D08 4px(얇게)+강한 드롭섀도. 커버용 `-ss 0.5` 프레임 jpg도 함께 추출.
메인이 한 줄에 안 들어가면(대략 4어절 이상) **자동으로 2줄**이 된다 — 줄이기만 하면 양끝이 잘린다.
최종 mp4에서 노랑을 재면 #FFDE00쯤 나온다 — yuv420p 크로마 서브샘플링 탓이지 설정 오류가 아니다. 이걸로 색을 다시 만지지 않는다.
- 인물 인서트형(프리셋 C)·모티베이션(A)·브이로그(B)는 자막 폰트가 **Pretendard Black**이다 — 위 가석원체 규칙은 P1~P6 기본 자막에 해당한다.
- **자막(ASS)** — 88편 관찰 기준 세 가지가 문법이다: ①짧은 단위(구, **≤12자** — 타이틀급 폰트 84px 기준 실측, 16자는 화면을 넘친다) ②**강조 단어만 색** ③위치는 소재를 피해서.
`make_subs.py <audio> phrases.txt [--accent FCED00] [--pos bottom|center] [--style box] [--words words.json]`
- `--style box`: **검정 박스 자막**(Pretendard, 줄 전체 단일 박스) — 배경이 복잡해 가독이 안 나올 때. BorderStyle 4라 윗변이 일자로 떨어진다(3은 색 구간마다 박스가 갈라져 울퉁불퉁 — 쓰지 말 것).
- **카라오케 자막**: `karaoke_subs.py <audio> phrases.txt [--accent FCED00]` — 말하는 단어가 강조색으로 차오른다(검정 박스형). *별표* 강조어의 발화 시각을 `accents.json`으로 내보낸다.
- `--anim fade`: 줄마다 부드럽게 뜨고 진다(\fad 120/100ms) — 자막이 딱딱 끊겨 보일 때. 인 모션은 앞, 아웃 모션은 뒤가 원칙(인을 끝에 붙이면 어색하다).
- phrases.txt에서 `*별표*`로 감싼 단어가 강조색으로 렌더된다. **줄마다 강조는 최대 1개** — 숫자·핵심어에만.
- `--pos center`는 화자가 하단에 있을 때(상하분할 등) 자막을 중앙으로 올린다. 합성 시 `fontsdir=_fonts`.
- 자막 줄바꿈은 글자수 그룹핑 금지 — 구 단위 문구 리스트로 정렬한다. 12자를 넘기면 구를 더 쪼갠다.
- 키네틱(화면 배치) 문구는 **한 줄이 화면 폭을 넘으면 자동 줄바꿈에 맡기지 말고 문구를 나눠 각각 pos로 배치**한다 — 자동 줄바꿈은 윗줄과 겹친다(실사고 2회).
- **위치 정본**: 기본 자막은 화면 중앙 가까이(y≈56~60%, MarginV 758)에 둔다 — 하단에 붙이면 인스타 UI(캡션·버튼)에 먹히고 존재감이 죽는다. make_subs 기본값이 이 위치다.
- **인스타 UI 가림 영역**(1080x1920): 하단 y>1580(캡션·계정명) · 우측 x>900(버튼) · 상단 y<170. 안전 영역 x 72~1008 · y 190~1560, 하단 CTA는 **y1500 위**.
좌표는 `scripts/layout.py` 상수만 참조하고, 오버레이 PNG는 `python layout.py check <png>`로 알파 픽셀을 재서 검수한다.
- ⚠️ **합성 시 `fontsdir=_fonts`** — `make_subs.py`가 쓴 폰트를 작업 폴더 `_fonts/`에 모아둔다. `assets/fonts`를 직접 주면 libass가 하위 폴더를 안 뒤져 **오류 없이 시스템 고딕으로 바뀐다**(v1.x 문서의 안내 오류, v2.0에서 수정).
- 배속 오디오·점프컷 오디오는 재전사하면 끝을 놓치거나 숫자 표기("다섯"↔"5")로 어긋난다 → `--words words.json`으로 단어 시각을 직접 넣는다(`word_subs.py words/map`).
- **강조는 색만 바꾸지 말고 크기까지 키운다** — `--emph-scale 3.0~4.0`. 숏폼 자막의 핵심 문법이고, 색만 바꾸면 레퍼 대비 존재감이 5분의 1로 떨어진다(2026-08 실측).
강조어는 **1~4자로 짧게** 잡아야 크게 키울 수 있다 — 긴 구를 강조로 잡으면 키울 수가 없다. 숫자·순서어(첫째/둘째)·핵심 명사가 적합.
- **글자색·외곽선색은 짝으로 정한다**: 밝은 배경 = 진한 글자 + 흰 외곽선 / 어두운 배경 = 흰 글자 + 검정 외곽선 / 강조 = 브랜드색 + 대비색 외곽선. 외곽선 두께는 강조에서 기본의 2~3배.
- ⚠️ **자막은 실제 발화와 같아야 한다.** 대본에 없는 단어를 자막에 넣지 않는다(음성과 어긋난다). make_subs가 불일치를 경고하면 반드시 고친다.
- **키네틱 스타일** (`--style kinetic`) — 인터뷰·감성·토킹헤드(P2·P6)의 문법. 하단 바 대신 **화면에 타이포를 배치**한다.
```
텍스트 | pos=x,y an=4 size=1.15 ← 줄마다 위치·정렬·크기 지정
~단어~ = 디밍(회색) · *단어* = 강조색 · 빈 줄 = 블록 경계(블록 안 줄들은 화면에 누적)
```
- 산세리프(Pretendard)·무외곽선 자동 적용. 핵심어는 **size 1.6~2.2**로 키워 위계를 만든다("99%" 문법).
- ⚠️ 외곽선이 없어 배경을 탄다 — **어둡고 조용한 영역(옷·그늘·벽) 위에만** 배치하고, 렌더 전 해당 프레임을 눈으로 확인한다.
- 컷마다 배경이 다르므로 pos는 컷 단위로 설계한다. **밝은 배경 대응 지시어**:
`ink=dark`(검정 잉크 + 빨강 강조 — 문서·흰 화면 위) · `box=1`(반투명 검정 박스 — CTA·어수선한 배경 위).
- 상단 워터마크(eyebrow 텍스트)는 넣지 않는다 — 화면만 좁아지고 시선을 뺏는다.
### 동봉 에셋 (assets/) — 자동으로 쓴다
스킬 폴더 안에 있으므로 **경로를 물어볼 필요가 없다.** 사용자가 위치를 몰라도 된다.
```
~/.claude/skills/reel/assets/
├─ fonts/ 폰트 — 자동으로 잡아 쓴다 (직접 넣은 잘난체 > 동봉 가석원체 > OS 기본 순)
└─ sfx/ 효과음 — 아래 규칙대로 얹는다
```
**폰트**: `make_typo.py`·`make_subs.py`가 `assets/fonts`를 자동 탐색한다.
특정 폰트를 쓰려면 `REEL_FONT=파일명일부` 환경변수로 지정한다. 사용자가 "OO 폰트로 해줘"라고 하면 이 방식으로 넘긴다.
**효과음 — 넣는 자리는 세 곳뿐이다.** 컷마다 넣으면 산만해져 오히려 싸구려로 보인다.
| 자리 | 시점 | 음량 |
|---|---|---|
| 타이틀 등장 | 0.3초 | 0.35 |
| 강조 전환 (핵심 문장 직전) | 해당 컷 시작 | 0.30 |
| 마지막 CTA | 종료 2초 전 | 0.35 |
```bash
# 나레이션 위에 효과음 두 개를 지정 시각에 얹는 패턴
ffmpeg -y -i reel.mp4 -i assets/sfx/whoosh_in.wav -i assets/sfx/pop.wav \
-filter_complex "[1:a]adelay=300|300,volume=0.35[s1];\
[2:a]adelay=24500|24500,volume=0.35[s2];\
[0:a][s1][s2]amix=inputs=3:duration=first:normalize=0[a]" \
-map 0:v -map "[a]" -c:v copy out.mp4
```
- ⚠️ `amix`는 기본적으로 음량을 나눠버린다 — **`normalize=0`을 반드시 넣는다.** 빼면 나레이션이 작아진다.
- 나레이션이 있는 구간에는 얹지 않는다. 말과 겹치면 둘 다 죽는다.
- `assets/sfx`가 비어 있으면 **효과음 없이 진행한다.** 없다고 멈추지 말 것.
- **효과음 라이브러리** — 215종, 전부 저작권 걱정 없음(`sfx/LICENSE.txt`).
| 위치 | 내용 |
|---|---|
| `sfx/*.wav` 7종 | **자체 합성**(원저작자 없음) — whoosh_in · whoosh_out · pop · tick · impact · riser · ding. 짧은 명령에서 바로 쓴다 |
| `sfx/cc0/<역할>/` 208종 | **CC0** — whoosh 13 · tick 25 · pop 48 · impact 79 · riser 13 · ding 30. 실제 녹음이라 합성본보다 질감이 낫다 |
- 고를 때: 역할 폴더에서 파일명으로 1차 추림 → 후보 3~5개를 사용자에게 들려주고 확정한다(소리의 좋고 나쁨은 귀로 판단한다).
- 새 효과음은 CC0(Kenney·OpenGameArt·Freesound CC0 필터) 또는 `scripts/make_sfx.sh` 합성 레시피로만 들인다. ⚠️ myinstants 같은 밈 사운드보드·macOS 시스템 사운드·BBC 효과음 라이브러리는 반입 금지(비상업 한정·권리 미정리).
### 이펙트 — 펀치인·셰이크·글리치 (`scripts/fx.py`)
ffmpeg 필터 문자열 생성기. concat 뒤(자막 번인 전) 체인에 끼운다: `[vc]<punch>,<shake>,<glitch>[vfx]`.
| 도구 | 언제 | 규칙 |
|---|---|---|
| `fx.punch(times)` | **강조어 발화 순간** 화면이 팍 확대→복귀 | `karaoke_subs.py`의 `accents.json` 시각을 그대로 넣는다(자동 동기화). 엔드카드 구간은 제외. amp 0.08~0.10 |
| `fx.shake(times)` | 임팩트 **효과음과 같은 시각** | 효과음 없는 셰이크는 어색하다 — 반드시 소리와 짝 |
| `fx.glitch(times)` | 컷 경계 전환 | 한 편에 2~3곳까지. 감성(프리셋04)·미니멀(05)에는 쓰지 않는다 |
- 속도 램핑은 필터가 아니라 레시피(fx.py 독스트링) — 나레이션 싱크가 깨지므로 **무음 컷 전용**.
- 이펙트는 양념이다: 펀치인+셰이크+글리치를 전부 쓴 컷이 연속되면 싸구려로 읽힌다. 컷당 1종 이하.
### 컷 레이아웃 — 컷마다 고른다
컷시트를 짤 때 **컷마다 레이아웃을 명시**한다. 상세와 합성 패턴은 `references/layouts.md`.
| | 레이아웃 | 언제 |
|---|---|---|
| L1 | 인물 풀 | 화자가 말하는 구간 |
| L2 | 실사 풀 | 현장·제품·동작 |
| L3 | 자료 풀 | 기사·앱·문서를 크게 |
| **L4** | **상하 분할** | 자료 + 화자 동시 — **자료가 있으면 기본값** |
| L5 | 삽입(PIP) | 본 화면 위에 참고 화면 |
| L6 | 타이포 단독 | 결정적 한 줄 · 전환 호흡 |
- 같은 레이아웃을 **3컷 이상 연속으로 쓰지 않는다.**
- **실사 컷만 나열하지 않는다 — 전체 컷의 1/3 이상은 자료·타이포 계열(L3·L5·L6)로 채운다.**
촬영 원본이 부족하면 만들어서 쓴다: 채팅·체크리스트 목업(make_mockup), 타이포 카드(make_typo overlay), 주석 그래픽(make_annot).
실사만 이어 붙인 결과물은 밋밋하다 — 자료 컷이 "설명하는 릴스"의 밀도를 만든다.
- 소재가 하나뿐이어도 타이포 카드(L6)는 항상 만들 수 있다 — 없는 "촬영 자료"를 억지로 만들지 말라는 것이지, 그래픽 컷을 생략하라는 뜻이 아니다.
### 자료 화면 연출 (설명형·사례형의 골격)
근거 자료를 그냥 얹으면 "스크린샷을 붙였구나"로 보인다. **아래 세 장치로 자료를 화면의 주인공으로 만든다.**
**① 아이폰 목업** — 앱·웹 화면은 목업 프레임에 넣는다. `scripts/make_mockup.py`
```bash
python make_mockup.py shot.png mock.png --w 620 --y 900 --tilt -4
# 1080x1920 투명 PNG → overlay=0:0
```
- `--w` 화면 폭(기본 640) · `--x/--y` 중심 좌표 · `--tilt` 기울기 · `--crop top|center|bottom`
- 스크린샷은 **앱 화면만** 넣는다. 이미 다른 UI가 담긴 이미지를 넣으면 화면 속 화면이 되어 지저분해진다.
**② 주석 그래픽** — 자료의 어디를 보라고 짚는다. `scripts/make_annot.py`
```bash
python make_annot.py circle out.png --at 540,700 --size 470,300
python make_annot.py arrow out.png --from 250,1400 --to 460,960 --add # --add로 덧그리기
python make_annot.py box out.png --at 540,1150 --size 720,190 --color 2E6BFF
python make_annot.py line out.png --at 540,1100 --size 560,0 # 밑줄
```
- 기본 빨강 `EE1E1E`. **브랜드 색이 있으면 `--color`로 통일**한다.
- 화살표는 `--bow`로 휘는 정도 조절(0이면 직선). 한 화면에 **주석은 하나만** — 두 개 이상이면 시선이 흩어진다.
**③ 화자 축소 배치** — 인물을 하단 1/3에 작게 깔고 위쪽을 자료로 채운다.
```
[1:v]scale=1080:-1,crop=1080:640:0:ih*0.25[spk]; # 화자 하단 밴드
[bg][spk]overlay=0:1280[v]
```
- 얼굴이 잘려도 무방하다. **인물은 신뢰 장치이지 주인공이 아니다.**
### 영상 처리
- ⚠️ **아이폰 촬영본은 HDR(HLG·BT.2020 10bit)** — 그대로 섞으면 출력에 HDR 태그가 오염돼 카톡·인스타 재인코딩 시 색이 물빠진다.
소스별 `ffprobe -show_entries stream=color_transfer`로 확인하고 HLG면 체인 앞에 톤매핑:
`zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p`
출력엔 항상 `-colorspace bt709 -color_primaries bt709 -color_trc bt709` 태깅.
- 모든 컷은 1080x1920·30fps·yuv420p로 통일 후 `concat=n=N:v=1:a=0`. 가로(16:9) 소스는 `crop=608:1080:X:0,scale=1080:1920`으로 인물·화면 중심 크롭.
- **최종본은 반드시 단일 패스 마스터 렌더**: 컷별 mp4 중간 인코딩 조립은 QA 반복 단계까지만. 마스터는 원본 소스들을 한 filter_complex에서 트림·크롭·concat·자막·타이틀까지 **1회 인코딩** — `-crf 18 -preset slow`, 업스케일 컷엔 `scale=...:flags=lanczos,unsharp=5:5:0.4`.
- ⚠️ `filter_complex` + `-af apad -shortest` 조합에서 `-shortest`가 무시돼 출력이 수십 분으로 늘어질 수 있다 → 출력 옵션에 `-t <영상길이>`를 명시하거나 사후 `-c copy -t`로 컷.
### 훅 공식 — 첫 3초 (레퍼런스 13편 전사 실측)
대본을 쓸 때 **첫 문장을 아래 다섯 계열 중 하나로 명확히 잡는다.** 어중간한 도입부가 이탈을 만든다.
| 계열 | 형태 | 쓰는 유형 |
|---|---|---|
| **질문형** | 숫자 낙차·양자택일·차이를 묻는다 — *"9,300만 적자에서 500만 흑자로. 어떻게?"* | 사례·상황극·비교·Q&A |
| **선언형** | 얻을 결과와 걸리는 시간을 못박는다 — *"한 달치 콘텐츠, 45분이면 됩니다"* | 튜토리얼·문제해결·랭킹·레벨 |
| **지적형** | 시청자나 통념을 정면으로 찌른다 — *"필요 이상으로 어렵게 하고 계십니다"* | 흔한실수·인터뷰 |
| **역설형** | 있을 수 없는 일을 보여주고 이유를 설명한다 — *"버틸 리 없는데, 보세요"* | 설명형 |
| **정보격차형** | *"이게 있는데 대부분 모릅니다"* — 소외 심리를 건드린다 | 리스트형 |
⚠️ **한국어는 서술어가 뒤에 와서 영어 훅을 그대로 옮기면 늘어진다.** 핵심어를 앞으로 빼는 도치를 쓴다.
### 대본 유형별 컷 리듬 (88편 실측 — 중앙값 기준)
⚠️ **기본값이지 규칙이 아니다.** 유형 안의 편차가 유형 간 차이의 2.9배다 — 같은 유형에서도 소재에 따라 10배 넘게 갈린다.
리듬을 정하는 건 유형이 아니라 소재다: **항목이 여러 개면 짧게 끊고, 한 대상을 오래 보여줘야 하면 늘린다.** 유형은 출발점일 뿐.
| 빠름 (컷당 2~3초) | 중간 (4~6초) | 느림 (6초 이상) |
|---|---|---|
| 레벨 2.0 · 상황극 2.2 · 사례 2.4 · 문제해결 2.9 | 비교 4.2 · Q&A 4.8 · 리스트 4.9 · 흔한실수 5.3 · 설명 5.5 | 튜토리얼 6.4 · 랭킹 8.0 · 인터뷰 11.5 · 리액션 13.0 |
- 설명형은 느리게 가되 **중반 한 번 속도 폭발**(0.2~0.5초 몽타주)로 이탈 구간을 넘긴다.
- 문제해결형은 **문제는 눌러 담고 해결은 몰아친다.**
- 느린 유형은 억지로 끊지 않는다 — 줌·자막 등장·레이아웃 전환으로 **화면 안에서 변화**를 준다.
공통 발견(21편 전부에서 반복):
- **강조색은 한 편에 하나만.** 흰색 자막 + 포인트 1색(빨강·형광노랑·시안 중 택1).
- **얼굴이 나오되 주인공이 아니다.** 화자는 하단 1/3에 작게, 화면 상단은 근거 자료가 채운다.
- **마지막은 댓글 유도 CTA.** 특정 단어를 댓글로 남기게 한다(`"자동화"라고 댓글 남겨주세요`).
- 자막은 문장을 그대로 옮기지 않고 **키워드 카드**(3~7단어)로 띄운다.
### QA (완료 선언 전 필수)
- 나레이션이 있으면 `python voice_tools.py qa <레퍼런스.wav> <청크들>` — 음색 드리프트(다른 사람처럼 들리는 청크)·먹히는 청크를 숫자로 걸러 재생성한다.
- ⚠️ **개인정보 프레임 확인 — 렌더 전·후 각 1회.** 화면 녹화·실계정 소재는 이름·전화번호·예약정보가 프레임에 남는다.
발견 시 렌더를 멈추고 보고한다: 데모 데이터 재녹화(원칙) 또는 해당 구간 블러. **테스트 렌더라도 예외 없음.**
- 컷별 프레임 7장을 `hstack` 스트립 1장으로 만들어 한 번에 검수.
- 중간 프레임 1장을 추출해 한글 렌더·자막 위치를 눈으로 확인한 뒤 완료 보고.
- 레퍼런스를 모사할 때: ①레퍼런스를 크롭 확대해 구조 파악(눈대중 금지) ②색상은 픽셀 추출 ③폰트는 후보 2~3종을 같은 문구로 렌더해 나란히 대조 ④완성 후 side-by-side 비교로 검증.
### 커버 (완성 보고 전 필수)
릴스가 완성되면 **커버를 스타일 2안으로 만들어 함께 제시**한다. `scripts/make_cover.py` — 스타일 6종 프리셋 (89편 첫 프레임 전수 분류 기준).
```bash
# 영상에서 표정·구도가 좋은 프레임을 골라 추출한 뒤
python make_cover.py badge frame.jpg cover.png --title "타이틀" --eyebrow "수식어"
python make_cover.py bar frame.jpg cover.png --title "타이틀" --color 2E6BFF # 브랜드색
python make_cover.py box frame.jpg cover.png --title "타이틀" --sub "서브 문구"
python make_cover.py big frame.jpg cover.png --title "한 단어"
```
| 스타일 | 언제 | 88편 내 빈도 |
|---|---|---|
| **duo** | 투톤 스택 키워드 — `*별표*` 단어만 포인트색. **기본 추천** | 최다 (~1/4) |
| box | 흰/검 상자 라벨 — 사례·후기형 | 많음 |
| big | 한 단어로 때리기 — 댓글 키워드 커버 | 많음 |
| badge | 수식 배지 + 대형 타이틀 | 있음 |
| bar | 하단 단색 띠 — 기사·예측·정보형 | 드묾 |
| **elegant** | 세리프 감성 — 외곽선 없이 조용하게. **뷰티·카페·공간 계열의 기본** | 소수 반복 (~8%) |
```bash
python make_cover.py duo frame.jpg cover.png --title '릴스 편집\n*자동화*로 끝내세요' --color FFD400
```
- duo는 줄을 `\n`으로 직접 나누는 걸 권장 — 강조 단어가 어느 줄에 갈지 설계가 곧 커버다.
- elegant는 명조(고운바탕)가 자동 적용된다. 사용자 업종이 뷰티·카페·공간·감성 계열이면 **duo 대신 elegant를 기본 추천**한다.
- 커버 타이틀은 **영상 훅과 같은 문장**을 쓴다(다르면 낚시로 느껴진다). 7단어 이내로 줄인다.
- **그리드 세이프존 자동 적용** — 텍스트는 중앙 1:1 크롭에서 살아남는 위치에만 놓이고, `_grid.jpg` 미리보기가 함께 나온다. 완성 보고 때 그리드 미리보기도 같이 보여준다.
- 프레임 선정: 얼굴이 나오면 **시선이 정면**인 프레임을 고른다. 눈 감김·흔들림 프레임 금지.
### 전달
- 결과물: `~/Downloads/릴스_<주제>_<날짜>.mp4`로 복사.
- 컷시트·대본은 작업 폴더에 md로 남긴다(다음 편 제작 시 톤 레퍼런스가 된다).
## 작업 디렉터리
작업 폴더 하위에 `reel_<주제슬러그>/`를 만들어 중간 파일을 격리한다. 재사용 스크립트는 이 스킬 폴더 `scripts/`가 정본
(setup.sh · setup.ps1 · tts_chunks.py · make_subs.py · make_typo.py · make_cover.py · make_mockup.py · make_annot.py · jumpcut_plan.py ·
ref_profile.py · karaoke_subs.py · fx.py · **word_subs.py · mg_kit.py · voice_tools.py · screen_cards.py · layout.py · reel_assets.py** ·
**preset_motivation/ · preset_longtake/**). 프리셋 폴더는 `reel_<슬러그>/`에 폴더째 복사해서 쓴다 — 스킬 폴더 안에서 직접 돌리지 않는다.
- 하루를 넘길 작업은 시스템 임시 폴더(`/tmp` 등)에 두지 않는다 — 운영체제가 며칠 지난 파일을 지워 스크립트까지 잃는다.