I Tried Running File Conversion Fully in the Browser (WASM, LibreOffice, FFmpeg)
Source: Dev.to
Intro – The Problem
Most online file converters work the same way: you upload your file, wait, then download the result. That raises privacy concerns and doubles transfer time for large files (upload + download = double the time).
Personal context: I’m an audio producer and needed to convert some legacy audio formats for a project. I tried five different converter sites but none of them supported the formats I needed—or they hit me with endless pop‑ups and CAPTCHA walls. The whole experience felt quite sketchy, so I thought: there has to be a better way. Turns out there is—but it’s not as simple as I thought.
I wondered: how much of this can realistically run in the browser?
Turns out: more than I expected, but with hard limits nobody talks about.
The LibreOffice WASM Dream (That Didn’t Work)
My first idea: compile LibreOffice head‑less to WebAssembly. It’s the Swiss‑army knife for document conversion (DOCX, ODT, PDF, PPTX …). If I could get it running in the browser, I’d be done.
Reality check
| Metric | Observation |
|---|---|
| Minimum binary size | ~150 MB (even stripped) |
| Startup time | 10–15 s just to initialise |
| Memory usage | 200–300 MB for a single DOCX → PDF conversion |
| Browser memory ceiling | ~500 MB before crashes |
Converting a single file? Not realistic today in a production browser environment.
What Actually Works in the Browser
Instead, I went format‑by‑format. Here’s what I got working:
Video / Audio
FFmpeg.wasm (~20 MB WASM binary)
- Performance: ~10–20 % of native FFmpeg
- Example: MP3 conversion takes ~10 s (native: 1 s)
- Trade‑off: slower, but files never leave the device
Images
Sharp.wasm + image‑js + canvg
- Performance: image resize ~2 s (native: 0.2 s)
- Handles: PNG, JPEG, WebP, SVG → PNG, GIF
PDFs
- pdf‑lib – creation / manipulation
- pdf.js – rendering / text extraction
Works great for simple operations (merge, split, text extraction). Fails on complex PDFs with embedded fonts/forms.
Spreadsheets
SheetJS (xlsx.full.min.js)
- Parses / creates Excel, CSV, ODS in the browser
- Limitation: large files (> 10 MB) freeze the UI
Archives
JSZip + pako + tar.js
- ZIP / GZIP / TAR creation / extraction
- Fast enough for most use cases
Optimization strategy
// Lazy‑load WASM modules on demand
let ffmpegLoaded = false;
const loadFFmpeg = async () => {
if (!ffmpegLoaded) {
await import('@ffmpeg/ffmpeg');
ffmpegLoaded = true;
}
};
// Total WASM payload: ~30 MB
// Initial bundle: 150 KB
The Performance Win I Didn’t Expect
Problem: MP4 → MOV conversion timed out after > 10 min. Full re‑encoding with FFmpeg.wasm is just too slow.
Solution: Container remux instead of re‑encode.
// Check if codecs are compatible
const compatibleContainers = {
mp4: ['mov', 'mkv'],
mov: ['mp4', 'mkv'],
mkv: ['mp4', 'mov'],
};
if (compatibleContainers[from].includes(to)) {
// Stream copy instead of re‑encode
ffmpegOptions.push('-c', 'copy');
// Result: {
// Browser‑side (≈ 90 % of conversions)
if (category === 'image') return false;
if (category === 'audio') return false;
if (category === 'video' && fileSize 100_000_000) return true; // Too large
return false;
};
Server‑side stack
- LibreOffice (headless) – Office docs
- Pandoc – Markdown / LaTeX / EPUB
- Native FFmpeg – Large videos
- Poppler (
pdftoppm,pdftotext) – Complex PDFs - ClamAV – Malware scanning on all uploads (auto‑reject infected files, delete after 5 min)
Why hybrid?
- Pure client‑side → unrealistic for complex formats, large files, and memory limits.
- Pure server‑side → privacy nightmare + infrastructure cost.
- Hybrid → best UX + reasonable privacy trade‑off.
The Real Trade‑offs
Client‑Side
| Pros | Cons |
|---|---|
| Privacy (files never leave device) | 10–20 % of native performance |
| Zero infrastructure cost | Memory limits (~50 MB practical ceiling) |
| Instant conversion (no upload wait) | Browser compatibility hell |
| Some formats impossible (Office docs) |
Server‑Side
| Pros | Cons |
|---|---|
| Full native performance | Files must be uploaded (privacy concerns) |
| Unlimited file size | Infrastructure cost |
| Complex formats supported | Latency from upload / download |
End of cleaned markdown.
Side Cons
- Privacy concerns (uploads)
- Infrastructure costs
- Upload/download overhead
Client
├── FFmpeg.wasm
├── Image tooling
├── PDF manipulation
└── SheetJS
↓ (fallback)
Server
├── LibreOffice
├── Pandoc
├── Native FFmpeg
└── Poppler
Key Takeaways
- Pure browser‑side is possible for ~90 % of conversions (images, audio, simple video)
- LibreOffice WASM is still unrealistic / unstable in 2026 (too large, too slow, too browser/platform‑dependent)
- Hybrid architecture is the pragmatic solution (browser‑first, server fallback)
- Container remux > re‑encode when possible (≈ 100× speedup)
- Memory limits are the real bottleneck, not CPU
If you’re building something similar: start with WASM, fall back to server only when necessary, and be honest with users about what runs where.
What I Built
Based on these experiments, I packaged this hybrid approach into a small project to test it in production.
Tech stack
- Frontend: Next.js (static), FFmpeg.wasm, Sharp.wasm, pdf‑lib, SheetJS
- Backend: Node/Express, LibreOffice, Pandoc, ClamAV, Redis
- Hosting: Cloudflare CDN (frontend), EU server (backend)
→ If you’re curious: anythingconverter.com
Questions?
I’m especially curious if anyone has cracked LibreOffice WASM or found better ways to handle large files in the browser.