DEV Community

Cover image for Compiling FFmpeg to WebAssembly: Building a Zero-Backend Video & Audio Converter
thisran
thisran

Posted on Originally published at solvemymedia.com

Compiling FFmpeg to WebAssembly: Building a Zero-Backend Video & Audio Converter

Converting MOV to MP4 or extracting audio from video has historically required either:

  1. Downloading sketchy desktop software bundled with adware.
  2. Uploading files to cloud conversion websites with 100MB limits and queue timers.

By compiling FFmpeg C code to WebAssembly with Emscripten, the entire transcoding pipeline runs directly inside the client's sandboxed browser process.

We built the In-Browser Converter on SolveMyMedia.


In-Memory Media Transcode via FFmpeg WASM

import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';

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

export async function convertMediaInMemory(file, targetFormat = 'mp4') {
  if (!ffmpeg.isLoaded()) await ffmpeg.load();

  ffmpeg.FS('writeFile', 'input_raw', await fetchFile(file));
  await ffmpeg.run('-i', 'input_raw', '-c:v', 'libx264', '-preset', 'ultrafast', `output.${targetFormat}`);
  const data = ffmpeg.FS('readFile', `output.${targetFormat}`);
  return new Blob([data.buffer]);
}
Enter fullscreen mode Exit fullscreen mode

Features:

  • Convert MOV, MKV, AVI, WebM to MP4.
  • Extract MP3 and WAV audio streams in 0.3 seconds.
  • 100% client-side privacy.

Test it live:
šŸ‘‰ Converter: https://solvemymedia.com/convert-video
šŸ‘‰ Extract Audio: https://solvemymedia.com/video-to-audio

Top comments (1)

Collapse
 
mno_tao_236ab4649edf4cf9f profile image
alex.toolkit •

One thing to watch with this pattern: FS('writeFile') copies the whole input into the wasm heap, and the output sits there too, so a 1 GB MOV needs well over 2 GB of memory before the Blob is even created. Mobile Safari tends to kill the tab long before that. Mounting the File through WORKERFS avoids the input copy. Also worth unlinking input_raw and the output after each run, otherwise the second conversion starts with the first one's files still on the heap. Are you on the single-thread core, or did you set up COOP/COEP for the multi-thread build?