Communitygithub.com

Edits 비디오 편집 (metapilot-native)

Meta의 Edits 비디오 편집기(macOS 앱, MCP 서버 'metapilot-native')를 구동하여 프로젝트 열기, 컷, 트림, 비트/샷 분할, 리프레임, 텍스트/자막/필터/효과/전환/LUT/속도 곡선/음악 추가, 오디오 정규화, 프레임 검사 및 내보내기를 수행합니다. 사용자가 Edits, Edits 앱, metapilot 또는 metapilot-native를 언급하거나, Edits에서 비디오 편집, 컷, 자막, 리프레임, 그레이딩 또는 내보내기를 요청할 때 사용합니다.

Edits 비디오 편집 (metapilot-native)란 무엇인가요?

이 스킬은 Claude Code와 같은 AI 에이전트가 Meta의 Edits 비디오 편집기(macOS 전용)를 완전히 제어할 수 있게 해줍니다. Edits 앱에 내장된 MCP 서버(metapilot-native, 포트 19501)를 통해 실시간으로 편집 명령을 실행하며, 모든 편집은 사용자가 화면에서 바로 확인할 수 있습니다. 지원하는 주요 기능으로는 프로젝트 관리(생성, 열기, 복제, 삭제), 미디어 가져오기(단, `~/Movies` 디렉토리에서만 가능), 클립 컷/트림/분할, 비트 감지 기반 자동 분할, 자동 리프레임, 텍스트 및 자막 추가, 필터/효과/전환/LUT/속도 곡선 적용, 오디오 노멀라이즈, 키프레임 기반 애니메이션, PIP(화면 속 화면) 구성, 비디오 미리보기 및 최종 내보내기(HEVC + AAC)를 포함합니다. 편집 영역(프로젝트 목록 화면, 편집 화면)에 따라 제공되는 도구 목록이 동적으로 변경되며, 도구 호출 실패 시 진단 스크립트(`scripts/mcp_client.py doctor`)로 원인을 파악할 수 있습니다. 특히, 여러 편집을 한 번에 실행하는 배치 스크립트를 권장하며, 각 도구의 매개변수(예: 시간, 좌표, 색상, 볼륨)와 열거형 값(속도 곡선: `MONTAGE`, 자동 자막 소스: `video`)을 정확히 지켜야 합니다. 내보내기 전에 `captureFrame`이나 `frameSheet`로 결과를 시각적으로 확인하고, 내보내기 설정(`setExportSettings`) 시 5개 필드(해상도, 종횡비, 품질, 다이내믹 레인지, FPS)를 모두 지정해야 합니다.

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

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

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

문서

metapilot-native를 통한 Edits 비디오 편집

Edits (/Applications/Edits.app, 번들 com.burbn.basel.mac)는 http://127.0.0.1:19501/mcp에 MCP 서버를 노출하며, Claude Code에 metapilot-native로 등록됩니다. 앱이 실행 중이어야 합니다. 모든 호출은 사용자가 볼 수 있는 라이브 앱에서 동작하므로 편집 내용이 즉시 반영됩니다.

참조 파일은 작업에 필요한 것만 읽으십시오:

  • references/tool-reference.md: 카테고리별 모든 274개 편집기 도구와 홈 전용 4개 도구, 매개변수 포함 (라이브 서버에서 로컬로 생성, 제공되지 않음)
  • references/catalogs.md: 모든 카탈로그 ID (필터, 효과, 전환, LUT, 글꼴, 텍스트 프리셋 및 애니메이션, 캡션 스타일, 속도 곡선, 마스크, 강조) (로컬로 생성, 제공되지 않음)

이 두 생성된 파일이 없으면, 사용하기 전에 생성하십시오: Edits가 실행 중인 상태에서 홈 화면에서는 python3 scripts/build_references.py --catalogs-only가 작동하고, python3 scripts/build_references.py --project-id <uuid>는 도구 참조를 추가합니다 (해당 프로젝트를 읽기 전용으로 열었다가 다시 닫습니다).

  • references/conventions-and-gotchas.md: 단위, 좌표, 스키마 함정, 측정된 타이밍
  • references/recipes.md: 일반적인 편집을 위한 테스트된 호출 시퀀스
  • scripts/mcp_client.py: MCP 도구가 세션에 로드되지 않았거나, 하나의 Python 스크립트에서 여러 호출을 배치 처리할 때 사용하는 직접 클라이언트
  • scripts/build_references.py: 앱 업데이트 후 두 생성된 참조를 다시 생성합니다

도구 세트는 화면을 따릅니다

서버는 앱 화면에 따라 도구 목록을 교체합니다 (tools.listChanged):

  • 홈: 약 30개의 도구. 프로젝트 (projects, openProject, newProject, renameProject, duplicateProject, deleteProject), 가져오기 (importMedia, addMedia, importMcomp), 그리고 모든 카탈로그 검색 (getCapabilities, listCatalogKinds, listCatalog, getCatalogItem).
  • 편집기: 프로젝트가 열린 후에만 274개의 도구.

도구가 없거나 호출이 실패할 때

세션 내에서 세 가지 다른 오류가 비슷하게 보이며, 각각 고유한 해결 방법이 있습니다. appState는 모든 화면에 존재하므로 이를 프로브로 사용하여 구분합니다. 단계별 진단을 위해 python3 scripts/mcp_client.py doctor를 실행하십시오.

  1. 서버에 연결할 수 없습니다. appState 자체가 실패하거나, 세션에 metapilot-native 도구가 전혀 없습니다 (서버가 세션 시작 시 다운되어 있었습니다). 연결 거부는 Edits가 실행 중이 아니거나 MCP 서버가 꺼져 있음을 의미합니다. pgrep -x Edits로 프로세스를 확인하십시오. HTTP 403 unauthorized는 ~/.claude.json에 저장된 토큰이 잘못되었거나 오래되었음을 의미합니다: 사용자는 Edits에서 현재 토큰을 복사하여 서버를 다시 등록해야 합니다 (README, 설치 단계 2 및 3). 403 본문은 에이전트에게 사용자가 토큰을 채팅에 붙여넣도록 요청합니다. 그렇게 하지 마십시오. 토큰은 등록 시 사용되는 것이지 대화 기록에 사용되는 것이 아닙니다. 화면을 전환해도 이러한 문제는 해결되지 않습니다. 사용자가 수정한 후 세션의 자체 클라이언트는 /mcp를 통해 다시 연결해야 할 수 있습니다. scripts/mcp_client.py는 실행할 때마다 새로 연결됩니다.
  2. 서버는 정상이지만 화면이 잘못되었습니다. appState가 home 또는 loading을 반환합니다. 편집기 도구가 아직 존재하지 않습니다: 프로젝트를 열고 (openProject) appState가 editor를 반환할 때까지 폴링합니다. 홈 화면에서 편집기 도구를 호출하면 unknown tool (not in current manifest): <name>이 반환되는데, 이는 잘못된 이름을 사용했을 때와 동일한 텍스트이므로 오류보다는 appState를 읽으십시오.
  3. 화면은 올바르지만 세션의 도구 목록이 오래되었습니다. appState가 editor를 반환하지만, 세션에 여전히 편집기 도구가 없습니다: 클라이언트가 tools/list_changed 후 목록을 다시 로드하지 않았습니다. 사용자에게 도구가 존재하지 않는다고 말하는 대신 scripts/mcp_client.py를 사용하십시오 (이 스크립트는 tools/call을 직접 호출하므로 이름으로 모든 편집기 도구가 작동합니다).

표준 워크플로우

  1. appState로 화면 확인 (home, editor, loading).
  2. projects로 목록을 확인한 다음 openProject({id}) (또는 {name}) 또는 newProject를 호출합니다. appState의 screen이 editor가 될 때까지 폴링합니다. 여는 데 약 0.3초가 걸리며, 클라우드에서 가져올 때는 더 오래 걸립니다. 새 프로젝트는 60fps의 1440x2560 (9:16)입니다. 제작 전에 모양과 속도를 설정하십시오: setAspectRatio({ratio:"16:9"}) 및 setFrameRate({fps:30}). 새로 연 프로젝트에서 setCanvas 사용을 피하십시오. "이전 편집이 아직 안정화 중입니다. 다시 시도하십시오."라는 응답을 계속 반환할 수 있습니다.
  3. 방향 파악: state (플레이헤드, 지속 시간, 클립 수), getCanvas (크기, 종횡비, fps), tracks, elements (긴 타임라인에서는 fields 및 limit 사용. 실제 필드 이름은 id, trackId, trackType, content, startTime, endTime), getElement({id})로 단일 요소에 적용된 카탈로그 항목, instanceIds 및 텍스트 요소의 text 및 fontSize를 확인합니다.
  4. 적용하기 전에 검색: listCatalog({kind, query?, limit?}), 그런 다음 항목 id를 해당 종류의 적용 도구에 전달합니다 (아래 표). 표시 이름에서 ID를 추측하지 마십시오.
  5. 편집합니다. 단일 실행 취소 배치 도구를 선호하십시오: splitAt (여러 컷), setTransforms (여러 포즈), autoReframe, splitScreen. 다중 호출 빌드는 하나의 스크립트로 작성하고 한 번만 실행하십시오: 다시 실행하면 모든 것이 두 번째 복사본으로 쌓이고 undo는 한 번에 한 호출씩 되돌릴 수 없으므로 되돌리는 속도가 느립니다 (각 undo 후 elements 확인).
  6. 완료했다고 선언하기 전에 시각적으로 확인: captureFrame({atSeconds}) 또는 captureFrame({times:"1,2.5,4"})로 정확한 합성 프레임 (720px 너비)을, frameSheet({times,columns,cellWidth})로 편집 내용의 레이블이 지정된 콘택트 시트 (기본 셀은 작으므로 cellWidth 전달, 3열의 경우 16:9는 약 420, 9:16은 약 300; 시간 레이블이 각 셀의 왼쪽 상단 모서리를 덮습니다)를, previewVideo로 모션 (최대 10초, 12프레임)을 확인합니다. mcp_client.Client.tool에 image_dir을 전달하여 이미지를 디스크에 저장하십시오: 서버가 반환하는 path는 앱의 샌드박스 내부에 있어 읽을 수 없습니다. 이미지를 보고; ok:true만 믿지 마십시오.
  7. saveProject. 요청 시에만 내보내기: 전체 프리셋 행으로 setExportSettings를 호출한 다음, export({path})를 호출하고 exportStatus를 폴링합니다 (레시피는 references/recipes.md에 있음). 그런 다음 ffprobe와 파일 자체의 콘택트 시트로 파일을 확인합니다.
  8. 사용자가 프로젝트에서 직접 작업하지 않는 경우 완료되면 closeProject.

카탈로그 종류 및 적용 도구

종류적용 도구매개변수적용 대상
전환addTransition({fromId,toId,filterId,durationSeconds})filterId두 메인 트랙 클립 사이의 경계
비디오 효과applyEffect({id,effect})effect비디오
필터applyFilter({id,filter,intensity})filter비디오
LUTapplyLUT({table})table선택된 클립, 또는 새 조정 레이어
텍스트 애니메이션setTextAnimation({id,animation})animation텍스트
텍스트 프리셋applyTextPreset({id or ids,name})name텍스트
캡션 스타일setCaptionStyle({style,id?})style캡션 (id 생략 시 모두)
속도 곡선 프리셋setSpeedCurve({id,preset})preset비디오 요소
글꼴setTextFont({id,family})family텍스트
강조 스타일setEmphasis({id,style,color?})style텍스트
마스크 모양setMask({id,shape,...})shape요소

지우기: 필터 normal, 효과 none, 전환 normal, 애니메이션 none, 마스크 none. 다른 작업을 취소하지 않고 적용된 필터, LUT 또는 효과 하나를 제거하거나 재조정하려면: removeCatalogItem({elementId,instanceId}) / updateCatalogItem({elementId,instanceId,intensity}), instanceId는 getElement에서 가져옵니다.

중요한 규칙

  • 단위: 이름에 *SourceSeconds 또는 *Ms가 없는 한 시간은 컴포지션 초입니다. 캔버스 좌표는 0에서 1로 정규화되고, 원점은 왼쪽 상단이며, +y는 아래쪽, x/y는 요소 중심입니다. 회전은 시계 방향 도입니다. 색상은 #RRGGBB 또는 #RRGGBBAA입니다. 볼륨은 선형 게인 0~10입니다 (1 = 유니티).
  • seek는 time이 아닌 seconds를 사용합니다. trim({id, side:"left"|"right", deltaSeconds}): 양수는 짧게, 음수는 길게 합니다. 속도가 빨라진 클립의 경우 deltaSeconds는 소스 초 단위이며 프레임에 스냅되고, 왼쪽 트림은 시작점을 이동시키므로 move({id,toSeconds})로 다시 이동하십시오.
  • ArgumentParser.CommandError error 1은 서버가 인수를 거부했음을 의미합니다. 앱이 실패한 것이 아닙니다. 마지막에 추가한 인수를 제거하십시오. 가장 일반적인 원인: dryRun을 전달하지 마십시오. 이를 제공하는 모든 도구 (10개)는 이 값이 설정되면 이런 방식으로 실패합니다. 대신 카탈로그를 읽어 검증하고, 적용한 다음 잘못된 경우 undo를 사용하십시오.
  • required 목록은 거짓말을 합니다: 대안이 모두 필수로 표시되고 (openProject id/name, frameSheet id/path, loudness id/path), 선택적 조정 매개변수 또한 마찬가지입니다 (findPauses, quietPoint, audioOnsets는 {id}만으로 실행됨; frameSheet는 cellWidth 없이 실행됨). 의도한 것만 전달하십시오.
  • 열거형과 같은 문자열은 정확합니다. 속도 곡선 프리셋은 대문자입니다 (MONTAGE, HERO, BULLET, JUMP_CUT, FLASH_IN, FLASH_OUT, RAMP, STROBE); 잘못된 값은 유효한 목록과 함께 오류가 발생하므로 오류를 읽으십시오. generateCaptions의 source는 video, voiceover, importedAudio 또는 all입니다. 많은 매개변수가 스키마에 열거형을 나열하지 않습니다. 의도적으로 잘못된 값을 한 번 보내면 오류가 유효한 목록을 반환합니다.
  • 내보내기는 새 프로젝트에 대해 전체 프리셋 행, 다섯 개 필드 모두 필요합니다: setExportSettings({resolutionType:"HD", aspectRatio:"nineBySixteen", quality:"High", dynamicRange:"SDR", frameRate:30}). 하나라도 빼먹으면 export가 "불완전한 프리셋 행, 누락됨: " 오류와 함께 실패하며, frameRate도 포함됩니다. 유효한 값: resolutionType 720p, HD, 2K, 4K; aspectRatio nineBySixteen, sixteenByNine, fourByFive, oneByOne, fiveByFour, fourByThree, threeByFour; quality Low, Med, High; dynamicRange SDR, HDR. 프로젝트 속도를 frameRate로 전달하십시오: 파일은 프로젝트 속도를 따르므로 setFrameRate를 먼저 호출하십시오. 출력은 AAC가 포함된 HEVC입니다.
  • Edits는 ~/Movies에서만 미디어를 가져옵니다. 앱은 샌드박스 처리됩니다: importToMediaBin은 ~/GitHub, 스크래치패드 또는 /private/tmp 아래 경로에서 import failed: copyFailed(...) NSCocoaErrorDomain Code=513 ("권한이 없어 파일을 복사할 수 없음") 오류와 함께 실패합니다. 가져오기 전에 모든 파일을 ~/Movies 아래 폴더 (예: ~/Movies/<project>/)에 렌더링하거나 복사하고, 미디어 path를 사용하는 모든 도구 (replaceElementMedia, 홈 가져오기 도구)를 동일하게 처리하십시오.
  • 텍스트 프리셋은 덮어씁니다: applyTextPreset은 글꼴, 색상, 크기 및 위치를 바꾸므로 먼저 프리셋을 적용한 다음 사용자 지정하십시오. id (또는 선택 영역)를 사용하는 경우 먼저 selectTool({tool:"textPresets"})가 필요합니다; ids를 사용하면 도구 자체가 열립니다.
  • 텍스트 위치에 대해 에코된 상태를 신뢰하지 마십시오: setTextPosition은 작동하지만, getElement.textPosition은 계속 [0,0]을 읽습니다. captureFrame으로 배치를 확인하십시오.
  • 텍스트는 선택한 열로 줄 바꿈되지 않습니다. 텍스트 상자 너비는 앱에 의해 고정되므로, 넓은 캔버스에서 큰 크기는 프레임 밖으로 나갑니다. 직접 줄을 나누십시오: editText({id, text:"첫 번째 줄\n두 번째 줄"}). DMSans18pt-SemiBold로 잘 읽히는 크기: 9:16에서는 24 (자체적으로 약 두 줄로 줄 바꿈), 16:9에서는 명시적 줄 바꿈과 함께 40.
  • replaceElementMedia({id,path})로 제자리에서 미디어 교체: 사진과 비디오 간 교환이 모두 작동하며, 타임라인 지속 시간, 변환 키프레임 및 전환이 유지됩니다. 비디오의 경우 인포인트가 0으로 재설정됩니다; slipClip({id,deltaSeconds})로 복원하십시오.
  • 브랜드 및 제품 에셋은 사용자의 실제 파일에서 가져오며, 대체 파일을 사용하지 않습니다. 로고의 경우 실제 마크(인라인 SVG 기호, 브랜드 키트, 디자인 가이드)를 찾아 렌더링하고, 찾을 수 없으면 물어보십시오. 태그라인도 마찬가지입니다: 정확한 문구를 사용하십시오.
  • 스틸 이미지용 배경 또는 단색 생성기가 없습니다. 각 프레임을 (헤드리스 Chrome으로 렌더링된 HTML 또는 ffmpeg) 캔버스 크기로 미리 합성하고 가져오십시오. 레시피: "스틸 이미지에서 비디오".
  • 라이선스 음악은 읽을 수 있는 소스가 없습니다: loudness, quietPoint 및 audioOnsets는 카탈로그 음악 요소에서 실패합니다 ("읽을 수 있는 소스 파일이 없음"). beatMarkers는 해당 요소에서 작동하며, 오디오 분석 도구는 비디오 클립 및 가져온 오디오에서 작동합니다. listMusicTracks를 license:"royaltyFree"로 호출하면 2026-11-08 기준으로 아무것도 반환되지 않았습니다. 카탈로그 트랙은 Meta 앱 내에서 사용하도록 라이선스가 부여되므로, Instagram을 떠나는 비디오의 경우 사용자가 소유한 오디오를 사용하고 재배포 전에 라이선스에 대해 문의하십시오.
  • setVolume({id,volume:0})은 트랙을 음소거하지만 isMuted는 false로 유지됩니다. 볼륨으로 판단하십시오.
  • 선택 기반 도구 (delete, cut, copy, applyLUT, applyTextPreset (id 없음)) 는 현재 선택 영역에서 작동합니다. 먼저 selectById로 명시적으로 설정하고 확인하십시오. selectById({ids:[]})는 CommandError와 함께 실패합니다. 선택을 지울 수 없습니다.
  • 파괴적인 도구는 사용자의 동의가 필요합니다: deleteProject, delete, cut, deleteCaptions, deleteSoundEffect, deleteVoiceoverClip, removeMusicTrack, deleteAccountFont. 실수로부터 복구하려면 삭제보다 undo를 선호하십시오.
  • 장기 작업: 분석 및 렌더링 도구는 요청 시간을 초과하고 작업 ID를 반환할 수 있습니다. jobStatus({id})를 폴링하십시오. describeClip은 약 10초, transcribeClip은 길이에 따라 확장됩니다. previewVideo는 동기식 (약 3.5초)이며 MP4 경로를 반환합니다. previewVideoStatus는 {includeFrames}만 사용합니다. export는 즉시 반환됩니다: exportStatus를 폴링하고 state 키 (preparing, progress 0~1의 exporting, complete)를 읽은 다음 파일이 존재하는지 확인하십시오.
  • 속도 곡선: setSpeedCurve를 사용하십시오. *SpeedPanel* 도구는 더 이상 사용되지 않는 UI 드라이버입니다.
  • 화면 속 화면: addOverlay({startSeconds,path,x,y,scale})는 전체 소스 길이의 클립을 새 오버레이 트랙에 배치합니다. scale 1은 캔버스 높이에 맞습니다. 불투명도 키프레임으로 페이드하십시오 (seek, toggleKeyframe({id,property:"opacity"}), setOpacity). 모든 키프레임을 먼저 배치한 후 오른쪽을 트리밍하십시오. 레시피: "화면 속 화면 클립".
  • 오디오 교체는 replaceAudio({id,path})를 사용합니다. replaceElementMedia (시각적 전용)가 아닙니다. 요소 ID와 이전 지속 시간을 유지합니다.

관련 스킬