What does motion do?
Motion graphics escritos como código: cada color, tiempo y margen sale de un archivo de marca, y nada se renderiza sin que la persona haya visto antes 2 o 3 fotogramas. Las reglas de abajo salen de correcciones reales; cada una dice por qué existe.
Para qué sirve
| Pieza | Qué es |
|---|---|
| Broll animado | Cubre un tramo de voz con una escena o un gráfico, a pantalla completa |
| Alfa | Gráfico con transparencia que va encima del vídeo, o detrás de la persona |
| Pop-up | Un dato que entra, se lee en algo más de 1 s y se va |
| Subtítulos | Sin caja y con una palabra destacada, o cinéticos (solo palabras clave) |
| Simulacro de chat | Una conversación de una app de mensajería, creíble y legible |
| Pantalla | Una web o una app de escritorio en una tarjeta 4:3 con titular |
| Portada | El fotograma 0 del reel |
Antes de maquetar, decide cuál de las dos formas es:
- Enseña datos o un producto por dentro (panel, métricas, bandeja): interfaz plana y densa, todo legible a la vez, fotos y vídeo reales dentro de las tarjetas, cámara casi quieta (escala 1,00 → 1,02). Los estados cambian en su sitio: la fila ya estaba y su etiqueta cambia. El cuadro, lleno.
- Cuenta una escena: manda el metraje. Toma grande, cámara que se mueve de verdad, poco adorno y una sola frase.
Un diagrama no es una pieza: si la idea se puede dibujar como un mapa de flechas, enseña el producto haciendo eso mismo.
Preparación
- Un proyecto de Remotion (
npx create-video@latest), Node y ffmpeg. - La marca en código en
src/marca/:tokens.ts(colores, tipos, radios, márgenes),movimiento.ts(tiempos y curva) y unuseMarca()que lo entrega todo escalado. Cómo se arma, con un ejemplo: referencias/tokens.md. - Una entrada por pieza (
src/piezas/<pieza>.tsx, con suregisterRooty susComposition): el bundle queda pequeño y una pieza no rompe otra. - Lienzo de 1080×1920 a 30 fps, salvo que la secuencia diga otra cosa: lee el tamaño y los fps de la secuencia antes de empezar.
El flujo
- Brief. Tramo exacto en la secuencia (entrada → salida), lo que dice la voz en ese tramo, datos permitidos y su fuente, material que se puede usar y lo que no quiere. Si falta algo, pregúntalo.
- Voz. Transcribe por palabra la voz tal como está en la línea de tiempo, no el archivo crudo (referencias/subtitulos.md). La voz real de un rodaje suele diferir del guion.
- Duración. La del tramo, en una constante con el timecode en el comentario, más 1 fotograma de colchón:
export const DURACION = 157; // 00:00:51:22 → 00:00:56:29. - Diseño. Lo que se ve es lo que dice la voz, frase a frase. Los instantes que comparten animación y sonido (cada mensaje que entra, cada golpe) van en una constante que leen la composición y el script de efectos.
- Boceto. 2 o 3 fotogramas clave con
remotion still, con las guías de zonas seguras pintadas. Enséñalos y espera el sí. - Render con fondo o con alfa (abajo).
- Sonido. Toda animación se entrega con su efecto de sonido: pasa los instantes a la skill
sonido. - Control y entrega (al final de esta página).
Lo que no se rompe
- Ningún color ni medida a mano en una composición: todo sale de los tokens. Por qué: cambiar un tono es tocar un archivo, y nadie inventa un gris nuevo en cada pieza.
- Una sola cosa destacada por cuadro, con el color de acento de tu marca: una palabra del titular o un botón, nunca los dos. Por qué: si dos cosas gritan, no se lee ninguna. (Los colores propios de una interfaz simulada no cuentan.)
- Nada rebota. Entradas y salidas con los tiempos y la curva de los tokens; nada de
spring(). Por qué:spring()se pasa y vuelve, y eso se lee como juguete. - Tiempos en segundos, nunca en fotogramas. Por qué: con retrasos en fotogramas, pasar de 30 a 60 fps duplica la velocidad.
- Zonas seguras, con aire (tabla de números). Lo que se lee va a ~100 px de los lados y a ~290 del techo: 54 y 224 son la raya que no se pisa, no donde se apoya el diseño. Por qué: la interfaz de la app tapa los bordes, y pegado al límite «se ve todo muy a los extremos».
- El centro de la composición, en x 540. No se corre el diseño para esquivar los botones de la app: lo que cae a esa altura se estrecha de forma simétrica. Por qué: una composición corrida se nota más que un icono encima.
- Cada objeto entero dentro del cuadro. Nada cortado por el borde; lo que no protagoniza el plano se aparta con un fundido. Por qué: un teléfono o una tarjeta cortados se leen como error.
- En un broll pasa algo: la cámara se mueve y ocurre una acción concreta que es la frase de la voz, no el tema. Por qué: «no pasa nada» es el rechazo más común. La excepción es el producto real de un cliente: se reproduce, no se recrea ni se le inventan movimientos.
- Algo nuevo cada 4 s como mucho, y nunca dos movimientos iguales seguidos. Por qué: dos acercamientos pegados borran el corte.
- Nada quieto al final: un empuje lentísimo en el último tramo. Por qué: un plano congelado se lee como un error de render.
- Un número que sube es un gráfico; uno que aparece es un rótulo. En un alfa, cada cifra lleva su objeto animado (contador, medidor, barra, icono que actúa) y el texto acompaña. Por qué: un texto plano sobre el vídeo se lee como subtítulo.
- Plano secuencia, profundidad y detalle. Una cámara que recorre la escena en vez de entradas sueltas, objetos a distinta profundidad, nombres, horas y estados en cada elemento. Por qué: las piezas que eran diagramas con mucho blanco se rechazaron por «muy simples».
- Subtítulos sin caja, una palabra destacada por oración; nunca sobre un broll ni donde un gráfico ya dice lo mismo (referencias/subtitulos.md).
- Chat simulado legible: teléfono al centro, la app entera ampliada por igual, un mensaje a la vez con tiempo para leer; para destacar, se desenfoca el resto, nunca un velo oscuro (referencias/alfas-y-chats.md).
- Una pantalla real en el plano manda: nada encima de su texto ni de su cabecera; el pop-up va en su zona vacía.
- Sin bordes negros ni filos duros: si la cámara se mueve sobre metraje, escala mínima 1,04 (1,18 si el plano se desplaza de lado); degradados de pasos suaves y esquinas redondeadas. Por qué: un zoom out que enseña negro, o un degradado a saltos, se lee como un recuadro.
- No se inventan datos ni se repiten piezas. Cifras, nombres y capturas salen de la persona; un simulacro nunca enseña datos de clientes reales. Cada pieza trae su propio gráfico: repetir el de otra se nota.
- Las animaciones se ajustan a la voz, nunca al revés: no se meten pausas en la voz para cuadrar un gráfico.
- Una corrección no se renderiza entera: solo los tramos que cambian, empalmados y con nombre nuevo (referencias/3d-y-trampas.md). Por qué: la versión ya colocada no se pisa, y no se pierde una hora de render por tres segundos.
Números
| Qué | Valor (lienzo de 1080×1920) |
|---|---|
| Laterales | 54 px a cada lado (lo que se lee, a ~100) |
| Techo | nada que leer por encima de y 224 (lo que se lee, desde ~290) |
| Franja de lectura | de y 420 a y 1495 |
| Columna de botones | desde x 897, de y 1228 hacia abajo; a esa altura, lo que se lee va dentro de x 183–897 |
| Cifra grande y ancha | entera por encima de y 1228 |
| Teléfono en plano detalle | como mucho 0,8 del ancho del cuadro |
| Conjunto en plano abierto | como mucho 1080 − 2 × 54 de ancho |
| Pop-up | algo más de 1 s en pantalla, y se va (si se quedan, a los 8 s hay seis y no se lee ninguno) |
| Ritmo | algo nuevo cada 4 s o menos |
| Escala mínima con cámara sobre metraje | 1,04 (1,18 con desplazamiento lateral) |
| Relleno de una pieza de datos | cerca del 75 % de la caja útil; por debajo del 50 % se lee como boceto |
| Relleno de una pieza de escena | 40–60 % |
| Recortes de portada | 4:5 del feed: y 285–1635 · 3:4 del perfil: y 240–1680 |
El relleno es la parte de la caja útil ocupada por algo que no es fondo; se mide sobre los stills, no a ojo.
Render
# Boceto: un fotograma suelto
npx remotion still src/piezas/mi-pieza.tsx MiPieza out/boceto_f45.png --frame=45
# Con fondo (opaco: tapa el plano)
npx remotion render src/piezas/mi-pieza.tsx MiPieza out/mi-pieza_FONDO.mov \
--codec=prores --prores-profile=4444 --pixel-format=yuv444p10le
# Con alfa (transparente: se ve el vídeo de debajo)
npx remotion render src/piezas/mi-pieza.tsx MiPieza-Alfa out/mi-pieza_ALFA.mov \
--codec=prores --prores-profile=4444 --pixel-format=yuva444p10le --image-format=png
# Toda pieza con 3D (CSS o three.js), en still y en render: --gl=angle
- Fondo y alfa son la misma composición con una prop
transparente; la versión en alfa no pinta lienzo y su id acaba en-Alfa. --prores-profile=4444solo no da alfa. Compruébalo:ffprobe -v error -select_streams v:0 -show_entries stream=pix_fmt -of csv=p=0 out/mi-pieza_ALFA.movtiene que empezar poryuva.- En alfa no hay lienzo: cada texto necesita su propia superficie o desaparece sobre metraje oscuro.
- Si el disco va justo: el ProRes 4444 con alfa ocupa ~1,35 GB por minuto a 1080. Pasarlo a PNG dentro de MOV (
ffmpeg -i x.mov -c:v png -pix_fmt rgba y.mov) es sin pérdida, conserva el alfa y pesa unas 7,5 veces menos. - Interfaces con perspectiva que salen con el texto blando: render con
--scale=2y bajar a 1080 con lanczos. - Para varios stills, un script que hace un solo bundle y lo borra al acabar (referencias/3d-y-trampas.md).
Portada en el fotograma 0
- La portada es el primer fotograma del reel exportado:
<Sequence durationInFrames={1}>con la portada y el reel entero en<Sequence from={1}>. Las plataformas eligen la portada entre los fotogramas del vídeo; así no queda un archivo suelto. Si el selector no atina con el 0, dale dos fotogramas. - Personaje al centro: eje en x 540, su centro cerca de y 900–960, y entero dentro del 4:5 y del 3:4, con el titular también dentro. Por qué: la cuadrícula del perfil y el feed recortan la portada, y en la miniatura se decide el clic.
- Nada de decoración grande en las esquinas. Antes de entregar, saca una versión con los recortes simulados (velo fuera del 4:5, líneas del 3:4 y eje central) y mírala.
- Si la portada se pega con ffmpeg desde un JPG, ojo con el rango de color (referencias/3d-y-trampas.md).
Estilo «liquid glass» (opcional)
Cristal tipo iOS para tarjetas y botones, sobre fondo claro. Funciona si hay algo que refractar, una sola luz para toda la escena y cosas vivas dentro; si no, «parece un folleto». Reglas y números en referencias/cristal.md, que también explica cómo tapar texto quemado en el metraje. Ningún estilo es para siempre: cada pieza trae algo que las anteriores no tenían.
Trampas que más cuestan
- Vídeo congelado: un
<OffthreadVideo>que entra después del fotograma 0 va dentro de<Sequence from={entrada} layout="none">. Si no, pide el tiempo desde el 0 de la composición y se queda quieto en su último fotograma, sin dar error. Comprueba questartFrom + duración visible ≤ duración del clip. - Primer fotograma negro en three.js con postproceso: el compositor tiene que pedir
delayRendery dibujar antes de soltarlo. Unremotion stillsuelto es la prueba. - 3D cortado en recto (medio teléfono en blanco): falta
--gl=angle. - Copias fantasma del texto con desenfoque de movimiento a 29,97 fps: el desenfoque, solo en las ventanas en que la cámara barre.
- Disco lleno: cada bundle copia
public/a la carpeta temporal del sistema; si no se borra, se acumula (en un caso real, cientos de GB). Miradf -hantes de renders largos. defaultPropsse mezclan con las props de cada render: en los defaults, solo lo obligatorio.
El resto (aparejo 3D en CSS, three.js, empalmes, ffmpeg, zsh): referencias/3d-y-trampas.md.
Qué se entrega y qué se verifica
Se entrega: el .mov (FONDO o ALFA) con la duración exacta del tramo y su efecto de sonido dentro o al lado, los stills de boceto aprobados y una línea en pieza.md con lo hecho y lo pendiente.
Se verifica, midiendo:
- Duración y fps iguales a la secuencia. Cuenta paquetes (
ffprobe -v error -count_packets -show_entries stream=nb_read_packets -of csv=p=0 x.mov): en ProRes,nb_framesmiente. - Alfa de verdad:
pix_fmtempieza poryuva. - Nada fuera de las zonas seguras: guías pintadas sobre los stills de los momentos clave y la tinta medida en la banda del texto (x mínima ≥ 54, x máxima ≤ 1026).
- Una sola cosa destacada por cuadro.
- Ningún vídeo congelado ni fotograma negro: reprodúcelo, no te quedes en los stills.
- Fotograma a fotograma donde entra un mensaje o barre la cámara: ni saltos ni fantasmas.
- El último fotograma, completo y con algo en movimiento.
-
npm run lint(eslint + tsc) pasa, y no hay un#hexsuelto fuera de los tokens.