Pitch: O que aprendemos construindo um editor de vídeo com IA local-first usando WebGPU e WebCodecs
Olá, pessoal do TabNews! 👋
Faço parte do projeto Timeline Studio, um editor de vídeo open source que estamos construindo para funcionar diretamente no navegador.
Mais do que apresentar o projeto, gostaria de compartilhar alguns dos problemas técnicos que encontramos ao tentar combinar edição de vídeo, uma linha do tempo multifaixa e modelos de IA executados localmente.
A pergunta que orienta o projeto é:
Até onde conseguimos levar um editor de vídeo no navegador sem depender de uma GPU remota para cada operação?
O que significa “local-first” neste projeto?
Local-first não significa que absolutamente tudo funciona sem internet desde o primeiro acesso.
Os modelos precisam ser baixados inicialmente, e alguns deles são relativamente grandes. Depois disso, o objetivo é manter os artefatos em cache e executar o processamento principal no dispositivo do usuário.
Essa arquitetura pode oferecer algumas vantagens:
- a mídia não precisa ser enviada a um servidor para cada processamento;
- modelos já baixados podem ser reutilizados;
- o custo de infraestrutura não cresce diretamente com cada inferência;
- projetos e arquivos intermediários podem permanecer locais;
- o usuário mantém mais controle sobre a mídia e o processo de edição.
Ao mesmo tempo, ela transfere vários problemas para o navegador: memória limitada, diferenças entre GPUs, tamanho dos modelos, inicialização das sessões, gerenciamento de cache e compatibilidade.
A arquitetura atual
A interface é construída com React e TypeScript. Para processamento de mídia e execução dos modelos, utilizamos principalmente:
- WebGPU e ONNX Runtime Web para inferência;
- WebCodecs para decodificação e processamento de vídeo;
- WebAssembly e FFmpeg como rotas de compatibilidade;
- Cache Storage e IndexedDB para modelos e dados locais;
- modelos ONNX para voz, transcrição, áudio e visão computacional.
O editor possui uma linha do tempo multifaixa para vídeo, áudio, legendas, imagens e sobreposições. Também suporta operações como cortes, transições, máscaras, keyframes, separação de áudio e exportação para MP4 ou WebM.
Mas fazer esses recursos aparecerem na interface foi a parte mais simples. O trabalho mais difícil foi manter seu comportamento correto durante a reprodução e a exportação.
1. Uma linha do tempo não é apenas uma lista de clipes
No início, é tentador representar cada clipe apenas com um tempo inicial e uma duração.
Isso funciona até começarem a aparecer operações como:
- ripple edit;
- rolling edit entre dois clipes;
- divisão de um segmento;
- alteração de velocidade;
- separação do áudio de origem;
- faixas bloqueadas;
- legendas vinculadas a uma narração;
- movimentação entre faixas.
Uma mudança de duração pode afetar vários elementos posteriores. Porém, nem todos devem se mover: alguns possuem tempo absoluto, outros estão vinculados ao clipe visual, e faixas bloqueadas precisam permanecer intactas.
Nossa conclusão foi que cada operação precisa declarar claramente:
- qual é o limite temporal afetado;
- quais clipes participam da mudança;
- qual é a diferença exata de duração;
- quais vínculos devem ser preservados;
- como desfazer a operação.
Sem essas regras explícitas, pequenos erros acumulam e eventualmente causam dessincronização entre imagem, áudio e legendas.
2. Miniaturas também fazem parte da precisão temporal
Outro problema apareceu nas miniaturas da linha do tempo.
Escolher o quadro mais próximo parece suficiente, mas pode produzir um erro visível perto de uma mudança de cena: a miniatura mostra a próxima tomada antes de o cursor realmente alcançar o corte.
Para evitar isso, passamos a trabalhar com os timestamps reais de apresentação dos quadros. A célula sob o cursor pode utilizar o quadro correspondente ao tempo exato da mídia, aplicando o mesmo mapeamento de tempo e velocidade usado na reprodução.
Também evitamos mostrar uma única imagem ampliada enquanto as miniaturas ainda estão sendo decodificadas. O clipe permanece em estado de preparação até que o conjunto normal de quadros esteja disponível.
Essa decisão melhora a percepção de causalidade: o que aparece na linha do tempo corresponde ao que aparece no monitor de prévia.
3. Prévia e exportação precisam compartilhar as mesmas regras
Um efeito não está realmente implementado se funciona apenas na prévia e desaparece no arquivo exportado.
Por isso, tentamos utilizar os mesmos parâmetros para:
- tempo de origem;
- curvas de velocidade;
- transformações;
- keyframes;
- máscaras;
- volume e fades;
- sincronização de legendas;
- efeitos visuais e de áudio.
A prévia pode usar caminhos otimizados para interação em tempo real, enquanto a exportação processa os quadros de forma determinística. Mesmo assim, ambas precisam partir da mesma descrição do projeto.
Esse princípio também facilita a automação: uma operação estruturada na linha do tempo deve produzir o mesmo resultado quando executada pela interface ou por uma ferramenta externa.
4. Executar modelos no navegador exige mais do que converter para ONNX
Transformar um modelo em ONNX não garante que ele funcionará bem no navegador.
Alguns dos problemas que encontramos incluem:
- operadores com suporte diferente entre WebGPU e WASM;
- valores FP16 expostos de formas diferentes pelo runtime;
- modelos que funcionam em uma GPU, mas falham em outra;
- alto consumo de memória durante a criação simultânea de sessões;
- downloads duplicados do mesmo artefato;
- resultados numericamente válidos, mas perceptualmente ruins;
- inicialização mais demorada do que a própria inferência.
Uma estratégia que tem funcionado melhor é baixar artefatos em paralelo, mas criar as sessões de inferência de forma serial. Depois da inicialização, mantemos o worker e as sessões ativos para reutilização.
Também preservamos uma rota WASM quando ela é mais estável. WebGPU nem sempre é automaticamente a melhor opção: em alguns modelos, o ganho de velocidade não compensa uma perda de qualidade ou compatibilidade.
5. Cache de modelos também é parte do produto
Modelos de IA podem ocupar centenas de megabytes. Se cada worker armazenar sua própria cópia, o espaço disponível desaparece rapidamente.
Por isso, estamos centralizando a escrita persistente dos modelos, normalizando a identidade dos arquivos provenientes de diferentes espelhos e reutilizando o mesmo cache entre execuções.
Também precisamos considerar:
- espaço disponível antes do download;
- remoção de versões antigas;
- downloads interrompidos;
- atualização por revisão imutável;
- execução em memória quando o cache opcional não está disponível.
Uma mensagem genérica como “Failed to fetch” não ajuda o usuário a distinguir falta de rede, espaço insuficiente, bloqueio do provedor ou incompatibilidade do navegador. Essa parte ainda está sendo aprimorada.
O que já pode ser testado?
A versão atual reúne:
- edição de vídeo em uma linha do tempo multifaixa;
- legendas automáticas;
- narração multilíngue;
- recursos locais de áudio e visão computacional;
- filtros, máscaras, transformações e keyframes;
- separação de áudio;
- geração local de música por IA;
- exportação no navegador;
- projetos editáveis no formato
.timeline; - interface traduzida para 11 idiomas.
Alguns recursos exigem WebGPU e um navegador Chromium recente. O desempenho varia bastante conforme a GPU, a memória e o modelo utilizado.
O projeto está sob licença MIT e ainda está em desenvolvimento.
Edição controlada por agentes
Também estamos experimentando uma integração chamada edit-timeline-studio, incluída no próprio repositório.
Ela permite que um agente inspecione um projeto, proponha alterações estruturadas, apresente uma diferença semântica e produza um novo arquivo sem sobrescrever o original.
A intenção não é criar uma segunda implementação do editor. A interface, a CLI e a integração com agentes devem compartilhar as mesmas regras da linha do tempo.
Gostaríamos de ouvir outras experiências
Temos interesse especial em conversar com pessoas que já trabalharam com:
- WebGPU em aplicações reais;
- WebCodecs e timestamps de apresentação;
- ONNX Runtime Web;
- gerenciamento de modelos grandes no navegador;
- exportação determinística de mídia;
- UX de linhas do tempo;
- sincronização entre áudio, vídeo e legendas.
Quais estratégias vocês têm utilizado para lidar com diferenças entre GPUs e navegadores? Em quais situações o processamento local realmente compensa em comparação com uma arquitetura baseada em servidor?
Editor:
https://video-editor.ai-creator.top/
Código-fonte:
https://github.com/MartinDelophy/ai-video-editor
Todo feedback técnico, relato reproduzível de erro ou contribuição será muito bem-vindo.