Installation
Install wasmpeg and get a first decode running — npm or CDN, in a bundler, a framework, or Node, with no build step and no special server headers.
wasmpeg ships as an ES module with the WASM binaries alongside it. No build step, no SharedArrayBuffer, no COOP/COEP headers, and no worker setup are required.
Quick install
Install the package.
Use
wasmpeg-fullinstead if you need H.264/H.265 encode (GPL) — see which package.Import it and load the module once.
import wasmpeg from 'wasmpeg'; await wasmpeg.load();load()fetches and initializes the WASM. It’s safe to call again — later calls resolve immediately.Decode something.
const info = await wasmpeg.probe(file); // File / Blob / URL / Uint8Array const dec = await wasmpeg.decode(file); const frame = dec.nextFrame(); // Uint8ClampedArray of RGBA8 dec.close();
That’s the whole setup. From here, the quick start covers decode, scale, probe, audio, and thumbnails.
Which package
The import surface is identical between them; only the codec set differs. Code written
against wasmpeg runs unchanged against wasmpeg-full — you only swap the package when you
specifically need x264/x265 encode and can meet the GPL terms.
wasmpeg | wasmpeg-full | |
|---|---|---|
| License | LGPL-2.1-or-later | GPL-2.0-or-later |
| H.264 / H.265 decode | Yes | Yes |
| H.264 / H.265 encode | No | Yes (libx264 / libx265) |
| Use for closed-source | Yes | Only under GPL terms |
| Import surface | Identical | Identical |
Loading the module
load() does three things: detects the environment, picks a build, and instantiates the
WASM. You await it once before any other call.
await wasmpeg.load();
It’s idempotent — call it from every module that needs wasmpeg if that’s simpler than
threading a “ready” flag around; only the first call does real work. The same is true of
the gpu namespace and the FFmpeg class, which share the one module instance.
If a browser can’t instantiate the module (no WebAssembly SIMD support), the failure surfaces
as a rejected load() promise, before any decode runs. Wrapping the first load() in a
try/catch is the simplest capability check — see Browser support.
Serving the WASM
The package contains dist/cpu.js and dist/cpu.wasm (plus webgpu.js / webgpu.wasm for
the GPU build). At runtime, the .js loads its .wasm from the same directory. How that
directory is served depends on your setup:
The wasmPath option
load() accepts { wasmPath } — a URL to the loader .js, with the matching .wasm
expected in the same directory. Reach for it when your bundler fingerprints or relocates
assets and the default same-directory resolution can’t find the binary. Point it at the .js
file; the loader derives the .wasm name from it.
// Serving the dist folder yourself at /vendor/wasmpeg/
await wasmpeg.load({ wasmPath: '/vendor/wasmpeg/cpu.js' });
If you’ve copied the WebGPU build instead, point at webgpu.js. When wasmPath is omitted,
the loader chooses webgpu.js where navigator.gpu exists and cpu.js otherwise.
cpu.wasm (a 404 in the network tab).
The fix is always the same: make sure the .wasm is served next to the .js, or pass an
explicit wasmPath. See Troubleshooting.Requirements
- Browsers — any with WebAssembly + SIMD128: Chrome 91+, Firefox 89+, Safari 16.4+. WebGPU scaling additionally needs a WebGPU-capable browser; everything else falls back to CPU. Full matrix in Browser support.
- Node — ≥ 18 (uses built-in
fetch/fs; no native addons).
No headers, no cross-origin isolation, and no Web Worker are required. wasmpeg runs on an ordinary static host and on the main thread (or any worker you choose to put it in).
Verify the install
A quick end-to-end check that the package resolved and the WASM loads:
await wasmpeg.load();
console.log('wasmpeg loaded'); // if this prints, the module instantiated
If load() rejects in the browser, it’s almost always one of two things: the runtime lacks
SIMD (an old browser), or the .wasm 404’d. The network tab tells you which.