What it is
A drop-in voice chat module that routes compressed audio packets entirely inside SpacetimeDB, with no external media server. It handles room membership, proximity-based delivery, muting, moderation, and per-speaker rate limiting at the database layer, leaving all audio encoding and playback to the client.
Where it fits
- Multiplayer games with voice rooms: A game lobby or squad channel where only members of a given room should hear each other, enforced server-side rather than by client trust.
- Proximity voice in virtual worlds: An open-world or social space where players only hear others within a configurable radius, with volume fading by distance and no packets sent at all beyond range.
- Stream overlay tools and collaborative apps: Browser-based tools where participants need low-latency voice without standing up a separate media server or third-party service.
- Cross-language SpacetimeDB projects: Apps built in Rust, C#, or TypeScript that need a single consistent voice schema so one browser client works against any backend language.
- Privacy-sensitive voice features: Situations where it matters that deafened users receive zero audio bytes and eavesdropping via subscription is structurally prevented rather than just discouraged.
How it works
When a speaker sends a voice packet, the module checks whether they are allowed to transmit (room membership, mute state, size limits, and a per-speaker rate cap), then writes the packet to an event table. Event tables broadcast their contents to subscribers on commit and hold no persistent state, so audio frames are never stored as long-lived rows. Each packet is tagged with an audience key, which is either the room identifier or, in proximity rooms, the speaker's position cell in a spatial grid.
Delivery is controlled by a row-level security rule that joins incoming packets against a separate listener-membership table. Each client holds membership rows for the audiences it is entitled to hear: its room, or the cluster of grid cells surrounding its current position. The database evaluates this join per subscriber, so a client only receives packets whose audience key matches one of its own membership rows. Deafened clients have no membership rows and receive nothing. Because the module itself updates positions when movement happens, clients cannot manipulate their own location to intercept nearby conversations.
The module never inspects or transforms the audio payload. It treats the bytes as opaque data and only enforces routing rules and limits. The client is responsible for encoding audio before sending and for decoding, buffering, and spatially positioning audio on receipt. This separation means any codec or client platform can work with the module as long as it follows the packet format.

