비디오 편집 워크플로우
사용자가 로우 비디오를 보낼 때마다 다음 단계를 따르세요. 도구 루트: /home/user/video-workflow (VW=/home/user/video-workflow). 비디오마다 스크래치패드에 새 작업 디렉토리를 사용하세요(예: $SCRATCH/<name>/work). 4단계 전에 STYLE_GUIDE.md(스타일), EFFECTS.md(17개 효과 라이브러리 - 모든 비디오에서 여러 개 사용) 및 templates/STORYBOARD_REFERENCE.md(구문)를 읽으세요.
0. 설정(컨테이너당 한 번)
$VW/vw.sh setup. huggingface.co가 차단되었다고 경고하면, 사용자에게 환경의 네트워크 설정에서 huggingface.co(및 *.hf.co)를 허용할 때까지 전사를 실행할 수 없다고 알리세요. 대체 전사본을 만들지 마세요.
1. 준비 + 전사 + 컷 제안
$VW/vw.sh prep RAW.mp4 WORK [--language ro|en] [--model small|medium]
- "씻긴(Washed)" SDR 푸티지(압축 앱이 톤 매핑 없이 재인코딩한 iPhone HDR: 검은색이 뿌옇고 흰색이 어두움 - 예: *_compressed.mp4)는 prepare.py에서 감지되어(검은색 포인트 Y45 이상, 흰색 포인트 Y203 미만 - 같은 세트의 톤 매핑된 .mov 클립 옆에 있는 어두운 흰색) 준비 단계에서 수준이 복원됩니다(휘도 스트레치 Y34..~215, 채도 x1.08). 승인된 톤 매핑 HDR(Mindri-Box-v3)의 자연스러운 룩과 일치합니다.
- 모든 클립에 대한 승인된 색상 룩(사용자 규칙 - "우리가 이야기했던 필터"): 정규화 후 prepare.py는
source.mov에 대해look_match를 실행합니다. 프레임의 상단 60%(배경 + 사람)를 측정하고 톤 커브 + 채도를 적용하여 모든 클립이 승인된 룩(Mindri-Box-v3 / Comanda-Ionut-v2/v4: 깊은 검은색, 생생한 주황색, 깨끗한 흰색 티셔츠; 대상 p5 38, p25 52, p50 76, p95 226, 채도 59)과 일치하도록 합니다. 그림자/중간톤만 깊게 하고, 어두운 흰색을 밝게 하며, 색상을 추가합니다(포인트당 최대 35레벨, 채도 최대 x1.3). 이미 룩에 맞는 클립은 건드리지 않습니다. 따라서 여러 클립 비디오는 서로 일치합니다. 상단의grade는natural로 유지됩니다. - HDR 휴대폰 푸티지(iPhone: HLG/PQ, BT.2020, 10비트, Dolby Vision)는 자동으로 SDR BT.709로 톤 매핑됩니다(zscale + hable, 100nit). 그렇지 않으면 모든 것이 창백하고 뿌옇게 보입니다. 출력은 BT.709로 태그됩니다.
- 30fps CFR, 1080x1920(커버 크롭)으로 정규화하고, 얼굴을 감지하며(MediaPipe 전체 범위), 타이틀 영역 밝기를 측정하여
layout.json(안전 영역; 밝은 영역은 타이틀을 박스 처리하고 유리 텍스트에 색조를 입힘)을 생성합니다. - 단어 타임스탬프로 전사합니다("음"/재시작 표시 유지) →
transcript.json. - 필러, 말더듬, 잘린 단어 및 재시작을 자동으로 플래그 지정합니다 →
edit.json+review.txt. - 루마니아어 또는 시끄러운 오디오에는
--model medium을 사용하고, 그 외에는 자동 언어 감지를 사용합니다. - 소스가 가로인 경우(경고 출력), 사용자에게 중앙 크롭되었다고 알리세요.
1b. 여러 로우 클립(하나의 스토리)
사용자가 여러 클립을 보내면 각각을 먼저 전사하고 말한 내용(일반적으로 촬영 순서)에서 순서를 파악하세요. 각 클립(WORK_k)에 대해 1-2단계 및 cut을 실행한 다음 결합합니다: python3 $VW/scripts/merge_clips.py WORK WORK_1 WORK_2 … → 하나의 타임라인; layout.json은 각 클립의 자체 프레이밍(clips[])을 유지하며, 렌더러와 효과는 화면에 표시되는 클립의 프레이밍을 사용합니다. 병합된 words.json에서 캡션 텍스트를 수정한 다음, WORK에서 4단계를 계속 진행합니다. 모든 클립 경계에 전환(zoom_through, flash, glitch)을 넣으세요.
2. 편집 검토(판단 단계 - 건너뛰지 마세요)
편집자처럼 WORK/review.txt를 처음부터 끝까지 읽고 WORK/edit.json을 수정하세요:
- 제거: 감지기가 놓친 실패한 테이크/재시작(마지막 좋은 테이크 유지), 실수한 문장, "잠깐, 다시 할게요", 주제에서 벗어난 이야기, 죽은 인트로("안녕하세요 여러분", "음, 오늘은…") – 비디오는 훅 라인으로 시작해야 합니다.
- 유지(
"keep": [idx…]): 감지기가 잘못 제거한 단어(의도적인 반복, "매우 매우", 목록). - 낮은 신뢰도 단어
(?): 문맥 확인; 잘못 들은 단어는 캡션 문제입니다(텍스트를transcript.json에서 수정하고, 타이밍은 유지). 컷 문제가 아닙니다. - 페이싱 매개변수:
max_gap0.20초(타이트함, 가이드 스타일); 단어 끝이 잘린 것처럼 들리면pad_after를 0.14로 높이세요. 그런 다음:
$VW/vw.sh cut WORK
Sync check: … OK를 출력해야 합니다. MISMATCH인 경우 → 중단하고 조사하세요(절대 배포 금지). 컷 포인트는 프레임에 스냅되고 침묵 구간에 배치되므로 립싱크가 정확합니다. WORK/words.json(새 타임라인)을 다시 읽으세요. 이후의 모든 타이밍은 이 타임라인을 사용합니다.
3. 캡션 텍스트 수정
words.json에서 철자 오류, 브랜드 이름, 숫자("ten" → "10", 읽기 더 좋을 때)를 수정하고, 사용자의 언어와 분음 부호(ă â î ș ț)를 유지하세요. 타이밍을 변경하지 마세요.
4. 스토리보드(판단 단계)
WORK/storyboard.json을 작성하세요(구문: templates/STORYBOARD_REFERENCE.md, 예제: templates/storyboard.example.json). 먼저 짧은 계획을 표(시간 · 말한 내용 · 시각적 요소 · 전환 · 효과음)로 작성하고 최종 답변에 사용자에게 보여주세요. 스타일 가이드의 규칙:
훅(0-3초) - 가장 강력한 주장을 거대한 title 요소로, 구문당 하나씩, 3초 안에 3개 이상의 시각적 변화(타이틀 교체 / 글꼴 교체 / 플래시 / 펀치-인). 타이틀 글꼴을 혼합하세요(세리프 → 볼드 → 이탤릭 골드). 인트로 없음.
본문 - 화면에서 약 1-3초마다 무언가 변경됩니다:
- 말하는 내용을 정확히 언급하는 단어에 맞춰 시각화합니다(요소의
start= 해당 단어의start): 도구/앱 →strike(거부될 때) 또는card; 지침/프롬프트 →prompt(입력); 숫자 →counter/stat; 단계 →step배지; 열거 →list; 핵심 구문 →title; 사용자가 제공한 스크린샷/로고 →image/card. - 문장당 하나의 핵심 키워드를
captions.keywords에 넣습니다(의미를 전달하는 단어, 필터가 아님). - 펀치-인 줌(
zooms, 스케일 1.06-1.12, 절대 더 크게 하지 않음)을 강조 라인에 사용하고, 1.0과 번갈아 사용합니다. 이렇게 하면 점프 컷을 숨기면서 화자를 정상 프레이밍으로 유지합니다. - 양식화된 전환은 섹션 변경/페이오프에서만 사용, 최대 5-10초에 하나:
flash,glitch,leak,whoosh,impact. - 10-15초마다 모드를 변경합니다(예: UI 카드 연속, 큰 타이틀 순간, 통계).
화자는 항상 보여야 함: 그래픽은 pos: "top"(머리 위, layout.json의 여유 영역에 자동 맞춤) 또는 "lower"(가슴 부분, 캡션 위)로 이동합니다. 얼굴 위로 center는 절대 안 됩니다. 타이틀이 머리 꼭대기를 약간 겹쳐도 됩니다(그게 룩입니다). 눈이나 입은 절대 안 됩니다.
"편집된" 참조 규칙(EFFECTS.md 하단) - 모든 비디오에서 필수: 항상 컬러 grade(기본 natural 프리셋 - 푸티지 자체 색상, 양식화된 필터 없음; 다른 룩은 요청 시에만), 30초당 1-3회 얼굴 track(추적), 구체적으로 언급된 사물에 대한 인터넷 photos(scripts/images.py, 먼저 보고 답변에 크레딧 포함), 훅 및 섹션 헤더용 combo 타이틀, 열거용 numcards.
효과 라이브러리(EFFECTS.md) - 모든 비디오에서 필수: 최종 비디오 약 4-6초마다 하나의 효과 모멘트(30초 → 5-7개, 60초 → 9-12개), 각각 말하는 내용과 일치, 약 15초 이내에 반복 금지, 카메라, 컷아웃 및 UI 패밀리 혼합. 훅에 하나를 넣으세요. 모든 효과가 포함된 예제: templates/storyboard.effects-example.json.
CTA / 엔딩(사용자가 원하는 것을 말한 경우): 마지막 4-6초에 comment(키워드 CTA) 및/또는 follow 카드.
브랜드 테마(사용자의 고정 선택) - 화면의 모든 것: 스토리보드 "style": "depth", "palette": "mindricel" → 타이틀, 카드, 단계, 타일/숫자, 차트, 체크리스트, 메모, 오비트 카드, 유리 텍스트 및 제품 모두 mindricel.ro 팔레트(주황색 #FF6600 그라데이션, 잉크 #0A0A0A 패널, 흰색 텍스트, 미세한 어두운 윤곽선)의 깊이 참조 룩을 사용합니다. 타이틀 줄의 편집 글꼴 이름은 자동으로 매핑됩니다. 낙서에는 주황색(#FF6600/#FF8533) 또는 흰색을 사용하세요. 녹색/크림 편집 색상을 절대 혼합하지 마세요.
캡션(사용자의 고정 선택 - "락업" 참조, 1:1 복사됨): "captions": {"style": "lockup", "palette": "scene"} (키워드 목록 불필요, 역할은 자동).
- 각 음성 구문(2-5단어)은 하나의 타이포그래피 구성입니다: 내용어는 크게(Montserrat ExtraBold, ~170px, 좁게 -0.045em, 발음 그대로 - 대부분 소문자), 기능어는 작게(Montserrat SemiBold, 1/3 크기, 흰색에 미세한 어두운 윤곽선) 큰 단어 모서리에 자리잡습니다. 큰 단어 앞: 위-왼쪽, 뒤: 아래-오른쪽("월 $10,000 이상"). 줄당 하나의 큰 단어, 줄은 빽빽하게 쌓이고 왼쪽/오른쪽으로 엇갈리게 정렬됩니다.
- 큰 단어별 채우기: 숫자/돈 → 녹색 그라데이션, 부정적인 단어(nu, fără, stop, greșeli, scump...) → 빨간색 그라데이션, 나머지 → 해당 클립의 푸티지 색상에서 가져온 그라데이션(
body_profile.py팔레트) 또는 흰색; 밝은 장면에서는 자동으로 더 진하고 채도가 높아지며, 어두운 장면에서는 밝아져 항상 읽을 수 있습니다. - 위치는 머리 / 가슴 / 머리 / 머리 위로 회전합니다. 타이틀이나 그래픽이 상단을 차지하는 동안 구문은 가슴에 유지됩니다. 앞에 있는 구문은 얼굴(머리카락에서 턱까지)을 가리지 않습니다. 대신 가슴이나 머리 위로 이동합니다.
- 깊이(사용자 규칙, 모든 비디오): 약 40%의 구문(
behind_share0.4)이 머리 뒤에 약간 위치합니다(뒷 레이어 + 컷아웃). 검색 범위는 "머리카락 아래쪽 가장자리를 스치는" 높이부터 얼굴 중간까지이며, 옆으로 최대 ±240px 이동합니다. 머리가 실제로 단어를 겹칠 때만(behind_min_overlap5%) 유효한 지점이며, 각 큰 단어는 최대 25% 숨겨집니다(짧은 단어는 글자당 ~4%, 예: 4글자의 경우 최대 16%). 첫 번째/마지막 글자의 상단 부분은 항상 보입니다. 클립(occ_max)에서 최악의 실루엣을 사용하며, 해당 순간에 활성화된 줌으로 확장됩니다. 3번 연속으로 뒤에 배치하지 말고, 그래픽이 상단을 차지하는 동안에는 절대 배치하지 마세요. QA에서 해당 프레임을 확인하세요. - 가독성: 모든 큰 단어에는 미세한 윤곽선(어두운 영역에서는 어둡게, 밝은 영역에서는 밝게) + 부드러운 그림자가 있습니다. 작은 단어에는 어두운 윤곽선이 있습니다. 채우기 색상은 구문 아래의 밝기를 정확히 기준으로 선택됩니다(
body_profile.py의lum맵): 어두운 영역 위는 밝은 색조, 밝은 영역 위는 진한 색조 - 팔레트는 푸티지를 유지합니다. - QA: 앞 구문이 얼굴에 닿지 않는지, 뒤 구문이 명확하게 읽히는지 확인하세요(각 구문에서 프레임 열기).
- 모션: 구문은 모션 블러 고스트와 함께 옆으로 휙 들어가고, 단어는 발음될 때 나타나며(빠른 블러 인), 다음 구문이 시작될 때 반대 방향으로 휙 나갑니다(구문 간 간격 없음).
- 읽기 시간: 구문은 발음되기
lead0.25초 전에 나타나며(단어가 목소리보다 약간 앞서감),min_phrase1.0초보다 짧은 구문은 다음/이전 구문과 병합됩니다(최대 7단어/34자). 마지막 구문은hold1.2초 동안 유지됩니다. 비디오는 마지막 단어 후tail0.8초의 그림을 유지합니다(edit.json매개변수; 푸티지가 더 일찍 끝나면 마지막 프레임이 유지됨). 여러 클립: 마지막 클립을 제외한 모든 클립에서"tail": 0. - 혼합 배경(예: 어두운 배경 위의 흰색 티셔츠, 구문 아래 밝기 차이 > 0.17): 어두운 윤곽선과 함께 비디오 자체 색상의 생생한 중간 톤("캡션 색상" 아래 참조).
- 대비 보호: 단어의 색상이 배경의 밝기와 너무 가까우면(
min_contrast0.42), 동일한 색상이 최대 대비 색조 + 미세한 윤곽선을 얻습니다. 절대 흰색으로 변하지 않습니다(사용자 규칙). - 민감/진지한 주제(장례식, 질병, 상실, 사과...): 락업 룩을 유지하지만
"motion": "fade"(부드러운 페이드 인, 휙 효과 없음),"semantic": false(녹색/빨간색 단어 색상 없음), 글리치/픽셀/버티고/프레임 브레이크 없음, 강한 효과음 없음(전혀 없어도 됨), 느린 푸시 인과 부드러운 트래킹만, 그레이드 강도 ~0.6, 사용자 자신의 브랜드가 아니면 mindricel 주황색 테마 없음. 사용자에게 분위기가 조정되었다고 알리고 에너제틱 버전을 제안하세요. - 이전 캡션 스타일(
clean헤드라인,depth,bold,editorial)은 요청 시에만 사용하세요.
숫자: tiles는 이제 하나의 어두운 둥근 알약으로 렌더링되며 큰 깨끗한 숫자가 세어지고 선택적 unit이 주황색으로 표시됩니다(예: {"type": "tiles", "text": "400-600", "unit": "cm³"}). 이전 사각형은 "look": "classic"에서만 사용됩니다.
전환(부동산 참조): 클립 변경/섹션 변경 시 flash_blur(과다 노출 디포커스), pixelate(픽셀 디졸브, 요소/이미지가 사라질 때도 좋음), zoom_through, 줌-점프 컷(punch, 점프 컷에서 1.0 / 1.1-1.15 번갈아 사용). glitch는 드물게 유지하세요.
사운드(사용자의 SFX 참조 비디오에서 추출 - 유일한 라이브러리; 이전 합성 라이브러리는 요청에 따라 삭제됨): sfx/에 10개의 WAV 파일(피크 -3dBFS): loading(디지털 틱 0.9초), click, air(짧은 바람 같은 휙), tap(부드러운 팝), marker(형광펜 스트로크), tick(작은 UI 틱), blur_hit(강한 임팩트 + 테일), swish, sub_boom(서브베이스 드롭), logo_hit(큰 리빌 히트). 자동 매핑됨(compose.py): flash_blur → blur_hit, zoom_through/leak/whoosh/swoosh 전환 → swish, flash → air, pixelate/glitch/rewind → loading, impact → sub_boom, punch → click; title/stat/combo → blur_hit(첫 번째 combo + sub_boom), strike/doodle/wall/accent → marker, cards/app/image/product info → tap, products → air + swish, steps/lists/checklists/numcards → click, counters/tiles/charts → loading, glass/cover → sub_boom, follow card → logo_hit, typing → tick. 이전 이름(pop, whoosh, deep_bass, ding, ...)은 여전히 SFX_ALIAS를 통해 작동합니다.
SFX 밀도(사용자: "효과음을 더 자주 사용하세요") - 기본 "sfx_density": "high": 요소 및 전환 사운드 외에도 compose.py는 캡션 구문 변경 시 조용한 추가 사운드(-15..-19dB)를 추가합니다(구문이 머리 뒤로 갈 때 air, 숫자/가격에 tap, 그 외 swish/tick 번갈아 사용; WORK/caption_events.json에서), 모든 점프 컷(click), 상단 그래픽이 사라질 때(air), 푸시/트랙 카메라 움직임에 추가합니다. 모든 추가 사운드는 다른 사운드와 0.3초 이상 간격을 유지합니다(~초당 1개 사운드). 조용한 주제: "sfx_density": "normal"(캡션 motion: "fade"일 때 자동).
더 적은 캡션(사용자 규칙, 모든 비디오): 모든 구문에 캡션이 있으면 피곤합니다. 구문의 약 60%만 캡션을 얻습니다(captions.density 0.6 = 40% 감소). 렌더러는 가장 의미 있는 구문(내용어, 숫자/가격, 부정어, 이름, 질문/감탄사; bă/mă/băi/deci 같은 필터는 점수가 낮음), 항상 첫 번째와 마지막 구문을 유지하며, 4개의 구문이 연속으로 캡션 없이 오지 않도록 합니다.