🧪 Cómo integrar FFmpeg en Vite para comprimir videos y audios desde el navegador


by Junior Ángeles •

La compresión de archivos multimedia es una necesidad común en aplicaciones web modernas, sobre todo cuando necesitamos enviar archivos por canales limitados como WhatsApp o email. Una solución poderosa es usar FFmpeg, una herramienta popular para procesar audio y video.

Gracias a la versión WebAssembly (WASM) de FFmpeg, podemos ejecutar este procesamiento directamente en el navegador sin necesidad de backend. En este artículo, te mostraré paso a paso cómo integrar FFmpeg en un proyecto creado con Vite para comprimir videos y audios en el navegador y convertirlos a Base64.

🧰 ¿Qué es FFmpeg?

  • FFmpeg es una suite de software libre que permite grabar, convertir y transmitir audio y video en múltiples formatos. Es ampliamente usado en entornos profesionales y proyectos multimedia. Con su versión WebAssembly (@ffmpeg/ffmpeg), es posible usarlo en aplicaciones web sin necesidad de instalar nada en el sistema del usuario.

Requisitos previos

  • Antes de comenzar, asegúrate de tener::
    • Node.js y Vite instalados.
    • Una aplicación web basada en React (aunque también funciona con otros frameworks).
    • Un poco de conocimiento básico de JavaScript.

📦 Paso 1: Instalar las dependencias

  • Ejecuta en tu terminal:
npm install @ffmpeg/ffmpeg @ffmpeg/util

Esto instala:

  • @ffmpeg/ffmpeg: la biblioteca principal que corre FFmpeg en el navegador.
  • @ffmpeg/util: herramientas de ayuda como fetchFile para leer archivos.

🏗️ Paso 2: Crear una instancia global de FFmpeg

  • Creamos un archivo para manejar la instancia compartida de FFmpeg:
// src/utils/ffmpegInstance.js
import { createFFmpeg } from "@ffmpeg/ffmpeg";

const ffmpeg = createFFmpeg({ log: true });

export default ffmpeg;

🔧 Paso 3: Crear una utilidad para convertir archivos a Base64

  • Creamos un archivo para manejar la instancia compartida de FFmpeg:
// src/utils/formats.js
export const fileToBase64 = async (file) => {
return new Promise((resolve, reject) => {

    if (!file) return reject("Archivo no válido");

const reader = new FileReader();

reader.onloadend = () => resolve(reader.result);

reader.onerror = reject;

reader.readAsDataURL(file);

});
};

🎞️ Paso 4: Crear funciones para comprimir video y audio

  • Creamos un archivo llamado compressor.js:
// src/utils/formats.js
// src/utils/compressor.js

import ffmpeg from "./ffmpegInstance";
import { fetchFile } from "@ffmpeg/util";
import { fileToBase64 } from "./formats";
// URLs del core de FFmpeg (evita problemas con WASM local)

const coreURL = "https://unpkg.com/@ffmpeg/core@0.12.10/dist/esm/ffmpeg-core.js";
const wasmURL = "https://unpkg.com/@ffmpeg/core@0.12.10/dist/esm/ffmpeg-core.wasm";

// 📼 Comprimir video

export const compressVideo = async (file) => {
if (!file) return null;
await ffmpeg.load({ coreURL, wasmURL });

      const inputData = await fetchFile(file);
      ffmpeg.writeFile("input.mp4", inputData);

      await ffmpeg.exec([
       	"-i", "input.mp4",
       	"-vcodec", "libx264",
       	"-acodec", "aac",
       	"-b:v", "400k",
       	"-b:a", "48k",
       	"-vf", "scale=360:-2",
       	"-preset", "ultrafast",
       	"-movflags", "+faststart",
       	"output.mp4"
      ]);

      const data = await ffmpeg.readFile("output.mp4");
      const blob = new Blob([data], { type: "video/mp4" });
      return await fileToBase64(blob);

};

// 🎵 Comprimir audio

export const audioCompress = async (file) => {
if (!file) return null;
await ffmpeg.load({ coreURL, wasmURL });

const inputData = await fetchFile(file);
ffmpeg.writeFile("input.mp4", inputData);

await ffmpeg.exec([
"-i", "input.mp4",
"-acodec", "aac",
"-b:a", "48k",
"output.mp4"
]);

const data = await ffmpeg.readFile("output.mp4");
const blob = new Blob([data], { type: "audio/mp4" });
return await fileToBase64(blob);
};

Paso 5: Usar la función en tu componente React

import { compressVideo } from "@/utils/compressor";

const handleUpload = async (event) => {
	const file = event.target.files[0];
	const compressedBase64 = await compressVideo(file);
	console.log("Base64 comprimido:", compressedBase64);
};
<input type="file" accept="video/*" onChange={handleUpload} />

🛠️ Configuración adicional en Vite (opcional)

  • Si llegas a tener errores relacionados con .wasm:
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
	plugins: [react()],
	assetsInclude: ["**/*.wasm"]
});

---

Este archivo `.md` ya está listo para integrarse en un blog con soporte para frontmatter (como Astro, Nuxt Content o Docusaurus). Si necesitas la versión como archivo descargable o con estilo de blog visual (como HTML estático), también puedo ayudarte.