· 6 min read

Hoe we Browser-Native MP4 Exporteren gebouwd hebben Geen Server vereist

PinePaper exporteert MP4 video volledig in de browser met behulp van WebCodecs. Hier is hoe de H.264 pijpleiding werkt, van canvas frames tot een afspeelbaar videobestand, zonder iets te uploaden.

Het probleem

Traditionele web-based animatietools exporteren video door frames naar een server te sturen, ze te coderen met ffmpeg en het resultaat terug te sturen. Dit heeft drie kosten: het uploaden van bandbreedte (zenden van megabytes van frame data), server compute (CPU/GPU tijd voor codering), en privacy (uw creatieve werk doorvoert een infrastructuur van derden).

PinePaper doet dit niet. Het MP4-bestand wordt volledig in uw browser aangemaakt. Geen frames verlaten uw apparaat. De codering gebeurt op de hardware video encoder van uw machine. Dit artikel legt uit hoe.

Webcodecs: Hardware Video Codering in de browser

De WebCodecs API [W3C, 2021] biedt low-level toegang tot de ingebouwde videocoder en decoder van de browser. Het werd verzonden in Chrome 94 (september 2021) en is nu beschikbaar in Chrome, Edge, en Opera. Safari en Firefox hebben gedeeltelijke of experimentele ondersteuning [Can I Use, 2026].

Webcodecs stelt twee belangrijke interfaces bloot:

  • VideoEncoder neemt ruwe videoframes, uitgangen gecodeerd H.264 (of VP8/VP9/AV1) bitstream brokken
  • VideoDecoder neemt gecodeerde brokken, geeft rauwe frames (gebruikt voor afspelen, niet exporteren)

Voor MP4 export gebruiken we VideoEncoder. De workflow:

  1. Maak een VideoEncoder geconfigureerd voor H.264 met de gewenste resolutie en bitrate
  2. Voor elk animatieframe: neem het canvas vast als een VideoFrame, voer het naar de encoder
  3. Verzamel de gecodeerde brokken (trek H.264 NAL eenheden)
  4. Mux de brokken in een MP4 container
  5. Het MP4-bestand aanbieden om te downloaden

Stap 1: Encoderconfiguratie

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

De codec string avc1.42E01E specificeert het H.264 basisprofiel. Dit is het meest compatibele H.264 profiel het speelt op elke telefoon, browser en social media platform. Hogere profielen (Main, High) bieden betere compressie maar minder compatibiliteit [Richardson, 2010].

De bitrate controleert kwaliteit vs bestandsgrootte. Bij 5 Mbps voor een 3-seconde clip: 5,000,000 bits/s × 3s = 15,000,000 bits = ~1.8 MB. De werkelijke grootte varieert op basis van de complexiteit van de inhoud statische scènes comprimeren beter dan snelle beweging.

Stap 2: Frame Capture en codering

Voor elk frame in de animatietijdlijn:

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
}

Het kritische detail: na het oprukken van de animatie en het renderen van het canvas, moet je wachten op requestAnimationFrame voordat je het oppakt. Hierdoor is de GPU klaar met compositing pixels. Zonder deze synchronisatie vangt u een oude buffer op en produceert u frames die leeg of gedupliceerd zijn.

Stap 3: MP4 Muxing

De VideoEncoder levert ruwe H.264 brokken (NAL eenheden). Dit is geen afspeelbaar bestand ze moeten verpakt worden in een MP4 container die timing, metadata en de codec configuratie opslaat.

PinePaper gebruikt de mp4-muxer bibliotheek [Vani, mp4-muxer] voor deze stap. De muxer ontvangt gecodeerde brokken met tijdstempels en produceert een geldig MP4 bestand met:

  • ftyp doos: bestandstype aangifte (isom, iso2, mp41)
  • moov doos: filmmetadata, track beschrijvingen, timing tabellen
  • mdat-doos: de eigenlijke gecodeerde videogegevens

Het resultaat is een norm-compliant MP4 dat speelt in elke videospeler, browser en social media platform.

Stap 4: Downloaden

De voltooide MP4 wordt samengesteld als een Blob, omgezet in een URL via URL.createObjectURL(), en geactiveerd als een 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);

De hele pijplijn frame capture, H.264 encoding, MP4 muxing, en downloaden gebeurt in de browser. Geen server. Geen upload. Geen verwerking van derden.

Prestaties

Op een 2023 MacBook Pro (M2), codering van een 1080×1080 animatie op 30 FPS:

Duur Frames Tijd coderen Bestandsgrootte
3 seconden 90 2 seconden ~1.8 MB
10 seconden 300 ~6 seconden ~5 MB
30 seconden 900 ~18 seconden ~14 MB

Encoding is sneller dan real-time omdat hardware H.264 encoders (Intel Quick Sync, Apple VideoToolbox, NVIDIA NVENC) de zware berekening verwerken. De webcodecs van de browser API gedelegeerden transparant aan deze hardwareversnellers [Mclroy, 2021].

Kies een lengte. Beide bars delen een schaal, dus de encodeer bar zittend in de clip bar is de claim en de overgang tussen de drie toont het werk groeien in verhouding tot de frames, dat is het deel een enkele rij kan niet tonen.

Interactive demo — open in editor pp:PinePaper

Browserondersteuning

Browser Webcodecs H.264 Coderen Status
Chrome 94+ Ja Ja Volledige steun
Rand 94+ Ja Ja Volledige ondersteuning (Chromium)
Opera 80+ Ja Ja Volledige ondersteuning (Chromium)
Safari 16,4+ Gedeeltelijk Alleen decoderen Coderen niet beschikbaar
Firefox Achter vlag Nee Experimenteel

Voor browsers zonder WebCodecs, PinePaper valt terug naar GIF export, die gebruik maakt van een pure JavaScript encoder (gif.js) en overal werkt.

Referenties

  • Kan ik gebruiken (2026). WebCodcs API browser ondersteuning tabel. caniuse.com/webcodecs.
  • McIlroy, D. (2021). Webcodecs Leg uit. W3C WICG. github.com/nicerobot/nicerobot.github.io/blob/master/nicerobot-explainer-webcodecs.md.
  • Richardson, IEG. (2010). * The H.264 Advanced Video Compression Standard* (2nd ed.). Wiley.
  • Vani, A. mp4-muxer JavaScript MP4 muxer voor WebCodecs. github.com/nicerobot/nicerobot.github.io.
  • W3C (2021). Webcodecs API Specificatie. w3c.github.io/webcodecs/.

Exporteer gratis MP4-video geen server, geen aanmelding, geen watermerk. Open pinepaper.studio/editor en probeer het.

Ready to create?

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

Open PinePaper Editor