🎬 Sequence from= — o offset de tempo
O prop from da Sequence é simples e poderoso: diz em que frame do vídeo esse bloco começa a existir. Antes desse frame, o componente filho simplesmente não é renderizado. Depois, o frame local começa em zero — como se o relógio reiniciasse para aquele elemento.
🎯 A ideia central
Dentro de uma Sequence, useCurrentFrame() devolve 0 no frame from, 1 no frame from+1, e assim por diante. Isso significa que animações dentro de Sequences são sempre relativas ao início delas — não ao início do vídeo.
- •O filho não existe antes do frame
from— não é renderizado nem ocupa espaço. - •O frame local dentro da Sequence sempre começa em 0.
- •Combinar com
durationInFrameslimita também o fim da existência.
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> </> ); };
💡 Dica prática
Arraste a barra de tempo do Remotion Studio para o frame 14 — o Subtitle ainda não existe. Vá para 15 — aparece. Esse controle visual direto é a melhor forma de calibrar seus offsets.
🪜 Stagger com index * N
O padrão de stagger é o mais recorrente em listas, menus e grids animados: cada item recebe um from baseado no seu índice multiplicado por uma constante N. O resultado é a sensação de "cascata" — os elementos entram um depois do outro de forma natural.
✓ O que FAZER
- ✓Usar
from={index * N}onde N = 4 a 8 frames. - ✓Combinar com spring() local para cada entrada suave.
- ✓Usar valores pequenos de N para listas longas (evitar espera longa).
✗ O que NÃO fazer
- ✗N muito grande (>15) faz a lista demorar demais para completar.
- ✗Stagger em itens que o espectador não acompanha na ordem.
- ✗Esquecer de somar o offset ao
fromdo grupo pai.
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 fim com início — overlap
Uma das técnicas mais eficazes de timing é fazer o elemento B começar enquanto o A ainda está saindo. Essa sobreposição intencional elimina o "buraco" de tela vazia e passa a atenção do espectador de forma suave de um elemento para o outro.
Calcule o from do elemento A
Ex: TITLE_START = 0, TITLE_DUR = 60 (frames que o título fica visível).
Defina o overlap desejado
Tipicamente 8–12 frames. Overlap muito longo cria confusão; muito curto não gera fluidez.
Derive o from de B
LIST_START = TITLE_START + TITLE_DUR - OVERLAP — B começa antes de A acabar.
Teste no Studio
Arraste o playhead pelos frames do overlap e verifique que nenhum dos dois elementos "compete" visualmente — um deve dominar.
💡 Dica prática
Se o elemento A tem um fade-out animado (opacidade 1→0 nos últimos 10 frames), ative o B exatamente quando A começa esse fade. O espectador percebe a transição mas não sente o corte.
🧮 Constantes nomeadas — sem magic numbers
Um código de timing limpo declara todos os offsets como constantes nomeadas no topo do componente. Assim, quando você precisa ajustar "o título demora um pouco mais", só muda TITLE_DUR — e todos os elementos que dependem dele se recalculam automaticamente.
// ✅ 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
✓ Vantagens das constantes
- ✓Mudar 1 número propaga para todos os dependentes.
- ✓Código auto-documentado: SUBTITLE_START fala por si.
- ✓Fácil de extrair para props e tornar o template configurável.
✗ Problema dos magic numbers
- ✗Mudar uma duração requer caçar e calcular todos os subsequentes.
- ✗
from={47}— impossível saber de onde veio sem depurar. - ✗Bug frequente: dois elementos que deveriam sincronisar ficam dessincronizados.
👁️ Evitar tudo no frame 0
O erro mais comum de quem começa a combinar elementos é não usar from= em nenhum deles — resultado: todos aparecem simultaneamente no frame 0. Para o espectador, é como receber um grito em vez de uma apresentação.
⚠️ O que acontece sem timing
- ✗Título, subtítulo, ícone e lista animam juntos no frame 0 — congestionamento visual.
- ✗O spring de cada elemento compete pela atenção no mesmo instante.
- ✗A hierarquia visual desaparece — o espectador não sabe o que é importante.
✅ Regra das prioridades
Ordene os elementos por importância e defina um from crescente para cada:
- 1.Frame 0: o elemento mais importante (logo, título principal).
- 2.Frame 10–15: elemento de suporte (subtítulo, descrição).
- 3.Frame 20+: elementos secundários (lista, ícones, decoração).
⚡ Timing com spring dentro de Sequence
A combinação de Sequence + spring é o padrão de entrada mais natural do Remotion. Como o frame local de cada Sequence começa em 0, o spring "dispara fresquinho" para cada elemento — independentemente de quando a Sequence foi aberta na linha do tempo.
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 que isso é poderoso
Cada Item é completamente independente — você pode reordenar o array, adicionar ou remover itens, e o stagger se recalcula automaticamente. Não há código que dependa da posição absoluta de nenhum elemento na linha do tempo.
📌 Resumo do módulo
Próximo módulo:
3.2 — Camadas & Composição Visual: AbsoluteFill empilhado, ordem de camadas e como manter legibilidade.