Rough cut: 불필요한 부분 제거
편집자들은 이 과정을 어셈블리(assembly) 와 러프 컷(rough cut) 이라고 부릅니다. 모든 사용 가능한 대사는 순서대로 들어가고, 자리를 차지할 가치가 없는 것은 제거됩니다. 완성된 영상이 아닙니다. 모든 초가 화자가 대사를 잘 말하는 버전이며, 이후 패스(페이싱, 색보정, 그래픽, 사운드)가 좋은 소재로 작업할 수 있도록 합니다.
기본 아이디어: 파형이 아닌 단어를 편집합니다. 모든 단어에 시작 및 종료 시간이 있는 대본을 얻고, 읽어서 무엇을 유지할지 결정하면, 타이밍에 따라 컷이 자동으로 생성됩니다. Descript와 Premiere, Resolve의 텍스트 기반 편집이 이러한 방식으로 작동합니다. 이 스킬은 여기에 두 가지 추가 기능을 제공합니다: 모든 컷을 실제 소리에 스냅하고, 렌더를 다시 들어보며 확인합니다.
설정 (한 번만)
sh ~/simcraft/skills/rough-cut/setup.sh
이 파일 옆에 Whisper(Apple Silicon에서는 mlx-whisper, 그 외에서는 faster-whisper)를 사용하는 .venv를 생성합니다. ffmpeg이 필요합니다: PATH에 ffmpeg가 있거나, $FFMPEG 환경 변수, 또는 ~/neatlogs-motion/ffmpeg에 있어야 합니다. 아래 모든 스크립트는 ~/simcraft/skills/rough-cut/.venv/bin/python으로 실행합니다.
작업 공간
비디오 하나당 하나의 폴더를 사용합니다. 사용자가 만들지 않은 경우 ~/Movies/edits/YYYY-MM-DD-<slug>/를 만들고 원본 파일을 raw/로 복사 (이동하지 마세요) 합니다. 스크립트는 audio/, cuts/, renders/ 폴더를 그 옆에 씁니다. raw/의 내용은 절대 변경되지 않습니다.
순서대로 진행되는 패스
1. 전사
python scripts/transcribe.py <workspace> [--lang en]
audio/words.json (모든 단어: 시작, 종료, 텍스트, 신뢰도)과 audio/transcript.txt (테이크당 한 줄)를 씁니다. M-시리즈 Mac에서 영상 2분당 약 1분 소요됩니다.
영어일 때 --lang en을 전달하면 더 정확합니다. 힌디어/영어 혼합 음성의 경우 생략합니다.
정확성을 유지하는 방법 (각각은 실제 영상에서 발생한 실패를 수정합니다):
- 각 테이크는 별도로 전사됩니다. 오디오는 0.5초 이상의 모든 일시 중지에서 분할됩니다. 전체 파일을 한 번에 전사하면 Whisper가 다섯 번 말한 줄을 한 번만 기록하므로 추가 테이크에 단어가 없어 컷할 수 없습니다.
- 필러는 대본에 유지됩니다. Whisper는 기본적으로 "음"과 "어"를 생략합니다. 주저함이 많은 프롬프트를 사용하면 다시 가져와서 컷할 수 있습니다.
- 반복 전사 루프는 제거됩니다. Whisper는 때때로 노이즈 위에서 구절을 수십 번 반복합니다("there you go there you go ..."). 초당 7단어 이상은 불가능하므로 해당 줄은 폐기됩니다.
2. 컷 찾기
python scripts/find_cuts.py <workspace> [--gap 0.35] [--keep-fillers]
cuts/edl.json (유지할 조각들, 순서대로)과 cuts/cut_sheet.md (모든 컷과 그 이유, 그리고 확인해야 할 낮은 신뢰도 단어)를 씁니다.
| 컷 유형 | 규칙 |
|---|---|
| 데드 에어 | --gap(0.35s)보다 긴 모든 일시 중지. 머리와 꼬리 무음도 포함. |
| 필러 | 음, 어, 음, 흠, 음, 아. |
| 반복 | 최대 4단어로 구성된 단어 또는 덩어리가 연속으로 두 번 말해진 경우 ("so the so the"): 두 번째를 유지. |
| 재시도 | 20초 이내에 같은 대사가 다시 말해진 경우, 철자로 매칭되어 잘못 들린 경우에도 매칭 ("Vanta" / "Wanda", "1" / "one"): 마지막 테이크를 유지. |
| 잘못된 시작 | 대사가 중간에 중단되고 완전히 말해진 경우 ("A 300 billion." 그 다음 "A 300 million dollar business."). |
| 동일한 끝맺음 | 시작은 다르게 바꿔 말했지만 같은 방식으로 끝나는 대사 ("That's, it's Vanta's own founder" 그 다음 "And that's not me saying it, it's Vanta's own founder"). |
| 유령 단어 | 그 아래에 음성이 없는 단일 단어. Whisper가 무음에서 이를 만들어냅니다 ("Thank you.", "hallelujah"). |
각 컷이 위치하는 곳:
- 모든 가장자리는 음성이 실제로 시작하고 멈추는 지점에 스냅되며, 10ms 단계의 음량과 방에 적응하는 임계값으로 측정됩니다. Whisper의 단어 시간은 0.1–0.3초 정도 차이가 날 수 있습니다.
- 가장자리는 최대 0.12초까지만 늦게 이동할 수 있습니다. 단어를 자르는 것이 숨을 유지하는 것보다 더 나쁘기 때문입니다.
- 음성 앞에는 0.06초, 뒤에는 0.10초의 여유 공간이 남습니다.
- 실제 간격이 없는 경우, 예를 들어 "uh"가 다음 단어에 붙어 있는 경우, 컷은 두 단어 사이에서 가장 조용한 10ms 지점에 위치합니다.
- 하나의 긴 Whisper "단어" 안에 숨은 일시 중지도 발견되어 컷됩니다.
3. 판단 패스 (실제 편집, 절대 건너뛰지 마세요)
audio/transcript.txt 옆에서 cuts/cut_sheet.md를 읽고 수동으로 cuts/edl.json을 수정합니다. 스크립트는 다음을 판단할 수 없습니다:
- 어떤 테이크가 가장 좋은지. 기본적으로 마지막 테이크가 유지되지만, 가장 좋은 테이크는 에너지가 있고, 깔끔하게 끝나며, 웃음으로 망가지지 않은 것입니다. 때로는 한 테이크의 전반부와 다른 테이크의 후반부가 가장 좋습니다.
- 농담의 일부인 필러. 펀치라인 전의 의도적인 "어"는 유지됩니다.
- "like", "you know", "I mean", "basically". 이들은 절대 자동으로 제거되지 않습니다. 순전히 지연시키는 것만 제거하세요. 모두 제거하면 화자가 자신답지 않게 들립니다.
- 박자 역할을 하는 일시 중지. 펀치라인, 반응, 또는 카메라를 바라보기 전의 일시 중지는 유지됩니다. 모든 침묵이 데드 에어는 아닙니다.
- 같은 요점을 다른 단어로 두 번 말하는 경우. 전체 문장을 제거합니다.
- 비음성 순간 (예: 노래, 시각적 개그, 반응 샷). 음성만 유지되므로 수동으로 이러한 조각을 추가합니다.
- 순서. 조각은 파일 순서를 따릅니다. 사용자가 원할 경우 가장 강력한 대사를 콜드 오픈으로 맨 위로 이동합니다.
- "확인할 단어" 목록. 낮은 신뢰도는 종종 중얼거림을 의미합니다. 대사가 명확하지 않으면 더 깨끗한 테이크를 찾습니다.
각 조각은 {"clip", "in", "out", "text"}이며, "speed"는 선택 사항입니다. 단어 사이에서 컷을 유지합니다.
4. 페이스 (먼저 물어보세요)
컷 시트는 초당 단어 수를 보고합니다. 빠른 토크 헤드 콘텐츠는 약 3.3–3.8입니다. 화자가 느린 경우 1.05–1.2의 속도를 제안하고 edl.json에 전체 비디오 또는 조각별로 "speed"를 설정합니다. 피치는 동일하게 유지됩니다. 음악이나 반응은 절대 속도를 높이지 마세요.
5. 미리보기 렌더
python scripts/render.py <workspace> --w 854 --v 1 [--aspect 9:16]
480p 미리보기가 renders/v1_854.mp4로 생성됩니다. 각 수정 라운드마다 --v 값을 높여 이전 버전을 유지합니다.
- 각 조각은 정확한 프레임 수와 압축되지 않은 오디오로 렌더링된 후, 모든 조각이 디코딩되어 연결됩니다. 스트림 복사 연결은 컷에서 프레임이 떨어지고 오디오가 몇 분 후에 약 2초 정도 드리프트됩니다.
- 각 조각에는 12ms 페이드 인과 20ms 페이드 아웃이 적용되어 컷에서 클릭 소리가 나지 않습니다.
- 모양이 다른 클립은 검은 막대 대신 흐릿한 복사본 위에 배치됩니다.
6. 검증 (항상, 사용자에게 보여주기 전에)
python scripts/verify.py <workspace> --v 1 [--lang en]
렌더를 다시 듣고, 조각별로 듣고, 컷 목록과 비교하여 cuts/verify_v1.md에 보고서를 씁니다. 보고서에는 네 가지 섹션이 있습니다:
- 음성이 아직 진행 중일 때 컷이 있는 경우: Whisper에 의존하지 않는 사운드 테스트입니다. 실제 단어 잘림 감지기입니다.
edl.json에서 해당 가장자리를 이동하여 각각을 수정합니다. - 누락된 단어: 예상되었지만 들리지 않은 단어.
- 예상치 못한 단어: 필러 또는 재시도 조각이 새어 나오는 경우.
- 잘못 들음: 두 대본이 단어 선택에 동의하지 않는 경우. 일반적으로 중얼거림이지 컷 문제가 아닙니다.
깨끗한 오디오의 목표는 단어 100% 존재, 소리 내 컷 0, 예상치 못한 단어 0입니다. 시끄럽거나 중얼거리는 오디오는 실제로 잘못 들음인 누락/예상치 못한 쌍을 생성합니다. 사운드 테스트를 신뢰하세요.
발견된 사항을 수정하고, 다시 렌더링하고, 다시 검증합니다.
7. 사용자에게 보여주고, 최종 작업
- 사용자에게 알립니다: 전후 길이, 컷 수, 검증 결과, 그리고 내린 판단(유지한 테이크, 의도적으로 유지한 일시 중지 등).
- 다음 버전을 만들기 전에 사용자의 의견을 기록합니다.
- 사용자가 미리보기를 승인한 후에만:
python scripts/render.py <workspace> --w <source width> --v N.
실제 영상 결과
3분 분량의 원본 토크 헤드 영상에서 재시도가 많았던 경우(한 대사에 9번 테이크, 다른 대사에 4번), 2:55의 대화가 0:36으로 줄었습니다. 각 대사의 마지막 깨끗한 테이크를 유지했으며, 검증 결과 단어 100% 존재, 소리 내 컷 0, 예상치 못한 단어 0이 발견되었습니다.
사용자의 취향
- 스냅합니다. 단어 간격에 점프 컷은 좋지만, 지속적인 번갈아 가며 찍는 펀치 인 줌은 좋지 않습니다.
- 욕설, 농담, 재미있는 부분은 유지합니다. 개성을 절대 지우지 마세요.
- 우우우 소리나 색보정은 이 단계에서 하지 않습니다.
- 사용자가 "좋은 부분만, 최대 X분"을 요청하면, 일시 중지만이 아닌 전체 순간을 잘라냅니다.