· 5 min read

Comment nous avons construit Navigateur-Native MP4 Export — Aucun serveur requis

PinePaper exporte la vidéo MP4 entièrement dans le navigateur en utilisant WebCodecs. Voici comment fonctionne le pipeline H.264 — des cadres de toile à un fichier vidéo jouable, sans rien télécharger.

Le problème

Les outils traditionnels d'animation Web exportent la vidéo en envoyant des images vers un serveur, en les encodant avec ffmpeg et en retournant le résultat. Cela comporte trois coûts : le téléchargement de la bande passante (envoyant des mégaoctets de données d'images), le calcul du serveur (temps CPU/GPU pour l'encodage) et la confidentialité (votre travail créatif transite l'infrastructure d'un tiers).

PinePaper ne fait rien de tout ça. Le fichier MP4 est entièrement créé dans votre navigateur. Aucun cadre ne laisse votre appareil. L'encodage se produit sur l'encodeur vidéo matériel de votre machine. Cet article explique comment.

WebCodecs: Encodage vidéo matériel dans le navigateur

Le WebCodecs API [W3C, 2021] fournit un accès de bas niveau à l'encodeur vidéo et au décodeur intégré du navigateur. Il a été expédié dans Chrome 94 (septembre 2021) et est maintenant disponible dans Chrome, Edge, et Opera. Safari et Firefox ont un support partiel ou expérimental [Puis-je utiliser, 2026].

WebCodecs expose deux interfaces clés :

  • VideoEncoder — prend des images vidéo brutes, sorties codées H.264 (ou VP8/VP9/AV1) morceaux bitstream
  • VideoDecoder — prend des morceaux encodés, sort des images brutes (utilisées pour la lecture, non pour l'exportation)

Pour l'exportation de MP4, nous utilisons VideoEncoder. Le flux de travail :

  1. Créer un VideoEncoder configuré pour H.264 à la résolution et au débit souhaités
  2. Pour chaque cadre d'animation : capturez la toile sous la forme d'un VideoFrame à l'encodeur
  3. Recueillir les morceaux encodés (ligne H.264 unités NAL)
  4. Mux les morceaux dans un conteneur MP4
  5. Offrez le fichier MP4 à télécharger

Étape 1: Configuration de l'encodeur

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 chaîne de codec avc1.42E01E spécifie le profil de base H.264. C'est le profil H.264 le plus largement compatible — il joue sur chaque téléphone, navigateur et plate-forme de médias sociaux. Des profils plus élevés (Main, High) offrent une meilleure compression mais moins de compatibilité [Richardson, 2010].

Le débit contrôle la qualité par rapport à la taille du fichier. A 5 Mbps pour un clip de 3 secondes : 5,000,000 bits/s × 3s = 15,000,000 bits = ~1.8 MB. La taille réelle varie en fonction de la complexité du contenu — les scènes statiques compressent mieux que les mouvements rapides.

Étape 2: Capture et encodage du cadre

Pour chaque cadre de la chronologie d'animation :

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
}

Le détail critique : après avoir avancé l'animation et rendu la toile, vous devez attendre requestAnimationFrame avant de capturer. Cela garantit que le GPU a fini de composer des pixels. Sans cette synchronisation, vous capturez un tampon et produisez des images vides ou dupliquées.

Étape 3: Muxing MP4

Le VideoEncoder produit des morceaux bruts de H.264 (unités NAL). Ce ne sont pas des fichiers jouables — ils doivent être enveloppés dans un conteneur MP4 qui stocke le timing, les métadonnées et la configuration du codec.

PinePaper utilise la bibliothèque mp4-muxer [Vani, mp4-muxer] pour cette étape. Le muxer reçoit des morceaux codés avec des horodatages et produit un fichier MP4 valide avec :

  • Boîte ftyp: déclaration de type de fichier (isom, iso2, mp41)
  • Boîte moov : métadonnées de films, descriptions de pistes, tables de timing
  • Boîte mdat : les données vidéo encodées

Le résultat est un MP4 conforme aux normes qui joue dans chaque lecteur vidéo, navigateur et plate-forme de médias sociaux.

Étape 4: Télécharger

Le MP4 complété est assemblé sous la forme d'un Blob, converti en un URL via URL.createObjectURL(), et déclenché en téléchargement:

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

La totalité du pipeline — capture de cadre, encodage H.264, muxing MP4 et téléchargement — se produit dans le navigateur. Pas de serveur. Pas de téléchargement. Pas de traitement par un tiers.

Rendement

Sur un MacBook Pro 2023 (M2), encodant une animation 1080×1080 à 30 FPS :

Durée Cadres Heure d'encodage Taille du fichier
3 secondes 90 ~2 secondes ~1.8 MB
10 secondes 300 ~6 secondes ~5 MO
30 secondes 900 ~18 secondes ~14 MO

L'encodage est plus rapide qu'en temps réel car les encodeurs du matériel H.264 (Intel Quick Sync, Apple VideoToolbox, NVIDIA NVENC) gèrent le calcul lourd. Le WebCodecs du navigateur API délègue à ces accélérateurs matériels de manière transparente [McIlroy, 2021].

Support du navigateur

Navigateur Codecs Web Code H.264 État
Chrome 94+ Oui Oui Soutien total
Edge 94+ Oui Oui Soutien complet (Chromium)
Opéra 80+ Oui Oui Soutien complet (Chromium)
Safari 16,4+ Partielle Décoder seulement Code non disponible
Firefox Derrière le drapeau Numéro Expérience

Pour les navigateurs sans WebCodecs, PinePaper revient à l'exportation de GIF, qui utilise un encodeur JavaScript pur (gif.js) et fonctionne partout.

Références

  • Puis-je utiliser (2026). WebCodecs API table de support du navigateur. caniuse.com/webcodecs.
  • McIlroy, D. (2021). W3C WIGG. github.com/nicerobot/nicerobot.github.io/blob/master/nicerobot-explainer-webcodecs.md.
  • Richardson, E.G. (2010). La norme H.264 de compression vidéo avancée (2e éd.). C'est Wiley.
  • Vani, A. mp4-muxer — JavaScript MP4 muxer pour WebCodecs. github.com/nicerobot/nicerobot.github.io.
  • W3C (2021). WebCodecs API Specification. w3c.github.io/webcodecs/.

Exporter gratuitement la vidéo MP4 — pas de serveur, pas d'inscription, pas de filigrane. Ouvrez pinepaper.studio/editor et essayez-le.

Ready to create?

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

Open PinePaper Editor