Skip to content

Obtain an ffmpeg.wasm module

afmpeg does not embed or bundle the ffmpeg WebAssembly module, and it never downloads one behind your back. You supply it — deliberately, so the module's licence (a full/GPL build links x264) never attaches to afmpeg's permissively licensed Go package (spec 0001 D-C). New returns ErrNoModule if none is given.

There are several ways to provide it. For the project's own releases, prefer the certified path; for your own builds, supply them directly.

WithModuleRelease fetches a published ffmpeg-wasi release by (tag, variant) and verifies it before it runs — the release's checksums.txt carries a detached OpenPGP signature made by a key held in AWS KMS (signable only by ffmpeg-wasi's tag pipeline), and afmpeg checks that signature against a public key pinned inside afmpeg (via gitlab.com/phpboyscout/go/signing), then the module's and provenance's checksums, then that the provenance names the variant you asked for:

var prov afmpeg.Provenance
rt, err := afmpeg.New(ctx, afmpeg.WithModuleRelease(
    "n8.1.2-11", afmpeg.VariantLGPL,
    afmpeg.WithReleaseProvenance(&prov), // optional: what was loaded
))
// prov.FFmpegVersion, prov.Variants[...] — verified, not just downloaded.

Verification is mandatory (the key is embedded — there is no skip flag). On online fetches afmpeg also cross-checks the embedded key against the copy published via WKD on openpgpkey.phpboyscout.uk — a second anchor independent of GitLab; a mismatch fails, a WKD outage falls back to the pinned key. Any tamper fails with a typed error: ErrSignatureInvalid, ErrChecksumMismatch, or ErrProvenanceMismatch. The verified module is cached, so later runs skip the download.

Options: WithReleaseProvenance (capture the verified provenance), WithReleaseProfile (select the capability profile — see below), WithReleaseBaseURL (fetch from a mirror / internal store — still verified against the pinned key), WithReleaseBundleDir (air-gapped: verify a local directory of pre-downloaded assets; skips WKD), WithReleaseWKDEmail (override the WKD identity, or "" to disable the cross-check), WithReleaseCacheDir, WithReleaseHTTPClient. See the trust model in verifying a release, or check a release yourself with verify a release by hand.

VariantLGPL is the default, proprietary-compatible build (H.264 via openh264); VariantGPL adds libx264. This path is for our releases — we can only certify what we publish; for your own builds use WithModuleURL or a file below.

Profiles: lean (default), intermediate, or full

The build comes in three capability profiles (ffmpeg-wasi spec 0022):

  • lean — web-delivery essentials at the smallest size (the default).
  • intermediate — lean plus every practical software codec, format, and filter (the LGPL encoders, the native codec/container batches, and text/subtitle burn-in).
  • full — intermediate plus the heavy encoders AV1 (SVT-AV1, both variants) and HEVC/H.265 (x265, GPL variant only). These need threads and SIMD, so full is native-only — there is no WASM full module.

Over the WASM path, WithReleaseProfile selects ProfileLean (default) or ProfileIntermediate — the intermediate build is a distinct, separately-signed asset (ffmpeg-wasi-intermediate-<variant>.wasm), fetched and verified through the identical trust chain:

rt, err := afmpeg.New(ctx, afmpeg.WithModuleRelease(
    "n8.1.2-11", afmpeg.VariantLGPL,
    afmpeg.WithReleaseProfile(afmpeg.ProfileIntermediate),
))

Omit the option (or pass afmpeg.ProfileLean) for the lean module. This is the certified equivalent of reaching for the intermediate build via WithModuleURL — same bytes, but verified against the pinned key rather than a checksum you supply.

ProfileFull is native-onlyWithModuleRelease refuses it (there is no WASM full module) and points you at the native driver. To run HEVC/AV1 encode or get native-speed software encode, load the signed native driver instead with native.NewFromRelease — the native equivalent of this whole page, verified through the same trust chain.

From a file or bytes

If you already have the .wasm on disk or in memory:

rt, err := afmpeg.New(ctx, afmpeg.WithModuleFile("ffmpeg.wasm"))
// or afmpeg.WithModuleBytes(b)
// or afmpeg.WithModuleFS(fs, "ffmpeg.wasm")  // from any afero.Fs

From a URL, with caching (no manual wrangling)

WithModuleURL downloads the module once and caches it under your OS cache dir, so subsequent runs are offline. You choose the URL and accept its licence. Because the module is executable code, pair it with WithSHA256:

rt, err := afmpeg.New(ctx, afmpeg.WithModuleURL(
    "https://gitlab.com/api/v4/projects/83847809/packages/generic/ffmpeg-wasi/n8.1.2-11/ffmpeg-wasi-lgpl.wasm",
    afmpeg.WithSHA256("160a91663696136940ebc48586ccc199f8b7c369c7a4502999174e790af8d19f"),
))

Options: WithSHA256 (verify), WithGunzip (decompress a .wasm.gz), WithCacheDir (override the cache location), WithHTTPClient (your own client, e.g. for proxies or timeouts). A checksum mismatch returns ErrChecksumMismatch and the bytes are never executed.

Where do I get a module?

  • ffmpeg-wasi (the route) — the companion libav-direct engine: current FFmpeg, published as lgpl (default) and gpl WASI modules, each with a checksum and provenance. Both encode H.264 — the lgpl module via openh264, the gpl module via libx264. Pin a release asset + its SHA-256 (the example above is the lgpl module from n8.1.2-11). It speaks the structured job spec — drive it with Command.JobSpec() / RunJob and Probe.

A GPL module makes the combined running program GPL; afmpeg keeps it at arm's length (a separate artifact you fetch), but your obligations follow the variant you choose. The lgpl module's self-compiled openh264 carries an AVC patent caveat. - Build your own — any current FFmpeg compiled to wasm32-wasi with the feature set afmpeg's runtime enables (the stable WebAssembly V2 set plus extended-const, tail-call and exception handling, the last of which carries the setjmp/longjmp lowering a real FFmpeg build needs). afmpeg runs it, and an engine that answers the vocabulary query must be recent enough — see which engine versions this afmpeg accepts.

Exact asset filenames, provenance keys, pinned key fingerprints and cache locations are in engine releases; the option defaults are in runtime options.