Video animado
Todo aquí se renderiza en remotion/ sin coste alguno. Dos niveles: prueba siempre el nivel 1 primero:
- Compón escenas integradas en un spec (minutos, sin código).
- Añade un nuevo tipo de escena al motor cuando una idea realmente lo necesite (código, probado y luego reutilizable por todos los agentes).
Antes de renderizar localmente: si falta remotion/node_modules, ejecuta cd remotion && npm ci
(el primer renderizado también descarga el Chrome sin interfaz de Remotion, ~170 MB, una sola vez).
Nivel 1 — el kit de escenas
escena (shots[].type) | mejor para | campos clave |
|---|---|---|
kinetic | el gancho, el remate | text, highlight, per_word (0.18) — las palabras aparecen una por una |
title | una sola línea en negrita | text ≤ 6 palabras, highlight |
number | una cifra impactante | value, prefix, suffix, decimals, caption, color — cuenta hacia arriba |
bars | cómo se comparan cosas en tamaño | title, unit, items[{label,value,color}] |
compare | ellos vs tú, mito vs realidad, antes/después | title, left{label,items,color}, right{…} |
list | "3 cosas", haz/no hagas | items, style tick/cross/number |
timeline | cómo sucedió | items[{year,text}] |
chat | una historia contada en mensajes | title (contacto), messages[{from: yo/ellos, text, at}] |
quote | una cita con fuente | text, by |
media | b-roll, una foto, el clip de IA | src, kenburns, headline, fit |
Cada escena acepta label (kicker), stamp (número de sello de goma), bg (foto/video atenuado detrás, con credit) y transition (fade por defecto, cut, slide, zoom, wipe). Las superposiciones (headline, textover, lowerthird, stamp) se colocan sobre cualquier escena. Referencia completa: remotion/SPEC.md.
Un ejemplo práctico de cada nueva escena: remotion/examples/animated.json.
Recetas
- Explicador sin rostro (20–40 s): gancho
kinetic→number→bars/compare→list→ título de remate que repite el gancho. Voz en off comoaudio, subtítulos desdewords, una cama musical suave a 0.08–0.12. - Historia de mensajes de texto: gancho
kinetic("Ella respondió a las 3am") → unchatpor intercambio (atespaciado 0.8–1.4 s, sincronizado con la narración) → giro contitle. Mantén cada burbuja ≤ 10 palabras. - Inserción animada en un video hablado: CLIP_1 …
numberocomparedurante 2–3 s en el golpe que lo dice (transition: "zoom") … de vuelta a CLIP_1 constartconfigurado donde se reanuda el clip. - Mito vs realidad:
compareconleft.color: "danger",right.color: "good", luego unstamp"FALSO" en el siguientetitle.
Planifica los ritmos con video-script (tools/beats.mjs ajusta las escenas a la voz), luego:
cd remotion
node render.mjs job/spec.json --validate
node render.mjs job/spec.json job/final.mp4 --preview job/check.jpg --at 0.1,<mitad de cada escena>,<final-1>
Mira siempre la tira de preview antes de entregar: gancho completamente dibujado a los 0.1 s, nada cortado en los bordes, sin texto superpuesto, color de acento legible, etiqueta generada por IA y marca de agua presentes.
Reglas de estilo
- Marca desde
settings.brand(especificacióntheme): un color de acento, usado para la única cosa que importa en cada escena. - ≤ 7 palabras por titular, ≤ 12 por superposición de texto, ≤ 4 elementos por columna de lista/comparación (la pantalla del teléfono es pequeña).
- Una escena permanece al menos 1.5 s por línea de texto en ella.
- Los números deben coincidir con
citations; nunca animes una cifra que no hayas referenciado. - Sin logotipos de marca, sin fotos de personas reales, sin capturas de chats reales.
Nivel 2 — un nuevo tipo de escena
Solo cuando ninguna combinación anterior pueda mostrar la idea (por ejemplo, una ruta en un mapa, un anillo de progreso, una reacción en pantalla dividida).
src/types.ts: añadeXShot = ShotBase & { type: "x"; … }y agrégalo a la uniónShot.src/shots/Shots.tsx: escribe el componente junto a los demás — anima conspring/interpolatedesdeuseCurrentFrame()(nunca animaciones CSS niMath.random: los renderizados deben ser deterministas), usat.font,t.accent,tone(t, color), tamaño para 1080×1920, luego añade unif (s.type === "x") body = …enShotView. Si está en pantalla en el segundo 0 (base === 0) dibújalo completamente sin entrada.render.mjs: añade"x"atypesy validación para sus campos obligatorios (el agente verificador se basa en estos mensajes).SPEC.md+ la tabla anterior: documéntalo. Añádelo aexamples/animated.json.- Prueba:
npx tsc --noEmit -p .,node render.mjs examples/animated.json out/animated.mp4 --preview out/animated.jpg --at …y míralo.