Vídeo de lançamento de produto
Produz um filme de ~40s onde a motion graphics carrega a narrativa e cada pixel do "produto" é realmente renderizado pelo app real.
Isto existe por causa de uma falsa escolha que as pessoas continuam fazendo:
- Um filme puro de motion graphics parece profissional mas não prova nada — sem produto real.
- Uma gravação de tela bruta prova tudo mas parece amadora — sem design de movimento.
A resposta não é nenhuma das duas: Remotion é a linha do tempo mestre, e as cenas do produto são frames reais capturados ao conduzir o app real em um navegador headless.
Construa um pequeno projeto Remotion junto ao produto: toolkit de captura compartilhado + primitivas, um diretório por filme do app (marca, cenas, script de captura, timeline). Veja references/toolkit.md para o layout recomendado.
Inegociáveis
Leia estes antes de escrever qualquer código. Cada um custou tempo real de depuração, e todos falham silenciosamente — você obtém uma saída com aparência plausível mas errada.
Captura
| Armadilha | O que acontece | Correção |
|---|---|---|
setViewport({deviceScaleFactor: 2}) | page.screencast() mede sua cadeia de filtros ffmpeg no DPR do sistema, então constrói uma cadeia 1× e descarta o detalhe retina. Nenhum erro. | Force no navegador: --force-device-scale-factor=2 + deviceScaleFactor: 0 no viewport (0 = "padrão do sistema"). |
| Headless não renderiza cursor | page.mouse.move() despacha eventos CDP que a página vê, mas nada é pintado. | Injete um cursor DOM via evaluateOnNewDocument. Coloque-o na página, não compostado no Remotion — então toda transformação Remotion (inserção de frame, zoom punch) o escala exatamente como uma gravação real. Um sprite exigiria inverter cada transformação, e 6px de desvio parece quebrado. |
| Headless não tem GPU | Qualquer conteúdo WebGL/three.js grava como um painel preto ou em branco. | --use-gl=angle --use-angle=swiftshader --enable-unsafe-swiftshader. Verifique com uma leitura de pixel, não apenas "existia um contexto?". |
| SwiftShader também compõe a página | Um driver GL de software compondo 2560x1440 limita a aba inteira a ~8fps, então cada cena animada grava como um slideshow. Parece um produto lento, não uma captura quebrada, então ninguém suspeita das flags. | Adicione --disable-gpu-compositing. O rasterizador CPU do Skia é muito mais rápido em 2D simples, WebGL ainda funciona, e stills A/B são idênticos. Medido na mesma página: 8,2fps → 60,1fps. |
| Julgar suavidade a olho nu | Quadros duplicados parecem bons em uma folha de contato e ao avançar um quadro por vez. Só a reprodução entrega, e nessa altura já foi renderizado. | Conte quadros distintos: ffmpeg -i take.mp4 -vf mpdecimate,showinfo -f null - 2>&1 | grep -c pts_time. Muito abaixo da contagem de quadros do arquivo significa gaguejo. |
page.mouse.click(x, y, {clickCount: 2}) | Envia uma pressão carregando metadados clickCount. Chrome nunca sintetiza dblclick. Dois cliques discretos com 60ms de intervalo também não. | Se o app precisa de um dblclick real, clique para o movimento visível do cursor e depois despache o evento dentro do frame nas próprias coordenadas do elemento. |
page.keyboard.type() após clicar em um iframe | As teclas vão para o que o pai da página focou. Se o pai encaminha teclas para o app (navegação por setas, atalhos), sua digitação silenciosamente dirige a UI em vez de inserir texto. | Digite no frame: frame.type(selector, text). |
evaluateOnNewDocument fazendo trabalho DOM | Executa no início do documento onde document.head e document.documentElement podem ser ambos nulos. Um appendChild não protegido lança exceção e aborta silenciosamente tudo depois dele naquele script. | Proteja, e adie para DOMContentLoaded. |
| Gravando a navegação | Enterra os segundos úteis no fundo do arquivo e incha o mezanino. | Divida cada cena em setup (não gravado) e action (gravado). |
| Confiar em timestamps de marcadores | Screencast tem taxa de quadros variável; a linha do tempo codificada comprime em relação ao tempo real, então um marcador em 22s não está em 22s no arquivo. | Use marcadores para encontrar aproximadamente onde olhar, depois escolha startAt extraindo quadros e verificando. |
| Ativos remotos/hotlinkados | CDNs de terceiros intermitentemente recusam o navegador de captura; grids de imagens pintam como quadriculados de transparência vazios, o que parece um produto quebrado. | Aguarde imagens e avise, então enquadre a cena para evitá-las. Não entregue uma tomada com arte em branco. |
window.scrollTo em um shell de app | Muitos shells rolam um elemento interno (<main class="overflow-y-auto">), não a janela. Rolar a janela é um no-op silencioso e a cena nunca se move. | Encontre o verdadeiro scroller e defina seu scrollTop. |
| Adivinhar coordenadas de clique | Apps frequentemente só aceitam interações em nós específicos — por exemplo, um editor inline que só aceita elementos folha (childElementCount === 0) enquanto cabeçalhos envolvem seu texto em spans. Clicar no alvo visualmente óbvio não faz nada. | Leia a própria fonte do app para a regra, depois pergunte à página onde estão seus alvos válidos (frame.evaluate) e mapeie coordenadas do frame → coordenadas da página através da caixa medida do iframe. |
Renderização
| Armadilha | O que acontece | Correção |
|---|---|---|
| Pular a transcodificação do mezanino | Remotion busca arbitrariamente; com um GOP normal, cada busca decodifica a partir do I-frame anterior. Uma renderização de 3 minutos se torna 40. | Transcodifique para all-intra: -c:v libx264 -crf 14 -g 1 -keyint_min 1 -sc_threshold 0 -pix_fmt yuv420p, mais tags bt709 explícitas para que o Chrome não mude a cor da marca. |
page.screencast({format:'mp4'}) | Emite VP9 dentro de um MP4 fragmentado — mal suportado. | format: 'webm', depois transcodifique. |
<TransitionSeries> com uma grade de beats | Transições se sobrepõem, então duração total = soma das sequências − soma das transições. Sua grade de quadros deriva silenciosamente. | Para um corte exato de quadro, use <Sequence from/durationInFrames> explícito e faça dissolves localmente. Afirme que a cadeia soma ao total. |
Uma <Sequence> mais longa que sua fonte | Congela no último quadro decodificado — parece uma parada, não um erro. | Limite cada duração pelo comprimento real da tomada. Grave durações da fonte em um comentário. |
premountFor em sequências sobrepostas | Uma sequência pré-montada renderiza cedo sobre a atual — você obtém texto duplo-exposto fantasmagórico. | Não pré-monte sequências que compartilham espaço de tela; pré-monte apenas em cortes secos. |
| Sobreposições posicionadas no espaço da composição | Se o componente de filmagem corta e escala a placa internamente, uma máscara ou destaque colocado em coordenadas da composição não se alinhará com nada no quadro — bordas cortam através do conteúdo. | Coloque sobreposições dentro da mesma transformação da placa, ou faça o tratamento nativamente em vez de sobre a filmagem. |
Math.random() / Date.now() em uma composição | Re-rola a cada quadro; o texto pisca. Remotion renderiza cada quadro independentemente. | Torne toda aleatoriedade uma função pura do índice (um hash baseado em sin). |
CSS animations / transitions / Tailwind animate-* dentro do Remotion | Renderização congelada ou lixo — Remotion conduz o tempo via useCurrentFrame(), não relógio de parede. | Reconstrua o movimento em useCurrentFrame(). Isso também significa que você geralmente não pode reutilizar os componentes animados do site de marketing. |
| Construir um loop deslocando para dentro do filme | Dois bugs de emenda: um flash preto se o intervalo abre em um dissolve, e um corte brusco onde ele envolve. | Dê ao loop sua própria composição e faça cross-fade de sua cauda para um <Freeze frame={0}> de sua própria cabeça. Escolha uma cena continuamente em movimento; qualquer coisa que pause é quase estática e ruim para autoplay. |
Processo
1. Estabeleça a verdade do produto antes de projetar o filme
O passo mais importante de todos. Leia o código para cada capacidade que o filme pretende afirmar. Páginas de marketing ilustram aspirações; não assuma que o produto faz o que sua própria animação de landing page implica.
Já aconteceu uma vez: a peça central planejada de um filme foi tirada de um componente animado no site de marketing mostrando um documento se transformando em quatro proporções diferentes. O produto codificava uma única proporção e uma etapa fixa de exportação — o componente era uma ilustração de uma ideia, não um recurso. Construir a cena principal nisso teria colocado uma afirmação não suportada na página inicial.
Verifique, especificamente:
- Qual conteúdo realmente renderiza? Registros antigos podem não ser renderizáveis pelo motor atual.
- Quais rotas precisam de autenticação? Quais redirecionam sem estado anterior?
- O que cada recurso interativo realmente exige para engajar?
2. Desrisque o pipeline com o menor teste possível
Em ordem, antes de construir qualquer coisa em cima:
- Prove a geometria da captura (página com cantos marcados → o arquivo é realmente 2×?).
- Prove a autenticação (o navegador consegue alcançar uma rota logada?).
- Prove WebGL se qualquer 3D estiver envolvido.
- Prove uma interação de ponta a ponta.
3. Explore, não adivinhe
Capture uma screenshot de cada superfície candidata e mostre ao usuário uma folha de contato antes de gastar tempo com tomadas de vídeo. A escolha do conteúdo domina o valor de produção: conteúdo demo medíocre transforma um filme bonito em um anúncio de um produto medíocre.
4. Escolha o conteúdo demo com cuidado
Prefira a própria marca do produto. Apresentar um terceiro reconhecível é mais persuasivo, mas coloca a marca registrada de outra pessoa na página inicial, e trocar um terceiro por outro não muda isso. Conteúdo auto-referencial também fecha o ciclo: o artefato que vende a ferramenta foi feito pela ferramenta.
Se o conteúdo ainda não existe, criá-lo é um trabalho de design, não de captura — está em cada quadro da segunda metade do filme. Esboce-o deliberadamente, produza alguns candidatos, e deixe o usuário escolher.
5. Corte em uma grade
120 BPM ⇒ 1 barra = 60 quadros = 2s a 30fps. Aterre cada corte em um múltiplo de 30 e cada limite de ato em 60. Não custa nada, e cortes de duração caem de graça.
6. Verifique olhando
Após cada renderização, extraia quadros e realmente olhe para eles. Construa uma folha de contato rotulada. Todo defeito real encontrado até agora — logotipos em branco, uma cena mostrando a página errada, uma legenda ilegível em um painel claro, uma faixa escura de um corte mal medido, uma costura de máscara através de um rótulo — foi encontrado olhando para quadros, não por qualquer teste que passava.
Assista sem áudio, já que é assim que será reproduzido automaticamente.
Regras editoriais
Estas são o que separa um filme que funciona de um que é bom.
Toda afirmação na tela deve ser apoiada pela filmagem ao lado dela. Um corte tinha "Compartilhe um link" sobre filmagem onde nada mostrava compartilhamento. Ou mostre ou declare claramente em um cartão — não insinue.
Cuidado com afirmações que são honestas em contexto mas não em escala de vídeo. Uma figura rotulada como "ilustrativa" em tipo pequeno se torna uma afirmação forte no momento em que é um quadro herói segurado em um filme de marketing. Mantenha essas fora de quadros segurados.
Cite o movimento do produto, não o reinvente. Pegue a própria curva de easing e vocabulário de entrada do app. Uma curva para tudo que entra ou aterrissa. Nada de saltos — overshoot parece hesitação.
Dois fundos, nunca cinza médio. Um fundo escuro para afirmações, um claro para explicações. Escolha-os dos próprios tokens do produto.
Um acento, usado com moderação — o cursor, a única palavra que carrega a frase, um estado mudando. Não decoração.
Nada no quadro que não seja para o público. Endereços de e-mail reais, nomes de organização, a própria conversa do operador com um assistente no app, badges de modo dev. Prefira os próprios mecanismos do app (cookies para uma barra lateral recolhida ou um banner dispensado) em vez de hacks CSS — sem flash na câmera.
Uma "cena principal" merece o maior tempo. Escolha o único momento mostrando algo que concorrentes estruturalmente não podem fazer, depois: câmera fixa, sem cortes, sem texto sobre ela, e deixe a música cair. Quietude diz ao olho que o sujeito está se movendo, não a câmera. Coloque a linha explicativa depois dela — texto antes da reação diz às pessoas o que pensar.
Legibilidade supera cobertura. Uma cena espalhada por quatro telas pode deixar nenhuma delas legível. Deter-se em uma geralmente é melhor.
Construa o beat em vez de filmá-lo quando a UI não puder performar. Uma tela estática não pode introduzir três coisas uma de cada vez. Se o beat precisa de uma sequência que o produto não faz, componha-a nativamente em Remotion usando o texto real e os tokens do produto — e mantenha visualmente distinta da filmagem para que pareça um explicador, não uma screenshot falsa.
Se não há narração, os cartões carregam 100% do significado. Reserve tempo de leitura.
Discuta com o usuário, não decida sozinho
- Slogans e texto na tela. Ofereça várias opções agrupadas por ângulo, com uma recomendação e a justificativa. Note que o filme quer uma deixa de demonstração enquanto um headline de site quer uma declaração de posicionamento durável — não precisam ser a mesma frase.
- Qual conteúdo destacar — mostre a folha de contato.
- Música. Você não pode licenciar uma faixa. Projete o filme para funcionar sem áudio e forneça uma folha de referência (BPM, onde qualquer queda ocorre) para que uma faixa fornecida caia na grade mais tarde. Quando uma chegar, verifique sua forma antes de colocá-la: meça o volume ao longo do tempo em vez de assumir que ela tem uma introdução ou uma queda para alinhar.
- Licenciamento Remotion. Gratuito para indivíduos, organizações sem fins lucrativos e empresas com até 3 funcionários; acima disso, uma licença comercial é necessária. Sinalize antes de enviar.
Comandos (forma)
A captura nunca inicia um servidor e nunca adivinha uma porta — URLs de autenticação são geralmente fixos.
# terminal 1 — produto já servindo
pnpm --filter <app> dev # ou equivalente
# terminal 2 — projeto do filme
pnpm install
pnpm check-webgl # se qualquer 3D
pnpm capture:<app> # ou uma cena: pnpm capture:<app> <shot>
pnpm mezzanine:<app> # obrigatório — veja armadilhas
pnpm studio
pnpm render:<app> # mp4 / webm / loop / poster conforme necessário
Autenticação para superfícies logadas: prefira emprestar um cookie de sessão ativo em vez de criar um usuário descartável (contas vazias forçam geração lenta de conteúdo antes de cada filmagem).
Envio para uma página
Duas formas, e é decisão do usuário:
- Loop curto, clique para o filme. Mais leve — alguns KB em autoplay, o filme completo só é buscado sob demanda.
- Filme completo em autoplay. Mais pesado, mas sem atrito. Exige mezanino all-intra.
Verificação final
Antes de enviar, releia cada afirmação no texto contra a filmagem ao lado. Mostre a folha de contato. Confirme a grade de beats. Confirme que nenhuma tomada está em branco.