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 bitstreamVideoDecoder— 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 :
- Créer un
VideoEncoderconfiguré pour H.264 à la résolution et au débit souhaités - Pour chaque cadre d'animation : capturez la toile sous la forme d'un
VideoFrameà l'encodeur - Recueillir les morceaux encodés (ligne H.264 unités NAL)
- Mux les morceaux dans un conteneur MP4
- 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