Communitygithub.com

Monet-AI-Editor/Monet

`editorctl`은 Monet의 CLI입니다. 먼저 직접 시도하세요. Monet은 `PATH`에 항상 유지하며 `~/.zshrc` / `~/.bash_profile`에 bin 디렉토리를 저장하여 서브셸과 PATH를 재작성하는 래퍼에서도 사용 가능합니다. **`command -v editorctl`이 아무것도 반환하지 않으면** 다음 순서로 대체하세요:

Monet란 무엇인가요?

이 스킬은 AI 비디오 에디터 Monet의 에이전트 제어 레퍼런스입니다. Monet CLI인 `editorctl`을 통해 프로젝트, 에셋, 시퀀스, 클립, 효과, 트랜지션 등을 완전히 제어할 수 있습니다. 로컬 HTTP API(`localhost:51847`)를 통해 JSON 명령을 주고받으며, Python 코드 예제도 제공됩니다. macOS, dev 트리 등 다양한 환경을 지원하며, CLI가 없어도 node 스크립트로 직접 실행할 수 있습니다. 또한 Matter.js 및 Paper.js를 활용한 캔버스 모드, Remotion을 사용한 React 기반 비디오 합성, 브랜드 에스테틱 추출 기능을 제공합니다. 출력 파일명은 중복을 피하기 위해 항상 고유한 이름을 사용해야 하며, 다중 클립 타임라인에 오디오를 추가할 때는 클립 병합이 필수입니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add Monet-AI-Editor/Monet

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

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

문서

AI 비디오 에디터 — 에이전트 제어 레퍼런스

⚠️ editorctl 찾기 — 필수 (먼저 읽으세요)

editorctl은 Monet의 CLI입니다. 먼저 직접 시도하세요 — Monet은 PATH에 항상 유지하며 ~/.zshrc / ~/.bash_profile에 bin 디렉토리를 저장하여 서브셸과 PATH를 재작성하는 래퍼에서도 사용 가능합니다. command -v editorctl이 아무것도 반환하지 않으면 다음 순서로 대체하세요:

  1. "$HOME/Library/Application Support/Monet/bin/editorctl" — macOS 설치 (대부분의 사용자)
  2. node /Applications/Monet.app/Contents/Resources/app.asar.unpacked/out/cli/cli/editorctl.js …
  3. node ./out/cli/cli/editorctl.js … — dev 트리

첫 번째 "command not found" 이후 포기하지 마세요. editorctl을 curl localhost:51847보다 선호하세요 — 항상 현재 명령어 표면과 인자 형태를 노출합니다.

⚠️ 출력 파일 이름 지정 — 필수 (먼저 읽으세요)

비디오나 이미지를 편집하거나 재생성할 때 파일 이름을 재사용하지 마세요. 에셋 캐시는 경로별로 이전 파일을 보관하므로 동일한 이름에 쓰면 이전 콘텐츠가 표시됩니다. 모든 편집/재생성은 새로운 고유 파일 이름을 생성해야 합니다 (예: clip_v1.mp4, clip_v2.mp4 또는 타임스탬프 접미사). 모든 비디오 렌더링, 이미지 생성, 캔버스 내보내기 및 썸네일에 적용됩니다. 대상 경로가 이미 존재하는 경우 _v2, _v3, …을 추가하세요 — 덮어쓰지 마세요.

⚠️ 다중 클립 타임라인의 오디오 — 필수

두 개 이상의 비디오 클립이 있는 타임라인에 오디오를 추가하면 오디오가 모든 클립 경계에서 잘립니다. 필수 흐름:

  1. 사용자에게 알리세요: "클립 사이에서 오디오가 끊기지 않도록 하기 위해 모든 비디오 클립을 먼저 하나의 결합된 비디오로 병합한 다음 오디오를 추가하겠습니다. 계속할까요?"
  2. 확인을 기다리세요 — 자동 병합하지 마세요.
  3. 모든 클립을 위 규칙에 따라 고유한 새 파일로 연결하세요.
  4. 다중 클립 비디오 트랙을 병합된 클립으로 교체한 다음 오디오를 추가하세요.

단일 클립 타임라인: 병합을 건너뛰세요.


⚠️ 캔버스 모드 — 필수 규칙 (먼저 읽으세요)

activeView=canvas가 훅 또는 editorctl get-state에 의해 보고될 때:

정확히 3개의 캔버스 옵션이 있습니다. 다른 것은 없습니다.

  1. Paper.js — 벡터 그래픽을 사용한 코드 드로잉 (canvas-run-paperjs)
  2. Matter.js — 물리 및 애니메이션 (canvas-run-matterjs)
  3. GPT image 2 — AI 생성 이미지 (generate-image + canvas-add-image)

제거됨 — 어떤 이름으로도 제공하지 마세요:

  • 디자인 모드 — 제거됨
  • 편집 가능한 레이어 — 제거됨
  • Figma 스타일 레이아웃 — 제거됨
  • 노드 기반 디자인 — 제거됨
  • 직접 캔버스 디자인 — 제거됨

사용자가 캔버스 모드에서 시각적인 것을 요청하면 이러한 정확한 레이블을 사용하여 이 세 가지 옵션만 제시하세요. 그대로 복사하세요. 네 번째 옵션을 만들거나 옵션 1을 디자인 관련으로 바꾸지 마세요.


API 브리지: POST http://localhost:51847 — JSON 본문 {"command":"<name>","args":{...}}

import urllib.request, json

def call(command, **args):
    data = json.dumps({"command": command, "args": args}).encode()
    req = urllib.request.Request(
        "http://localhost:51847", data=data,
        headers={"Content-Type": "application/json"}, method="POST"
    )
    return json.loads(urllib.request.urlopen(req).read())["result"]

call("ping")   # → {"status":"ok","version":"1.0.0","port":51847}
call("help")   # → 전체 명령어 목록

명령어

프로젝트 / 설정

명령어인자반환값
get_project—전체 프로젝트 JSON
get_settings—모델 + 공급자 구성

에셋

명령어인자반환값
list_assets—[{id, name, path, type, duration, semantic}]
get_assetassetId시맨틱 + 트랜스크립트가 포함된 단일 에셋
import_filespaths: string[]가져온 에셋 레코드
transcribe_assetassetId, language?Whisper를 통한 {segments}
embed_assetsall?: booltext-embedding-3-small을 통한 {embedded, total}
search_mediaquery, limit?코사인 유사도 검색 (키워드로 대체)
search_spokenquery, limit?트랜스크립트된 세그먼트 내 부분 문자열 검색

시퀀스 및 트랙

명령어인자반환값
list_sequences—모든 시퀀스
create_sequencename새 시퀀스
activate_sequencesequenceId활성화된 시퀀스
get_tracks—활성 시퀀스의 [{id, name, kind, clipCount}]
add_trackkind: video|audio|caption업데이트된 시퀀스

클립

명령어인자반환값
list_clipssequenceId?startTime으로 정렬된 모든 클립 (trackKind 포함)
add_clipassetId, trackId, startTime, duration?, inPoint?{clipId, clip}
remove_clipclipId{success}
move_clipclipId, startTime{success}
trim_clipclipId, inPoint?, duration?, startTime?업데이트된 클립
split_clipclipId, time업데이트된 시퀀스
duplicate_clipclipId, offsetSeconds?{clipId, clip}
update_clip_labelclipId, label{success}

효과 및 속성

명령어인자반환값
list_effects—사용 가능한 효과 + 매개변수 문서
add_effectclipId, effectType, parameters업데이트된 프로젝트
remove_effectclipId, effectId업데이트된 프로젝트
set_speedclipId, speed업데이트된 프로젝트 (0.1–10배 재생)
set_volumeclipId, volume업데이트된 프로젝트 (0–4, 1=일반)
set_transitionclipId, side: in|out, type, duration?{success}

기록

명령어인자
undo—
redo—

효과 유형

유형매개변수
fade_induration (초)
fade_outduration (초)
color_gradebrightness (-1→1), contrast (0.5→2), saturation (0→3)
blurradius (px, 기본 5)
sharpenamount (0→3, 기본 1)

트랜지션 유형

crossfade · dip_to_black · wipe · slide


주요 개념

  • inPoint = 클립 재생이 시작되는 소스 파일 내 위치
  • startTime = 클립이 배치되는 타임라인의 위치
  • duration = 클립이 재생되는 시간 (소스보다 짧을 수 있음)
  • 모든 변경 사항은 즉시 project:updated를 푸시하여 UI에 실시간으로 반영됩니다.
  • 효과는 실시간으로 미리보기(CSS)되며 내보내기 시 FFmpeg를 통해 렌더링됩니다.

편집 안전 규칙

  • 사용자가 명시적으로 일시 정지, 비트 또는 검은색 간격을 요청하지 않는 한 타임라인 간격을 버그로 취급하세요.
  • 시퀀스를 생성하거나 클립을 이동한 후 list_clips(sequenceId)로 연속성을 확인하고, 편집이 연속적인 경우 각 클립이 이전 클립이 끝나는 정확한 시간에 시작하는지 확인하세요.
  • create_sequence 또는 activate_sequence만으로 충분하다고 가정하지 마세요. 항상 이후에 list_sequences 또는 get_project로 활성 시퀀스를 확인하세요.
  • 음성 하이라이트 컷을 만들 때는 비디오, 오디오, 캡션 및 마커를 함께 이동하세요. 편집을 조인 후 캡션이나 마커를 이전 타이밍에 남겨두지 마세요.
  • 클립 간 재생이 중지되는 것처럼 보이면 미리보기 플레이어가 고장난 것으로 가정하기 전에 먼저 타임라인에서 빈 간격을 검사하세요.
  • 컷을 조일 때 누적 오프셋 계산보다 정확한 대상 시작 시간을 선호하세요. 컷 계획에서 각 클립의 의도된 startTime을 다시 계산하세요.

URL에서 브랜드 에스테틱

필수 — 예외 없음: 사용자 메시지에 URL이나 도메인이 포함된 경우, 캔버스/디자인 코드를 작성하기 전에 아래 가져오기 명령어를 실행하고 브랜드 토큰을 추출해야 합니다. 가정하거나 기억한 브랜드 색상을 사용하지 마세요. 먼저 가져오고, 그 다음 디자인하세요 — 매번 그렇게 하세요. 가져오기가 실패하면 사용자에게 16진수 값을 붙여넣도록 요청하세요; 추측으로 대체하지 마세요.

curl -sL "<url>" | grep -Eo '(#[0-9a-fA-F]{3,8}|font-family:[^;"}]+|font-size:[^;"}]+|border-radius:[^;"}]+)' | sort -u | head -60

추출 대상: 배경 색상, 표면 색상, 기본/강조 색상, 텍스트 색상, 글꼴 패밀리, 글꼴 크기/두께, 테두리 반경, 간격 및 그림자. 로고도 찾으세요 — 브랜드 색상과 시각적 톤의 진실의 원천입니다. 실제 URL이 사용 가능할 때 절대 추측하지 말고 해당 정확한 값을 하드코딩하세요.

# 로고 찾기
curl -sL "<url>" | grep -Eo '(src|href)="[^"]*logo[^"]*"' | head -10
curl -sL "<url>" | grep 'og:image'

캔버스 — Matter.js 물리 프레임

canvas_run_matterjs를 사용하여 라이브 대화형 물리 장면을 캔버스에 배치하세요.

MCP 도구

도구인자
canvas_run_matterjsid? (업데이트할 프레임 ID), name?, script (JS 문자열), width?, height?
canvas_add_framename, width, height, mode: 'matterjs'
canvas_matterjs_scenestyle (balls/stacks/pendulum/bridge/ragdoll), gravity?, count?, colors?
canvas_frames— → {frames: [{id, name, mode, width, height}]}

스크립트 패턴 — 하나를 선택하세요

패턴 A — 자체 포함 (풍부한 UI, 사용자 정의 2D 드로잉, rAF 루프)

const { Engine, Bodies, Composite, Mouse, MouseConstraint, Events } = Matter;
const W = 390, H = 844;
const engine = Engine.create({ gravity: { y: 1.5 } });
const canvas = document.querySelector('canvas'); // ← 항상 이것을 사용하세요; 새로 만들지 마세요
canvas.width = W; canvas.height = H;
const ctx = canvas.getContext('2d');
// ... 바디 추가, 마우스 설정 ...
function loop() {
  Engine.update(engine, 1000/60);
  ctx.fillStyle = '#121212'; ctx.fillRect(0, 0, W, H);
  // ctx로 그리기
  requestAnimationFrame(loop);
}
loop();

패턴 B — 바디만 (템플릿이 엔진/렌더/러너 관리)

// engine, render, width, height 및 모든 Matter 변수는 이미 선언됨 — 다시 선언하지 마세요
var ground = Bodies.rectangle(width/2, height+25, width, 50, { isStatic: true, render: { fillStyle: '#334155' } });
var ball = Bodies.circle(width/2, 50, 30, { restitution: 0.8, render: { fillStyle: '#5b82f7' } });
Composite.add(engine.world, [ground, ball]);
engine.gravity.y = 1;
// Runner.run과 Render.run은 이 스크립트 후에 자동으로 호출됨 — 여기서 호출하지 마세요

중요 규칙

  • Runner.run에는 두 개의 인자가 필요함: Runner.run(Runner.create(), engine) — 단일 인자 Runner.run(engine)은 Matter.js 0.20.0에서 조용히 아무것도 하지 않습니다.
  • Render.create에서 element: document.body를 절대 사용하지 마세요 — 보이지 않는 두 번째 캔버스를 생성합니다; 대신 canvas: document.querySelector('canvas')를 사용하세요.
  • 패턴 B에서 const engine 또는 let engine을 절대 선언하지 마세요 — 템플릿에 이미 var engine이 있습니다; const/let으로 다시 선언하면 SyntaxError가 발생하여 캔버스가 조용히 비워집니다.
  • 패턴 B에서 Render.run / Runner.run을 절대 호출하지 마세요 — 템플릿이 스크립트 실행 후에 이를 수행합니다; 두 번 호출하면 이중 속도 또는 깨진 렌더링이 발생합니다.
  • 패턴 B에서 Matter 변수를 가져오거나 다시 선언하지 마세요 — Engine, Bodies, Composite 등은 이미 구조 분해되었습니다; const { Engine } = Matter는 SyntaxError를 발생시킵니다.

패턴 B에서 사용 가능한 전역 변수

engine · render · width · height · Engine · Render · Runner · Bodies · Composite · World · Body · Events · Constraint · Mouse · MouseConstraint

CLI

editorctl canvas-add-frame "Name" 390 844 matterjs        # matterjs|paperjs|html
editorctl canvas-run-matterjs <frameId> "$(cat script.js)"
editorctl canvas-run-paperjs  <frameId> "$(cat script.js)"
editorctl canvas-run-html     <frameId> "$(cat scene.html)"
editorctl canvas-frames
editorctl canvas-done

Remotion — React 비디오 합성

Remotion을 사용하여 애니메이션 비디오 에셋(타이틀 카드, 하단 서드, 슬라이드쇼, 모션 그래픽)을 생성하고 타임라인으로 직접 가져오세요.

MCP 도구

도구인자반환값
video_editor_list_remotion_compositions—합성 ID 목록
video_editor_render_remotioncompositionId, outputFilename?, props?, durationInFrames?, fps?{outputPath, assetId}

CLI

npm run remotion:studio                                          # localhost:3000에서 실시간 미리보기
npx remotion render remotion/src/index.ts <ID> out.mp4 --props '{"key":"value"}'

내장 합성

IDProps
TitleCardtitle (str), subtitle? (str), backgroundColor, textColor, accentColor — 150프레임 @ 30fps
Slideshowimages (절대 경로[]), frameDuration (프레임), transitionDuration (프레임) — 300프레임 @ 30fps
HtmlInCanvasGlitchtitle, subtitle, glitchIntensity (0–40), backgroundColor, textColor, accentColor — 180프레임 @ 30fps. <HtmlInCanvas>를 통한 RGB 분할 글리치

HTML-in-canvas (Remotion ≥ 4.0.455)

⚠️ 이름 충돌 — 먼저 읽으세요. Remotion <HtmlInCanvas>(이 섹션)는 타임라인용 비디오 파일을 생성합니다. Monet 캔버스 HTML 프레임(canvas-add-frame ... html, canvas_update_frame)은 캔버스 탭 아트보드에 라이브 HTML 장면을 생성합니다. 다른 시스템입니다. 대상에 따라 선택하세요: 타임라인 → Remotion; 캔버스 탭 → Monet HTML 프레임. 하나의 작업에서 두 가지를 혼합하지 마세요.

<HtmlInCanvas>를 사용하여 DOM 서브트리를 <canvas>에 그리고 Canvas 2D / WebGL / WebGPU로 후처리하세요. 글리치, 돋보기, CRT, 변위, 색조 회전 효과에 가장 적합합니다.

import { HtmlInCanvas, type HtmlInCanvasOnPaint } from 'remotion'

const onPaint: HtmlInCanvasOnPaint = ({ canvas, element, elementImage }) => {
  const ctx = canvas.getContext('2d')!
  ctx.reset()
  ctx.filter = 'blur(8px)'
  const transform = ctx.drawElementImage(elementImage, 0, 0)
  element.style.transform = transform.toString() // <-- 항상 다시 적용
}

<HtmlInCanvas width={1920} height={1080} onPaint={onPaint}>
  <YourDomTree />
</HtmlInCanvas>

규칙:

  • drawElementImage 반환 값을 element.style.transform에 항상 다시 적용하여 레이아웃/입력이 정확하게 유지되도록 하세요.
  • 다른 <HtmlInCanvas> 안에 <HtmlInCanvas>를 절대 중첩하지 마세요 — Chrome은 외부 것만 렌더링하고 Remotion이 오류를 발생시킵니다. 하나의 onPaint로 효과를 병합하세요.
  • Config.setChromiumOpenGlRenderer('angle')은 이미 설정되어 있습니다.

관련 스킬