Cum am construit Browser-Native MP4 Export
PinePaper exportă video MP4 în întregime în browser folosind WebCodecs. Iată cum funcționează conducta H.264 de la rame de pânză la un fișier video redat, fără a încărca nimic.
Problema
Instrumente de animație tradiționale bazate pe web exportă video prin trimiterea de cadre la un server, codarea lor cu ffmpeg, și returnarea rezultatului. Acest lucru are trei costuri: lărgime de bandă de încărcare (trimiterea megabytes de date cadru), calcul server (CPU/GPU timp pentru codificare) și confidențialitate (munca creativă tranzitează infrastructura unei terțe părți).
PinePaper nu face asta. Fișierul MP4 este creat în întregime în browser-ul dvs. Niciun cadru nu-ţi părăseşte dispozitivul. Codificarea se întâmplă pe codorul video hardware al maşinii tale. Acest articol explică cum.
Coduri web: Coduri video hardware în browser
The WebCodecs API [W3C, 2021] oferă acces redus la codorul și decodorul video încorporat al browserului. Acesta a fost expediat în Chrome 94 (septembrie 2021) și este acum disponibil în Chrome, Edge și Opera. Safari şi Firefox au suport parţial sau experimental [Pot utiliza, 2026].
WebCodecs expune două interfețe cheie:
VideoEncoderVideoDecoder
Pentru export MP4, folosim VideoEncoder. Fluxul de lucru:
- Creați un
VideoEncoderconfigurat pentru H.264 la rezoluția dorită și bitrate - Pentru fiecare cadru de animatie: captura panza ca un
VideoFrame, hraneste-l la codor - Colectează bucățile codificate (unități H.264 NAL)
- Mux bucăți într-un recipient MP4
- Oferă fișierul MP4 pentru descărcare
Pasul 1: Configurare codor
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
});
Codec string avc1.42E01E specifică H.264 Profilul de bază. Acesta este cel mai compatibil H.264 profil Profilele superioare (Main, High) oferă o mai bună compresie, dar mai puțină compatibilitate [Richardson, 2010].
Bitrate controlează calitatea vs dimensiunea fișierului. La 5 Mbps pentru un clip de 3 secunde: 5,000,000 bits/s × 3s = 15,000,000 bits = ~1.8 MB. Dimensiunea reală variază în funcție de complexitatea conținutului .
Pasul 2: Captarea cadrului și codificarea
Pentru fiecare cadru din cronologia animației:
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
}
Detaliile critice: după avansarea animației și redarea pânzei, trebuie să așteptați requestAnimationFrame înainte de capturare. Acest lucru asigură că GPU a terminat de compus pixeli. Fără această sincronizare, capturați un tampon vechi și produceți cadre care sunt goale sau duplicate.
Pasul 3: MP4 Muxing
VideoEncoder iese bucăţi brute H.264 (unităţi NAL). Acestea nu sunt un fişier redate .
PinePaper folosește biblioteca mp4-muxer [Vani, mp4-muxer] pentru acest pas. Muxerul primește bucăți codificate cu marcaje temporale și produce un fișier MP4 valid cu:
- Caseta
ftyp: declarația de tip de fișier (izom, izo2, mp41) - Caseta
moov: metadate de film, descrieri de cale, tabele de sincronizare - Caseta
mdat: datele video reale codificate
Rezultatul este un MP4 conform standardelor care joacă în fiecare video player, browser, și platforma de social media.
Pasul 4: Descărcare
MP4 completat este asamblat ca un Blob, convertit la un URL prin URL.createObjectURL(), și declanșat ca o descărcare:
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);
Întreaga conductă de captare a cadrului, H.264 codare, MP4 muxing, și descărcați se întâmplă în browser. Nici un server. Fără încărcare. Fără procesare de către terţi.
Performanță
Pe o MacBook Pro 2023 (M2), codând o animație 1080×1080 la 30 FPS:
| Durata | Cadre | Codează ora | Mărime fișier |
|---|---|---|---|
| 3 secunde | 90 | ~2 secunde | ~1.8 MB |
| 10 secunde | 300 | ~6 secunde | ~5 MO |
| 30 secunde | 900 | ~18 secunde | ~ 14 MO |
Codarea este mai rapidă decât în timp real, deoarece hardware-ul H.264 encodoare (Intel Quick Sync, Apple VideoToolbox, NVIDIA NVENC) manipula calculele grele. Browser-ul WebCodecs API deleagă aceste acceleratoare hardware în mod transparent [McIlroy, 2021].
Suport navigator
| Navigator | Codul web | H.264 Cod | Stare |
|---|---|---|---|
| Chrome 94+ | Da | Da | Sprijin deplin |
| Edge 94+ | Da | Da | Suport complet (Chrium) |
| Opera 80+ | Da | Da | Suport complet (Chrium) |
| Safari 16.4+ | Parţial | Decodează numai | Cod nedisponibil |
| Firefox | În spatele steagului | Nu | Experimental |
Pentru browserele fără WebCodec, PinePaper revine la exportul GIF, care utilizează un codor JavaScript pur (gif.js) și funcționează peste tot.
Referințe
- Pot folosi (2026). WebCodecs API suport browser tabel. canise.com/webcodecs.
- McIlroy, D. (2021). WebCodecs Explicationer. W3C WICG. github.com/nicerobot/nicerobot.github.io/blob/master/nicerobot-explainer-webcodecs.md.
- Richardson, I.E.G. (2010). The H.264 Advanced Video Compression Standard (2nd ed.). Wiley.
- Vani, A. mp4-muxer .
- W3C (2021). WebCodecs API Specification. w3c.github.io/webcodecs/.
Exportaţi video MP4 gratuit Deschide paper.studio/editor și încearcă.
Ready to create?
Start making animated GIFs, videos, and graphics — free, no signup.
Open PinePaper Editor