Console
Docs/Integrate

Web

@aurix/web-sdk for browsers and Electron — WebTransport, WebRTC and WebSocket transports, Opus in a worklet, device handling, effects.

Install#

bash
npm i @aurix/web-sdk

Ships as ESM with types. Requires a secure context (HTTPS or localhost) for microphone access.

Connect and join#

ts
import { AurixClient } from '@aurix/web-sdk';

const t = await fetch('/voice/token', { method: 'POST' }).then((r) => r.json());   // your backend
const voice = new AurixClient({
  apiUrl: 'https://eu-central.cell.aurix.run',   // your project's cell endpoint (Keys & SDK)
  wsUrl: t.endpoint.ws_url,
  token: t.token,
  refreshToken: () => fetch('/voice/token', { method: 'POST' }).then((r) => r.json()).then((x) => x.token),
  transport: 'auto',      // webtransport → webrtc → websocket; or pin one
});

await voice.connect();
await voice.joinChannel(t.channels[0].id);

connect() resolves with the SessionInfo; the microphone is requested lazily on the first join unless you call voice.setInputDevice() earlier. Attach playback to an element you control (voice.attachAudioOutput(audioEl)) or let the SDK create one; call voice.resumeAudio() from a user gesture if autoplay is blocked.

Transports#

TransportWhenNotes
WebTransportChromium 97+, Firefox 114+HTTP/3 over QUIC straight to the node; lowest latency under loss
WebRTCEverywhereOpus over SRTP with TURN fallback
WebSocketLast resortTCP tunnel; works behind strict proxies

Read voice.mediaTransport after connecting to show it in diagnostics; voice.on('mediaTransport', …) fires when it changes.

Events#

ts
voice.on('participantJoined', ({ channelId, participant }) => …);   // also participantLeft / participantUpdated
voice.on('speaking', ({ userId, speaking }) => …);
voice.on('stats', (s) => console.log(s));                             // RTT, loss, jitter, MOS
voice.on('networkQuality', (q) => …);
voice.on('sessionClosed', ({ reason }) => …);                         // connectionState for the full state machine

Positional audio#

ts
voice.updatePosition(channelId, { x, y, z }, { yaw, pitch, roll });   // 10–20 Hz

The SDK renders remote participants with the Web Audio panner; voice.channelAudioPolicy(channelId) tells you what the server configured.

Devices, mute, levels#

ts
await voice.setInputDevice(deviceId);  await voice.setOutputDevice(deviceId);
voice.setInputGain(1.2);  voice.setOutputVolume(0.8);  voice.setOutputMuted(false);
voice.setTransmission('ptt');  voice.transmitToChannel(teamChannelId);
voice.setParticipantVolume(userId, 0.5);  voice.setParticipantMuted(userId, true);

Effects (setVoiceEffects), visemes (setVisemes), audio injection (injectAudio for bots and tests) and server-side ducking are available on the same client — see the typed API in the package.

Electron and kiosks#

Works unchanged; WebTransport needs Chromium ≥ 97 and a certificate the node advertises (handled automatically with the hash-pinned certificates Aurix nodes issue).

Channel patterns#

PatternChannels per playerNotes
Co-op / squadone teammute = PTT off; nothing positional
Shooter with proximitypositional (shard) + team (squad)transmit on the team channel by default, hold a key to speak locally
Open worldpositional (shard), optional whisper for direct callsroster_radius keeps the participant list small
Event / stageaudience-shaped channel, hosts with prioritythousands of listeners, a few speakers

The transmit channel is a client-side choice: join several, send to one, hear all with receive. Positional audio needs positions roughly 10 times a second; between updates the node interpolates.

Latency and quality#

Expect 30–60 ms mouth-to-ear on the same continent over QUIC, more over TURN. Opus runs at 32 kbps with DTX by default; the spending ladder may lower it to 16 kbps when your forecast exceeds the limit. Server-side noise suppression is on by default and costs nothing on the client.

Testing without a full build#

  • Two players: the rooms demo in a browser plus your build — they share a cell, so a token from your backend joins the same channel by name.
  • Mic path: an echo channel plays your own voice back through the real pipeline.
  • Network: throttle UDP on one machine and watch the transport fall back to WebRTC / WebSocket in the SDK's connection state.

Troubleshooting#

SymptomCheck
connected, no audiocapture started? channel grant speak/receive? OS microphone permission?
audio but no spatialisationpositions sent on the positional channel id, not the team channel
random drops on mobilethe SDK pauses capture in the background by design; resume on foreground
QUOTA_EXCEEDED on connectplan concurrency cap or spending ladder step 4 — see Spending limit