Communitygithub.com

비디오 종이 편집 (Paper Edit)

녹화된 토크 영상을 DaVinci Resolve에서 조립된 러프 컷으로 변환합니다. 영상 드라이브에서 클립을 가져와 로컬로 자막을 추출하고, 실패한 테이크, 방언, 여백 및 데드 에어를 제거한 후, 세부 편집을 위한 두 개의 페이퍼 편집 타임라인이 포함된 새로운 Resolve 프로젝트를 생성합니다.

비디오 종이 편집 (Paper Edit)란 무엇인가요?

이 스킬은 '페이퍼 에디트', '내 원본 영상 잘라줘', '러프 컷 만들어줘', '이 영상 정리해줘' 등의 트리거로 실행되며, 사용자의 원본 카메라 파일이 담긴 폴더를 가리키면 자동으로 작동합니다. 작업 흐름은 크게 11단계로 구성됩니다: (1) 영상 드라이브에서 푸티지 찾기, (2) 모든 클립을 로컬 whisper.cpp로 전사, (3) 전사 결과를 사람이 읽고 컷 리스트 작성, (4) JSON 형식의 컷 리스트 생성, (5) 세그먼트 빌드, (6) 사용자에게 컷 리스트 공개 및 승인, (7) Resolve에서 실제 빌드, (8) 핸드오프, (9) 선택적 펀치인(확대) 타임라인, (10) 컬러 그레이딩 (LUT 적용), (11) 사진 오버레이 등 고급 기능을 포함합니다. 이 스킬은 DaVinci Resolve의 API를 직접 활용하여 새 프로젝트를 생성하고 타임라인을 구성하므로, Resolve 설정에서 'External scripting'이 'Local'로 활성화되어 있어야 합니다. 또한 ffmpeg, ffprobe, whisper-cli, Python 3 등이 필요하며, 첫 번째 실제 테스트에서는 14분 17초의 원본을 10분 16초로 줄여 제작자의 수동 편집 결과(10분 32초)와 유사한 결과를 냈습니다. AI 모델(Claude)이 광범위한 컷을 담당하고, 사용자가 세부 트림을 수행하는 분업 구조를 가집니다. 컷 리스트 작성 시, 의도적인 반복(교육적 목적)은 유지하고, 확신이 없는 부분은 보수적으로 남깁니다. 3~4개의 트리거 문장을 인식하여 사용자의 의도를 빠르게 파악합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/beachyphotoandfilm-arch/video-skills/tree/HEAD/skills/paper-edit

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

종이 편집 (Paper Edit)

원본 카메라 파일을 받아서 DaVinci Resolve에서 조립된 러프 컷을 출력합니다. 첫 번째 실제 테스트 영상에서: 원본 14:17, 출력 10:16, 제작자의 수동 편집 결과(10:32)와 비슷했습니다.

역할 분담: 클로드(Claude)가 대략적인 컷을 수행하고, 제작자가 세부 트림을 합니다. 완성된 편집을 제공하려고 하지 말고, 너무 보수적으로 해서 사용자가 명백한 부분을 다시 작업해야 하는 상황도 피하세요.

설정: 다음을 채우세요

플레이스홀더설명예시
<FOOTAGE_DRIVE>원본 푸티지가 있는 드라이브, 비디오당 하나의 폴더/Volumes/MyWorkDrive
<LUT_PATH>선택적 LUT, Resolve의 LUT 폴더 기준 상대 경로MyLuts/SLog3-to-709.cube
WHISPER_MODEL (환경 변수)whisper.cpp 모델 파일기본값 ~/.cache/whisper-models/ggml-small.en.bin
RESOLVE_APP (환경 변수, 선택)비표준 경로의 Resolve 앱 경로기본값 /Applications/DaVinci Resolve/DaVinci Resolve.app

필요 사항: ffmpeg, ffprobe, whisper-cli (whisper.cpp), Python 3, execute_resolve_code를 노출하는 Resolve MCP 서버가 있는 DaVinci Resolve.

실행 방법

작업 디렉토리: 세션 스크래치패드 사용 (예: <scratchpad>/paperedit). 스킬 디렉토리는 아래 .claude/skills/paper-edit 입니다.

1. 푸티지 찾기

푸티지는 <FOOTAGE_DRIVE>에 있으며, 비디오당 하나의 폴더로, 이름이 느슨하게 지정되어 있습니다.

find "<FOOTAGE_DRIVE>" -maxdepth 4 -iname "*<keyword>*" -not -path "*/.*"

두 개 이상 일치하면 사용자와 폴더를 확인하세요. 파일을 복사하지 마세요. Resolve는 드라이브의 파일을 링크합니다.

2. 모든 클립 전사하기

bash <skill>/scripts/transcribe.sh "<FOOTAGE_DRIVE>/<folder>" "<work>"

<clip>.json (단어 수준), <clip>.wav, clips.ndjson (길이 포함)을 작성합니다. 15분 분량의 푸티지에 약 90초 소요됩니다. 이미 완료된 클립은 건너뛰므로 다시 실행해도 안전합니다.

3. 직접 전사 내용 읽기

python3 <skill>/scripts/sentences.py "<work>"

전부 읽으세요. 이 부분은 스크립트로 처리할 수 없는 부분입니다. 반복 구문 감지기를 시도했지만 심각하게 실패했습니다. 교사가 의도적으로 문구를 반복하기 때문에 737초 중 428초를 자르려고 했습니다.

4. 컷 리스트 작성

<work>/cuts.json, 제거당 하나의 객체, 시간은 해당 클립 시작부터 초 단위:

[{"clip":"C0002","start":32.58,"end":39.76,"why":"말 더듬: '내가 깨달은 것은 가끔은...'"}]

다음을 자르세요:

  • 방언 및 카메라 대화: "꽤 괜찮았어, 거짓말 안 할게", "이 카메라 곧 배터리 나갈 것 같아", "이거 아마 7분짜리 영상이 될 거야"
  • 잘못된 시작, 마지막 시도를 유지하세요. 화자는 종종 문장을 두 번 말하는데 두 번째가 더 낫습니다.
  • CTA(클릭 유도 문구)의 실패한 테이크. 보통 끝에 3-4개가 있습니다. 마지막 것을 유지하세요.
  • 섹션 사이의 긴 침묵, 괄호로 표시된 소음 ([BLANK_AUDIO], (키보드 소리), (웅성거림))
  • 생각 중간에 버려지고 다시 구성된 문장 ("예전에 이렇게 안 했던 이유는 두려웠기 때문이고...")
  • 쉼표로 표시되고 다시 시작된 절로 표시된 문장 내의 짧은 재시작: "내가 요구한 건 간단한 리뷰와 이것, 그리고 리뷰 부분을 추가하는 것..." 버려진 절에서 재시작 지점까지 자릅니다. 이들은 1-2초로 읽기 쉽습니다.
  • Whisper 단어 시간 오프셋 약 0.5초 정도 부정확합니다. 같은 단어를 다시 말하는 잘못된 시작의 경우 ("나는 제안하기를 좋아합니다, 나는 시작하기를 좋아합니다"), 첫 번째 시도의 끝이 아니라 두 번째 "나는"의 시작에서 컷을 끝내십시오. 그렇지 않으면 잘못된 단어가 남습니다.
  • 컷은 유지할 단어의 to 오프셋에서 시작하고, from에서는 절대 시작하지 마세요. 한 테스트에서 컷이 40.30에서 시작했지만 유지할 단어가 40.19-40.92에서 실행되어 훅의 마지막 단어가 잘렸고 수동으로 다시 끌어와야 했습니다. 모든 컷 앞의 단어에 대해 from|to로 오프셋을 출력하세요.
  • 긴 [BLANK_AUDIO] 실행 후에는 시간이 신뢰할 수 없습니다. Whisper가 30초의 침묵 후 첫 번째 훅 테이크의 단어를 압축하여 컷이 비디오의 첫 1초에 단어 조각을 남겼습니다. 데드 에어 후 테이크가 시작되면 오디오 레벨(ffmpeg astats)을 확인하여 단어 오프셋을 신뢰하는 대신 음성이 실제로 시작되는 위치를 찾으세요.

유지하세요:

  • 교육적 리듬을 위해 의도적으로 사용된 반복
  • 여전히 무언가를 가르치는 여담 (사용자가 달리 말하지 않는 한)
  • 확실하지 않은 모든 것. 자르는 대신 요약에 표시하세요.

5. 세그먼트 빌드

python3 <skill>/scripts/segments.py "<work>"

segments-v1.json (판단 컷만), segments-v2.json (0.50초 이상의 일시 정지를 0.22초로 트림), cutlist.txt를 생성합니다. 환경 변수를 통해 조정 가능: MIN_GAP, KEEP_PAUSE, NOISE_DB.

또한 음성 없는 블립을 제거합니다: 말하는 수준의 오디오가 없는 1초 미만의 v2 세그먼트. 이들은 마우스 클릭이나 노트북 응시로, 트리밍된 일시 정지 사이에 남은 섬입니다. 조정 가능: BLIP_MAX, SPEECH_DB.

사용자에게 보여주기 전에 cutlist.txt의 모든 join: 줄을 읽으세요. 각 컷을 가로질러 문장이 어떻게 읽히는지 출력합니다. 같은 구문이 |의 양쪽에 나타나면 컷이 너무 짧은 것입니다.

두 패스 모두 중요합니다. 판단 컷만으로는 "특히 시작 부분에 큰 일시 정지가 있다"는 피드백이 있었습니다. 일시 정지 트림이 11:32를 10:16으로 줄인 것입니다. KEEP_PAUSE를 약 0.20초 이하로 낮추지 마세요. 서두르는 느낌이 들기 시작합니다.

6. 빌드 전에 컷 리스트 보여주기

요약을 붙여넣으세요: 원본 길이, v1, v2, 컷 수, 그리고 이유와 함께 주목할 만한 컷. 사용자가 원하는 것을 거부합니다.

7. Resolve에서 빌드하기

Preferences > System > General > External scripting using: Local 필요 (한 번 설정하면 유지됨). 사용자에게 Resolve를 열라고 요청하지 마세요. 먼저 다음을 실행하세요. Resolve가 닫혀 있으면 실행하고 API가 응답할 때까지 기다립니다:

bash <skill>/scripts/ensure_resolve.sh

Resolve가 실행 중인데 시간 초과되면 스크립팅이 비활성화된 것입니다. 사용자에게 수정을 요청해야 하는 유일한 것입니다.

<work>/params.json 작성:

{"project":"<Video Name> - YYYY-MM-DD","work":"<work>",
 "files":["<FOOTAGE_DRIVE>/<folder>/C0001.MP4","..."],
 "fps":23.976,"width":1920,"height":1080}

그런 다음 한 번의 execute_resolve_code 호출:

PARAMS = "<work>/params.json"
exec(open("<skill>/scripts/resolve_build.py").read())

여러 비디오: 한 번에 하나씩 빌드하고, 절대 병렬 도구 호출로 하지 마세요. Resolve에는 현재 프로젝트가 하나이므로 두 개의 빌드가 동시에 충돌합니다. 한 번 두 빌드가 함께 실행되어 스크립트가 모든 항목이 추가되었다고 보고했지만 v2 중 하나가 비어 나왔습니다. 각 빌드 후에 각 타임라인의 항목 수를 직접 확인하세요.

프로젝트 이름을 <Video> - YYYY-MM-DD로 지정하여 같은 이름의 프로젝트가 혼동되지 않도록 하세요. 새 프로젝트를 만들고, 클립을 가져오고, Paper Edit v1과 Paper Edit v2 (tight)를 빌드합니다. 기존 항목은 건드리지 않습니다. 이는 execute_resolve_code의 승인된 사용입니다. append_to_timeline은 in/out 포인트를 사용할 수 없으므로 대체 도구가 없습니다. 세션에서 처음으로 사용자에게 코드를 보여주세요.

Resolve에 연결할 수 없는 경우 대체 (클라우드/예약 실행 또는 ensure_resolve.sh 실패): 세그먼트당 하나의 asset-clip 요소로 FCPXML을 작성하고, start 및 duration을 frames*1001/24000s로 설정하여 사용자가 가져올 수 있도록 하세요. 동일한 결과, 한 번의 추가 클릭.

8. 핸드오프

사용자에게 두 타임라인이 모두 존재하며, 먼저 스크러빙할 타임라인(v2)과 v2가 잘린 것처럼 느껴지면 v1이 안전망임을 알리세요. 그런 다음 컷이 잠겼는지 물어보십시오. 오버레이는 그 후에 옵니다 (video-overlays 스킬이 있는 경우 참조).

9. 펀치인 (선택적 세 번째 타임라인)

정적 프레이밍 변화는 토크 영상을 시청 가능하게 만듭니다. Resolve의 API에는 키프레임 접근이 없으므로 슬로우 푸시는 스크립트로 불가능합니다. 정적 클립별 프레이밍 ("가끔 클립 중 하나가 약간 더 확대됨")이 가능한 것입니다.

모든 변경을 타이머가 아닌 전사 내용에 연결하세요. 타이머 기반 버전은 무작위로 느껴졌습니다. 중요한 대사나 새 주제가 시작되는 부분에 펀치인하여 의미 있게 만드세요.

<work>/framing.json 작성:

[{"clip":"C0002","at":361.40,"framing":"med","why":"팁 3"},
 {"clip":"C0002","at":371.80,"framing":"close","why":"'이것이 중요한 부분입니다'"}]

at는 sentences.py의 문장 시작입니다. 그런 다음 python3 <skill>/scripts/punchins.py "<work>"를 실행하고 params.json에서 "punchins": true로 설정하세요. 마크가 세그먼트 내에 떨어질 때마다 문장 시작 근처에서 가장 조용한 지점에서 세그먼트를 분할합니다. 토크 헤드는 종종 일시 정지 없이 길게 실행되어 변경이 늦게 미끄러지기 때문입니다.

사용자가 Resolve에서 v2를 수동 트리밍한 경우, 그들의 타임라인이 컷입니다. 항목을 읽고 (GetLeftOffset/GetDuration, 프레임 x 1.001/24 = 초) segments-locked.json에 넣고, SEGMENTS=segments-locked.json으로 실행하고, "timelines": ["v3"]와 함께 기존 프로젝트에 v3만 추가하세요. 약 20-40초마다 한 번씩 변경을 목표로 하세요: 새 주제마다 와이드, 가르칠 때 미디엄, 중요한 대사에 클로즈업. 빌더는 각 변경에 이유를 명명한 파란색 마커를 배치하여 로직을 볼 수 있게 합니다.

프레이밍: wide 1.00, med 1.11 (틸트 -12), close 1.21 (틸트 -24).

사용자가 트리밍 중에 v2에 그레이딩을 한 경우, v3는 LUT만으로 처음부터 빌드되므로 빌드 직후 v2 그레이드를 v3에 복사하세요:

src = v2.GetItemListInTrack("video", 1)[5]          # 그레이딩된 v2 항목
src.CopyGrades(v3.GetItemListInTrack("video", 1))    # 타임라인 간 작동; 줌/틸트 유지

모든 v3 항목에서 GetNodeGraph().GetToolsInNode(1)로 확인하세요. 갤러리 경로 (GrabStill + ExportStills to .drx)를 사용하지 마세요. 내보내기가 API를 통해 False를 반환합니다. GrabStill을 사용한 경우 갤러리를 깨끗하게 유지하기 위해 스틸을 삭제하세요.

잠긴 v2 읽기: GetLeftOffset() 및 GetDuration()은 소스 프레임을 제공합니다. 첫 번째 세그먼트는 훅이 트리밍되었는지 알려줍니다. 잠긴 세그먼트를 segments-v2.json과 비교하고 변경된 사항을 기록하여 다음 편집을 보정하세요.

10. 컬러

params.json에서 "lut": "<LUT_PATH>"을 설정하여 모든 클립의 노드 1에 적용하세요. 카메라가 로그 프로파일(예: S-Log3)을 촬영하는 경우 그레이딩되지 않은 푸티지는 평평하고 회색으로 보이므로 LUT를 설정하는 것이 좋습니다. API는 두 번째 노드를 추가할 수 없습니다. 다중 노드 그레이딩의 경우 하나의 클립을 수동으로 그레이딩하고 CopyGrades로 푸시하세요.

11. 사진 오버레이 (선택 사항)

화자가 스틸 사진을 가지고 있는 것에 대해 이야기할 때, v3의 V2에 흰색 배경 위에 배치하세요.

  • 카드 형식, 슬라이드쇼가 아님. 순수 흰색 배경에 1920x1080 PNG를 렌더링하세요: 세 개의 초상화 나란히 (h840으로 스케일, 50px 간격), 두 개의 초상화 (h880, 60px 간격), 또는 하나의 가로 사진 (h900). 말하는 내용에 따라 사진을 그룹화하세요.
  • 각 카드를 잠긴 전사 내용의 문장 시작에 맞추고, 다음 문장에서 카드를 전환하세요. 카드당 약 2-5초. 설명되는 동안에만 사진을 유지하세요.
  • 스틸이 아닌 정확한 길이의 ProRes .mov로 가져오세요. 스틸은 Resolve에서 고정 2초로 들어와 서로 겹칩니다. 번호가 매겨진 이름 (card1.png, card2.png)은 단일 이미지 시퀀스로 가져오므로 단어 이름을 사용하세요. ffmpeg -loop 1 -framerate 24000/1001 -i x.png -frames:v N -c:v prores_ks -profile:v 3로 렌더링하세요.
  • .mov의 경우 AppendToTimeline은 endFrame = 프레임 수 (count-1이 아님)가 필요합니다. 그렇지 않으면 모든 카드가 한 프레임 짧아져 카드 사이에 화자가 깜빡입니다. 오디오가 함께 오지 않도록 "mediaType": 1을 전달하세요.
  • 트랙 이름을 " photos"로 지정하고, 카드를 자체 미디어 풀 폴더에 넣고, LUT를 절대 적용하지 마세요 (이미 그레이딩됨).
  • 배치하기 전에 채팅에서 카드의 콘택트 시트를 사용자에게 보여주세요.

알아두면 유용한 사실

  • 실제 편집에서 얻은 보정: v2 이후 제작자는 일반적으로 약 10분 컷에서 10-20초를 수동으로 제거합니다. 대부분은 세그먼트 가장자리에서 프레임 수준의 조정과 반복된 문장입니다. 여기서 요점이 말해지고 몇 초 내에 더 잘 다시 말해집니다. 문장이 그 앞의 문장을 다시 말하면 첫 번째 버전을 자르세요. 이는 섹션 전체에 걸쳐 문구를 반복하는 의도적인 교육적 반복과 다릅니다. 요점이 멀리 떨어져 두 번 나오면 약한 테이크를 가능한 컷으로 표시하세요.
  • 일반적인 우려는 오버컷으로 인해 다시 추가해야 하는 것이므로, 직감이 아닌 증거에 의해서만 조이세요.
  • 예시 소스 형식: 4K 23.976 MP4 with 48kHz 오디오; 최종 타임라인 1920x1080 23.976, 01:00:00:00에서 시작. 사용자의 푸티지에 맞게 params.json의 fps/width/height를 조정하세요.
  • 23.976에서 타임코드는 타임코드 초당 24프레임을 계산합니다: frames = round(seconds / 1.001 * 24).
  • AppendToTimeline은 endFrame을 배타적으로 처리합니다: 원하는 마지막 프레임 다음 프레임을 전달하세요. "포괄적, 1 빼기" 규칙은 모든 세그먼트에서 한 프레임을 떨어뜨립니다 (10분 타임라인에서 약 4초, 1프레임 세그먼트는 사라짐).
  • 일부 화자는 거의 필러 단어를 사용하지 않습니다. 필러 제거를 중심으로 빌드하기 전에 확인하세요.
  • 대략 원본 토크 푸티지의 20%가 제거 가능하며, 그중 약 3/4은 판단(테이크 및 재시작), 1/4은 데드 에어입니다.
  • Whisper 모델: ggml-small.en.bin으로 충분히 정확합니다. 몇 단어를 잘못 듣기도 하지만 컷 포인트에는 영향을 미치지 않으며, 화자를 인용할 때는 문제가 됩니다.

관련 스킬

  • video-overlays: 애니메이션 그래픽, 컷이 잠긴 후에 실행 (설치된 경우)
  • video-reels: 동일 푸티지의 세로 컷 (설치된 경우)
  • video-thumbnails: 썸네일 및 제목 (설치된 경우)
  • lapel-sync: 오디오가 별도 라펠/레코더로 녹음된 경우 먼저 실행

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

beachyphotoandfilm-arch/video-skills

Sync camera footage to a separate lapel or field-recorder track (e.g. Tascam DR-10L and similar) and lay it up in DaVinci Resolve. Stitches the recorder's split files, finds each clip's exact place in the audio by matching words then waveforms, cuts one lapel slice per clip so every later skill works unchanged, checks for clipping, and builds a synced timeline in a new Resolve project. Trigger on "sync the lapel", "sync my audio", "line up the recorder", "I used a lav", or any shoot with a separate audio folder (live talks, events, workshops). Run it before paper-edit or video-reels.

beachyphotoandfilm-arch/video-skills

Design a unique Instagram cover for each reel in your house style. Reads what the reel is about, writes a short hook headline, picks one of your own photos from a tagged photo library, lays it out like your existing covers, and proofs it in grid view at phone size. Renders locally, never with AI image generation. Can be called by a scheduling skill before reels are scheduled. Trigger on "make covers", "reel covers", "cover photo for this reel", "design the IG covers".

beachyphotoandfilm-arch/video-skills

Render finished reels out of DaVinci Resolve, write captions in the creator's voice, attach a custom Instagram cover from reel-covers, and schedule them to Instagram, TikTok and YouTube Shorts through Metricool. Handles the Drive upload hop, collision checks against the existing calendar, and cleanup. Trigger on "schedule the reels", "post these", "put these on the calendar", or after reels are approved.

beachyphotoandfilm-arch/video-skills

Build animated brand overlays (motion graphics) for a talking-head video, timed to the speaker's exact words, plus a DaVinci Resolve import file. House style is in-scene type (text beside and behind the speaker's head) plus diagrams. Transcribes the rough cut locally, picks the moments, renders transparent .mov clips, and writes an FCPXML that drops every clip onto the timeline already in position. Trigger on "make animations for this video", "add overlays/motion graphics", "animate this", "b-roll graphics for my YouTube video", or when the user shares a rough cut and asks for graphics.

beachyphotoandfilm-arch/video-skills

Cut vertical Instagram reels out of a long-form talking-head video, hook first. Picks the strongest standalone moments from the transcript, opens each reel on its punchiest line, builds vertical timelines in DaVinci Resolve framed on the speaker's face with the LUT applied, and finishes them: a hook (a held text card, or a word-by-word "build" hook with punch-in) and burned-look captions on V3; this-or-that reels get product graphics and a comment-keyword CTA card. You trim and render, nothing to import. Trigger on "make reels", "clip this for Instagram", "cut some verticals", or after a YouTube video is cut.

beachyphotoandfilm-arch/video-skills

Design YouTube thumbnails and titles for a talking-head video. Pulls graded full-res frames out of the raw footage, renders brand-styled variants in two proven layouts, and proofs them at phone size where the click actually gets decided. Trigger on "make thumbnails", "thumbnail for this video", "title and thumbnail", or after a video is cut.

beachyphotoandfilm-arch/video-skills

Run the whole YouTube video pipeline end to end, one stage at a time, stopping for the creator's approval at every gate. Paper edit, punch-ins, reels, reel covers, scheduling the reels, overlays, thumbnail and title, then scheduling the long-form video, all through Metricool. Keeps state per video so you can stop anywhere and pick up later. Trigger on "/youtube", "let's do the whole video", "run the video pipeline", "continue the <name> video", or when handed raw footage for a YouTube video.

관련 스킬