Originally published at ffmpeg-micro.com
ffmpeg.wasm looks like magic the first time you see it. Run FFmpeg right in the browser. No server, no install, no infrastructure. Your user picks a file, you process it client-side, and nobody's video ever leaves their machine.
Then someone uploads a 200MB file and the tab crashes.
What ffmpeg.wasm actually is
ffmpeg.wasm is a WebAssembly port of FFmpeg that runs entirely in the browser. Your JavaScript can do this:
import { FFmpeg } from '@ffmpeg/ffmpeg';
const ffmpeg = new FFmpeg();
await ffmpeg.load();
await ffmpeg.writeFile('input.mp4', videoData);
await ffmpeg.exec(['-i', 'input.mp4', '-vf', 'scale=640:360', 'output.mp4']);
const data = await ffmpeg.readFile('output.mp4');
No server call. No API key. The entire operation happens in the user's browser tab.
Where ffmpeg.wasm works well
For small, quick operations on small files:
- Thumbnail extraction from short clips (under 50MB)
- Format detection and metadata inspection
- Quick trims of short videos
- Privacy-sensitive workflows where video can't leave the device
The five walls you'll hit
1. Memory ceiling
A 500MB video needs at least 500MB of RAM just for the input. The practical limit is roughly 100-200MB per file on desktop, less on mobile.
2. Single-threaded performance
A transcode that takes 30 seconds on a server can take 5-10 minutes in the browser. Multi-threaded builds require SharedArrayBuffer and specific CORS headers that break third-party embeds.
3. Codec limitations
The Wasm build doesn't include every codec. Licensing and binary size constraints mean you get a subset.
4. Mobile is unreliable
Mobile browsers have tighter memory limits and more aggressive tab killing. A transcode that works on your MacBook will crash Safari on an iPhone 12.
5. No batch processing
Processing 50 files means the user keeps the tab open. Any browser crash kills the entire batch.
Comparison table
| Factor | ffmpeg.wasm | Hosted FFmpeg API |
|---|---|---|
| Max file size | ~100-200MB | No practical limit |
| Processing speed | 5-10x slower | Server-grade |
| Mobile support | Unreliable | Works everywhere |
| Batch processing | Manual, fragile | Built-in queuing |
| Privacy | Video stays on device | Video uploaded to server |
| Cost | Free (client CPU) | Pay per minute processed |
The hybrid approach
Use ffmpeg.wasm for lightweight client-side ops and route heavier work to an API:
const FILE_SIZE_THRESHOLD = 50 * 1024 * 1024; // 50MB
async function processVideo(file) {
if (file.size < FILE_SIZE_THRESHOLD) {
return processClientSide(file); // ffmpeg.wasm
}
return processServerSide(file); // FFmpeg Micro API
}
Read the full post with detailed analysis on ffmpeg-micro.com.
Top comments (0)