Communitygithub.com

kylefritz/video-skill

터미널에서 비디오를 만들고, 편집하고, 확인하고, 이해합니다. 비디오를 직접 볼 수 없는 AI 에이전트를 위해 설계되었습니다.

video-skill란 무엇인가요?

이 스킬은 비디오를 시각적으로 확인할 수 없는 AI 에이전트가 터미널 환경에서 비디오 관련 작업을 수행할 수 있도록 설계되었습니다. OpenAI의 OpenFilm 프레임워크를 기반으로 영화 제작(자막, 모션 그래픽, 사진 슬라이드쇼 등)을 지원하며, 각 단계를 '프레임 → 연락처 시트 → 수정'의 읽기 가능한 형태로 변환합니다. macOS에서 선호되며, ffmpeg을 통한 사운드 처리, iPhone 영상의 HDR/회전/가변 프레임레이트 교정(probe/proxy), 장면 변화에 따른 프레임 샘플링(frames) 및 배달 전 코덱/프레임레이트/로드니스 검사(check)를 자동화합니다. 또한 음성 전사(parakeet-mlx), WebP/GIF 루프 생성, 메타데이터 제거 등을 지원하며, 사용자는 사진 검색 및 다운로드를 위해 photo-skill을 함께 사용할 것을 권장합니다.

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

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

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

문서

video-skill은(는) 무엇을 하나요?

스크립트는 이 파일과 같은 디렉토리의 scripts/에 위치합니다. 아래에서는 $S로 표기하지만, 각 명령어에는 절대 경로를 그대로 사용해야 합니다. 셸 변수는 Bash 호출 간에 유지되지 않기 때문입니다.

비디오를 직접 볼 수 없으므로, 모든 단계는 당신이 볼 수 있는 프레임과 확인할 수 있는 숫자로 변환됩니다. 영화 제작은 작성 → 프레임 렌더링 → 연락처 시트 확인 → 수정의 순서를 따릅니다. 푸티지 분석은 프로브 → 프록시 → 타임스탬프 시트 + 트랜스크립트 → 판단으로 이어집니다. 배달은 코덱, 프레임레이트, faststart, 로드니스를 검사하는 스크립트를 통해 "모든 곳에서 재생된다"는 사실을 보장합니다.

Mac에서 처음 사용할 때

직접 sh $S/setup.sh를 실행하세요. 이 스크립트는 mise와 ffmpeg를 확인하고(가능하면 Homebrew로 ffmpeg 설치), 첫 사용 시 고정된 OpenFilm을 설치한 후 openfilm doctor를 실행합니다. 출력된 각 TODO를 수정하거나, 그 내용을 사람에게 명확히 설명하세요. 여러 번 실행해도 안전합니다.

영화 제작: OpenFilm

OpenFilm(MIT)은 저작 형식입니다. 영화는 HTML 페이지, 푸티지, 사진, 사운드를 함께 편집하는 film.html이 포함된 폴더입니다. 각 페이지는 요청된 모든 순간 t를 그립니다. Studio는 로컬 브라우저 편집기입니다.

  1. 매뉴얼을 출력하여 전체를 읽으세요(짧으며 버전마다 변경됩니다): $S/openfilm. 이 파일이 우선하되, 매뉴얼을 따르세요.
  2. $S/openfilm이 여기서 OpenFilm을 실행하는 유일한 방법입니다. 버전을 고정하고, 첫 사용 시 mise를 통해 설치하며, Studio가 브라우저 창을 띄우지 않도록 합니다. npx openfilm(고정 우회) 또는 npx skills add openfilm/openfilm(이 스킬과 충돌하는 상위 스킬)을 사용하지 마세요.
  3. FILM은 항상 절대 경로($HOME/Movies/OpenFilm/Projects/<film-name>)입니다. 상대 경로는 현재 폴더(예: 다른 사람의 git 저장소)에 위치합니다. 영화는 저장소에 절대 들어가지 않습니다.
단계명령어
생성 또는 열기$S/openfilm open FILM
전체 영화 확인$S/openfilm -C FILM look
특정 순간, 구간, 파일 확인… look 4.5, look 3-6, look assets/bed.wav
빠른 장면 전환 확인… look 0-2 --count 24
MP4 렌더링$S/openfilm -C FILM render
연결된 미디어 서비스 확인$S/openfilm get
설치 진단$S/openfilm doctor

look과 render는 Studio 없이 실행되며, FILM 기준 상대 경로를 출력합니다. Studio 주소에는 액세스 키가 포함되어 있습니다: 함께 작업하는 사람에게만 제공하세요(로컬 주소 127.0.0.1, Chrome 또는 Edge, 휴대폰에서는 불가).

무언가를 보여주기 전에 모든 look 시트를 읽고 발견한 문제를 수정하세요. look의 검사(동일한 t가 동일한 그림을 그리는지, 폰트 로드, 텍스트 클리핑, 로드니스)는 취향이나 레이아웃에 대해 말하지 않습니다. 장면 전환 중 텍스트 잘림에 대한 !는 괜찮지만, 정지 상태에서 잘리는 것은 버그입니다. 그런 다음 몇몇 순간을 전체 크기(look 12.5)로 확인하세요: 300px 타일은 작은 것(사람 포함)을 숨깁니다.

영화 제작 과정을 통해 배운 점:

  • 샷당 하나의 페이지; 페이지가 공유하는 것(ken Burns 효과, 폰트, 색상)은 모듈로 분리하여 가져옵니다. 모든 값은 t만의 함수입니다: 타이머, 애니메이션 루프, 상태 없음.
  • 페이지는 자체적으로 페이드(투명도를 t로 조절)합니다. 한 트랙에서 샷 사이의 검은색 페이드가 가장 간단한 전환입니다. 크로스 디졸브는 들어오는 샷이 나가는 샷 위의 트랙에 있어야 합니다.
  • 사진 위 텍스트는 배경에 음영(하단 그라데이션)이 필요합니다. 그렇지 않으면 복잡한 장면에 묻힙니다.
  • 폰트는 FILM/fonts/에 @font-face로 배치하며, window.film.ready(document.fonts.ready)로 로딩을 기다립니다. 사진의 경우 ready: img.decode().
  • #t=in,out으로 트리밍하며, 새 파일을 자르지 마세요. 영화보다 긴 사운드는 영화를 연장합니다.

사운드

$S/openfilm get은 연결된 서비스를 보여줍니다. 생성된 음성, 음악, 효과음은 사용자 자신의 제공자 키가 필요합니다(Studio: OpenFilm 로고 → 설정 → 제공자). 키가 없으면 ffmpeg로 사운드를 만들어 FILM/assets/에 저장하고, 명령어를 FILM/sound-notes.txt에 기록하여 재구성할 수 있도록 하며, 어떤 서비스가 더 나은 결과를 제공할 수 있을지 설명하세요. 소리를 들을 수 없으므로 숫자로 판단하세요.

  • 최종 믹스(팟캐스트, 대부분의 웹 비디오)의 경우 -16 LUFS 통합; 스트리밍 플랫폼은 -14 부근으로 정규화합니다. 실제 피크는 -1 dBTP 이하로 유지하세요. 음성 아래 배경음은 약 -22입니다.
  • 측정: ffmpeg -i X -af ebur128=peak=true -f null -. 생성된 배경음은 loudnorm=I=-16:TP=-1.5:LRA=7로 정규화합니다. 최종 마스터의 경우 loudnorm을 두 번 실행(측정 후 measured_* 값을 다시 입력)하여 게인이 선형이 되도록 합니다.
  • look은 믹스의 로드니스를 출력하며, footage.py check는 목표에 미치지 못하는 렌더를 실패 처리합니다.

전달받은 푸티지: 인입

휴대폰 비디오는 겉보기와 다른 경우가 많습니다. 푸티지를 보거나 편집하기 전에 다음을 실행하세요:

uv run --no-project --with pillow python -I $S/footage.py probe CLIP.mov ...
uv run --no-project --with pillow python -I $S/footage.py proxy CLIP.mov <scratch>/clip.mp4

probe는 각 문제에 대해 경고하고, proxy는 한 번에 모두 수정합니다(SDR BT.709, 회전 내장, 고정 30fps, 짝수 크기, H.264 yuv420p, AAC 48kHz, faststart):

  • HDR(iPhone은 기본적으로 HLG 기록: color_transfer=arib-std-b67, BT.2020). SDR로 읽으면 탁하고 색상이 변합니다: 주홍색이 주황색으로 변합니다. proxy는 macOS 내장 avconvert로 톤 매핑하거나, ffmpeg zscale(많은 Homebrew 빌드에서 누락됨)을 사용하거나, 경고합니다.
  • 회전: 휴대폰은 세로 비디오를 회전 플래그와 함께 옆으로 저장합니다. 일부 도구는 이를 무시합니다.
  • 가변 프레임레이트: 명목 24fps, 평균 23.997fps. 프레임 시간이 변동하고 컷 후 오디오가 동기화에서 밀려납니다. probe는 0.001fps 이상의 차이를 플래그합니다.
  • 홀수 크기: H.264 yuv420p는 짝수 너비와 높이가 필요합니다.

프록시를 보고 편집하세요. 원본은 전체 품질이 필요한 경우에만 보관하세요.

푸티지 이해하기

uv run --no-project --with pillow python -I $S/footage.py frames <scratch>/clip.mp4 <scratch>/sheets --every 4

이 명령은 모든 장면 변화(--scene 0.3)에서 프레임을 캡처하고, 최소 --every 초마다 하나씩, 최대 --max 60개까지, 5×6 타일 시트에 0007 · 1:23.4 형식으로 레이블을 붙이고, manifest.json에 각 ID와 시간을 매핑합니다. 시트를 읽고 ID와 시간으로 답변하세요. 규칙보다는 실제 경험에 따르세요:

  • 제작된 영화: 샷 길이에 따른 균일 샘플링. 발견된 푸티지: 장면 변화 + 2-5초마다 최소 한 프레임. 빠른 액션: --every 0.5로 짧은 구간.
  • 시트의 긴 쪽을 약 2,500px 이하로 유지하고 한 번에 몇 장씩 읽으세요. 긴 푸티지의 경우, 시트별로 서브 에이전트로 분산하여 각 타일 ID당 하나의 JSONL 평결을 작성한 후, python3 -I $S/check_verdicts.py manifest.json out/*.jsonl로 확인하세요(누락, 중복 또는 가짜 ID는 실패; 모든 타일이 같은 답변을 받은 시트는 대충 읽었을 가능성이 높음).
  • 말하는 비디오의 대부분은 오디오에 있습니다. 단어 시간과 함께 온디바이스 전사: uvx parakeet-mlx AUDIO.wav --output-format json --output-dir <scratch>(먼저 오디오 추출: ffmpeg -i clip.mp4 -ar 16000 -ac 1 audio.wav). 단어를 시간별로 프레임에 연결하세요. 고유명사는 잘못 나올 수 있으므로("torii" → "Torrey"), 인용 전에 이름을 시각 정보와 대조하세요.

배달

uv run --no-project --with pillow python -I $S/footage.py check FILM/<name>.mp4 --duration 30
uv run --no-project --with pillow python -I $S/footage.py share FILM/<name>.mp4 <scratch>/<name>-share.mp4
uv run --no-project --with pillow python -I $S/footage.py gif FILM/<name>.mp4 <scratch>/loop.webp --start 2.5 --duration 6 --width 480
  • 파일을 전달하기 전에 check가 통과해야 합니다: H.264, yuv420p, 짝수 크기, 고정 프레임레이트, moov가 mdat보다 앞에 있음(faststart: 다운로드 중 재생), 지속 시간, 로드니스 ±1.5 LU, 실제 피크.
  • 사용자가 파일을 요청하거나 이 Mac에 접근할 수 없을 때 렌더링하세요. 마지막 확인으로 MP4 자체에 look을 실행하세요. share는 웹 페이지나 채팅을 위해 작은 복사본(1280 너비, CRF 28: 30초 1080p 렌더가 34MB에서 3.8MB로 감소)을 만듭니다. 영화의 원본 MP4는 변경되지 않습니다.
  • 루프: 애니메이션 WebP가 GIF보다 우수. 느린 줌이 있는 5.6초 사진 루프는 GIF에서 6.7MB, WebP에서 1.6MB였습니다. GIF는 모든 픽셀이 움직일 때 픽셀을 재사용할 수 없습니다. 대상이 WebP를 표시할 수 없는 경우에만 GIF를 사용하세요. 그런 다음 footage.py gif X.gif는 생성된 팔레트(palettegen/paletteuse)를 사용합니다.
  • 전송되어서는 안 되는 데이터 제거: iPhone 비디오는 메타데이터에 GPS, 휴대폰 모델, 시간을 포함합니다. proxy와 share는 모두 제거합니다(-map_metadata -1). AirDrop 또는 Photos 내보내기로 만든 원본 파일 또는 복사본은 이를 유지합니다. exiftool -GPSCoordinates FILE로 확인하세요.

영화 속 사진

photo-skill 스킬(github.com/kylefritz/photo-skill; 설치되지 않은 경우 ~/.claude/skills/photo-skill에 클론할 것을 제안)을 사용하여 사진을 찾고(라이브러리에서 설명으로 검색한 후 연락처 시트 판단) 풀해상도 원본을 다운로드하세요: 미리보기는 1080p에 너무 작습니다. 영화가 사용하는 사진을 FILM/assets/에 EXIF 없이 다시 저장하여 복사하세요. 사진이 포함된 영화를 어디든 보내기 전에 각 샷을 전체 크기로 확인하세요: 얼굴 감지는 군중을 놓치고, 300px 타일은 1080p 프레임이 보여주는 사람을 숨깁니다.

기타 도구

OpenFilm은 영화가 일반 HTML이고 look이 정확히 필요한 정보를 반환하기 때문에 에이전트에 가장 적합합니다. 2026년 후반 기준 대안:

도구저작 방식참고
HyperFrames (HeyGen, Apache-2.0)HTML/CSS + GSAP, headless Chrome으로 렌더링가장 유사한 도구; check --json 린트/레이아웃/대비 게이트, 스냅샷, Claude Code 플러그인
RemotionReact 컴포넌트성숙하고 공식 에이전트 스킬이 있음; 소스 사용 가능 라이선스로 작은 규모 이상의 회사는 유료 라이선스 필요
Manim (MIT)Python 장면수학 및 다이어그램 설명
MoviePy (MIT) / raw ffmpegPython / 필터그래프간단한 컷과 오버레이; ffmpeg는 I/O 계층으로 가장 적합

OpenFilm 업그레이드

상류에서 자주 배포됩니다. 릴리스 노트를 읽고 먼저 npm view openfilm scripts를 실행한 후( preinstall 또는 postinstall 항목은 확인 필요), scripts/openfilm의 OPENFILM_VERSION을 변경하고 setup.sh를 다시 실행하세요. 그런 다음 ls ~/Library/Caches/ms-playwright: OpenFilm의 첫 실행은 링크 마커가 없는 Playwright 브라우저를 삭제합니다. setup.sh가 제거한 항목을 보고하며, 필요한 프로젝트에서 npx playwright install chromium을 실행하면 다시 설치됩니다.

흔한 실수

실수수정
npx openfilm …$S/openfilm …: npx는 고정을 우회함
잘못된 폴더에서 look 또는 render 실행$S/openfilm -C FILM …
PNG를 열지 않고 look의 검사를 신뢰시트를 읽으세요. 통과한 검사는 레이아웃에 대해 아무것도 말하지 않습니다
iPhone 푸티지를 직접 편집 또는 확인probe 후 proxy: HDR, 회전, VFR 모두 문제 발생
마스터 MP4를 채팅에 전송share한 후 check로 복사본 확인
README나 페이지에 GIF 사용WebP, 약 4배 작음
업그레이드 후 오래된 Studio이전 studio/server/main.mjs 프로세스 중지(pgrep -fl openfilm); 하나의 Studio는 두 개의 프로세스

관련 스킬