Build ffmpeg-wasi and run it¶
In a few minutes you'll build current FFmpeg into a single WebAssembly module and watch it run under a pure-Go runtime — no native FFmpeg, no CGO, sandboxed. This is the "it really works" tour.
What you need¶
- Docker and Go installed.
- A clone of the repo:
Step 1 — build the module¶
Docker pulls the wasi-sdk image, clones FFmpeg, compiles the libav* libraries to
wasm32-wasi, and links them with the engine. When it finishes:
That single file is FFmpeg's media stack, compiled to WebAssembly.
Step 2 — run it under wazero¶
The repo includes a small wazero harness — a pure-Go WebAssembly runtime. Run the module through it:
You'll see the engine report itself:
ffmpeg-wasi engine
ffmpeg: n8.1.2
libavcodec 4070502 libavformat 4066406 libavfilter 724582
encoders:
libx264 yes # gpl variant only (no on lgpl)
aac yes
...
decoders:
h264 yes
aac yes
...
What just happened¶
- You compiled current FFmpeg (n8.1.2) — not an end-of-life pin — to a portable
.wasm. - It ran under a pure-Go runtime: that harness cross-compiles to a single static binary with no CGO and no native FFmpeg anywhere.
- Everything executed inside the WebAssembly sandbox.
The harness in tools/run does the same two things any host must: provide the env
setjmp/longjmp imports and enable the right WebAssembly features (see
The build). In real use, afmpeg
does this for you and bridges the filesystem so you can run media jobs entirely in memory.
Next¶
- Understand the design → Why libav-direct
- Pick a release artifact instead of building → Choose & verify a variant
- The operations the engine accepts → The job-spec vocabulary
Transcoding works today
--report is just the smoke test. The engine also runs probe and the full
filter_complex process op — real decode→filter→encode→mux. From Go, drive it with
afmpeg's RunJob over an in-memory filesystem;
the job shapes are in the job-spec reference.