🎬 Sequence from= — el offset de tiempo
La prop from de la Sequence es simple: indica en qué frame del video este bloque empieza a existir. Antes de ese frame, el componente hijo simplemente no se renderiza. Después, el frame local empieza en cero, como si el reloj se reiniciara para ese elemento.
🎯 La idea central
Dentro de una Sequence, useCurrentFrame() devuelve 0 en el frame from, 1 en el frame from+1, y así sucesivamente. Esto significa que las animaciones dentro de Sequences son siempre relativas a su inicio — no al inicio del video.
- •El elemento secundario no existe antes del frame
from— no se renderiza ni ocupa espacio. - •El frame local dentro de Sequence siempre empieza en 0.
- •Combinar con
durationInFramestambién limita el fin de la existencia.
import { Sequence, useCurrentFrame, spring, useVideoConfig } from "remotion"; export const StaggedEntry = () => { const { fps } = useVideoConfig(); return ( <> {/* Título aparece imediatamente */} <Sequence from={0}> <Title /> </Sequence> {/* Subtítulo entra 15 frames depois */} <Sequence from={15}> <Subtitle /> </Sequence> {/* Lista entra após 30 frames */} <Sequence from={30}> <ItemList /> </Sequence> </> ); };
💡 Consejo práctico
Arrastra la barra de tiempo de Remotion Studio hasta el frame 14: Subtitle aún no existe. Ve al 15: aparece. Este control visual directo es la mejor manera de calibrar tus offsets.
🪜 Stagger con index * N
El patrón de stagger es el más común en listas, menús y grids animados: cada elemento recibe un from basado en su índice multiplicado por una constante N. El resultado es la sensación de «cascada»: los elementos entran uno después del otro de forma natural.
✓ Qué HACER
- ✓Usar
from={index * N}donde N = 4 a 8 frames. - ✓Combinar con spring() local para cada entrada suave.
- ✓Usar valores pequeños de N para listas largas (evitar una espera larga).
✗ Qué NO hacer
- ✗Un N demasiado grande (>15) hace que la lista tarde demasiado en completarse.
- ✗Stagger en elementos que el espectador no sigue en orden.
- ✗Olvidar sumar el offset a
fromdel grupo padre.
const items = ["React", "Remotion", "TypeScript", "Vite"]; const STAGGER = 6; // frames entre cada entrada return ( <> {items.map((item, index) => ( <Sequence key={item} from={index * STAGGER}> <AnimatedItem text={item} /> </Sequence> ))} </> ); // Dentro de AnimatedItem: const frame = useCurrentFrame(); // começa em 0 para cada item const { fps } = useVideoConfig(); const scale = spring({ frame, fps, config: { damping: 14 } }); const opacity = interpolate(frame, [0, 8], [0, 1], { extrapolateRight: "clamp" });
🔗 Sincronizar el final con el inicio — overlap
Una de las técnicas de timing más eficaces es hacer que el elemento B empiece mientras la A todavía está saliendo. Esta superposición intencional elimina el «hueco» de pantalla vacía y dirige suavemente la atención del espectador de un elemento al otro.
Calcula el from del elemento A
Ej.: TITLE_START = 0, TITLE_DUR = 60 (frames durante los que el título queda visible).
Define el overlap deseado
Por lo general, 8–12 frames. Un overlap demasiado largo crea confusión; demasiado corto no genera fluidez.
Deriva el from de B
LIST_START = TITLE_START + TITLE_DUR - OVERLAP — B empieza antes de que A termine.
Prueba en Studio
Arrastra el playhead por los frames del overlap y verifica que ninguno de los dos elementos "compita" visualmente: uno debe dominar.
💡 Consejo práctico
Si el elemento A tiene un fade-out animado (opacidad 1→0 en los últimos 10 frames), activa B exactamente cuando A empieza ese fade. El espectador percibe la transición, pero no siente el corte.
🧮 Constantes con nombre — sin magic numbers
Un código de timing limpio declara todos los offsets como constantes con nombre al inicio del componente. Así, cuando necesitas ajustar «el título tarda un poco más», solo cambias TITLE_DUR — y todos los elementos que dependen de él se recalculan automáticamente.
// ✅ Constantes no topo — fáceis de ajustar const TITLE_START = 0; const TITLE_DUR = 45; const OVERLAP = 10; const SUBTITLE_START = TITLE_START + TITLE_DUR - OVERLAP; // 35 const LIST_START = SUBTITLE_START + 30; // 65 // ❌ Magic numbers — impossível de manter // <Sequence from={35}> ← por que 35? ninguém sabe // <Sequence from={65}> ← muda TITLE_DUR e quebra
✓ Ventajas de las constantes
- ✓Cambiar 1 número se propaga a todos los elementos dependientes.
- ✓Código autodocumentado: SUBTITLE_START se explica por sí mismo.
- ✓Fácil de extraer a props y hacer que la plantilla sea configurable.
✗ Problema de los números mágicos
- ✗Cambiar una duración requiere buscar y calcular todas las siguientes.
- ✗
from={47}— es imposible saber de dónde vino sin depurar. - ✗Error frecuente: dos elementos que deberían sincronizarse quedan desincronizados.
👁️ Evitar que todo aparezca en el frame 0
El error más común al empezar a combinar elementos es no usar from= en ninguno de ellos — resultado: todos aparecen al mismo tiempo en el frame 0. Para el espectador, es como recibir un grito en vez de una presentación.
⚠️ Qué sucede sin timing
- ✗El título, el subtítulo, el ícono y la lista se animan juntos en el frame 0 — congestión visual.
- ✗El spring de cada elemento compite por la atención en el mismo instante.
- ✗La jerarquía visual desaparece — el espectador no sabe qué es importante.
✅ Regla de prioridades
Ordena los elementos por importancia y define un from creciente para cada:
- 1.Frame 0: el elemento más importante (logo, título principal).
- 2.Frame 10–15: elemento de apoyo (subtítulo, descripción).
- 3.Frame 20+: elementos secundarios (lista, íconos, decoración).
⚡ Timing con spring dentro de Sequence
La combinación de Sequence + spring es el patrón de entrada más natural de Remotion. Como el frame local de cada Sequence empieza en 0, el spring "se activa desde cero" para cada elemento — independientemente de cuándo se haya abierto la Sequence en la línea de tiempo.
const Item = ({ label }: { label: string }) => { const frame = useCurrentFrame(); // sempre 0 no primeiro frame do item const { fps } = useVideoConfig(); const progress = spring({ frame, fps, config: { damping: 12, stiffness: 120 }, }); return ( <div style={{ opacity: progress, transform: `translateY(${(1 - progress) * 20}px)`, }}> {label} </div> ); }; // No componente pai — stagger automático: {["A", "B", "C"].map((l, i) => ( <Sequence key={l} from={i * 5}> <Item label={l} /> </Sequence> ))}
💡 Por qué esto es poderoso
Cada Item es completamente independiente: puedes reordenar el array, agregar o quitar elementos, y el stagger se recalcula automáticamente. No hay código que dependa de la posición absoluta de ningún elemento en la línea de tiempo.
📌 Resumen del módulo
Próximo módulo:
3.2 — Capas y composición visual: AbsoluteFill apilado, orden de las capas y cómo mantener la legibilidad.