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 that hands you the vocabulary you'd expect from Wwise, FMOD, or Unreal: an Engine you talk to, a Mixer made of named Buses, Sounds that spawn Voices, Snapshots that crossfade your whole mix, and Parameters that drive any value with smooth ramps.
Designed around the realities the Web Audio API doesn't smooth over:
autoplay restrictions, iOS Safari's quirky AudioContext lifecycle,
click-free parameter changes, polyphony at scale, and the discipline of disposing
everything you constructed. The library makes those concerns explicit and named, so
your application code can stay 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.13.0
- 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;createSoundfor procedural buffers. - Sprites: one buffer, many named regions, one fetch — for cascades, UI variants, dialogue chunks.
- Streams:
loadStreamfor music tracks > 30s viaHTMLAudioElement+MediaElementAudioSource. - Crossfade:
engine.crossfade(from, to, { duration })— 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.spatializerexposed for livesetPan/setPosition. - Loudness: RMS-based normalization on load (
loadSound({ normalize: true })) so sounds sit at uniform perceived loudness. - Parameters & Snapshots: named knobs with
bindTomapping; whole-mix capture and crossfade. - DX:
BusNotFoundError("sxf"; did you mean "sfx")with Levenshtein suggestions; CLI (zvuk transcode+zvuk gen bank.json); auto-built TypeDoc reference, Pagefind search, OG cards, and an agent-readablellms.txt.
What's next
See the roadmap for sized, prioritised items, and the changelog for what's already landed. v1.0.0 is the first stable release; the next pass is community-driven — PRs welcome.
Read next
- Quickstart — two functions, sound playing.
- The Engine — lifecycle, unlock, state machine.
- Asset formats — the encoding pipeline you should be using.