Publiquei um segundo motor de renderização para o preview bater com o export. Piorou tudo.
Meu editor de clipes com IA tinha dois motores de renderização para o preview bater com o export. Dois motores divergem. Veja por que apaguei um e refiz tudo num único pipeline FFmpeg.
3 de setembro de 2026
Katto é um clipador de vídeo com IA. Você joga um vídeo longo, ele corta os melhores momentos em shorts verticais, e um editor deixa você ajustar o enquadramento, as legendas e o layout antes de exportar. Eu construo isso sozinho, em público. Esta é a história de um erro que cometi nesse editor, e do que consertá-lo me ensinou sobre "o que você vê é o que você leva".
O problema que eu estava resolvendo
Um editor de clipes vive ou morre por uma única promessa. O que você vê no preview é exatamente o que você baixa. Se a legenda fica um pixel mais alto no export, se o recorte desliza, se uma cor sai errada, o usuário para de confiar na ferramenta. E a confiança é o produto inteiro.
Meu preview é uma composição React renderizada no navegador. Meus exports eram renderizados no servidor com FFmpeg. Dois renderizadores diferentes desenhando o mesmo clipe. Eles divergiram, como era de se esperar. Fontes das legendas, renderização de emoji, o recorte exato numa tela dividida. O clássico "o preview não bate com o export".
A correção que parecia certa (e não era)
Então fiz o óbvio. Fiz com que a mesma composição React que desenha o preview do navegador também renderizasse o export no servidor, através de um Chromium headless (Remotion). Um componente, uma fonte única de verdade. Preview igual ao export, garantido.
Isso não é uma crítica ao Remotion. Ele é excelente naquilo para o que foi feito. O erro foi meu. Eu o parafusei como um segundo motor de export ao lado de um pipeline FFmpeg já existente.
Meus clipes iniciais, os que a IA gera antes de você sequer abrir o editor, ainda eram renderizados pelo FFmpeg. É rápido, é comprovado, roda o pipeline inteiro. Eu não ia arrancar isso.
Então agora eu tinha dois motores produzindo arquivos. FFmpeg para o clipe gerado, Chromium e Remotion para o re-export editado. A divergência exata que eu me propus a matar ficou pior. O clipe que você via na sua lista de resultados (FFmpeg) e o mesmo clipe re-exportado depois de uma edição minúscula (Remotion) podiam sair sutilmente diferentes. Eu tinha transformado um renderizador em dois e chamado isso de paridade.
Além disso, a renderização do Chromium era lenta. Três a quatro minutos por clipe, contra cerca de 30 segundos do FFmpeg. E ela falhava de vez em quando. Quando falhava, recorria silenciosamente ao FFmpeg e entregava ao usuário um arquivo com as edições dele descartadas sem aviso. A pior falha possível. Errada, e silenciosa.
A ficha caindo
"Preview igual ao export" não se alcança fazendo do preview o renderizador. Alcança-se tendo uma fonte única de verdade para a renderização, e deixando o preview ser uma aproximação fiel dela.
Um Player de navegador é um ótimo preview. Ele nunca deveria ter virado um segundo motor de export. No momento em que virou, eu tinha duas implementações da mesma geometria, divergindo a cada mudança.
O que eu fiz
- FFmpeg é o único motor que produz arquivos. Geração e re-export passam pelo mesmo pipeline. Os exports de um clipe típico com menos de 60s caíram para cerca de 30 segundos (medi 32s), contra os três a quatro minutos que o caminho do Chromium levava.
- O Player do navegador voltou ao que faz bem, o preview interativo. Ele não renderiza nada que vá para o usuário.
- Portei para o FFmpeg os floreios que só o navegador conseguia fazer, as legendas com cor rotativa por palavra e a proporção ajustável da divisão no layout empilhado, para que o caminho rápido cubra os casos comuns.
- O fallback silencioso morreu. Se uma renderização não pode ser produzida fielmente, o usuário recebe um erro visível, nunca um arquivo silenciosamente errado.
- Um único conjunto de coordenadas, a última peça que estou terminando. Quando você arrasta um recorte no preview, esses retângulos exatos deveriam ser o que o FFmpeg usa, não uma segunda geometria que o servidor recalcula por conta própria. Essa é a sutil. Mesmo depois de unificar o motor, o preview calculava os retângulos de recorte de um jeito e o export de outro. Estou fechando isso agora, fazendo o FFmpeg consumir os retângulos exatos do estado do editor, porque a lição é a mesma um nível abaixo. Qualquer segundo cálculo da mesma coisa é uma fonte de divergência.
As lições
- "Fazer do preview o renderizador" é sedutor e quase sempre errado. Você acaba com dois renderizadores no dia em que tiver qualquer outro caminho de renderização. Uma fonte única de verdade para a saída. O preview a aproxima.
- Um segundo motor "para paridade" vira uma terceira fonte oculta de divergência. Se dois caminhos de código calculam a mesma geometria ou formato, eles vão divergir. A única pergunta é quando.
- Fallbacks silenciosos são o pecado capital. Um arquivo levemente errado sem aviso custa mais confiança do que um erro honesto. Falhe alto.
- Verifique o artefato, não os logs. Meus logs diziam "renderizou o layout empilhado". Só encontrei o bug de verdade puxando o MP4 exportado real do armazenamento e olhando um frame. Os pixels são a verdade.
Sou um fundador solo, entregando rápido, em público. Esse aqui me custou um desvio bem-intencionado. Se você está construindo qualquer editor com preview e export, o caminho mais curto para a confiança é sem graça. Um renderizador, erros honestos, e cheque os frames.
O Katto está em katto.tech. Se você constrói ferramentas de vídeo, eu adoraria de verdade trocar ideias sobre paridade de preview e export.
Artigos relacionados
Pronto para transformar seus vídeos em clipes virais?
O Katto corta, legenda e reenquadra automaticamente seus vídeos longos em conteúdo de formato curto.
Experimente o Katto grátis →