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;createSoundfor procedural buffers. - Sprites: one buffer, many named regions, one fetch. For cascades, UI variants and dialogue chunks.
- Streams:
loadStreamfor music tracks > 30s viaHTMLAudioElement+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.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: errors carry a Levenshtein suggestion, so a mistyped bus name says
Did you mean "sfx"?; a CLI withzvuk transcodeandzvuk gen bank.json; an auto-built TypeDoc reference, Pagefind search, generated OG cards, and machine-readablellms.txtplusllms-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.