Remotion Motion Graphics — Vídeo 2D Baseado em Quadros
O Remotion renderiza React como vídeo. Cada quadro é uma função pura do índice do quadro, portanto a saída é determinística, difável e revisável. É a melhor escolha padrão para vídeos focados em texto e orientados a dados, e o melhor "compositor" para montar passes do Blender ou Manim com tipografia, legendas e transições.
Leia references/REMOTION-PLAYBOOK.md para convenções e references/REMOTION-RECIPES.md para componentes prontos para copiar. Consulte a documentação oficial e a CLI instalada para a API atual: https://www.remotion.dev/docs/
1. Configuração
node --version # Requer 18+, preferível 20/22 LTS
npx create-video@latest meu-video # escolha o modelo em branco
cd meu-video
npx skills add remotion-dev/skills # habilidades oficiais do agente Remotion (recomendado)
npm run dev # Remotion Studio em http://localhost:3000
Renderizar:
npx remotion render <entrada> <IdDaComposicao> out/video.mp4 --codec=h264
npx remotion render <entrada> <IdDaComposicao> out/preview.mp4 --scale=0.5
npx remotion render <entrada> <IdDaComposicao> out/frames --sequence --image-format=png
As flags exatas variam por versão; confirme com npx remotion render --help.
Licenciamento: O Remotion é código-fonte disponível, não open source OSI. Gratuito para indivíduos e pequenas organizações elegíveis sob seus termos atuais; usos comerciais ou de automação maiores podem exigir uma licença paga. Verifique https://www.remotion.dev/docs/license/pricing para o caso real do usuário antes de prometer uma entrega. Não o descreva como "MIT" ou "gratuito para qualquer empresa".
2. Estrutura do projeto
Adapte-se ao modelo inicial em vez de lutar contra ele:
src/
Root.tsx # registra composições
compositions/
MainVideo.tsx # sequencia as cenas
scenes/
Intro.tsx Feature.tsx Outro.tsx
components/
AnimatedTitle.tsx Background.tsx Grid.tsx Caption.tsx Transition.tsx
animations/
easing.ts timing.ts reveal.ts
data/
content.ts # cópia e números, separados do layout
styles/
tokens.ts # paleta, escala tipográfica, espaçamento
public/
audio/ fonts/ images/ video/
Regras:
- Uma cena por arquivo;
MainVideoapenas as sequencia. - Cópia e dados vivem em
data/, nunca inline em cinco cenas. - Tokens de design em
styles/tokens.ts; sem valores hexadecimais mágicos espalhados. - Primitivas reutilizáveis em
components/, nunca duplicadas por cena. staticFile("...")para tudo empublic/.
3. Determinismo (a regra fundamental)
Todo estado visual é derivado do quadro atual:
import { useCurrentFrame, useVideoConfig, interpolate, spring } from "remotion";
const frame = useCurrentFrame();
const { fps, durationInFrames, width, height } = useVideoConfig();
Proibido como drivers de animação: Date.now(), setTimeout, setInterval, requestAnimationFrame, keyframes CSS, Math.random() sem semente, dados assíncronos que mudam entre renderizações.
Aleatoriedade com semente quando a variação for desejada:
export const rand = (seed: number) => {
const x = Math.sin(seed * 12.9898) * 43758.5453;
return x - Math.floor(x);
};
Ativos assíncronos devem ser resolvidos antes da renderização do quadro. Use delayRender/continueRender corretamente, sempre continuando em um catch, ou pré-carregue ativos fora do quadro (recomendado).
4. Temporização
durationInFramesé explícito. A 30 FPS, 10 s = 300 quadros, índices 0–299.- Converta uma vez:
const s = (n: number) => Math.round(n * fps). - Limites de cena vêm de uma linha do tempo cumulativa, nunca de arredondamento por cena.
- Use
<Sequence from={inicio} durationInFrames={len}>; verifique se nada se estende além da composição. - Torne as sobreposições intencionais; uma lacuna de um quadro é um flash visível.
- Use
calculateMetadataquando a duração ou as dimensões vierem de props.
5. Técnicas de animação
| Movimento | Primitiva |
|---|---|
| Entrada/estabilização | spring ou interpolate com Easing.out(Easing.cubic) |
| Saída | Easing.in(Easing.cubic) |
| Movimento simétrico | Easing.inOut(Easing.cubic) |
| Mecânico/contínuo | Easing.linear |
| Número/cor/rotação | interpolate com extrapolação fixada |
| Escalonamento | deslocar from por elemento (30–80 ms) |
const enter = spring({ frame, fps, config: { damping: 18, stiffness: 120, mass: 0.8 } });
const opacity = interpolate(frame, [0, 12], [0, 1], {
extrapolateLeft: "clamp", extrapolateRight: "clamp",
});
Não use spring em tudo. Não anime todas as propriedades. Prefira transformações e opacidade (amigáveis à GPU) em vez de propriedades de layout. Garanta pelo menos ~0,8–1,2 s de permanência para um título curto, mais para corpo do texto.
6. Tipografia e design
- Defina uma escala tipográfica (ex.: 96/64/40/28/20 px em 1080p) e use-a em todos os lugares.
- Carregue fontes de
public/fontscom@remotion/fontsou o padrão documentado do modelo inicial, e aguarde a prontidão antes de renderizar. Evite depender de fontes do sistema. - Verifique o comprimento da linha (≈45–75 caracteres), a altura da linha (1,1–1,4 para títulos) e o espaçamento entre letras.
- Mantenha 5–8% de margens de segurança; verifique sobreposições de interface de plataforma para formatos verticais/sociais.
- Para Persa/Árabe: use
dir="rtl"correto, fonte com capacidade de modelagem, verifique números/URLs mistos e inspecione o quadro renderizado — o Chrome headless formata texto de forma diferente de algumas ferramentas de design. - Verifique a cópia final caractere por caractere. Erros de digitação em vídeo são bugs de envio.
7. Composição e transições
- Um ponto focal por batida; anime o olho, não toda a tela.
- Use um vocabulário de transição: corte, crossfade de 6–10 quadros, máscara de varredura, zoom através, desfoque através. Reutilize deliberadamente.
- Prefira cortar em uma batida a dissolver tudo.
- Para vídeos longos, primeiro crie um gráfico de temporização (segundos → quadros → cena) e codifique-o em um arquivo.
8. Áudio e legendas
import { Audio, staticFile } from "remotion";
<Audio src={staticFile("audio/musica.mp3")} volume={0.6} />
- Importe apenas para uma sequência que comece onde o som deve começar.
- Faça fade in/out com
interpolateemvolume; evite cliques. - Abafe a música sob a narração; mantenha o diálogo inteligível.
- Legendas: queime com
<Caption>para redes sociais, ou exporte.srtpara plataformas. Respeite áreas seguras e velocidade de leitura (~15–20 caracteres/seg). - Verifique a mixagem no arquivo codificado, não apenas na pré-visualização.
9. Desempenho
- Reduza a concorrência em máquinas com memória limitada:
--concurrency=4. - Evite desfoques gigantescos, cadeias de filtros, SVGs enormes e milhares de nós DOM; use Canvas para gráficos densos.
- Armazene em cache fundos estáticos (
<Freeze>ou imagem pré-renderizada). - Otimize imagens (tamanho correto, WebP/AVIF quando suportado) e reduza ativos de vídeo.
- Renderize pré-visualizações com
--scale=0.5e intervalos de quadros curtos primeiro.
10. Vídeo em lote e orientado a dados
- Defina um esquema de props e valide antes de renderizar.
- Mantenha dados em JSON/CSV; mantenha layout em componentes.
- Ajuste de texto: número máximo de linhas, tamanho de fonte de fallback, regras de truncamento, testes de estouro.
- Renderize cada variante da mesma composição com
--propsdiferentes. - Escreva um manifesto e verifique a duração e o tamanho não vazio de cada saída.
npx remotion render src/index.ts Main out/acme.mp4 --props='{"marca":"Acme","tagline":"Construa mais rápido"}'
11. Híbrido com Blender
- Renderize a cena do Blender na mesma FPS, resolução e número de quadros que a composição do Remotion.
- Mapeie o quadro 1 do Blender → índice de quadro 0 do Remotion, a menos que o projeto defina um deslocamento.
- Para transparência, exporte sequência PNG ou ProRes 4444 e verifique o alfa sobre um tabuleiro de xadrez; MP4 não tem alfa.
- Combine o pipeline de cores: codifique o passe do Blender com as mesmas premissas de transferência/transformação de visualização que a saída do navegador e, em seguida, inspecione a composição.
- Coloque o passe com
<OffthreadVideo>(não<Video>) dentro de uma<Sequence>e definastartFrom/deslocamentos de quadro a partir do mapa de quadros.
12. Validação antes da entrega
npx remotion compositions src/index.ts # liste ids e dimensões
ffprobe -v error -show_entries format=duration,size \
-show_entries stream=codec_name,width,height,r_frame_rate,pix_fmt,channels \
-of json out/video.mp4
Em seguida, inspecione os quadros 0, cada limite de cena, cada transição, cada quadro com muito texto e o quadro final. Verifique se há texto cortado, fontes ausentes, quadros pretos e dessincronização de áudio. Consulte video-composition para receitas de codificação/normalização e motion-studio/references/QUALITY-CHECKLIST.md para a lista de verificação completa.
13. Modos de falha comuns
- Composição não encontrada → arquivo de entrada ou ID está errado; execute
npx remotion compositions. - Renderização em branco, mas pré-visualização funcionando → o caminho do ativo resolve no Studio, mas não no headless; use
staticFile, verifique a capitalização depublic/. - Fontes voltam para Times → fonte não carregada antes da renderização; aguarde a prontidão.
- Saída diferente entre renderizações → tempo de relógio ou aleatoriedade sem semente.
- OOM ou extremamente lento → diminua
--concurrency, reduza desfoque/escala, divida a renderização. - Áudio fora de sincronia →
startFromerrado, incompatibilidade de fps ou fonte de taxa de quadros variável.