Skip to main content
The Spatius JavaScript Server SDK connects Node.js backends to Motion Server. It creates a Session Token, opens a WebSocket session, uploads audio, and returns motion data through a callback. TypeScript declarations are included.
Run this SDK on your backend, not in a browser, and keep the API Key private. For browser rendering, use the Web AvatarKit SDK.

Install

Requires Node.js 22 or later. Both ES modules and CommonJS are supported.
See npm package metadata for releases and runtime requirements, and GitHub for source and examples.

Quick start

Save this as avatar.mjs, replace the credential placeholders, and run node avatar.mjs. Provide audio.pcm containing raw mono signed 16-bit little-endian PCM at 16000 Hz, without a WAV header.
This example waits for the last motion data payload rather than closing immediately after sending audio. Adjust the timeout to your audio duration. Your backend must also deliver response audio to the client; see Backend Mode Setup.

Session lifecycle

Call init() and start() once for each session. A closed session cannot restart; create a new one to reconnect. Always close sessions in a finally block. Symbol.asyncDispose is also supported for runtimes or TypeScript builds that support await using.

Region and authentication

The default region is auto, including an empty or whitespace-only string. Initialization resolves the recommended region and caches it for five minutes. If resolution fails, the SDK uses the last successfully resolved region or us-west. Set region: "us-west", "ap-northeast", or "cn-beijing" to pin a region. Explicit consoleEndpointUrl and ingressEndpointUrl options are advanced overrides. See Regions. By default, WebSocket credentials use X-App-ID and X-Session-Key headers. useQueryAuth: true uses appId and sessionKey query parameters instead. Query authentication does not make it safe to expose this SDK or the API Key in a browser.

Audio streaming

AudioFormat.PCM_S16LE ("pcm_s16le") is the default: raw mono 16-bit little-endian PCM at the configured sampleRate (default 16000). The SDK does not resample your input. All chunks share a request ID until end=true. The next call starts a new request. Await each send to keep chunks ordered and avoid building an unbounded queue:
Finishing the input does not mean output is complete. In WebSocket mode, wait for transportFrames with isLast=true before closing or completing the response turn.

Ogg Opus

Set audioFormat: "ogg_opus" to send one continuous Ogg Opus stream per request ID. Without oggOpusEncoder, sendAudio() expects pre-encoded Ogg Opus pages, not raw PCM or individual Opus packets. Enable the bundled WebAssembly encoder to send raw PCM while uploading Ogg Opus. No native codec installation is required:
  • Encoder sample rates: 8000, 12000, 16000, 24000, or 48000 Hz.
  • Frame durations: 10, 20, 40, or 60 ms; default 20.
  • Applications: "voip" (default), "audio", or "restricted_lowdelay".
  • bitrate: 0 for automatic selection, or 500–512000 bits per second.
  • PCM chunks must contain complete 16-bit samples. end=true flushes the encoder and ends the request.
  • onEncodedAudio receives one complete encoded stream when input finishes. Enabling it retains the encoded audio in memory until then.

Callbacks

Callbacks are synchronous; their return values are not awaited. Catch failures in asynchronous work started by a callback. Session method failures must also be handled with try / catch; do not rely only on onError.

RTC egress

LiveKit and Agora egress are low-level Server SDK capabilities, not additional integration paths. Use LiveKit Agents Integration or Agora Convo AI Integration for the packaged workflows.
Set one egress provider to send audio and motion data to its room or channel instead of receiving transportFrames callbacks:
Optional fields are extraAttributes (string map) and idleTimeout (seconds, 0 uses server defaults). Prefer apiToken; apiKey and apiSecret are deprecated LiveKit credentials, distinct from your Spatius API Key.
interrupt() requires egress mode and a previously sent request. It targets the latest request even after end=true. In Backend Mode, discard cancelled turns in your delivery layer and interrupt playback on the client.

Warm up a worker

prewarm() resolves the region before creating sessions. Enable token prefetch to cache a token for later sessions with matching API Key, App ID, and Console endpoint:
Warm-up is best-effort and does not throw on failure. It does not open a session; still call init() and start(). Options include region, endpoint overrides, timeoutMs, and sessionExpireAt (one hour by default). The result also includes consoleEndpointUrl and ingressEndpointUrl. Prefetch is off by default. A cached token keeps the expiry chosen by sessionExpireAt, not a later session’s expireAt. Keep it disabled if your backend requires single-use tokens. Unlike Python and Go, JavaScript does not expose a TLS warm-up option.

Session configuration

Error handling

SessionTokenError extends AvatarSDKError. Catch token errors first if you need separate handling:
Structured errors expose code, message, and phase, plus optional httpStatus, serverCode, serverTitle, serverDetail, connectionId, reqId, rawBody, closeCode, closeReason, and cause. Use AvatarSDKErrorCode for program logic. Values include sessionTokenExpired, sessionTokenInvalid, appIDUnrecognized, appIDMismatch, avatarNotFound, billingRequired, creditsExhausted, sessionDurationExceeded, unsupportedSampleRate, invalidEgressConfig, egressUnavailable, idleTimeout, upstreamError, invalidRequest, connectionFailed, connectionClosed, protocolError, serverError, and unknown. See Server Error Handling for recovery guidance. Never log API Keys or Session Tokens.

Telemetry

The SDK exports OpenTelemetry metrics and traces by default, not logs. Configure it before using sessions or prewarm():
configureTelemetry(endpoint) sets another collector. shutdownTelemetry() flushes and stops the process-wide providers; do not call it after each session.

Changelog

See GitHub releases.