First
Frame

We needed a way to capture the first frame (poster) of videos. Usually, this means firing up ffmpeg on the command line, or spinning up a server to process videos. But I knew ffmpeg.wasm existed - a WebAssembly port of ffmpeg that runs entirely in the browser. This seemed like the perfect use case for a frontend-only tool.

The whole thing runs client-side. You drag a video file, it processes in the browser, and you download the result. The video never leaves your machine.

Virtual Filesystem

The interesting part is how it works under the hood. FFmpeg expects a filesystem - it needs to read input files and write output files. In the browser, there's no filesystem. So ffmpeg.wasm implements a virtual one in memory.

You write files to it like this:

await ffmpeg.writeFile('input.mp4', await fetchFile(videoFile))

Then run ffmpeg commands as if you're on the command line:

await ffmpeg.exec(['-i', 'input.mp4', '-vf', 'select=eq(n\\,0)', 'output.jpg'])

And read the results back:

const data = await ffmpeg.readFile('output.jpg')

It's all happening in memory. The video file gets loaded into the virtual filesystem, processed, and the output image is read back out as a blob. No actual files are created anywhere.

The Code

I kept the UI dead simple - just a drag and drop area, a loading overlay, and the result. No frameworks, just vanilla TypeScript, HTML, and CSS. The whole thing is maybe 200 lines of code.

The interesting thing is how uninteresting the code is. It's just: load ffmpeg, write file to virtual filesystem, run command, read result. The complexity is hidden in ffmpeg.wasm itself.

This is one of those tools that feels like it should be more complicated than it is. But with ffmpeg.wasm, video processing in the browser is just... normal now.

Published on: 2025-11-06