Reference

Building from source

Building from source

The published npm package ships compiled WebAssembly, so using the library needs no build step. Build from source only when you want to audit the toolchain, pin a different libopus, or hack on the bindings.

#Prerequisites

  • Emscripten (emcc) on your PATH; CI uses version 6.0.10.
  • pnpm — the repo's package manager.
  • Node.js 22.12 or newer for the test toolchain. The published library still supports Node.js 22 or newer.

Verify the toolchain:

emcc --version
pnpm --version

#Build

pnpm install
pnpm build

pnpm build runs three steps:

  1. build:wasm — node scripts/build-libopus-wasm.mjs downloads **libopus
  2. 1.6.1** from Xiph.Org, verifies it against a pinned SHA-256, compiles it with Emscripten, and emits a single-file ES module into src/generated/.

  3. tsc — type-checks and compiles the TypeScript in src/ to dist/.
  4. copy-generated — copies the generated WASM module into dist/.

The result in dist/ is exactly what gets published.

#Test

pnpm test

This rebuilds the WASM module and runs the Vitest suite, which exercises encode/decode roundtrips, Float32 paths, FEC and PLC, CTL validation, error handling, and the discord.js adapter.

Type-check without emitting:

pnpm typecheck

#Clean

pnpm clean   # removes dist/ and the .cache/ build directory

The first build downloads and extracts libopus into .cache/; later builds reuse that source. Every build recompiles libopus and the wrapper. pnpm clean also removes the cached download and source.

#How the WASM is packaged

The build emits a single-file ES module with the .wasm bytes inlined as base64. That is what makes the package browser-safe with no locateFile hook and no second network request. The C entry points are thin wrappers in native/opus_wasm_wrapper.c (prefixed oc_) that the TypeScript in src/index.ts calls into.

The module reserves a 1 MiB C stack so long stereo frames fit safely. Unlike the WebAssembly heap, this stack cannot grow; Emscripten's default 64 KiB is not enough for every supported Opus frame duration.

#Next

  • Benchmark — measure the build against the native addon.
  • API reference — the surface the bindings expose.