🧪 How to Integrate FFmpeg in Vite to Compress Videos and Audio in the Browser


by Junior Ángeles •

Compressing multimedia files is a common need in modern web applications, especially when sending them through limited channels like WhatsApp or email. A powerful solution is to use FFmpeg, a popular tool for processing audio and video.

Thanks to the WebAssembly (WASM) version of FFmpeg, we can perform this processing directly in the browser without needing a backend. In this article, I’ll show you step-by-step how to integrate FFmpeg into a project built with Vite to compress videos and audio in the browser and convert them to Base64.

🧰 What is FFmpeg?

  • FFmpeg is a free and open-source software suite used to record, convert, and stream audio and video in multiple formats. It is widely used in professional environments and multimedia projects. With its WebAssembly version (@ffmpeg/ffmpeg), it’s possible to use it in web applications without installing anything on the user’s system.

Prerequisites

  • Before getting started, make sure you have:
    • Node.js and Vite installed.
    • A web application based on React (although it also works with other frameworks).
    • Basic knowledge of JavaScript.

📦 Step 1: Install the dependencies

Run the following in your terminal:

npm install @ffmpeg/ffmpeg @ffmpeg/util

This installs:

  • @ffmpeg/ffmpeg: the main library that runs FFmpeg in the browser.

  • @ffmpeg/util: helper tools like fetchFile to read files.

🏗️ Step 2: Create a global FFmpeg instance

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

🔧 Step 3: Create a utility to convert files to Base64

  • Create a helper function:
// 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);

});
};

🎞️ Step 4: Create functions to compress video and audio

  • Create a file named 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);
};

🧪 Step 5: Use the function in your React component

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} />

🛠️ Additional configuration in Vite (optional)

  • If you run into errors related to .wasm:
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

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

Now your application will be ready to compress videos and audio directly in the browser using FFmpeg and convert them to Base64 format.


---

✅ This file is ready to be used in any documentation-based blog system like Astro, Docusaurus, or Nuxt Content.

Would you also like a downloadable version or a styled HTML export?