Skip to main content
Web Only: RTC Mode is currently available for Web applications only.
Do not call initializeAudioContext() — it is not needed in RTC Mode. Avatar audio is delivered as a native WebRTC audio track by the Agora client SDK, not through the AvatarKit SDK’s internal audio player. The AvatarPlayer adapter only feeds animation data to the SDK for rendering; audio playback is handled entirely by Agora’s WebRTC stack.

Installation

pnpm add @spatialwalk/avatarkit @spatialwalk/avatarkit-rtc agora-rtc-sdk-ng
You also need to configure your build tool for WASM files — see Build Tool Configuration.

Authentication

CredentialHow to ObtainNotes
App IDDeveloper Platform → Create AppFor SDK initialization
Session TokenYour backend → AvatarKit ServerFor avatar loading (max 1 hour)
Agora App IDAgora ConsoleFor RTC connection
Agora TokenYour backend → Agora ServerRequired in production

Quick Start

1

Initialize SDK in Host Mode

import { AvatarSDK, AvatarManager, AvatarView, DrivingServiceMode, Environment } from '@spatialwalk/avatarkit'

await AvatarSDK.initialize('your-app-id', {
  environment: Environment.intl,
  drivingServiceMode: DrivingServiceMode.host,  // MUST be host for RTC
})

AvatarSDK.setSessionToken('your-session-token')
2

Load Avatar & Create View

const avatar = await AvatarManager.shared.load('avatar-id')
const container = document.getElementById('avatar-container')!
const avatarView = new AvatarView(avatar, container)
3

Create Player with Agora Provider

import { AvatarPlayer, AgoraProvider } from '@spatialwalk/avatarkit-rtc'

const provider = new AgoraProvider({
  debugLogging: true,  // Optional: enable verbose debug logs
})
const player = new AvatarPlayer(provider, avatarView, {
  logLevel: 'warning',
})
4

Connect to Agora

await player.connect({
  appId: 'your-agora-app-id',
  channel: 'channel-name',
  token: 'your-agora-token',  // Required in production
  uid: 0,                      // 0 = auto assign
})
5

Start Voice Interaction

// Start microphone publishing
await player.startPublishing()

// Stop microphone
await player.stopPublishing()

// Disconnect when done
await player.disconnect()

AgoraProvider Options

const provider = new AgoraProvider(options?: AgoraProviderOptions)
interface AgoraProviderOptions {
  /** Enable verbose debug logging, default false */
  debugLogging?: boolean
}

AvatarPlayer API

Constructor

new AvatarPlayer(provider: AgoraProvider, avatarView: AvatarView, options?: AvatarPlayerOptions)

AvatarPlayerOptions

interface AvatarPlayerOptions {
  /** Start speaking transition frames, default 5 (~200ms at 25fps) */
  transitionStartFrameCount?: number

  /** End speaking transition frames, default 40 (~1600ms at 25fps) */
  transitionEndFrameCount?: number

  /** Log level: 'info' | 'warning' | 'error' | 'none', default 'warning' */
  logLevel?: LogLevel
}

Connection

// Connect to Agora
await player.connect(config: AgoraConnectionConfig)

// Disconnect and clean up
await player.disconnect()

// Reconnect using last config (useful after stalls)
await player.reconnect()

// Check connection status
player.isConnected  // boolean
player.getConnectionState()  // ConnectionState

AgoraConnectionConfig

interface AgoraConnectionConfig {
  appId: string     // Agora App ID
  channel: string   // Channel name
  token?: string    // Auth token (required in production)
  uid?: number      // User ID (0 = auto assign)
}

Microphone Control

// Start microphone (requests permission automatically)
await player.startPublishing()

// Stop microphone
await player.stopPublishing()

Custom Audio Publishing

For non-microphone audio sources.
// Publish a custom audio track
await player.publishAudio(track: MediaStreamTrack)

// Stop custom audio
await player.unpublishAudio()
unpublishAudio() does not stop the track. You are responsible for calling track.stop() to release the resource.

Native Client Access

Access the underlying Agora client for advanced features.
import { AgoraClient } from '@spatialwalk/avatarkit-rtc'

// Via provider (recommended — full type safety)
const client = provider.getNativeClient()  // AgoraClient | null

// Via player (requires type assertion)
const client = player.getNativeClient() as AgoraClient | null

console.log('Connection state:', client?.connectionState)

ConnectionState

type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'failed'

Events

player.on(event: string, handler: Function)
player.off(event: string, handler: Function)
EventCallbackDescription
'connected'()Connected to Agora
'disconnected'()Disconnected from Agora
'error'(error: Error)An error occurred
'connection-state-changed'(state: ConnectionState)Connection state changed
'stalled'()Data stream stalled (no frames for 3s)
When a stalled event fires, the avatar automatically transitions to idle animation. Consider calling player.reconnect() to recover.

Complete Example

import { AvatarPlayer, AgoraProvider } from '@spatialwalk/avatarkit-rtc'
import { AvatarSDK, AvatarView, AvatarManager, DrivingServiceMode, Environment } from '@spatialwalk/avatarkit'

async function init() {
  // Initialize SDK in host mode
  await AvatarSDK.initialize('your-app-id', {
    environment: Environment.intl,
    drivingServiceMode: DrivingServiceMode.host,
  })
  AvatarSDK.setSessionToken('your-session-token')

  // Load avatar and create view
  const avatar = await AvatarManager.shared.load('character-id')
  const container = document.getElementById('avatar-container')!
  const avatarView = new AvatarView(avatar, container)

  // Create player with Agora provider
  const provider = new AgoraProvider({ debugLogging: true })
  const player = new AvatarPlayer(provider, avatarView, {
    logLevel: 'info',
  })

  // Listen to events
  player.on('connected', () => console.log('Connected!'))
  player.on('disconnected', () => console.log('Disconnected!'))
  player.on('error', (err) => console.error('Error:', err))
  player.on('stalled', async () => {
    console.log('Stream stalled, reconnecting...')
    await player.reconnect()
  })

  // Connect to Agora
  await player.connect({
    appId: 'your-agora-app-id',
    channel: 'my-channel',
    token: 'your-agora-token',
    uid: 0,
  })

  // Start microphone
  await player.startPublishing()
}

Browser Compatibility

BrowserMinimum VersionNotes
Chrome74+H.264 + SEI
Firefox78+H.264 + SEI
Safari14.1+H.264 + SEI
Edge79+Same as Chrome