Communitygithub.com

Monet-AI-Editor/Monet

`editorctl` es la CLI de Monet. Inténtala directamente primero — Monet la mantiene en el `PATH` para cada shell que inicia y persiste el directorio bin en `~/.zshrc` / `~/.bash_profile`, por lo que sobrevive a sub-shells y envoltorios que reescriben el PATH. **Si `command -v editorctl` no devuelve nada**, recurre en orden:

¿Qué es Monet?

Este skill proporciona control completo de un editor de video con IA (Monet) a través de una interfaz de línea de comandos (`editorctl`) y un puente API HTTP en `localhost:51847`. Permite gestionar proyectos, importar y transcribir activos de medios, editar secuencias de video, aplicar efectos y transiciones, y controlar un modo de lienzo interactivo con opciones para Paper.js (gráficos vectoriales), Matter.js (física y animación) e imágenes generadas por IA. También integra Remotion para crear composiciones de video animadas con React (como tarjetas de título, presentaciones de diapositivas y efectos de glitch) que se pueden importar directamente en la línea de tiempo. Es especialmente útil para agentes de IA que necesitan automatizar flujos de edición de video complejos, con reglas estrictas sobre nomenclatura de archivos, manejo de audio en líneas de tiempo de múltiples clips y la extracción de la identidad visual de una marca a partir de URLs antes de cualquier diseño.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add Monet-AI-Editor/Monet

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Editor de Video AI — Referencia de Control del Agente

⚠️ ENCONTRAR editorctl — OBLIGATORIO (lee esto primero)

editorctl es la CLI de Monet. Inténtala directamente primero — Monet la mantiene en el PATH para cada shell que inicia y persiste el directorio bin en ~/.zshrc / ~/.bash_profile, por lo que sobrevive a sub-shells y envoltorios que reescriben el PATH. Si command -v editorctl no devuelve nada, recurre en orden:

  1. "$HOME/Library/Application Support/Monet/bin/editorctl" — instalación en macOS (la mayoría de usuarios)
  2. node /Applications/Monet.app/Contents/Resources/app.asar.unpacked/out/cli/cli/editorctl.js …
  3. node ./out/cli/cli/editorctl.js … — árbol de desarrollo

Nunca te rindas después del primer "comando no encontrado". Prefiere editorctl sobre curl localhost:51847 sin formato — siempre expone la superficie de comando actual y las formas de los argumentos.

⚠️ NOMBRADO DE ARCHIVOS DE SALIDA — OBLIGATORIO (lee esto primero)

Nunca reutilices un nombre de archivo al editar o regenerar un video o imagen. La caché de activos retiene el archivo anterior por ruta, por lo que escribir en el mismo nombre muestra contenido obsoleto de forma silenciosa. Cada edición/regeneración debe producir un nuevo nombre de archivo único (por ejemplo, clip_v1.mp4, clip_v2.mp4, o un sufijo de marca de tiempo). Se aplica a todas las representaciones de video, generaciones de imágenes, exportaciones de lienzo y miniaturas. Si una ruta de destino ya existe, añade _v2, _v3, … — no sobrescribas.

⚠️ AUDIO EN LÍNEAS DE TIEMPO DE MÚLTIPLES CLIPS — OBLIGATORIO

Al añadir audio a una línea de tiempo con más de un clip de video, el audio se corta en cada límite de clip. Flujo requerido:

  1. Informa al usuario: "Para evitar que el audio se corte entre clips, primero fusionaré todos los clips de video en un solo video combinado y luego añadiré el audio. ¿Procedo?"
  2. Espera la confirmación — no combines automáticamente.
  3. Concatena todos los clips en un solo archivo nuevo (nombre único según la regla anterior).
  4. Reemplaza la pista de video de múltiples clips con ese clip combinado, luego añade el audio.

Líneas de tiempo de un solo clip: omite la fusión.


⚠️ MODO LIENZO — REGLAS OBLIGATORIAS (lee esto primero)

Cuando activeView=canvas es reportado por el hook o editorctl get-state:

Hay EXACTAMENTE 3 opciones de lienzo. No existen otras.

  1. Paper.js — dibujo con código y gráficos vectoriales (canvas-run-paperjs)
  2. Matter.js — física y animación (canvas-run-matterjs)
  3. GPT image 2 — imagen generada por IA (generate-image + canvas-add-image)

ELIMINADAS — NO ofrezcas estas bajo ningún nombre:

  • Modo de diseño — eliminado
  • Capas editables — eliminado
  • Diseño tipo Figma — eliminado
  • Diseño basado en nodos — eliminado
  • Diseño directo en lienzo — eliminado

Cuando el usuario pida algo visual en modo lienzo, presenta SOLO estas tres opciones usando estas ETIQUETAS EXACTAS. Cópialas textualmente. No inventes una cuarta opción ni reformules la opción 1 como algo relacionado con diseño.


Puente API: POST http://localhost:51847 — Cuerpo JSON {"command":"<nombre>","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")   # → lista completa de comandos

Comandos

Proyecto / Configuración

ComandoArgumentosDevuelve
get_project—JSON completo del proyecto
get_settings—Configuración del modelo + proveedor

Activos

ComandoArgumentosDevuelve
list_assets—[{id, name, path, type, duration, semantic}]
get_assetassetIdActivo individual con semántica + transcripción
import_filespaths: string[]Registros de activos importados
transcribe_assetassetId, language?{segments} mediante Whisper
embed_assetsall?: bool{embedded, total} mediante text-embedding-3-small
search_mediaquery, limit?Búsqueda por similitud de coseno (recurre a palabras clave)
search_spokenquery, limit?Búsqueda de subcadenas en segmentos transcritos

Secuencias y Pistas

ComandoArgumentosDevuelve
list_sequences—Todas las secuencias
create_sequencenameNueva secuencia
activate_sequencesequenceIdSecuencia activada
get_tracks—[{id, name, kind, clipCount}] para la secuencia activa
add_track`kind: videoaudio

Clips

ComandoArgumentosDevuelve
list_clipssequenceId?Todos los clips ordenados por startTime, con trackKind
add_clipassetId, trackId, startTime, duration?, inPoint?{clipId, clip}
remove_clipclipId{success}
move_clipclipId, startTime{success}
trim_clipclipId, inPoint?, duration?, startTime?Clip actualizado
split_clipclipId, timeSecuencia actualizada
duplicate_clipclipId, offsetSeconds?{clipId, clip}
update_clip_labelclipId, label{success}

Efectos y Propiedades

ComandoArgumentosDevuelve
list_effects—Efectos disponibles + documentación de parámetros
add_effectclipId, effectType, parametersProyecto actualizado
remove_effectclipId, effectIdProyecto actualizado
set_speedclipId, speedProyecto actualizado (reproducción 0.1–10×)
set_volumeclipId, volumeProyecto actualizado (0–4, 1=normal)
set_transition`clipId, side: inout, type, duration?`

Historial

ComandoArgumentos
undo—
redo—

Tipos de Efecto

TipoParámetros
fade_induration (seg)
fade_outduration (seg)
color_gradebrightness (-1→1), contrast (0.5→2), saturation (0→3)
blurradius (px, por defecto 5)
sharpenamount (0→3, por defecto 1)

Tipos de Transición

crossfade · dip_to_black · wipe · slide


Conceptos Clave

  • inPoint = posición en el archivo fuente donde comienza la reproducción del clip
  • startTime = posición en la línea de tiempo donde se coloca el clip
  • duration = cuánto tiempo se reproduce el clip (puede ser más corto que el origen)
  • Cada mutación envía instantáneamente project:updated → la interfaz refleja los cambios en vivo
  • Los efectos se previsualizan en tiempo real (CSS) y se aplican mediante FFmpeg en la exportación

Reglas de Seguridad de Edición

  • Trata los espacios vacíos en la línea de tiempo como un error a menos que el usuario solicite explícitamente una pausa, un tiempo o un espacio negro.
  • Después de crear una secuencia o mover clips, verifica la continuidad con list_clips(sequenceId) y comprueba que cada clip comience exactamente cuando termina el clip anterior si la edición debe ser continua.
  • No asumas que create_sequence o activate_sequence es suficiente por sí solo. Siempre verifica la secuencia activa después con list_sequences o get_project.
  • Al construir un corte destacado con voz, mueve video, audio, subtítulos y marcadores juntos. No dejes subtítulos o marcadores en tiempos antiguos después de ajustar la edición.
  • Si la reproducción parece detenerse entre clips, inspecciona primero la línea de tiempo en busca de espacios vacíos antes de asumir que el reproductor de vista previa está roto.
  • Prefiere tiempos de inicio exactos sobre cálculos de desplazamiento acumulativos al ajustar un corte. Recalcula el startTime previsto de cada clip a partir del plan de corte.

Estética de Marca desde una URL

OBLIGATORIO — SIN EXCEPCIONES: Si el mensaje del usuario contiene alguna URL o dominio, DEBES ejecutar los comandos de obtención a continuación y extraer los tokens de marca antes de escribir cualquier código de lienzo/diseño. No uses colores de marca asumidos o memorizados. Obtén primero, diseña después — cada vez. Si la obtención falla, pide al usuario que pegue los valores hexadecimales; nunca recurras a adivinanzas.

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

Extrae: colores de fondo, colores de superficie, colores primarios/de acento, colores de texto, familias de fuentes, tamaños/pesos de fuente, radios de borde, espaciado y sombras de caja. También encuentra el logotipo — es la verdad fundamental para los colores de marca y el tono visual. Codifica esos valores exactos — nunca adivines cuando hay una URL real disponible.

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

Lienzo — Marcos de Física Matter.js

Usa canvas_run_matterjs para colocar una escena de física interactiva en vivo en el lienzo.

Herramientas MCP

HerramientaArgumentos
canvas_run_matterjsid? (id del marco a actualizar), name?, script (cadena 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}]}

Patrones de script — elige UNO

Patrón A — Autónomo (interfaces enriquecidas, dibujo 2D personalizado, bucle 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'); // ← usa siempre este; nunca crees uno nuevo
canvas.width = W; canvas.height = H;
const ctx = canvas.getContext('2d');
// ... agrega cuerpos, configura mouse ...
function loop() {
  Engine.update(engine, 1000/60);
  ctx.fillStyle = '#121212'; ctx.fillRect(0, 0, W, H);
  // dibuja con ctx
  requestAnimationFrame(loop);
}
loop();

Patrón B — Solo cuerpos (la plantilla gestiona engine/render/runner)

// engine, render, width, height y todas las variables de Matter ya están declaradas — NO las redeclares
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 y Render.run se llaman automáticamente después de que este script se ejecute — no los llames aquí

Reglas críticas

  • Runner.run necesita dos argumentos: Runner.run(Runner.create(), engine) — Runner.run(engine) con un solo argumento no hace nada en Matter.js 0.20.0
  • Nunca element: document.body en Render.create — genera un segundo canvas invisible; usa canvas: document.querySelector('canvas') en su lugar
  • Nunca declares const engine o let engine en el Patrón B — la plantilla ya tiene var engine; redeclarar con const/let causa un SyntaxError que deja el lienzo en blanco silenciosamente
  • Nunca llames a Render.run / Runner.run en el Patrón B — la plantilla lo hace después de que tu script se ejecuta; llamarlos dos veces causa velocidad duplicada o renderizado roto
  • Nunca importes o redeclares variables de Matter en el Patrón B — Engine, Bodies, Composite, etc. ya están desestructurados; const { Engine } = Matter dará un SyntaxError

Variables globales disponibles en el Patrón B

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

CLI

editorctl canvas-add-frame "Nombre" 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 — Composición de Video con React

Usa Remotion para generar activos de video animados (tarjetas de título, tercios inferiores, presentaciones de diapositivas, gráficos en movimiento) e importarlos directamente a la línea de tiempo.

Herramientas MCP

HerramientaArgumentosDevuelve
video_editor_list_remotion_compositions—Lista de IDs de composición
video_editor_render_remotioncompositionId, outputFilename?, props?, durationInFrames?, fps?{outputPath, assetId}

CLI

npm run remotion:studio                                          # vista previa en vivo en localhost:3000
npx remotion render remotion/src/index.ts <ID> out.mp4 --props '{"key":"value"}'

Composiciones incorporadas

IDProps
TitleCardtitle (str), subtitle? (str), backgroundColor, textColor, accentColor — 150 fotogramas @ 30fps
Slideshowimages (abs path[]), frameDuration (fotogramas), transitionDuration (fotogramas) — 300 fotogramas @ 30fps
HtmlInCanvasGlitchtitle, subtitle, glitchIntensity (0–40), backgroundColor, textColor, accentColor — 180 fotogramas @ 30fps. Glitch de división RGB mediante <HtmlInCanvas>

HTML en canvas (Remotion ≥ 4.0.455)

⚠️ Colisión de nombres — lee primero. El <HtmlInCanvas> de Remotion (esta sección) produce un archivo de video para la línea de tiempo. Los marcos HTML de Monet canvas (canvas-add-frame ... html, canvas_update_frame) producen una escena HTML en vivo en el tablero de la pestaña de lienzo. Sistemas diferentes. Elige por destino: línea de tiempo → Remotion; pestaña de lienzo → marco HTML de Monet. Nunca mezcles los dos en una misma tarea.

Usa <HtmlInCanvas> para dibujar un subárbol DOM en un <canvas> y posprocesarlo con Canvas 2D / WebGL / WebGPU. Ideal para glitch, lupa, CRT, desplazamiento, efectos de matiz.

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() // <-- siempre reaplica
}

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

Reglas:

  • Siempre reaplica el valor devuelto por drawElementImage a element.style.transform para que el diseño y la entrada sigan siendo correctos.
  • Nunca anides <HtmlInCanvas> dentro de otro — Chrome solo pinta el exterior y Remotion lanza un error. Combina los efectos en un solo onPaint.
  • Config.setChromiumOpenGlRenderer('angle') ya está configurado en

… [truncado para la traducción]

Skills relacionados