Overview

What is zvuk?

An audio engine for the web. Tiny, ESM, type-safe. Built from a real shipping slot-game stack.

zvuk is a Web Audio API library built around the vocabulary a game audio team already uses. There is an Engine you talk to, a Mixer made of named Buses, Sounds that spawn Voices, Snapshots that crossfade the whole mix, and Parameters that drive any value through a curve. Wwise, FMOD and Unreal all name these things the same way.

It is designed around the parts the Web Audio API leaves to you. Autoplay restrictions. iOS Safari's AudioContext lifecycle. Click-free parameter changes. Polyphony at scale. Disposing everything you constructed. Each of those is a named concern here, which is what keeps the code at the call site short.

Conventions

All time-valued options are in seconds, matching the Web Audio API (AudioContext.currentTime, every AudioParam schedule). That includes fades (voice.fade({ duration: 0.8 })), crossfades (engine.crossfade(a, b, { duration: 1.5 })), snapshot applies (snap.apply({ fade: 0.25 })), and every dynamics processor's attack/release. No millisecond fields, no per-API conversions to remember.

What's in v1.14.1

  • Runtime: lazy AudioContext, audio-clock scheduler, decode cache, codec ladder.
  • Mixer: Master with headroom + optional soft limiter, named Buses with click-free fades, FX chain inserts.
  • Sources: Sound + Voice with jitter, fades, pause / resume, live setPlaybackRate, abort signals, lifecycle promises; createSound for procedural buffers.
  • Sprites: one buffer, many named regions, one fetch. For cascades, UI variants and dialogue chunks.
  • Streams: loadStream for music tracks > 30s via HTMLAudioElement + MediaElementAudioSource.
  • Crossfade: engine.crossfade(from, to, { duration }) for an equal-power music swap in one call.
  • Concurrency: per-bus voice limit with steal strategies (oldest / lowest-priority / quietest / none).
  • FX: Compressor, Reverb (synthetic IR or your own), Filter (six biquad types), Ducker (sidechain), pitch-preserving StretchProcessor (offline) plus a realtime AudioWorklet variant.
  • Spatializer: 2D StereoPanner + 3D HRTF PannerNode per voice, with voice.spatializer exposed for live setPan / setPosition.
  • Loudness: RMS-based normalization on load (loadSound({ normalize: true })) so sounds sit at uniform perceived loudness.
  • Parameters & Snapshots: named knobs with bindTo mapping; whole-mix capture and crossfade.
  • DX: errors carry a Levenshtein suggestion, so a mistyped bus name says Did you mean "sfx"?; a CLI with zvuk transcode and zvuk gen bank.json; an auto-built TypeDoc reference, Pagefind search, generated OG cards, and machine-readable llms.txt plus llms-full.txt.

What's next

The roadmap lists sized, prioritised items and the changelog covers what has already landed. Pull requests are welcome; CONTRIBUTING.md says what the gates are.

Read next

  • Quickstart gets sound playing in two functions.
  • The Engine covers lifecycle, unlock and the state machine.
  • Asset formats is the encoding pipeline you should be using.