Communitygithub.com

ukvalley/video-editing-skills

원본 카메라 영상을 FFmpeg를 사용하여 비트에 맞춰진 시네마틱 9:16 세로 릴(Instagram Reels / YouTube Shorts)로 편집합니다. 예를 들어 차량 인도, 이벤트, 제품 또는 여행 릴 등에 사용합니다.

video-editing-skills란 무엇인가요?

이 스킬은 FFmpeg 명령줄 도구를 사용하여 여러 개의 원본 클립과 음악 트랙을 15~45초 길이의 비트 동기화된 시네마틱 세로 릴(9:16 비율)로 변환합니다. 사용자는 편집이 가능한 편집 목록(`edl.json`)을 통해 편집 과정을 완전히 제어할 수 있으며, 변경 사항이 있을 때마다 처음부터 다시 시작할 필요 없이 특정 세그먼트만 다시 렌더링할 수 있습니다. 이 스킬은 Instagram Reels, YouTube Shorts, 차량 인도, 제품 출시, 이벤트 하이라이트 등 다양한 유형의 숏폼 콘텐츠 제작에 적합합니다. Claude Code, Cursor, Codex 등의 AI 에이전트와 함께 사용할 수 있으며, 사용자가 제공한 클립과 음악 파일을 분석하여 자동으로 샷 플랜을 생성하고, 비트 감지, 색보정, 트랜지션, 텍스트 오버레이 등을 포함한 최종 렌더링을 수행합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ukvalley/video-editing-skills/tree/HEAD/skills/cinematic-reel

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

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

문서

시네마틱 릴 편집기

원본 클립 폴더와 음악 트랙을 15~45초 길이의 9:16 비트 동기화 시네마틱 릴로 만듭니다. 모든 편집은 명령줄에서 FFmpeg를 사용하여 이루어집니다. 편집 계획은 편집 가능한 편집 목록(edl.json)에 저장되므로 처음부터 다시 시작하지 않고도 변경 사항을 다시 렌더링할 수 있습니다.

0. 확실한 규칙

  • raw/ 안의 파일을 절대 수정하거나 삭제하지 마세요. 모든 출력물은 work/와 out/에 작성하세요.
  • 음악은 사용자가 제공해야 합니다(라이선스 / 로열티 프리). music/이 비어 있으면 트랙을 요청하세요. 저작권이 있는 음악을 다운로드하지 마세요.
  • 샷 계획(4단계)을 사용자에게 보여주고 최종 렌더링 전에 승인을 받으세요.
  • 비트에 맞춰 하드 컷을 선호하세요. 트랜지션은 절제해서 사용하세요(릴당 최대 2~3개).

1. 사전 요구 사항 확인

ffmpeg -version && ffprobe -version
python3 -c "import librosa, numpy" || pip install librosa numpy soundfile

FFmpeg가 없으면 사용자에게 설치를 알리고(Windows: winget install ffmpeg, Mac: brew install ffmpeg, Linux: sudo apt install ffmpeg) 중단하세요.

2. 폴더 구조

project/
  raw/      # 카메라 클립 (읽기 전용)
  music/    # 하나의 음악 트랙
  luts/     # 선택 사항인 .cube LUT 색보정용
  work/     # 썸네일, 세그먼트, edl.json, beats.json
  out/      # 최종 렌더링 (reel_v1.mp4, reel_v2.mp4 ...)

3. 푸티지 목록 확인 및 살펴보기

모든 클립에 대해 지속 시간, 해상도, fps 및 방향을 기록합니다:

ffprobe -v error -show_entries format=duration:stream=width,height,r_frame_rate,codec_type -of json raw/CLIP.mp4

클립당 연락처 시트를 만듭니다(2초마다 한 프레임). Read 도구로 확인하여 각 샷에 무엇이 있는지 파악하세요:

ffmpeg -y -i raw/CLIP.mp4 -vf "fps=1/2,scale=320:-1,tile=4x3" -frames:v 1 work/thumbs/CLIP.jpg

각 사용 가능한 순간에 태그를 지정합니다: 샷 유형(와이드 / 미디엄 / 클로즈업 / 디테일), 피사체, 움직임, 품질(선명함, 안정적임, 조명 좋음), 슬로우 모션 가능 여부(소스 ≥ 50 fps).

4. 스토리 구성 (샷 계획)

모든 릴을 다음과 같이 구성합니다:

  1. 훅 (0~2초) — 가장 인상적인 샷. 로고나 텍스트 인트로 없음.
  2. 빌드업 — 디테일과 기대감(클로즈업, 슬로우 모션).
  3. 히어로 순간 — 가장 큰 비트/음악 드롭에 맞춤.
  4. 감정 / 보상 — 반응, 사람들, 축하.
  5. 아웃트로 (마지막 2~3초) — 깔끔한 와이드 샷, 선택 사항으로 텍스트 또는 로고, 음악 페이드.

차량 인도 템플릿(푸티지에 맞게 조정): 외부 와이드 → 로고 클로즈업 → 휠/헤드라이트 디테일 → 가족 걸어오기(슬로우 모션) → 커버 공개(드롭에 맞춰) → 키 인계 → 반응/미소 → 실내 + 스티어링 → 케이크/화환/푸자 → 첫 드라이브 어웨이(와이드, 아웃트로).

규칙: 샷 크기를 다양화하세요(연속으로 두 개의 와이드 샷 금지), 각 샷을 0.5~2.5초로 유지하세요, 감정적이거나 공개 샷에만 슬로우 모션을 사용하세요, 가능하면 움직임에 맞춰 컷하세요.

5. 비트 감지

# work/beats.py
import librosa, json, sys
y, sr = librosa.load(sys.argv[1])
tempo, frames = librosa.beat.beat_track(y=y, sr=sr)
beats = librosa.frames_to_time(frames, sr=sr).tolist()
onset = librosa.onset.onset_strength(y=y, sr=sr)
json.dump({"tempo": float(tempo), "beats": beats}, open("work/beats.json", "w"), indent=1)
print(f"tempo {float(tempo):.1f} BPM, {len(beats)} beats")

비트에 맞춰 컷하세요(빠른 구간은 모든 비트, 느린 구간은 2번째 또는 4번째 비트마다). 드롭(가장 큰 에너지 점프)을 찾아 그곳에 히어로 샷을 배치하세요.

6. 편집 목록 work/edl.json 작성

{
  "output": {"w": 1080, "h": 1920, "fps": 30},
  "music": {"file": "music/track.mp3", "start": 12.0, "fade_out": 1.5},
  "grade": {"lut": "luts/teal_orange.cube", "vignette": true},
  "shots": [
    {"id": 1, "src": "raw/C0001.mp4", "in": 4.20, "dur": 1.40, "speed": 1.0, "crop_x": "center", "note": "훅 – 차량 와이드"},
    {"id": 2, "src": "raw/C0007.mp4", "in": 10.0, "dur": 1.00, "speed": 0.5, "crop_x": "center", "note": "휠 슬로우 모션"}
  ],
  "transitions": [{"after_shot": 4, "type": "fade", "dur": 0.3}],
  "text": [{"text": "어서 오세요", "start": 18.0, "end": 21.0}]
}

dur은 타임라인의 길이입니다. speed가 0.5이면 사용되는 소스 범위는 dur × speed초입니다. 렌더링 전에 이 계획을 간단한 표(샷, 시간, 설명)로 사용자에게 보여주세요.

7. 각 샷을 균일한 세그먼트로 렌더링

모든 세그먼트는 동일한 해상도, fps, 픽셀 형식을 가져야 하며 오디오가 없어야 깔끔하게 결합할 수 있습니다:

# 가로 소스 → 9:16 크롭, 스피드, 그레이딩
ffmpeg -y -ss IN -t SRC_DUR -i raw/CLIP.mp4 -an -vf "\
setpts=PTS/SPEED,\
scale=-2:1920,crop=1080:1920,\
fps=30,\
lut3d=luts/teal_orange.cube,\
eq=contrast=1.06:saturation=1.10,\
vignette=PI/5,\
format=yuv420p" \
-c:v libx264 -crf 16 -preset medium work/seg_01.mp4
  • SRC_DUR = dur × speed. 슬로우 모션에는 고프레임 소스를 사용하세요. 요청하지 않는 한 minterpolate는 피하세요(느리고 인공물 발생).
  • 세로 소스: scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920을 사용하세요.
  • LUT를 사용할 수 없는 경우: 영화 같은 느낌을 위해 eq=contrast=1.08:saturation=1.15:gamma=0.98과 curves=preset=increase_contrast를 사용하세요.
  • 선택 사항인 시네마틱 바는 9:16 릴에서 사용되지 않습니다.

8. 세그먼트 결합

트랜지션 없음 – concat 디먹서:

printf "file 'seg_%02d.mp4'\n" 1 2 3 ... > work/list.txt
ffmpeg -y -f concat -safe 0 -i work/list.txt -c copy work/video.mp4

두 세그먼트 사이에 트랜지션이 있는 경우 xfade를 사용하세요(오프셋 = 첫 번째 클립 길이 − 트랜지션 지속 시간):

ffmpeg -y -i work/seg_04.mp4 -i work/seg_05.mp4 -filter_complex \
"[0][1]xfade=transition=fade:duration=0.3:offset=1.2,format=yuv420p" work/seg_04_05.mp4

각 트랜지션은 타임라인을 해당 지속 시간만큼 단축시킵니다. 비트 정렬을 다시 확인하세요.

9. 음악, 텍스트, 최종 내보내기

ffmpeg -y -i work/video.mp4 -ss MUSIC_START -i music/track.mp3 -filter_complex "\
[1:a]afade=t=in:d=0.3,afade=t=out:st=FADE_START:d=1.5,loudnorm=I=-14:TP=-1:LRA=11[a];\
[0:v]drawtext=fontfile=FONT.ttf:text='어서 오세요':fontsize=72:fontcolor=white:\
x=(w-text_w)/2:y=h*0.72:enable='between(t,18,21)':alpha='if(lt(t,18.4),(t-18)/0.4,1)'[v]" \
-map "[v]" -map "[a]" -shortest \
-c:v libx264 -crf 18 -preset slow -profile:v high -pix_fmt yuv420p -r 30 \
-c:a aac -b:a 192k -movflags +faststart out/reel_v1.mp4

drawtext에 사용할 글꼴 파일을 시스템에서 찾으세요(또는 물어보세요). 텍스트를 최소화하고 안전 영역 내에 유지하세요(상단 15%와 하단 25%는 피하세요. Instagram UI가 있는 곳입니다).

10. 품질 확인 (항상)

  • ffprobe out/reel_vN.mp4 → 1080×1920, 30 fps, H.264, AAC, 계획된 지속 시간.
  • 최종 릴의 연락처 시트(fps=2,scale=270:-1,tile=6x5)를 보고 확인하세요: 검은 프레임 없음, 잘못된 크롭(머리 잘림) 없음, 일관된 색상.
  • 음량을 확인하고 히어로 샷이 드롭에 맞는지 확인하세요.
  • 사용자에게 보고하세요: 지속 시간, 샷 개수, 파일 경로, 그리고 확실하지 않은 사항.

11. 수정

처음부터 다시 시작하지 마세요. work/edl.json을 편집하고(샷 교체, in/dur, 속도, 텍스트, 그레이딩 변경), 변경된 세그먼트만 다시 렌더링하고, 결합하여 다음 버전(reel_v2.mp4)으로 내보내세요. 사용자가 비교할 수 있도록 이전 버전을 유지하세요.

Individual skills in this repo

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

관련 스킬