Communitygithub.com

gustavopascaner/motion

Guión a video de motion graphics con voz en off IA (argentina), subtítulos dinámicos, música de fondo y proyecto editable Premiere.

motion とは?

Motion es una skill de IA capaz de transformar cualquier guion (texto o archivo .txt/.md/.docx) en un video animado de aproximadamente 1 minuto, sin necesidad de cámara. Está diseñada para Claude Code, Codex y otras herramientas similares, ofreciendo un flujo completo: desde la selección de voz (Edge TTS o ElevenLabs, con acentos latinoamericanos) y marca (colores, tipografías, logo) hasta la generación de escenas animadas con subtítulos dinámicos, música de fondo de Envato y efectos de sonido sutiles. El resultado es un archivo MP4 final optimizado (−14 LUFS) acompañado de subtítulos SRT y un proyecto editable para Adobe Premiere (XML con pistas separadas), lo que permite refinamientos posteriores. La skill incluye un potente motor de dirección visual que aplica automáticamente criterios de ritmo, variedad y jerarquía de escenas, y soporta versiones iterativas (v2) reutilizando el directorio de trabajo para cambios parciales, reduciendo tiempos de re-renderizado.

対応✓Claude Code✓Codex CLI~Cursor
npx skills add gustavopascaner/motion

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

/motion — guión → video de motion graphics con voz en off

Entrada: un guión (texto pegado o archivo .txt/.md/.docx). No hay video de cámara: todo son escenas animadas a pantalla completa. Salida: <carpeta>/<NOMBRE>_MOTION/ con <NOMBRE>.mp4 (H.264 + AAC, −14 LUFS), <NOMBRE>.srt, <NOMBRE>_premiere.xml (proyecto editable), Assets/{Escenas,Subtitulos,Overlay,Voz,Musica,SFX}, LEEME.md y .work/ (persistente, permite hacer v2). Hablarle al usuario en español rioplatense (voseo). Avisar el avance entre pasos largos.

Rutas: SK = carpeta de esta skill (Claude Code: ~/.claude/skills/motion; Codex: ~/.codex/skills/motion). PY = el Python de la skill: $SK/.venv/bin/python -I (Windows: $SK\.venv\Scripts\python.exe -I). Usarlo para todos los scripts .py. Catálogo de escenas: $SK/reference/escenas.md · ejemplo completo: $SK/reference/ejemplo/ (script.json + story.js). Si doctor.py marca algo con ✗: bash $SK/scripts/install.sh (Windows: powershell -ExecutionPolicy Bypass -File $SK\scripts\install.ps1).

0 · Preguntas iniciales (SIEMPRE, antes de producir)

Leer primero el guión y $PY $SK/scripts/brand.py list (marcas guardadas). Después preguntar todo junto en una sola tanda (en Claude Code con la herramienta AskUserQuestion; en Codex u otros, un solo mensaje numerado). No preguntar lo que el usuario ya dijo.

  1. Voz — Mujer o Hombre. Por defecto argentina (edge-tts: es-AR-ElenaNeural / es-AR-TomasNeural). Si el usuario pide otro acento usar la voz de ese país (tts.py voices es lista todas: es-UY, es-MX, es-ES, es-CL, es-CO…). Si tiene ELEVENLABS_API_KEY y quiere más realismo, ofrecer ElevenLabs (tts.py voices eleven argentine).
  2. Marca — una de las guardadas (mostrarlas por nombre) o Marca nueva.
  3. Formato — Vertical 9:16 (Reels/TikTok/Shorts, por defecto) · Cuadrado 1:1 · 4:5 (feed) · Horizontal 16:9 (YouTube).
  4. Música — Enérgica (Upbeat 110–140 BPM) · Cálida/inspiradora (Medium 90–110) · Corporativa/tranquila · Tengo mi música (pedir la ruta).

Si es marca nueva, segunda tanda (también todo junto):

  • Nombre de la marca y logo (ruta a PNG/SVG, o "sin logo") y usuario de redes (ej. @consultorio). Si da logo: $PY $SK/scripts/brand.py colors <logo> y proponer la paleta a partir de esos colores.
  • Colores — opciones: Sacarlos del logo · Negro + naranja (editorial) · Azul profundo + celeste (salud/confianza) · Verde + crema (bienestar); o hex propios. Se necesitan 4: dark (fondo oscuro), light (fondo claro), accent (resaltado principal), accent2 (secundario, opcional).
  • Tipografías — brand.py fonts lista combinaciones: Editorial condensada · Moderna geométrica · Impacto · Elegante (o cualquier familia de Google Fonts por nombre).
  • Estilo — subtítulos sí/no (por defecto sí), decorado de fondo: grano + grilla + manchas de color (default) · anillos · puntos · limpio. Crear $SK/brands/<slug>/brand.json copiando brands/editorial/brand.json (en cada tipografía dejar solo family, weight, y para títulos upper/stretch/tracking/leading; para acento italic), poner logo con la ruta absoluta y correr $PY $SK/scripts/brand.py setup <slug> (baja las fuentes, copia el logo, chequea contraste: corregir los ⚠️). Mostrar la muestra: node $SK/scripts/render.js --brand-preview=<slug> --out=<work>/marca.jpg --format=<formato> → mirar la imagen y mostrársela al usuario; confirmar antes de seguir (es rápido de ajustar). La marca queda guardada para la próxima.

1 · Preparación

  • NOMBRE en MAYÚSCULAS_CON_GUIONES a partir del tema. Carpeta: la del archivo de guión, o el directorio de trabajo si lo pegó. work=<carpeta>/<NOMBRE>_MOTION/.work.
  • $PY $SK/scripts/timing.py start "<work>" (cronómetro) y $PY $SK/scripts/doctor.py.
  • config.json:
{ "name": "NOMBRE", "out_dir": "/abs/<carpeta>/NOMBRE_MOTION", "edit_dir": "/abs/<carpeta>/NOMBRE_MOTION",
  "format": "9:16", "fps": 30, "brand": "<slug>", "tail": 1.6, "keywords": ["palabra","clave"], "sfx_max": 6,
  "music": {} }

keywords = 3–6 palabras del guión que se resaltan en los subtítulos. Opcionales: "captions": false, "logo_corner": false.

2 · Guión → beats → voz

El guión es del usuario: no reescribir el contenido. Solo partirlo y ajustar la pronunciación.

  • Partir en beats (1 frase o idea, 2–6 s cada uno; 10–18 beats para 1 minuto). Cada beat suele ser una escena.
  • say (opcional) = cómo se pronuncia cuando el texto escrito confunde a la voz: números grandes ("70 %" → "setenta por ciento"), siglas ("OMS" → "o eme ese"), símbolos, años, abreviaturas. text queda como está escrito.
  • pause = silencio después del beat (default 0,38 s si termina en punto/pregunta, 0,18 s si no). Más pausa (0,6) antes de un remate o del CTA.
  • <work>/script.json: {"voice":{"engine":"edge","id":"es-AR-ElenaNeural","rate":"+5%"},"lead":0.35,"target":60,"beats":[{"id":"b01","text":"…"},…]}
  • $PY $SK/scripts/tts.py "<work>" → voice.wav + words.json (tiempo de cada palabra) y la duración. Duración objetivo ≈ 60 s:
    • más de 66 s → subir rate (máximo +15%); si igual se pasa, proponer recortes concretos al usuario y esperar respuesta.
    • más corta → está bien, no estirar el guión (se puede bajar rate hasta -5% si suena apurada).
  • Escuchar mentalmente el ritmo: si un beat queda muy largo (> 7 s), partirlo. Solo se regeneran los beats que cambian (caché).

3 · Música

  • Si el usuario dio música: "music": {"path": "/abs/tema.mp3", "offset": 0}.
  • Si no, Envato (siempre instrumental): $PY $SK/scripts/envato.py search "<work>" music "<estilo en inglés>" --mood <mood> --tempo "<tempo>" [--genre <género>]. Elegir por tono y por el perfil de energía (parejo, sin caídas largas en el primer minuto) y $PY $SK/scripts/envato.py use "<work>" music <búsqueda>#<n>. Poner offset (segundo donde entra la parte con energía; mirar el perfil ▁▂▃█).
  • Niveles automáticos en mix.py: más fuerte antes de la voz (intro −8 dB), baja debajo de la voz (bed −21 dB), sube en la cola (outro −10 dB) y fade final. Ajustables en config.music.
  • La vista previa de Envato tiene marca de agua: en la entrega avisar que hay que licenciarla. Con navegador con sesión de Envato: pedir confirmación una vez, licenciar con el nombre del video y descargar en WAV; si no, darle el link al usuario. Luego $PY $SK/scripts/envato.py collect "<work>" y volver a correr solo mix.py (no hace falta re-renderizar).

4 · Storyboard → <work>/story.js

Basarse en reference/escenas.md y reference/ejemplo/story.js. Una llamada S(tipo, inicio, params) por escena, en orden:

  • inicio: id de beat ('b03') o w('palabra') (arranca en esa palabra). La escena dura hasta que empieza la siguiente; la primera arranca en 0.
  • Dentro de params, todos los tiempos internos se sincronizan con la voz usando w('palabra') (o w('palabra', 1) para la 2ª aparición): ítems de lista, conteos, sellos, mensajes, botón del CTA.
  • Comunes a todas: bg ('dark'|'light'|'accent'|'accent2'; si se omite alterna solo), tr ('wipe'|'slide'|'circle'|'push'|'zoom'|'cut'; si se omite rota), cap:false (sin subtítulos), sfx (null = sin sonido · 'pop' · [['ding',1.2]]).
  • Helpers de texto: H('texto') = resaltado en caja de color · A('texto') = texto en color de acento.

Criterio de dirección (obligatorio):

  • Gancho en los primeros 2 s: question, bigword, kinetic o title fuerte, en fondo accent. El primer cambio de escena antes de los 3–4 s.
  • Ritmo: una escena cada 3–5 s (12–18 escenas por minuto). Nada quieto más de ~5 s: si la escena es larga, que se vaya armando (ítems sincronizados).
  • Variedad: no repetir el tipo de escena seguido; máximo 2 kinetic seguidas; alternar escenas de texto con gráficas (stat, bars, donut, icons, steps, compare, phone).
  • Mostrar, no repetir: el texto en pantalla son palabras clave, datos y estructura, no la frase entera (salvo kinetic/quote, que muestran la frase mientras se dice y apagan los subtítulos).
  • Datos → stat/bars/donut. Enumeraciones → list/steps/icons. Contrastes (mito/realidad, antes/después) → compare. Preguntas → question. Conversaciones/mensajes → phone. Remates → bigword. Fotos del usuario → image.
  • Cierre con cta (seguir / comentar una palabra / guardar / link) sincronizado con lo que dice el guión.
  • Textos cortos: títulos de 1–3 palabras por línea, ítems de ≤ 6 palabras.

5 · Plan, prueba y render

  1. node $SK/scripts/render.js "<work>" --plan → escenas con tiempos, SFX y avisos de Dirección. Corregir todos los ⚠️ y repetir.
  2. node $SK/scripts/render.js "<work>" --test --at=0.3,mid,end → <work>/sheet.jpg (3 cuadros por escena: entrando, a la mitad, armada). Mirar la hoja y corregir: textos que se achican de más (aviso "se achicó al N %"), cortes, superposiciones con los subtítulos, colores con poco contraste, escenas vacías a la mitad (el contenido tiene que aparecer rápido).
  3. Render final (en segundo plano, ~1 min por minuto de video): node $SK/scripts/render.js "<work>" → <work>/video.mp4.
  4. $PY $SK/scripts/mix.py "<work>" → <NOMBRE>.mp4 + <NOMBRE>.srt en out_dir.
  5. Proyecto para Premiere (por defecto siempre; saltear solo si config.premiere es false): node $SK/scripts/render.js "<work>" --premiere (en segundo plano, ~2–3 min) y $PY $SK/scripts/build_xml.py "<work>". Pistas: V1 escenas (una por clip, con la transición de entrada ya compuesta) · V2 subtítulos con alfa · V3 logo · A1 voz (una frase por clip) · A2 música con keyframes de volumen · A3+ SFX. Marcadores por escena.
  6. Mirar 3–4 cuadros del MP4 final (ffmpeg -ss <t> -i <mp4> -frames:v 1 x.jpg) para confirmar.

6 · Entrega

  • $PY $SK/scripts/timing.py report "<work>".
  • LEEME.md en out_dir: cómo abrirlo en Premiere (Archivo → Importar → <NOMBRE>_premiere.xml; no mover ni renombrar la carpeta; tabla de pistas; qué se edita ahí — cortar/mover/borrar escenas, re-timear frases de la voz, cambiar música y volúmenes, sacar SFX, usar el .srt como subtítulos nativos — y qué no: el texto dentro de cada gráfico, que se cambia pidiéndoselo a Claude), voz usada, marca, formato, duración, estructura (tabla escena → texto → tiempo), música (con envato.py report y si falta licenciar), SFX, tiempo de procesamiento, cómo pedir cambios.
  • Responder corto: ruta del MP4 y del XML, duración, voz y música elegidas (avisar si la música es vista previa sin licenciar), escenas destacadas, tiempo total.

Versiones (v2, ajustes)

Reusar .work: cambiar script.json (voz/texto: solo se regeneran los beats tocados) y/o story.js, apuntar out_dir a <NOMBRE>_MOTION_v2 y repetir desde el paso que corresponda (cambio de música o volumen → solo mix.py + build_xml.py; cambio visual → render + mix + render.js --premiere --only=<n.º de escena> + build_xml.py; cambio de texto → tts + todo). Cambiar un texto de un gráfico ya importado en Premiere: editar story.js y correr render.js --premiere --only=N (re-renderiza solo esa escena con el mismo nombre de archivo), el MP4 si se quiere, y avisar al usuario que en Premiere haga clic derecho en el clip → Reemplazar/Vincular medios (o cierre y reabra el proyecto) para ver el cambio. Si cambia la duración de la escena, regenerar el XML y reimportar. Escenas nuevas: agregarlas a engine/engine.html siguiendo escenas.md.

Notas técnicas

  • Capas para Premiere: escenas en ProRes 422 HQ (opacas); subtítulos y logo en ProRes 4444 con alfa. El audio en Premiere queda ~2 dB más bajo que el MP4 (el MP4 lleva una normalización final a −14 LUFS).
  • Motor: engine/engine.html renderizado cuadro a cuadro con Chrome (puppeteer-core) en paralelo, H.264 yuv420p. Todas las escenas son funciones puras del tiempo.
  • El contenido de cada escena se escala solo para entrar en el área segura (por formato) sin desbordar; si se achica mucho, avisa.
  • SFX: usa la librería de la skill edicion si está instalada (o assets/sfx propia con el mismo catalog.json); si no hay sonidos, sigue sin ellos.
  • Voz: edge-tts usa el servicio de voz de Microsoft Edge (requiere internet, sin clave). ElevenLabs: {"engine":"eleven","id":"<voice_id>"} + variable ELEVENLABS_API_KEY.
  • No usar rm -rf con globs relativos.

関連スキル