· 5 min read

Como construímos o navegador-Native MP4 Export — Nenhum servidor necessário

PinePaper exporta vídeo MP4 inteiramente no navegador usando WebCodecs. Veja como funciona o gasoduto H.264 — desde quadros de tela até um arquivo de vídeo jogável, sem carregar nada.

O Problema

Ferramentas tradicionais de animação baseadas na web exportam vídeo enviando quadros para um servidor, codificando-os com ffmpeg e retornando o resultado. Isso tem três custos: largura de banda de upload (enviar megabytes de dados de frame), computação do servidor (tempo PCU/GPU para codificação) e privacidade (seu trabalho criativo transita a infraestrutura de um terceiro).

O PinePaper não faz nada disto. O arquivo MP4 é criado inteiramente em seu navegador. Nenhuma armação deixa o dispositivo. A codificação acontece no codificador de vídeo de hardware da sua máquina. Este artigo explica como.

WebCodecs: codificação de vídeo de hardware no navegador

O WebCodecs API [W3C, 2021] fornece acesso de baixo nível ao codificador de vídeo e decodificador incorporado do navegador. Ele foi enviado no Chrome 94 (setembro 2021) e agora está disponível no Chrome, Edge e Opera. Safari e Firefox têm suporte parcial ou experimental [Posso usar, 2026].

WebCodecs expõe duas interfaces chave:

  • VideoEncoder — leva quadros de vídeo brutos, saídas codificadas H.264 (ou VP8/VP9/AV1) blocos de bitstream
  • VideoDecoder — pega pedaços codificados, sai quadros brutos (utilizados para reprodução, não exportação)

Para exportação MP4, usamos VideoEncoder. O fluxo de trabalho:

  1. Crie um VideoEncoder configurado para H.264 na resolução desejada e taxa de bits
  2. Para cada quadro de animação: captura a tela como um VideoFrame, alimenta-a ao codificador
  3. Recolha os blocos codificados (unidades H.264 NAL em bruto)
  4. Mux os pedaços em um recipiente MP4
  5. Oferecer o arquivo MP4 para download

Passo 1: Configuração do codificador

const encoder = new VideoEncoder({
  output: (chunk, metadata) => {
    // chunk.data contains encoded H.264 bytes
    // metadata.decoderConfig contains SPS/PPS on first chunk
    muxer.addVideoChunk(chunk, metadata);
  },
  error: (e) => console.error('Encoder error:', e)
});

encoder.configure({
  codec: 'avc1.42E01E',  // H.264 Baseline Profile Level 3.0
  width: 1080,
  height: 1080,
  bitrate: 5_000_000,    // 5 Mbps
  framerate: 30
});

O texto de codec avc1.42E01E especifica H.264 Perfil de base. Este é o perfil H.264 mais amplamente compatível — ele joga em cada telefone, navegador e plataforma de mídia social. Perfis mais elevados (Main, High) oferecem melhor compressão, mas menos compatibilidade [Richardson, 2010].

A taxa de bits controla a qualidade vs tamanho do arquivo. A 5 Mbps para um clipe de 3 segundos: 5,000,000 bits/s × 3s = 15,000,000 bits = ~1.8 MB. O tamanho real varia com base na complexidade de conteúdo — cenas estáticas comprimem melhor do que movimento rápido.

Passo 2: Captura de quadros e codificação

Para cada quadro na linha do tempo de animação:

for (let frameNum = 0; frameNum < totalFrames; frameNum++) {
  const frameTime = frameNum / fps;

  // Advance animation to this time
  app.setPlaybackTime(frameTime);
  paper.view.draw();  // Full render (not view.update!)
  await new Promise(r => requestAnimationFrame(r));  // Wait for paint

  // Create VideoFrame from canvas
  const frame = new VideoFrame(canvas, {
    timestamp: frameNum * (1_000_000 / fps)  // microseconds
  });

  // Encode (keyframe every 2 seconds)
  encoder.encode(frame, {
    keyFrame: frameNum % (fps * 2) === 0
  });
  frame.close();  // Release GPU memory
}

O detalhe crítico: após avançar a animação e renderizar a tela, você deve esperar pelo requestAnimationFrame antes de capturar. Isso garante que a GPU tenha terminado a composição de pixels. Sem essa sincronização, você captura um buffer velho e produz quadros em branco ou duplicados.

Passo 3: MP4 Muxing

O codificador de vídeo produz pedaços brutos de H.264 (unidades NAL). Estes não são um arquivo jogável — eles precisam ser embrulhados em um recipiente MP4 que armazena o tempo, metadados e a configuração do codec.

PinePaper usa a biblioteca mp4-muxer [Vani, mp4-muxer] para esta etapa. O muxer recebe blocos codificados com timestamps e produz um arquivo MP4 válido com:

  • Caixa ftyp: declaração do tipo de ficheiro (isom, iso2, mp41)
  • Caixa moov: metadados de filmes, descrições de faixas, tabelas de tempo
  • Caixa mdat: os dados de vídeo codificados

O resultado é um MP4 compatível com padrões que joga em cada player de vídeo, navegador e plataforma de mídia social.

Passo 4: Baixar

O MP4 completo é montado como um Blob, convertido para um URL via URL.createObjectURL(), e acionado como um download:

await encoder.flush();  // Wait for all frames to encode
const mp4Blob = muxer.finalize();
const url = URL.createObjectURL(new Blob([mp4Blob], { type: 'video/mp4' }));

const a = document.createElement('a');
a.href = url;
a.download = 'animation.mp4';
a.click();
URL.revokeObjectURL(url);

Todo o pipeline — captura de quadros, codificação H.264, muxing MP4 e download — acontece no navegador. Sem servidor. Sem upload. Nenhum processamento de terceiros.

Desempenho

Em um 2023 MacBook Pro (M2), codificando uma animação 1080×1080 em 30 FPS:

Duração Molduras Codificar hora Tamanho do Ficheiro
3 segundos 90 ~2 segundos ~1.8 MB
10 segundos 300 ~6 segundos ~5 MB
30 segundos 900 ~18 segundos ~ 14 MB

A codificação é mais rápida do que em tempo real porque os codificadores de hardware H.264 (Intel Quick Sync, Apple VideoToolbox, NVIDIA NVENC) lidam com a computação pesada. Os delegados WebCodecs API do navegador a estes aceleradores de hardware de forma transparente [McIlroy, 2021].

Suporte ao navegador

Navegador WebCodecs Código H.264 Estado
Chrome 94+ Sim Sim Suporte completo
Contorno 94+ Sim Sim Suporte total (Crômio)
Opera 80+ Sim Sim Suporte total (Crômio)
Safari 16,4+ Parcial Apenas decodificar Codificar não disponível
Firefox Atrás da bandeira Não Experimental

Para navegadores sem WebCodecs, o PinePaper retorna à exportação GIF, que usa um codificador JavaScript puro (gif.js) e funciona em qualquer lugar.

Referências

  • Posso usar (2026). WebCodecs API tabela de suporte ao navegador. caniuse.com/webcodecs.
  • McIlroy, D. (2021). WebCodecs Explainer. W3C WICG. github.com/nicerobot/nicerobot.github.io/blob/master/nicerobot-explicador-webcodecs.md.
  • == Ligações externas == * H.264 Advanced Video Compression Standard* (2nd ed.). Wiley.
  • Vani, A. mp4-muxer — JavaScript MP4 muxer for WebCodecs. github.com/nicerobot/nicerobot.github.io.
  • W3C (2021). Especificação WebCodecs API. w3c.github.io/webcodecs/.

Exportar vídeo MP4 gratuitamente — sem servidor, sem inscrição, sem marca d'água. Abra pinepaper.studio/editor e experimente.

Ready to create?

Start making animated GIFs, videos, and graphics — free, no signup.

Open PinePaper Editor