import { RTCProvider } from './RTCProvider'; import { RTCConnectionConfig, RTCPrepareConnectionConfig } from '../types'; import { LogLevel } from '../utils'; import { AvatarView } from '@spatialwalk/avatarkit'; /** * Options for configuring AvatarPlayer. */ export interface AvatarPlayerOptions { /** * Log level for SDK output. * - 'info': Show all logs (debug mode) * - 'warning': Show warnings and errors (default) * - 'error': Show only errors * - 'none': Disable all logs */ logLevel?: LogLevel; /** * Enable jitter buffer for smoother animation playback. * When enabled, frames are buffered and rendered in sequence order at a steady 25fps, * absorbing network jitter and out-of-order delivery. * Default: true */ enableJitterBuffer?: boolean; /** * Maximum delay (in ms) a frame can sit in the jitter buffer before being rendered. * Only used when enableJitterBuffer is true. * Default: 80 (2 frames at 25fps) */ maxBufferDelayMs?: number; } /** * Unified Avatar Player. * * Main entry point for applications to interact with RTC avatar streaming. * Handles connection management, audio publishing, animation rendering, * and coordinates with avatarkit for display. * * @example * ```typescript * import { AvatarPlayer, LiveKitProvider } from '@spatialwalk/avatarkit-rtc'; * import { AvatarView, Avatar } from '@spatialwalk/avatarkit'; * * // Create avatar and view (from avatarkit) * const avatar = await Avatar.create(characterId); * const avatarView = new AvatarView(avatar, container); * * // Create player * const provider = new LiveKitProvider(); * const player = new AvatarPlayer(provider, avatarView); * * // Connect * await player.connect({ url: 'wss://...', token: '...' }); * * // Option 1: Use microphone (most common) * await player.startPublishing(); * await player.stopPublishing(); * * // Option 2: Use custom audio source * const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); * await player.publishAudio(stream.getAudioTracks()[0]); * await player.unpublishAudio(); * stream.getTracks().forEach(t => t.stop()); * * // Disconnect * await player.disconnect(); * ``` */ export declare class AvatarPlayer { /** * Create a new AvatarPlayer instance. * @param provider - RTC provider implementation (e.g., LiveKitProvider) * @param avatarView - AvatarView instance from @spatialwalk/avatarkit * @param options - Optional configuration for transitions */ constructor(provider: RTCProvider, avatarView: AvatarView, options?: AvatarPlayerOptions); /** * Check if currently connected to RTC server. */ get isConnected(): boolean; /** * Connect to RTC server. * @param config - Connection configuration (URL, token, room name, etc.) * @throws Error if already connected or connection fails */ connect(config: RTCConnectionConfig): Promise; /** * Pre-warm a future RTC connection when the provider supports it. * This is best-effort and does not change the connected state. */ prepareConnection(config: RTCPrepareConnectionConfig): Promise; /** * Disconnect from RTC server. * Stops all tracks and cleans up resources. */ disconnect(): Promise; /** * Publish an audio track to the RTC server. * * The audio source is controlled externally - you can pass any audio track: * - Microphone: `getUserMedia({ audio: true })` * - Browser audio: `audioElement.captureStream()` * - Web Audio API: `audioContext.createMediaStreamDestination().stream` * - Screen share audio: `getDisplayMedia({ audio: true })` * * @param track - MediaStreamTrack to publish (must be an audio track) * @throws Error if not connected or track is invalid * * @example * ```typescript * // Microphone * const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); * await player.publishAudio(stream.getAudioTracks()[0]); * * // Browser audio element * const audioEl = document.querySelector('audio'); * const stream = audioEl.captureStream(); * await player.publishAudio(stream.getAudioTracks()[0]); * ``` */ publishAudio(track: MediaStreamTrack): Promise; /** * Stop publishing audio. * Note: This does NOT stop the track - the caller is responsible for managing the track lifecycle. */ unpublishAudio(): Promise; /** * Start publishing microphone audio. * * This requests microphone permission and publishes it to the RTC session. * For custom audio sources (e.g., audio files), use `publishAudio(track)` instead. * * @throws Error if not connected, permission denied, or no microphone found * * @example * ```typescript * await player.startPublishing(); * // ... later * await player.stopPublishing(); * ``` */ startPublishing(): Promise; /** * Stop publishing microphone audio and release the microphone. * * This stops the microphone track and releases the device. * If you used `publishAudio()` with a custom track, use `unpublishAudio()` instead. */ stopPublishing(): Promise; /** * Get current connection state. * @returns Connection state string (e.g., 'connected', 'disconnected') */ getConnectionState(): string; /** * Get the native RTC client object. * * Returns the underlying RTC client for advanced use cases: * - LiveKit: Returns the Room instance * - Agora: Returns the IAgoraRTCClient instance * * @returns The native RTC client object, or null if not connected * * @example * ```typescript * // Access LiveKit Room * const room = player.getNativeClient() as Room; * console.log('Participants:', room?.remoteParticipants.size); * * // Access Agora Client * const client = player.getNativeClient() as IAgoraRTCClient; * console.log('State:', client?.connectionState); * ``` */ getNativeClient(): unknown; /** * Add event listener. * @param event - Event name ('connected', 'disconnected', 'error', 'stalled', etc.) * @param handler - Event handler function */ on(event: string, handler: (...args: unknown[]) => void): void; /** * Remove event listener. * @param event - Event name * @param handler - Event handler function (must be same reference as added) */ off(event: string, handler: (...args: unknown[]) => void): void; /** * Reconnect to RTC server using the last connection configuration. * Useful for recovering from connection issues or stream stalls. * * @example * ```typescript * player.on('stalled', async () => { * console.log('Stream stalled, attempting reconnection...'); * await player.reconnect(); * }); * ``` * * @throws Error if no previous connection config exists or reconnection fails */ reconnect(): Promise; } //# sourceMappingURL=AvatarPlayer.d.ts.map