Morph Edit (B-roll animado)
Creas clips de gráficos animados para el video de un creador. Cada clip es una sola forma que nunca corta: transforma su tamaño, esquinas y color de un estado a otro, mientras su contenido se intercambia con un breve desenfoque. Un cursor impulsa los cambios con clics y arrastros reales, y cada cambio coincide con una palabra hablada.
El resultado es un conjunto de clips que el creador puede insertar en su editor. También entregas una vista previa renderizada de su video con los clips insertados, y dos páginas HTML: una para recorrer los clips, otra para comparar antes y después.
Todo lo necesario está en esta carpeta de habilidad:
engine/: el motor de movimiento (motion.js), la estructura de página (base.css),build.py(clip → HTML autocontenido),render.js(renderizado fotograma a fotograma con desenfoque de movimiento),beats.js(hojas de contactos de fotogramas fijos), fuentes (Geist, OFL).scripts/:setup.sh,inspect_video.py,words.py,composite.py,make_pages.py.reference/engine-api.md: cómo escribir un clip. Léelo antes de escribir tu primer clip.examples/opus-aoe2/: seis clips completos para un video real de 54 segundos. Úsalos como referencia de calidad y como punto de partida.
A continuación, $SKILL significa la carpeta de esta habilidad. Trabaja en una carpeta motion/ dentro del proyecto del usuario.
1. Configuración (solo la primera vez)
bash $SKILL/scripts/setup.sh ./motion
Esto verifica que Node, Python 3 y ffmpeg estén instalados, e instala Playwright + Chromium en motion/node_modules. Ejecuta todos los scripts del motor con NODE_PATH=./motion/node_modules.
2. Entrevista
Usa la herramienta AskUserQuestion; mantenla a una sola ronda. Necesitas:
- El video. Una ruta. Cópialo o refiérelo como
motion/work/source.*. - La transcripción. Opcional. Si no hay (o solo texto plano), transcribe el audio con
scripts/transcribe.py(ver paso 3). Esto proporciona marcas de tiempo reales de las palabras, que son más precisas que las estimaciones SRT. - Densidad:
- Ligera: 2–4 clips por minuto, solo los momentos más fuertes.
- Media (predeterminada): 4–7 por minuto.
- Alta: la mayoría de las líneas cubiertas, con breves espacios de rostro.
- Estilo:
- La paleta predeterminada: lienzo gris cálido, componentes en blanco y negro, un acento naranja.
- O su marca: colores y, opcionalmente, una fuente. Pídeles que coloquen un logotipo, capturas de pantalla o colores de marca en
motion/inputs/, y léelos.
- Algo que evitar o incluir. Líneas que dejar en el rostro, números o nombres reales que mostrar, capturas de pantalla de productos que recrear.
Omite cualquier pregunta que el usuario ya haya respondido.
3. Inspeccionar el metraje
python3 $SKILL/scripts/inspect_video.py motion/work/source.mp4 motion/work
python3 $SKILL/scripts/words.py transcript.srt > motion/work/words.txt
# sin transcripción (o quieres tiempos exactos de palabras): transcribe el audio en su lugar
motion/.venv/bin/python $SKILL/scripts/transcribe.py motion/work/source.mp4 motion/work
transcribe.py escribe words.txt y transcript.srt. Muestra al usuario la transcripción para que puedan corregir nombres o términos malinterpretados antes de la planificación.
Mira motion/work/contact.png tú mismo. video.json proporciona la resolución, fps y secciones de diseño:
- full: el hablante llena el encuadre.
- pip: el hablante está en un recuadro y el resto está vacío. Incluye la posición del recuadro y una advertencia si el recuadro cambia de tamaño o se mueve.
Los clips deben coincidir con la resolución y fps del video. Los tiempos de palabras de un SRT son estimaciones (±0.2s); trátalos como tales.
4. Planificar y obtener aprobación antes de escribir código
Muestra una tabla con una fila por clip:
| # | Entrada–Salida | La línea que cubre | Qué hace la forma, en qué palabras | Tratamiento | Por qué |
Dirección creativa: decide cuánto del encuadre ocupa cada clip. Esta es la decisión más importante; tómala por clip y da la razón.
- Corte de cámara a pantalla completa. El encuadre es solo el hablante, y la línea describe algo que ver: un producto, un proceso, una comparación, un número, un cambio de capítulo.
- Corta durante la duración de la idea (3–10 s), luego vuelve al rostro.
- No cortes en el primer segundo del gancho ni en líneas personales, emocionales o de opinión.
- Deja al menos ~2 s de rostro entre cortes.
- Panel en el espacio vacío. La edición ya deja espacio: un recuadro PiP, una división, una región simple.
- Renderiza un clip transparente (
bg:null) centrado en el área vacía, con un tamaño que se mantenga alejado del recuadro del hablante en todo momento. - Puede durar mucho (15 s+) como una sola transformación continua, porque el hablante permanece en pantalla.
- Si
inspect_video.pyinforma que el recuadro cambia, pregunta si es intencionado, luego dimensiona para el recuadro más grande o divide el panel en el cambio.
- Renderiza un clip transparente (
- Nada. La línea trata sobre el hablante, o está demasiado cerca de otro clip.
Reglas de contenido:
- Muestra objetos reales del tema: la carpeta, la terminal, el archivo, el producto, el resultado. Extráelos de las palabras. Asigna cada idea a una interacción del vocabulario en
reference/engine-api.md(píldora + clic, progreso, verificación, isla de estado, tarjeta con arrastre, control deslizante, alternador, pestañas, gráfico + información sobre herramientas, búsqueda/filtro, arrastrar y soltar archivos, escritura en terminal, comparación lado a lado, tarjeta de capítulo). - Nunca inventes números, citas, precios o resultados. Usa barras relativas, líneas de texto esqueleto o etiquetas tomadas de la transcripción, y enumera lo que es ilustrativo. Pon cifras reales solo cuando el usuario las proporcione.
- Una idea por clip. Un tramo continuo (una sección PiP completa) puede ser un clip largo con varios estados.
- Ritmo al habla, no a la música: un cambio por compás hablado, con aproximadamente 0.4–1.2 s de separación.
Espera a que el usuario apruebe o edite el plan.
5. Construir
Escribe un fragmento por clip en motion/clips/NN-nombre.html, siguiendo reference/engine-api.md y los ejemplos. Luego construye:
python3 $SKILL/engine/build.py motion/dist motion/clips/*.html
Coloca cada cambio de estado en su palabra: tiempo local del clip = tiempo de la palabra − punto de entrada del clip.
6. Verificar fotogramas fijos en las palabras clave
NODE_PATH=./motion/node_modules node $SKILL/engine/beats.js motion/dist/NN-nombre.html motion/work/NN.png 0.4 1.2 2.1 …
Elige los momentos en que cada estado se ha estabilizado y un par de momentos de transformación intermedia. Mira cada hoja tú mismo. Corrige cualquier cosa apretada, recortada, ilegible o desfasada, o donde el cursor salga del encuadre. Luego verifica una vez más. Los clips de panel se renderizan sobre negro en la hoja para que puedas evaluarlos.
7. Renderizar
NODE_PATH=./motion/node_modules node $SKILL/engine/render.js motion/dist/NN-nombre.html motion/out/NN-nombre_0m32s40.mp4 30000/1001
- Usa los fps del video.
- Los clips de panel (
bg:null) deben escribirse en.mov, que da ProRes 4444 con canal alfa. - Nombra cada archivo por su punto de entrada en la línea de tiempo (
0m32s40= 0:32.40). - El renderizado toma 4 subfotogramas por fotograma, por lo que es más lento que el tiempo real. Ejecuta dos clips en paralelo en una máquina multinúcleo.
8. Entregar
Escribe motion/plan.json (esquema en reference/engine-api.md). Para efectos de sonido de interfaz de usuario, da a cada clip una lista "sfx": [[tiempo local del clip, tipo], …] tomada de sus señales: click y toggle en clics del cursor, pickup/drop en inicio/fin de arrastre, whoosh en transformaciones de forma, pop en la introducción y placas, rise/fall en barras, type en escritura, tick en elementos que aparecen, shutter en capturas de pantalla, y success en verificaciones. Luego:
python3 $SKILL/scripts/composite.py motion/plan.json motion/out/preview.mp4
python3 $SKILL/scripts/sfx.py motion/plan.json motion/out/preview.mp4 # Efectos de sonido de UI, si el usuario los quiere
python3 $SKILL/scripts/make_pages.py motion/plan.json motion/out/preview.mp4
python3 $SKILL/scripts/make_gallery.py motion/plan.json motion/out/preview.mp4
El usuario recibe, todo en motion/out/:
- los clips
TIMING.md: archivo, entrada, salida, la línea que cubre, el tratamiento, y qué es ilustrativopreview.mp4: su video con los clips insertados, cortes directos, audio original (más SFX cuando se usan)sfx/: los efectos de sonido de cada clip como WAV separados, para mezclar en su editorindex.html: todos los clips reproduciéndose a la vez en una cuadrícula, con la vista previa completa y enlaces a las otras páginas (abre esta primero)viewer.html: recorre los clipscompare.html: original vs vista previa, sincronizados, lado a lado, apilados o con barrido
Di claramente que la vista previa es para revisión: para el corte final, colocan los clips en su propio editor, donde pueden ajustar la sincronización, agregar transiciones y mezclar audio.
Tarjetas de suscripción (opcional)
Pregunta al creador si quiere una tarjeta final de suscripción en su línea de llamada a la acción y uno o dos recordatorios cortos. Las plantillas son fragmentos de clip en $SKILL/templates/subscribe/ (end-card.html, reminder.html). Copia uno en motion/clips/, luego:
- Reemplaza
__CHANNEL__,__HANDLE__y__AVATAR__(el logotipo o foto del creador como una URI de datos; sin imagen, usa una letra en el círculo). Pregunta por estos; nunca adivines un nombre o identificador. - Vuelve a sincronizar las constantes al principio del
<script>(IN, los tiempos de clic,T) con las propias palabras del creador. La tarjeta final hace clic en Compartir, Suscribirse, Campana, Me gusta y Comentar en las palabras que el creador dice; el recordatorio hace clic en Suscribirse y Campana. - Construye, verifica fotogramas fijos, renderiza y agrega a
plan.jsoncomo cualquier otro clip. Renderiza la tarjeta como un panel.movtransparente para que se superponga al metraje.
Subtítulos (opcional)
Crea un SRT en el idioma hablado y un SRT en inglés, para subir como subtítulos opcionales (no quemados). Trabaja en motion/work/cap/:
motion/.venv/bin/python $SKILL/scripts/captions/find_gaps.py motion/work/words.txt "<video>": Whisper puede omitir tramos enteros de habla en videos largos. Imprime los huecos; vuelve a transcribirlos conretx.py "<video>" "<lista de huecos>" motion/work/gapwords.json [idioma].python3 $SKILL/scripts/captions/make_cues.py motion/work/words.txt motion/work/gapwords.json motion/work/capescribe las señales y cuatro fragmentos.- Traduce los fragmentos en paralelo (cuatro subagentes, uno por fragmento) usando
templates/caption_brief.md. Cada uno escribeout1..4.jsoncon{"i","orig","en"}para cada señal. - Corrige las señales marcadas, luego
python3 $SKILL/scripts/captions/build_srt.py motion/work/cap motion/out/captionsescribecaptions_original.srtycaptions_english.srt(dos líneas equilibradas, hasta 42 caracteres cada una). - Indica al creador que pruebe el SRT en VLC o en una subida no listada antes de publicar.
Valores predeterminados de estilo
La marca del usuario anula estos valores.
- Color: lienzo
#E9E7E2, tinta#0B0B0B, componentes blancos, un acento#FF5A1F. Los clips de panel sobre metraje oscuro usan formas claras (#F4F2EE). - Tipografía e iconos: Geist para texto de UI, Geist Mono para código, nombres de archivo y terminales. Un conjunto de iconos con un solo grosor de trazo (
M.icon). - Movimiento: muelles con un mínimo de sobreimpulso como máximo. Los bordes delanteros y traseros se mueven con diferentes muelles para que los indicadores se estiren. La cámara hace zoom para que cada estado llene el encuadre.
- Prohibido: animaciones rebotantes, partículas, brillos, degradados en el cromo de la interfaz de usuario, trazos de iconos mixtos, tiempo muerto, cualquier cosa que parezca una plantilla, datos inventados.
Errores comunes
- Nunca pongas
will-changeen nada que la cámara escale; el texto se renderiza borroso. - El intercambio de texto dentro de un contenedor en transformación necesita su propia sincronización de entrada y salida (
M.visdin/lin/lout), o el texto antiguo y el nuevo se superponen. - Las etiquetas con
mix-blend-mode: differencedeben estar en una capa que tenga el modo de mezcla en sí misma. Un padre filtrado las aísla. - Los elementos que se deslizan bajo un resaltado necesitan resortes
M.FAST, o la fila resaltada queda vacía por un momento. - Mantén el cursor dentro del encuadre en cada zoom de cámara, incluso durante las transformaciones.
- Las estimaciones de palabras de un SRT se desvían dentro de una señal; cuando sea posible, coloca los cambios importantes en la primera o última palabra de una señal.
- Un clip termina manteniendo su último estado; la composición mantiene el último fotograma si su ranura es más larga.