Communitygithub.com

0xSero/video-edit

원시 화면/OBS/강연 녹화본을 전문적인 업로드용 영상으로 정리합니다. 스크립트 기반 컷 편집, 무음/정적 화면 제거, 민감한 개인 정보 차단, 오디오 개선, 강력한 오프닝 구성 및 렌더링 검증을 수행합니다. 사용자가 "녹화한 영상 편집해줘", "조용한 부분 잘라내줘", "부끄러운 부분 제거해줘", "누출되면 안 돼", "유튜브에 올릴 수 있게 해줘"라고 말할 때 사용하세요. 슬라이드로 프로모/모션 그래픽 영상을 만들기 위한 도구가 아닙니다. 썸네일만 필요한 경우 youtube-pack을 사용하세요.

video-edit란 무엇인가요?

이 스킬은 로컬 macOS 환경에서 실행되는 고급 AI 비디오 편집 에이전트입니다. 스크립트 기반의 정밀한 워크플로우를 통해 화면 녹화(OBS 포함), 강연, 팟캐스트 녹화본을 전문적인 유튜브 업로드 품질로 가공합니다. 주요 기능으로는 Whisper(mlx_whisper)를 이용한 자동 전사 및 타임라인 기반 편집, DeepFilterNet3 기반 오디오 노이즈 제거, OCR(Apple Vision)을 통한 화면 내 민감 정보(IP, API 키, 이메일 등) 자동 탐지 및 블러/박스 처리, 웹캠 영상에서 프라이버시 침해 부분(손동작, 타인 등장 등) 감지 및 컷 편집, 프레임 차분 기반 정적 화면 자동 제거, -16 LUFS / -1.5 dBTP의 전문가 수준 오디오 노멀라이제이션, 자동 챕터 생성 및 다국어 자막(SRT) 생성을 포함합니다. 최종 출력물은 1080p, 2개 오디오 트랙(원본+개선), 메타데이터(제목, 설명, 태그, 챕터)와 함께 ~/Downloads 폴더에 저장되고 자동으로 열립니다. 'verify_output.py'로 프레임 정합성, 오디오 트랙 동기화, 출력물 내 누수(leak) 제거 여부를 검증합니다. 이 도구는 Claude Code, Cursor, Codex와 같은 AI 코딩 에이전트와 함께 사용하도록 설계되었으며, 사용자의 의도를 문장으로 이해하고 복잡한 편집 파이프라인을 자동 실행합니다.

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

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

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

문서

비디오 편집 (화면 / OBS / 강연 녹화)

스크립트 킷: 이 스킬의 scripts/ 디렉토리 (prep.sh, transcript_txt.py, ocr_scan.py, cam_flags.py, df_enhance.py, build_edl.py, render.py, verify_output.py, chapters.py, overview.py, job.example.json, selftest.sh). <workdir>/scripts/의 복사본에서 실행하여 작업이 스킬 디렉토리에 종속되지 않도록 하세요. scripts/selftest.sh는 설치가 제대로 되었는지 몇 분 안에 처음부터 끝까지 검증합니다.

입력

  • <src>: 녹화 파일, 일반적으로 가장 최근의 ~/Desktop/*.mov 파일 (OBS 명명 규칙 YYYY-MM-DD HH-MM-SS.mov). 최근 녹화 파일이 여러 개인 경우, 긴 파이프라인을 시작하기 전에 어떤 파일인지 확인하세요. 잘못된 영상을 편집하면 한 시간을 낭비합니다.
  • <target_minutes>: 주어지지 않으면 물어보세요. 일반적으로 45-90분 원본에서 20-30분을 목표로 합니다.
  • <workdir>: 새로운 임시 작업 디렉토리 (예: /tmp/<session>/edit).
  • 도구 체인: ffmpeg 6+, python3, mlx_whisper, DeepFilterNet3, Pillow/numpy/soundfile, Apple Vision (pyobjc-framework-Vision/-Quartz).

단계

  1. 정찰, 원본은 절대 건드리지 마세요. ffprobe <src> (해상도, fps, 오디오). <workdir> 내의 복사본/추출본으로만 작업하세요.
  2. 준비. prep.sh "<src>" $W: orig48.wav, mono16.wav, frames/ (2초당 1장), camall/ (웹캠 크롭, 1fps, 해상도에서 자동으로 형상 추론), sheet_overview.jpg, silences_raw.txt (진단용), 그리고 transcript.json (mlx_whisper large-v3-turbo, 워드 타임스탬프, 약 4분). Whisper는 prep이 반환된 후에도 백그라운드에서 계속 실행됩니다. 지금 df_enhance.py orig48.wav df_enhanced.wav (DeepFilterNet3, CPU 약 6분)를 시작하세요. 이 작업은 독립적입니다.
  3. 전체 전사(transcript)를 읽으세요 (transcript_txt.py ... --from/--to로 3개의 청크로 나누어 읽음). 유지 구간(소스 초 단위)을 job.json -> keep에 기록하세요. 무음 제거는 미미합니다 (47분 중 약 2분). 실제 분량 감소는 콘텐츠 결정에서 비롯됩니다. Whisper가 스스로 알려줍니다: 10회 이상 반복되는 구절이나 빈 세그먼트 연속 = 데드 에어, 잘라내세요.
  4. 정적 화면 검사. "아무 일도 일어나지 않는" 것은 종종 정적 화면이지 무음이 아닙니다. 0.5fps 프레임의 프레임 차분: 약 10초 창에서 픽셀 변화가 1% 미만 = 비활성; 1초 이내 순간 중단으로 분리된 실행은 병합; 자르려면 최소 4초 필요; 0.5초 핸들. 깜빡이는 커서/스피너는 가짜 활동입니다. 마스킹하거나 임계값을 높이고 중간 프레임에서 변경-복구 폭발을 확인하세요. 타이핑은 노이즈이지 무음이 아닙니다: 게이트는 원시 silencedetect가 아닌 개선된(enhanced) 트랙의 RMS (pause.loud_db)를 사용합니다.
  5. 오프닝. 첫 번째 실제 콘텐츠 이전의 모든 것을 자르세요. 시작이 느리거나 지루하면 가장 흥미로운 데모부터 시작하고, 선택적으로 1-2개의 흥미로운 클립으로 콜드 오프닝한 다음 인트로를 속도 높여 재생하세요. 배경화면/검은 화면으로 절대 열지 마세요. 처음 30초가 조잡하면 쓰레기로 간주됩니다.
  6. 누출 스캔 (읽는 동안 실행). frames/에 대해 run 후 ocr_scan.py scan: IPv4/v6, *.ts.net, 이메일, API 키, SSH 자료. 모든 터미널/설정 관련 구간에 대해 2fps 고밀도 패스 (ocr_scan.py dense src.mov dense 600:60 ...). 정적 텍스트 -> boxes (단색 채움); 스크롤링 터미널 출력 -> 전체 창을 블러 처리 (blur window + blur_regions, 소스 픽셀 단위). 샘플 사이의 행별 박스는 텍스트를 놓칠 수 있습니다. 127.0.0.1/localhost는 괜찮습니다. 모든 창을 job.json에 기록하세요.
  7. 프라이버시 컷 (웹캠). cam_flags.py (Vision을 통한 손-입 근처 감지) + cam_flags.py --sheet S:DUR 각 플래그가 지정된 클러스터의 2fps 줌 시트. 사용자가 게시하고 싶지 않을 순간을 자르세요: 일시 정지 중 손이 얼굴에 있는 순간, 자리 비움, 다른 사람이 프레임에 들어온 순간, 얼굴 전체 화면 구간. 평범한 생각하는 포즈나 작은 제스처는 괜찮습니다. 제스처 때문에 문장 중간을 절대 자르지 마세요. 가장 가까운 문장 경계로 스냅하고 손실된 내용이 무엇인지 기록하세요.
  8. 사용자 타임스탬프 컷은 문자 그대로 적용됩니다. "0000 - 01:12 잘라" -> job.cuts (또는 keep)에 넣고 정확히 적용한 후 이음새 주변의 페이싱을 다시 확인하세요.
  9. 오디오 마스터링. 온전성 검사: 개선된 버전과 원본의 상관 관계 > 0.95 (df_enhance.py가 출력). 기본 audio_chain은 highpass 75, 220 Hz / 3.2 kHz / 9 kHz 주변의 컷/부스트, 디에서서, 3:1 컴프레서입니다. 지속적인 팬 노이즈는 equalizer 항목을 추가하여 노치 처리하세요. render.py가 -16 LUFS / -1.5 dBTP로 2패스 loudnorm을 수행합니다. 건드리지 않은 마이크는 오디오 트랙 2로 유지됩니다.
  10. EDL + 렌더링. build_edl.py -> segments.json (유지 구간 내 0.7초 이상의 일시 정지는 0.4초로 단축; 프로브된 프레임 레이트로 스냅; 0.3초 미만은 제거). render.py: 그룹화된 병렬 h264_videotoolbox 인코딩, -c copy로 연결, 두 트랙 모두 먹싱. 그룹별로 재시작 가능합니다. 그룹이 실패하면 수정하고 다시 실행하면 변경되지 않은 그룹은 건너뜁니다. 특별한 요청이 없으면 1080p로 제공하세요 (4K는 렌더링 시간이 두 배가 됩니다).
  11. 제공하기 전에 검증하세요. verify_output.py는 프레임 수가 EDL과 일치하고, 두 오디오 트랙이 비디오 지속 시간과 일치하고, 모든 교정(redaction) 창에 걸쳐 4fps로 출력물을 OCR한 결과 누출이 0건인 경우에만 0을 반환합니다. 또한 각 프라이버시 컷과 0:00-1:00 구간의 출력 프레임을 가져와서 확인하세요. 자료가 민감한 경우 --full을 사용하여 전체 파일 누출 스캔을 수행하세요.
  12. 새로 잘린 영상을 다시 전사하세요. 자막과 챕터는 소스 타임라인이 아닌 출력 타임라인과 일치해야 합니다. SRT/챕터를 작성하기 전에 잘린 영상에 대해 다시 Whisper를 실행하거나 (chapters.py는 EDL을 통해 다시 매핑합니다) EDL을 통해 다시 매핑하는 chapters.py를 사용하세요. 소스 전사본에서 가져온 SRT 시간을 절대 사용하지 마세요.
  13. 메타데이터 + 제공. 두 번 묻지 않고 수행: 챕터 타임스탬프 (chapters.py, 3개 이상, 첫 번째는 0:00), 2-3개의 제목 옵션, 500자 미만의 약 30개 태그 (+요청 시 2개의 태그/설명 변형), 설명, 언어별 SRT (줄당 약 42자, 다국어 요청 시), 모두 일반 텍스트로 제공. 썸네일은 youtube-pack을 통해: 사용자의 마지막 10개 썸네일 스타일을 읽어서 스타일 파악; 기본값은 흰색/크림색 배경 + 검은색 텍스트, 요청이 없으면 얼굴 없음, 로고/텍스트는 크고 깔끔하게. 그런 다음 <output>.mp4 (및 SRT/메타데이터)를 ~/Downloads로 이동하고 파일을 open / 폴더를 기본 앱으로 여세요.

출력

  • <Topic> - YYYY-MM-DD - edit.mp4 (1080p, 2개 오디오 트랙) ~/Downloads에 저장, 기본 앱으로 열림.
  • <workdir>: job.json, segments.json, group_bounds.json, vf_<n>.txt, 교정/프라이버시 로그.
  • ~/Downloads: SRT, metadata.txt (제목, 설명, 태그, 챕터).
  • 요청 시 선택 사항: 동일한 소스에서 분할된 주제별 하위 비디오, 각각 자체 챕터 포함.

구성 가능 스킬

whisper/DFN3 (킷 내장) -> video-edit (검증된 mp4, ~/Downloads) -> youtube-pack (thumbnail.png) -> 사용자의 다른 비디오와 유사하게 구성된 YouTube Studio로 브라우저 업로드.

규칙

  • 소스 녹화 파일을 절대 수정하지 마세요.
  • 목표 길이는 목표일 뿐입니다. 강연 내용을 훼손하지 않고는 줄일 수 없다면 약간 초과하여 제공하고 다음 두 컷을 지정하세요.
  • 일시 정지를 더 자르기 전에 전체 주제를 먼저 자르세요. 하드웨어 이야기, 라이브 데모, 솔직한 주의사항, 요약은 유지하세요.
  • 항상 다음으로 끝내세요: ~/Downloads로 이동 + 열기.
  • 정직하게 보고하세요: 결과물을 들을 수 없습니다. 그렇게 말하고 트랙 2를 가리키세요.
  • 별도로 녹음된 오디오(Discord/Craig)는 대개 존재하지 않습니다. Desktop/Downloads/iCloud/Voice Memos를 확인하고, 없으면 OBS 마이크를 사용했다고 말하세요.
  • 공간 확보 요청 시: 수락되지 않은 오래된 드래프트/변형은 삭제하고, 소스와 최종본은 유지하세요.
  • 여러 명의 팟캐스트: 올바른 오디오 트랙을 찾으세요 (보통 여러 개 중 2개), 오디오를 올바른 화자에게 매핑하고, 말하는 사람에 따라 비디오를 전환하며, 깔끔한 전환을 만드세요.
  • 렌더링이 완료되었다고 편집이 완료되었다고 말하지 마세요. 오직 verify_output.py + 육안 프레임 확인만이 결정합니다.

검증

  • verify_output.py가 PASS (프레임 수, 두 오디오 트랙, 창 내 누출 없음)를 출력하고 0으로 종료합니다.
  • 0:00-1:00 및 모든 프라이버시 컷에서 육안 프레임 확인 (verify_output.py --sheet 0:60).
  • SRT 재전사본을 잘린 영상과 대조하여 스팟 체크합니다.
  • 제공된 파일을 ffprobe로 확인: 지속 시간, 해상도, fps, 2개의 오디오 스트림.

알려진 실패

  • 잘못된 영상 편집 -> 파이프라인 시작 전에 최신/주제 일치 확인.
  • 소스 타임라인의 자막/챕터 -> 컷 편집 후 재전사 (12단계).
  • 출력에 호스트명 표시 -> OCR 샘플 사이 스크롤 텍스트; 전체 창 블러, 창 확장, 출력 측 OCR 수행.
  • Silencedetect가 타이핑/비디오 재생을 자름 -> 무음 단독이 아닌 개선된 오디오 RMS (pause.loud_db)로 게이트.
  • 조잡한 검은색 오프닝 -> 출력 0:00-1:00 프레임 확인, 실제 콘텐츠로 콜드 오프닝.
  • cp -i 덮어쓰기 프롬프트 / 샌드박스 TCC가 ~/Downloads 차단 -> 샌드박스 비활성화하고 /bin/cp 사용.
  • ffmpeg 필터가 약 100개 between() 조건 이후 사망 ("Cannot allocate memory") -> render_groups 수 줄이기.
  • 깜빡이는 커서가 프레임 차분에서 활동으로 간주됨 -> 마스킹/임계값 조정, 중간 프레임 확인.
  • render.py 프레임 불일치 -> 연결을 거부함; render_<n>.log 읽기 (키프레임이 아닌 지점의 -ss, 깨진 디코더).
  • transcript.json을 읽을 때 Whisper가 아직 실행 중 -> transcript_txt.py가 빈 세그먼트를 보고함; whisper.log가 완료될 때까지 기다리세요.

예시

  • 2026-09-02 강연, 47분 -> 26분: 32개 유지 구간, 2개 프라이버시 컷 (9:52-9:58, 26:08-26:14), 2개 블러 창 + 1개 박스 (*.ts.net 호스트명), 렌더링 약 2시간 벽시계 시간, 출력 측 OCR로만 누출 발견.
  • 2026-09-24 OBS 교육 세션: 사용자가 첫 번째 컷을 거부함 ("배경 소음, 타이핑, 시작이 매우 지루함") -> 타이핑 소음 제거, 더 나은 오프닝 선택, 전사 다시 수행, 0:00-1:12 문자 그대로 머리 자르기, 누출 스캔, 더 큰 로고가 있는 흰색/크림색 썸네일, 2개 메타데이터 변형, Downloads로 이동.
  • 팟캐스트 (2026-09-18): 1시간 40분 비디오 + 5개 후보 오디오 파일 -> 올바른 화자별 트랙 2개 식별, 음성을 비디오에 매핑, 1080p, 머리 자르기, SRT + ES/AR/HI 번역, 챕터 타임스탬프, 두 화자가 있는 썸네일, 상단 텍스트, 검은색 배경 없음.

관련 스킬