When we moved video processing out of our servers and into the browser tab, I expected a weekend project. It was two weeks of dead ends, and the architecture lessons were worth more than the feature. Here's the honest account.
Dead end 1: SharedArrayBuffer. The 0.11-generation ffmpeg.wasm core wants SharedArrayBuffer, which demands site-wide COOP/COEP headers — and those headers silently break every third-party embed on your site. One video tool nuking your analytics iframes is a bad trade. We moved to the single-threaded 0.12 core: no SAB, no headers.
Dead end 2: CDN workers. new Worker('https://unpkg.com/...') throws SecurityError from any http origin. The blob-classURL workaround people blog about? Ignored by 0.12.10. Workers must be same-origin, period. We vendor the engine: /assets/vendor/ffmpeg/ served once, cached aggressively.
Dead end 3: UMD in a module worker. The error failed to import ffmpeg-core.js with zero detail means exactly one thing: you served the UMD core to a module worker, which does await import(coreURL) and reads .default — which UMD doesn't export. Serve the ESM core build. That's the whole fix.
The bill, honestly stated. 35 MB of vendored WASM (one-time, cached), conversion speed bound to the user's CPU, and honest UX limits — a browser merges two clips beautifully, not twenty. What you get in exchange is the property that matters: files never transmitted, never stored, never logged, because there is nowhere to transmit them to. Analytics stay anonymous; the Network tab shows zero file bytes leaving the device.
Where to see it running. The same engine powers our live tools: video compression (https://toolfyra.com/video-compressor.html), format conversion (https://toolfyra.com/video-converter.html), trimming (https://toolfyra.com/video-trimmer.html), merging (https://toolfyra.com/video-merger.html), audio extraction (https://toolfyra.com/video-to-audio.html), and audio conversion (https://toolfyra.com/audio-converter.html). Drag a file into any of them and watch the Network tab — that's the demo.
The transferable lesson. Client-side isn't a gimmick tier; for media workloads it's the privacy architecture, and the constraints it forces — vendoring, chunking, honest limits, progress events — make the product better, not worse. If you're building anything that touches user files in 2026, ask the question before you ship: does this file actually need a server? More often than not, the answer is no.
The full page index, if you want to browse everything built this way: https://toolfyra.com/sitemap.xml.
Top comments (0)