· 5 min read

Come abbiamo costruito Browser-Native MP4 Export — Nessun server richiesto

PinePaper esporta video MP4 interamente nel browser utilizzando WebCodecs. Ecco come funziona la pipeline H.264 — da telai a un file video giocabile, senza caricare nulla.

Il problema

Tradizionale web-based strumenti di animazione esportare video inviando cornici a un server, codificandoli con ffmpeg, e restituire il risultato. Questo ha tre costi: upload larghezza di banda (in attesa di megabyte di dati frame), elaborazione del server (tempo CPU/GPU per la codifica), e privacy (il tuo lavoro creativo transita in infrastrutture di terzi).

PinePaper non fa niente di tutto questo. Il file MP4 è creato interamente nel tuo browser. Nessun frame lascia il tuo dispositivo. La codifica avviene sul codificatore video hardware della vostra macchina. Questo articolo spiega come.

WebCodecs: codifica video hardware nel browser

Il WebCodecs API [W3C, 2021] fornisce un accesso a basso livello all'encoder video integrato del browser e decoder. È stato spedito in Chrome 94 (settembre 2021) ed è ora disponibile in Chrome, Bordo e Opera. Safari e Firefox hanno un supporto parziale o sperimentale [Can I Use, 2026].

WebCodecs espone due interfacce chiave:

  • VideoEncoder — prende cornici video grezzi, uscite codificate H.264 (o VP8/VP9/AV1) bitstream
  • VideoDecoder — prende pezzi codificati, uscite cornici grezzi (utilizzati per la riproduzione, non esportare)

Per l'esportazione MP4, utilizziamo VideoEncoder. Il flusso di lavoro:

  1. Creare un VideoEncoder configurato per H.264 alla risoluzione desiderata e bitrate
  2. Per ogni cornice di animazione: catturare la tela come VideoFrame, alimentarla all'encoder
  3. Raccogliere i pezzi codificati (raw H.264 unità NAL)
  4. Mux i pezzi in un contenitore MP4
  5. Offri il file MP4 per il download

Passo 1: Configurazione codificatore

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
});

La stringa codifica avc1.42E01E specifica H.264 Baseline Profile. Questo è il profilo H.264 più ampiamente compatibile — gioca su ogni telefono, browser e piattaforma di social media. I profili più alti (Main, High) offrono una migliore compressione ma meno compatibilità [Richardson, 2010].

Il bitrate controlla la qualità vs dimensione del file. A 5 Mbps per un clip di 3 secondi: 5,000,000 bits/s × 3s = 15,000,000 bits = ~1.8 MB. Le dimensioni effettive variano in base alla complessità dei contenuti — le scene statiche comprimeno meglio del movimento rapido.

Fase 2: Cattura della cornice e codifica

Per ogni fotogramma nella timeline di animazione:

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
}

Il dettaglio critico: dopo aver avanzato l'animazione e il rendering della tela, devi aspettare requestAnimationFrame prima di catturare. Questo assicura che la GPU abbia finito i pixel compositing. Senza questa sincronizzazione, si cattura un buffer stantio e produce cornici vuote o duplicate.

Passo 3: MP4 Muxing

Il VideoEncoder emette pezzi grezzi H.264 (unità NAL). Questi non sono un file giocabile — devono essere avvolti in un contenitore MP4 che memorizza tempistiche, metadati e la configurazione codec.

PinePaper utilizza la libreria mp4-muxer [Vani, mp4-muxer] per questo passaggio. Il muxer riceve pezzi codificati con timestamp e produce un file MP4 valido con:

  • ftyp scatola: dichiarazione di tipo di file (isom, iso2, mp41)
  • moov box: metadati di film, descrizioni delle tracce, tabelle di temporizzazione
  • mdat box: i dati video codificati effettivi

Il risultato è un MP4 conforme agli standard che gioca in ogni video player, browser e piattaforma di social media.

Passo 4: Scarica

Il MP4 completato viene assemblato come Blob, convertito in URL tramite URL.createObjectURL() e attivato come 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);

L'intera pipeline — cattura frame, codifica H.264, MP4 muxing e download — avviene nel browser. Nessun server. Nessun caricamento. Nessun trattamento di terze parti.

Prestazioni

Su un MacBook Pro del 2023 (M2), codifica un'animazione 1080×1080 a 30 FPS:

Durata Cornici Encode Time Dimensione del file
3 secondi 90 - 2 secondi ~1.8 MB
10 secondi 300 - 6 secondi ~ 5 MB
30 secondi 900 18 secondi ~ 14 MB

La codifica è più veloce che in tempo reale perché gli codificatori hardware H.264 (Intel Quick Sync, Apple VideoToolbox, NVIDIA NVENC) gestiscono il calcolo pesante. WebCodecs API del browser delega a questi acceleratori hardware in modo trasparente [McIlroy, 2021].

Supporto Browser

Browser WebCodecs H.264 Codice Stato
Cromo 94+ Supporto completo
Bordo 94+ Supporto completo (Chromium)
Opera 80+ Supporto completo (Chromium)
Safari 16.4+ Particolare Decode only Encode non disponibile
Firefox Dietro la bandiera No Sperimentale

Per i browser senza WebCodecs, PinePaper torna all'esportazione GIF, che utilizza un encoder JavaScript puro (gif.js) e funziona ovunque.

Referenze

  • Posso usare (2026). Tabella di supporto del browser WebCodecs API. caniuse.com/webcodecs.
  • McIlroy, D. (2021). W3C WICG. github.com/nicerobot/nicerobot.github.io/blob/master/nicerobot-explainer-webcodecs.md.
  • Richardson, I.E.G. (2010). La norma di compressione video avanzata H.264 (2a ed.). Wiley.
  • Vani, A. mp4-muxer — JavaScript MP4 muxer per WebCodecs. github.com/nicerobot/nicerobot.github.io.
  • W3C (2021). Specificazione WebCodecs API. w3c.github.io/webcodecs/.

Esportare video MP4 gratuitamente — senza server, senza registrazione, senza filigrana. Aprire pinepaper.studio/editore e provarlo.

Ready to create?

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

Open PinePaper Editor