🕐 useCurrentFrame() — o relógio
Em uma página web você usaria requestAnimationFrame ou um setInterval e acumularia estado. No Remotion, esquece tudo isso. Você só pergunta: "em que frame estou agora?" — e useCurrentFrame() responde com um número inteiro que cresce de 0 até o fim do vídeo.
🎯 A ideia central
O frame é a entrada e a imagem é a saída. Mudou o frame, recalcula tudo do zero. Esse hook é o ponto de partida de praticamente todo template da biblioteca.
- •Retorna um número: 0 no começo, e cresce de 1 em 1.
- •O componente é re-executado para cada frame durante o render.
- •Você nunca "avança" o tempo — o Remotion faz isso por você.
import { useCurrentFrame } from "remotion"; export const MyVideo = () => { const frame = useCurrentFrame(); // 0, 1, 2, 3 … return <div>Frame atual: {frame}</div>; };
💡 Dica prática
Quer testar? Abra o Remotion Studio e arraste a barra de tempo. O número que aparece é exatamente o que useCurrentFrame() devolve. Ver o número mudar enquanto você arrasta torna o conceito concreto.
⚙️ fps e durationInFrames — a régua
O frame sozinho não diz quanto tempo passou. Quem dá escala é o fps (frames por segundo). A 30fps, o frame 30 é "1 segundo". O durationInFrames diz quantos frames o vídeo tem no total — é o seu limite de tempo.
📊 Conversões que você vai usar toda hora
- segundos × fps = frames — 2s a 30fps = 60 frames
- frames ÷ fps = segundos — 90 frames a 30fps = 3s
- 30fps — padrão web/social, leve para renderizar
- 60fps — mais fluido, dobra o custo de render
✓ O que FAZER
- ✓Definir fps e duração na
<Composition>. - ✓Derivar tempos a partir do fps (
fps * 1.5para 1,5s). - ✓Pensar a animação dentro da janela de durationInFrames.
✗ O que NÃO fazer
- ✗Cravar "frame 45" sem lembrar que isso muda se o fps mudar.
- ✗Animar além de durationInFrames (some no render final).
- ✗Misturar 30 e 60fps entre cenas sem converter.
📐 useVideoConfig() — dimensões e fps
Como saber o fps dentro do componente, sem hardcode? E a largura, para centralizar algo? O useVideoConfig() devolve tudo: width, height, fps e durationInFrames da composição que está sendo renderizada.
const { width, height, fps } = useVideoConfig(); const frame = useCurrentFrame(); // "1 segundo" funciona em 30 ou 60fps: const apareceu = frame > fps; // centralizar sem saber o tamanho exato: const cx = width / 2;
💡 Por que isso importa
O mesmo componente pode rodar em 16:9 (1920×1080) e 9:16 (1080×1920) sem mudar uma linha — se você ler width/height de useVideoConfig() em vez de cravar números. É assim que um template vira reutilizável entre YouTube e Reels.
🎯 O frame como fonte de verdade
Aqui está a regra de ouro: a imagem de um frame depende SÓ do número do frame. Nada de useState acumulando, nada de timers, nada de "quanto tempo passou desde que cliquei". Cada frame é uma função pura.
O render pede frames fora de ordem
Para ir rápido, o Remotion renderiza vários frames em paralelo — pode calcular o frame 80 antes do 20. Só funciona porque cada um é independente.
Estado de tempo real quebra isso
Um setInterval assume que o tempo corre continuamente. No render isso não existe — cada frame é um cálculo isolado. Por isso a animação vem do frame, não de timers.
Tudo deriva de uma entrada
Posição, opacidade, cor, escala — todos são funções do frame. Mudou o frame, recalcula. Essa disciplina é o que mantém o vídeo consistente.
🔁 Determinismo — mesmo frame, mesma imagem
Consequência direta da regra anterior: renderizar o frame 42 hoje, amanhã ou em outra máquina produz exatamente o mesmo pixel. Isso se chama determinismo — e tem um inimigo claro: a aleatoriedade não-semeada.
⚠️ Atenção: o que destrói o determinismo
- ✗
Math.random()— dá um valor diferente em cada cálculo, faz partículas "piscarem". - ✗
Date.now()/new Date()— muda a cada execução. - ✗Qualquer dado externo que varie entre renders.
✅ A solução: random() semeado
O Remotion oferece random("seed"): dada a mesma semente, devolve sempre o mesmo número. Você ganha "aleatoriedade" visual sem perder reprodutibilidade.
import { random } from "remotion"; // mesma seed → mesmo valor, sempre: const x = random("particula-7") * width;
⏱️ Pensar em frames, não em segundos
Última mudança de hábito do módulo: a sua unidade de trabalho passa a ser o frame. "O título entra em meio segundo" vira "o título entra em 15 frames". Segundos só aparecem na borda do sistema — quando um humano digita um valor.
✓ Mentalidade frame
- ✓"Aparece do frame 0 ao 15" — direto na API.
- ✓Stagger: item N começa no frame N×5.
- ✓Converter segundos só na entrada:
0.5 * fps.
✗ Mentalidade segundo
- ✗Calcular "0,5s" no meio da animação toda hora.
- ✗Misturar segundos e frames na mesma conta.
- ✗Esquecer que mudar o fps reescala tudo em segundos.
💡 Regra de bolso
A 30fps: 15 frames = 0,5s, 30 frames = 1s, 45 frames = 1,5s. Decore esses três e você estima qualquer timing de cabeça.
📌 Resumo do módulo
Próximo módulo:
1.2 — interpolate(): transformar o número do frame em opacidade, posição e escala.