· 5 min read

Cómo construimos Navegador-Native MP4 Export — No se requiere servidor

PinePaper exporta vídeo MP4 completamente en el navegador utilizando WebCodecs. Así es como funciona el oleoducto H.264, desde marcos de tela hasta un archivo de vídeo jugable, sin subir nada.

El problema

Herramientas de animación tradicionales basadas en la web exportan vídeo enviando marcos a un servidor, codificandolos con ffmpeg y devolviendo el resultado. Esto tiene tres costos: subir ancho de banda ( megabytes de datos de marco), computador de servidor (CPU/GPU para codificación), y privacidad (su trabajo creativo transita la infraestructura de un tercero).

PinePaper no hace nada de esto. El archivo MP4 se creó completamente en su navegador. No hay marcos que dejen su dispositivo. La codificación ocurre en el encoder de vídeo de hardware de su máquina. Este artículo explica cómo.

WebCodecs: Codificación de video en el navegador

El WebCodecs API [W3C, 2021] proporciona acceso de bajo nivel al codificador y decodificador de vídeo incorporado del navegador. Fue enviado en Chrome 94 (septiembre 2021) y ahora está disponible en Chrome, Edge, y Opera. Safari y Firefox tienen soporte parcial o experimental [Can I Use, 2026].

WebCodecs expone dos interfaces clave:

  • VideoEncoder — toma marcos de vídeo crudos, salidas codificadas H.264 (o VP8/VP9/AV1) trozos de bitstream
  • VideoDecoder — toma trozos codificados, produce marcos crudos (utilizados para la reproducción, no para la exportación)

Para la exportación MP4, utilizamos VideoEncoder. El flujo de trabajo:

  1. Crear un VideoEncoder configurado para H.264 en la resolución deseada y bitrate
  2. Para cada marco de animación: capturar el lienzo como un VideoFrame, alimentarlo al encoder
  3. Recoger los trozos codificados (fuerzos H.264 NAL)
  4. Mux los trozos en un contenedor MP4
  5. Ofrezca el archivo MP4 para descargar

Paso 1: Configuración de encoder

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 cadena codec avc1.42E01E especifica H.264 Perfil Baseline. Este es el perfil H.264 más compatible — juega en cada teléfono, navegador y plataforma de redes sociales. Los perfiles más altos (Main, High) ofrecen una mejor compresión pero menos compatibilidad [Richardson, 2010].

El bitrate controla la calidad vs tamaño del archivo. A 5 Mbps para un clip de 3 segundos: 5,000,000 bits/s × 3s = 15,000,000 bits = ~1.8 MB. El tamaño real varía según la complejidad del contenido — las escenas estáticas se comprime mejor que el movimiento rápido.

Paso 2: Captura del marco y codificación

Para cada marco en la línea de tiempo de animación:

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
}

El detalle crítico: después de avanzar la animación y renderizar el lienzo, debe esperar a requestAnimationFrame antes de capturar. Esto asegura que la GPU ha terminado de componer píxeles. Sin esta sincronización, usted captura un búfer establo y produce marcos que están en blanco o duplicados.

Paso 3: MP4 Muxing

El VideoEncoder produce trozos H.264 crudos (unidades NAL). Estos no son un archivo jugable — necesitan ser envueltos en un contenedor MP4 que almacena el tiempo, metadatos y la configuración codec.

PinePaper utiliza la biblioteca mp4-muxer [Vani, mp4-muxer] para este paso. El muxer recibe trozos codificados con timetamps y produce un archivo MP4 válido con:

  • ftyp: declaración del tipo de archivo (isom, iso2, mp41)
  • moov: metadatos de películas, descripciones de pistas, tablas de tiempo
  • mdat: los datos de vídeo codificados

El resultado es un MP4 compatible con estándares que juega en cada reproductor de vídeo, navegador y plataforma de redes sociales.

Paso 4: Descargar

El MP4 completado se monta como un Blob, convertido a un URL vía URL.createObjectURL(), y activado como una descarga:

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

Todo el oleoducto — captura de marco, codificación H.264, muxing MP4 y descarga— ocurre en el navegador. No hay servidor. No suba. Sin procesamiento de terceros.

Ejecución

En un 2023 MacBook Pro (M2), codificando una animación 1080×1080 a 30 FPS:

Duración Frames Tiempo de codificación Tamaño del archivo
3 segundos 90 ~2 segundos ~1.8 MB
10 segundos 300 ~6 segundos ~5 MB
30 segundos 900 ~18 segundos ~14 MB

La codificación es más rápida que en tiempo real porque los encoders de hardware H.264 (Intel Quick Sync, Apple VideoToolbox, NVIDIA NVENC) manejan la computación pesada. Los delegados de WebCodecs API del navegador a estos aceleradores de hardware transparentemente [McIlroy, 2021].

Soporte de navegador

Navegador WebCodecs H.264 Encode Situación
Chrome 94+ Apoyo completo
Edge 94+ Soporte completo (Chromium)
Opera 80+ Soporte completo (Chromium)
Safari 16.4+ Parcial Decodificar sólo Código no disponible
Firefox Detrás de bandera No Experimental

Para los navegadores sin WebCodecs, PinePaper vuelve a la exportación GIF, que utiliza un encoder de JavaScript puro (gif.js) y funciona en todas partes.

Referencias

  • ¿Puedo usar (2026). WebCodecs API tabla de soporte del navegador. caniuse.com/webcodecs.
  • McIlroy, D. (2021). WebCodecs Explainer. 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 (2a edición). Wiley.
  • Vani, A. mp4-muxer — JavaScript MP4 muxer for WebCodecs. github.com/nicerobot/nicerobot.github.io.
  • W3C (2021). Especificación API WebCodecs. w3c.github.io/webcodecs/.

Exportar vídeo MP4 gratis — ningún servidor, ninguna señalización, ninguna marca de agua. Abrir pinepaper.studio/editor y probarlo.

Ready to create?

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

Open PinePaper Editor