A-roll 처리하기
목표: 하나의 긴 녹화본 또는 동일한 스크립트의 여러 녹화본을 입력받아, 각 대사의 최상의 테이크로 구성된 깔끔한 러프 컷을 생성합니다. 말이 끊김 없이 이어지고, 모든 단어가 온전하며, 마치 한 번에 깔끔하게 녹화한 듯한 결과물을 첫 시도에 만들어냅니다.
이 스킬은 Claude Code 및 Runneth를 위해 제작되었습니다. 필요 도구:
- ffmpeg: 오디오 측정, 스틸 프레임 캡처, 비디오 컷
- 모든 발화에 대한 단어 타임코드: 각 단어의 시간 정보를 제공하는 음성-텍스트 변환(STT) 도구 (Whisper, faster-whisper, whisper.cpp)
- 화면 평가 방법: 아래 "테이크 평가 방법" 참고
- 검증 스크립트:
scripts/cut_check.py(python3, numpy, ffmpeg 필요)
편집자에게는 일상적인 언어로, 한 번에 하나의 아이디어씩 전달하세요.
시작 전: 도구 확인
Runneth에서는 모든 도구가 이미 설치되어 있습니다. 이 섹션은 건너뛰세요.
Claude Code에서는 이 스킬이 video-editing-setup 스킬이 설치하는 무료 비디오 도구가 필요합니다. ~/.video-editing-tools/bin/ffmpeg -version이 정상 실행되는지 확인하세요. 실행된다면 ~/.video-editing-tools/bin 디렉토리의 도구들(ffmpeg, ffprobe, python)을 이 스킬의 ffmpeg, ffprobe, python3 대신 사용하고 계속 진행하세요. 실행되지 않는다면 먼저 video-editing-setup 스킬을 수행한 후 다시 이곳으로 돌아오세요.
0단계: 작업 전 두 가지 빠른 확인
-
파일이 편집자가 의도한 파일인지 확인합니다. 편집자가 재촬영 또는 새 클립이라고 말했는데 이전 클립과 길이나 설정이 동일하다면, 시작 전에 한 줄로 질문하세요.
-
다음 질문을 정확히 두 가지 옵션으로 한 번에 묻습니다.
"제가 고른 테이크를 먼저 보여드릴까요, 아니면 바로 편집을 진행할까요?"
- 먼저 보여주기 → 아래 모든 단계를 따르되, 4단계에서 편집자의 승인을 위해 멈춥니다.
- 바로 편집하기 → 모든 단계를 중단 없이 처음부터 끝까지 실행합니다. 확실하지 않은 내용이 있으면 마지막에 한 번 언급합니다.
편집자가 이미 어떤 방식을 원하는지 말했다면("그냥 컷 해줘", "테이크 먼저 보여줘") 질문을 건너뜁니다. 답변할 사람이 없다면 "바로 편집하기"로 간주합니다.
1단계: 단어(텍스트) 추출
- 각 녹화본의 길이, 방향(가로/세로), 프레임 레이트를 확인합니다(
ffprobe). 여러 개의 녹화본이 있는 경우 각각에 간단한 레이블(비디오 A, 비디오 B, 비디오 C)을 붙이고 아래 모든 단계를 모든 파일에 대해 실행합니다. - 각 녹화본에서 오디오를 추출합니다:
ffmpeg -i IN.mov -vn -ac 1 -ar 16000 audio.wav. - 모든 발화 구간을 찾습니다:
ffmpeg -i audio.wav -af silencedetect=n=-35dB:d=0.3 -f null -. 무음 사이의 구간이 **발화 섬(speech islands)**입니다. 모든 단어는 이 섬 안에 있으며, 이는 어떤 자막 타임코드보다 정확합니다. - 단어별 타임코드와 함께 텍스트를 변환합니다. faster-whisper 사용 시: 모델
base,word_timestamps=True,condition_on_previous_text=False, 그리고 비디오에 등장할 법한 이름이나 브랜드 단어를 포함한initial_prompt를 설정합니다. 더 큰 영어 전용 모델은 말을 다시 시작하는 부분을 조용히 정리하여 이 스킬이 감지해야 할 잘못된 시작(false starts)을 숨길 수 있습니다. - 긴 구간에서 텍스트 변환 결과는 정확도가 떨어지거나 건너뛸 수 있습니다. 모든 발화 섬에는 단어가 할당되어야 합니다. 특정 섬에 단어가 없거나 무음 구간 사이에 단어가 누락된 것으로 보이면, 해당 구간만 다시 변환합니다: 섬 시작 약 1초 전부터 끝 약 1초 후까지를 윈도우로 설정하고, 음성 필터를 끕니다(
vad_filter=False). - 짧게 재변환된 윈도우는 끝부분에 실제로 말하지 않은 단어를 생성할 수 있습니다("Thank you very much", "Thanks for watching"). 발화 섬 안에 있고 문맥에 맞는 단어만 유지하며, 동일한 타임코드에 쌓인 단어는 생성된 것으로 간주합니다.
- 이름이나 브랜드 단어의 명백한 오인식을 수정합니다. 스크립트가 있다면 이를 대사 맵으로 사용하고, 없다면 변환 결과를 맵으로 사용합니다.
2단계: 테이크 그룹화
- 푸티지를 대사(문장 또는 하나의 생각 단위)로 나누고, 모든 녹화본에서 동일한 대사에 대한 모든 시도를 그룹화합니다. 하나의 스크립트에 대한 여러 녹화본은 하나의 테이크 풀로 간주됩니다: 대사 1은 비디오 A, B, C의 모든 테이크 1과 나란히 배치되며, 각 테이크는 녹화본 레이블("비디오 B, 테이크 3")로 표시됩니다. 일반적으로 동일한 대사의 시도는 처음 몇 단어가 동일합니다.
- 테이크는 한 시도의 시작부터 해당 시도의 마지막 단어 끝까지이며, 다음 시도가 시작되기 전까지입니다.
- 각 테이크를 완료(전체 대사를 말함) 또는 잘못된 시작(중간에 중단됨)으로 표시합니다.
- 대사 내의 모든 구절은 독립적인 조각으로 간주됩니다. 하나의 대사는 서로 다른 테이크(테이크 4의 첫 문장, 테이크 2의 두 번째 문장)의 최상의 조각으로 구성될 수 있으며, 잘못된 시작의 깔끔한 조각도 포함됩니다.
3단계: 모든 테이크 평가
각 대사의 모든 테이크(한 번만 말해진 대사 포함)를 평가합니다. 각 구절의 최상의 버전이 어떤 테이크나 순서에 관계없이 선택됩니다. 연결 부위가 깔끔할 경우(아래 규칙 7 참조) 해당 최상의 조각들로 대사를 구성합니다. 아래 "최종 선정 테이크의 기준"을 사용하고, 테이크 파일(템플릿: templates/takes.md)에 테이크당 한 행씩 기록합니다: 대사, 테이크, 시간, 관찰 내용, 선택 여부, 간단한 이유.
테이크 평가 방법
평가할 항목은 두 플랫폼에서 동일합니다. 이를 확인하는 방법은 도구에 따라 다릅니다:
- Runneth(또는 Gemini와 같이 비디오를 시청할 수 있는 모델에 비디오를 보낼 수 있는 설정)에서는 해당 모델이 모든 녹화본을 시청하고 각 반복된 대사를 "최종 선정 테이크의 기준"과 어조, 강조, 농담 타이밍, 주저함에 따라 평가하도록 합니다. 자신의 선택을 모델에 보내지 않아 두 평가가 독립적으로 유지되도록 합니다. 모델이 자신과 다른 테이크를 선택하면 모델의 선택을 따릅니다. 타임코드는 항상 텍스트 변환 결과와 발화 섬에서 가져오고, 비디오 모델에서 가져오지 않습니다. 비디오 모델의 타임스탬프는 부정확하고 대사를 건너뛰는 경우가 있습니다.
- Claude는 비디오를 볼 수 없으므로, 자체적으로 확인할 수 있는 세 가지 항목으로 평가합니다:
- 단어(텍스트 변환 결과): 전체 대사, 더듬거림 없음, 불필요한 말 없음, 중간 재시작 없음.
- 소리(각 테이크의
astats): 일정한 볼륨, 클리핑 없음, 갑작스러운 소음이나 버스트 없음. - 화면(스틸 프레임): 각 반복 대사에 대해 모든 테이크를 하나의 시트로 결합, 초당 2프레임:
ffmpeg -nostdin -ss START -t LENGTH -i IN.mov -vf fps=2,scale=160:-2,tile=10xN take.jpg, 테이크당 하나씩 생성하여 하나의 이미지로 결합합니다. "최종 선정 테이크의 기준"의 모든 항목에 대해 시트를 검토합니다.
- 화면 녹화(음성 포함): 문장, 음성, 그리고 포인팅이나 클릭이 말하는 내용과 일치하는지 평가합니다.
4단계: 선택 결과 표시(편집자가 먼저 보기를 요청한 경우에만)
- 컷 목록을 표시합니다: 유지된 조각당 번호가 매겨진 행,
시작-끝시간 및 정확히 유지된 단어. 근소한 차이로 선택된 경우 해당 행에 "(근소한 차이: 테이크 2도 동등하게 깔끔함)"을 추가하여 편집자가 확인할 위치를 알게 합니다. 명확한 선택은 별도 표시 없습니다. 편집을 막는 요소(알아들을 수 없는 단어)가 있는 경우에만 마지막에 한 줄을 추가합니다. - 편집자는 승인하거나, 테이크를 교체하거나("대사 4는 테이크 2를 사용"), 대사를 삭제할 수 있습니다. 이후 비디오 모델이 다른 의견을 제시하더라도 편집자의 변경 사항이 우선합니다. 테이크 교체 시 편집자가 이유를 말하지 않았다면 한 줄로 이유를 묻습니다. 편집자의 이유는 스킬이 학습하는 방법입니다(7단계).
5단계: 컷 생성
컷은 매우 빡빡합니다: 유지된 테이크 내부를 포함하여 모든 곳에서 말이 곧바로 이어집니다. 구절 사이의 생각할 시간이나 숨소리는 잘라냅니다. 유지되는 유일한 정적 구간은 마지막 프레임에서 약 0.5초입니다.
- 경계는 텍스트 변환 결과가 아닌 발화 섬에서 가져옵니다. 각 유지된 조각은 해당 섬의 첫 번째 소리에서 시작하여 마지막 소리에서 끝납니다. 첫 단어 이전의 숨소리, 입술 소리, 조작 소음은 -30dB 이상으로 올라와 섬에 포함될 수 있으므로, 조각은 첫 번째 단어의 시작점(레벨이 말하기 수준인 약 -25dB 이상으로 급상승하는 지점)에서 시작하며, 첫 번째 작은 소음이 아닙니다. 조각 시작이나 끝의 숨소리나 소음 구간은 잘라냅니다. 끝 부분은 반대로 작동합니다: 대사는 종종 조용히 흐려집니다("밤에 잠들었어"를 부드럽게 말하는 경우). 따라서 조각은 마지막 단어가 나머지보다 조용하더라도 해당 단어 이후에 끝납니다. 모든 대사의 마지막 단어가 컷의 텍스트 변환 결과에 포함되는지 확인하세요.
- 유지된 테이크 내부의 일시 중지는 더 민감한 설정인
silencedetect=n=-30dB:d=0.2로 찾아내어 0.25초 이상의 모든 일시 중지를 잘라냅니다. 테이크 내의 재시작이나 반복된 단어도 잘라내고 깔끔한 최종 구문만 유지합니다. - 각 조각의 양쪽에 약 0.05초를 추가로 남깁니다. 더 길게 남기면 일시 중지가 생기고, 더 짧게 남기면 단어가 잘립니다. 그런 다음 모든 경계를 정수 프레임에 맞춥니다(시작은 이전 프레임으로 내림, 끝은 이후 프레임으로 올림). 프레임 사이의 경계는 프레임 중복이나 누락을 유발하여 이후의 모든 컷이 한두 프레임씩 밀리게 되고, B-roll이 컷 위에 배치될 때 잘못된 프레임이 나타날 수 있습니다.
- 약 0.3초보다 짧은 조각은 거의 항상 남은 부분(잘못된 음절)입니다. 전체 단어를 담고 있지 않으면 제거합니다.
- 모든 연결 부위에 20ms 오디오 페이드를 추가하고 작업 복사본에서 하나의 재인코딩으로 모든 것을 연결합니다. 원본 파일은 그대로 유지됩니다.
- 조각 목록(
[[시작, 끝], ...](초))을clips.json으로 저장합니다. 검증 스크립트가 이 파일을 읽습니다.
6단계: 편집자가 보기 전에 컷 검증
편집자가 보는 모든 버전은 해당 파일에 대해 모든 검사를 통과한 것입니다. 실행되지 않은 검사는 실패로 간주됩니다.
- 검증 스크립트 실행:
python3 scripts/cut_check.py --voice audio.wav --clips clips.json --out CUT.mp4. 다음 세 가지를 확인하고RESULT PASS또는FAIL을 출력합니다:- 끝부분: 모든 조각의 마지막 50ms가 말하기 수준(-30dB) 미만입니다. 그렇지 않으면 단어가 잘린 것이므로 레벨이 떨어지는 지점으로 끝을 늦춥니다.
- 시작부분: 각 조각 시작 전 30ms가 조용하므로 조각이 단어 중간에 시작하지 않습니다.
- 갭: 최종 정적 구간을 제외하고 컷 내 어디에도 0.25초 이상의 일시 중지가 없습니다.
여러 녹화본이 있는 경우 녹화본당 한 번씩 실행합니다: 해당 녹화본의 오디오를
--voice로, 해당 녹화본의 조각만clips.json에 담고, 매번 동일한 컷을--out으로 지정합니다. 사운드가 다른 파일(별도 마이크)에서 오는 경우, 카메라 자체 오디오도 동일한 트림으로 잘라--camlock으로 전달하여 스크립트가 동기화도 확인하도록 합니다(매 3초마다 40ms 이내).
- 모든 단어가 온전하고 한 번씩만: 컷을 단어 타임코드와 함께 텍스트 변환하고 컷 목록과 단어 단위로 비교합니다. 연결 부위에서 절반 단어는 해당 경계가 너무 빡빡하다는 의미입니다. 연결 부위에서 반복된 단어나 구절은 남은 재시작을 의미합니다. 단어 사이에 데드 에어 없음: 해당 텍스트 변환 결과에서 한 단어의 끝과 다음 단어의 시작 사이의 갭이 약 0.3초보다 길지 않아야 합니다(최종 정적 구간 제외). 스크립트의 갭 검사는 조용한 일시 중지만 찾습니다. 숨소리로 가득 찬 일시 중지는 통과할 수 있을 정도로 크므로, 이 단어-갭 검사가 이를 잡아냅니다. 조각을 첫 번째 단어로 다듬고 모든 검사를 다시 실행합니다.
- 각 연결 부위를 하나씩: 모든 컷에 대해 그 앞의 마지막 단어와 뒤의 첫 번째 단어를 명명하고, 둘 다 완전히 발화되었는지 확인합니다. 각 연결 부위 주변 2초 윈도우를 텍스트 변환하여 확인합니다(일반적인 "문제 있나요?"는 잘린 단어를 놓칠 수 있습니다). Runneth에서는 비디오 모델이 까다로운 첫 시청자처럼 컷을 시청하고 잘리거나 잘못된 단어, 글리치, 정지 프레임, 불편한 점프 등 문제를 시간과 함께 나열하도록 합니다.
- 길이: 컷의 길이가 컷 목록의 총 시간과 일치해야 합니다.
실패한 모든 항목을 수정하고 다시 컷한 후 모든 검사를 재실행합니다.
7단계: 편집자로부터 학습
편집자가 테이크를 교체하거나, 경계를 변경하거나, 특정 테이크가 더 나은 이유를 설명할 때마다 그 이유를 일반 규칙으로 전환하여 아래 "최종 선정 테이크의 기준"(또는 컷의 빡빡함에 관한 경우 5단계)에 병합합니다. 목록을 짧게 유지하세요: 새 규칙을 쌓아두지 말고 기존 규칙을 다시 쓰고 결합합니다. 편집자의 이유만이 규칙을 변경합니다.
최종 선정 테이크의 기준
이 규칙들은 한 편집자가 자신의 독백 비디오에서 실제로 선택한 내용을 바탕으로 만들어졌습니다. 순서대로 적용한 후, 편집자의 이유가 들어오면 해당 규칙으로 교체하세요.
- 전체 대사가 깔끔하게 말해짐. 더듬거나 단어가 누락된 테이크는 아무리 화면이 좋아도 깔끔한 테이크에 패합니다.
- 얼굴을 가리는 것이 없음. 입 앞에 손이나 마이크가 있으면 테이크에서 제외됩니다.
- 에너지. 몸짓, 움직임, 활기찬 전달이 정적이고 평평한 읽기보다 낫습니다.
- 가장 행복한 표정. 두 개의 깔끔한 테이크 사이에서는 진짜 미소와 밝은 눈이 승리합니다.
- 표정이 대사에 어울림. 펀치라인에 큰 눈, 행복한 대사에 진짜 미소.
- 자연스럽고 고른 속도. 서두르지 않고, 긴 일시 중지 없음.
- 최상의 조각, 깔끔하게 연결. 최상의 테이크는 어떤 녹화본에 있든 승리하며, 두 테이크의 부분으로 만들어진 대사는 각 부분이 더 나은 버전일 때 하나의 완전한 테이크보다 낫습니다. 연결 부위는 화자의 머리와 손이 양쪽에서 거의 같은 위치에 있을 때(이전 및 이후 프레임 확인), 또는 나중에 B-roll로 가려질 때 깔끔합니다. 녹화본 간 전환도 양쪽에서 동일한 외관(헤어스타일, 조명, 구도, 손에 든 제품)이 필요합니다. 외관이 변경되면 전환은 대사 사이에 이루어지고 B-roll 또는 줌 변경으로 가려집니다.
- 더 강하게 전달될 때 더 짧게. 이미 말한 내용을 반복하거나 비디오 속도를 늦추는 나머지 부분은 대사를 가장 강력한 부분으로 줄입니다("다 떨어질 때까지" 대신 "얼마나 도움이 되고 있었는지 깨닫지 못했어요. 다 떨어질 때까지").
- 근소한 차이는 근소한 차이로 남음. 두 테이크가 동등하게 깔끔하고 프레임에서 실제 차이가 없으면 하나를 선택하고 근소한 차이로 표시합니다. 스틸 프레임은 어조를 보여줄 수 없으므로, 하나가 명확히 낫다고 가장하지 마세요.
모든 컷에 대한 규칙
- 컷의 모든 단어는 오디오에서 비롯됩니다. 알아들을 수 없는 단어는 추측하지 않고 불명확으로 표시합니다.
- 시간은 원본 녹화본의 시간선을 기준으로 하며, 컷 목록의 모든 조각은 해당 녹화본을 명시합니다.
- AI 시간은 정확하지 않고 근사치입니다. 모든 경계는 발화 섬에서 설정하고 오디오에서 확인합니다.