Quick Start
Client-Side Authentication
For browser applications, use client tokens instead of your permanent API key. Client tokens are short-lived tokens safe to expose in client-side code.Learn more about client tokens and why they’re important for security.
Step 1: Create a backend endpoint
Your server creates client tokens using the SDK:Step 2: Use the client token in your frontend
Fetch the client token from your backend and use it to connect:Connecting
Getting Camera Access
Request access to the user’s camera using the WebRTC getUserMedia API:Establishing Connection
Connect to the Realtime API with your media stream:stream(required) - MediaStream from getUserMediamodel(required) - Realtime model frommodels.realtime()onRemoteStream(required) - Callback that receives the transformed video streaminitialState.prompt(required) - Initial style prompttext- Style descriptionenhance- Whether to auto-enhance the prompt (default: true)
Managing Prompts
Change the transformation style dynamically without reconnecting:prompt(required) - Text description of desired styleoptions.enhance(optional) - Whether to enhance the prompt (default: true)
Prompt enhancement uses Decart’s AI to expand simple prompts for better results. Disable it if you want full control over the exact prompt.
Unified State Update
Theset() method lets you update the prompt, reference image, or both in a single atomic call. For Lucy 2 (lucy_2_rt), it ensures prompt and image changes are applied together.
SetInput):
prompt(optional) - Text description of desired style (at least one ofpromptorimageis required)enhance(optional) - Whether to enhance the prompt (default: true)image(optional) - Reference image as aBlob,File, URL string, ornullto clear
Avatar Live
The Avatar Live model animates portrait images with audio input. Unlike other realtime models that transform camera streams, Avatar Live takes a static image and audio to generate animated video.Connecting with Avatar Image
Avatar Live doesn’t require a camera stream. Pass
null as the first argument to connect().Playing Audio
Send audio to animate the avatar:Blob- Audio blob (e.g., from MediaRecorder)File- Audio file from file inputArrayBuffer- Raw audio data
Avatar Behavior Prompts
Control how the avatar behaves and expresses:Complete Avatar Live Example
Connection State
Monitor and react to connection state changes:"connecting"— Initial connection in progress"connected"— Connected and ready to send prompts"generating"— Actively generating transformed video (sticky until disconnected)"reconnecting"— Connection was lost unexpectedly; the SDK is automatically retrying"disconnected"— Not connected (initial state, afterdisconnect(), or after reconnect failure)
The SDK automatically reconnects when an unexpected disconnection occurs (e.g., network interruption). During auto-reconnect, the state transitions to
"reconnecting" while the SDK retries with exponential backoff (up to 5 attempts). If all retries fail, the state moves to "disconnected" and an error event is emitted.Error Handling
Handle errors with the error event:INVALID_API_KEY- API key is invalid or missingWEB_RTC_ERROR- WebRTC connection failedMODEL_NOT_FOUND- Specified model doesn’t existINVALID_INPUT- Invalid input parameters
Telemetry and Observability
The JavaScript SDK provides realtime observability in two ways:- SDK telemetry forwarding (enabled by default) sends stats and diagnostics to Decart’s telemetry ingestion pipeline.
- Local event stream lets you consume observability events in your app via
on("stats")andon("diagnostic").
Telemetry forwarding
Telemetry is enabled by default. You can disable it when creating the client:Local observability events
phaseTimingiceCandidateiceStateChangepeerConnectionStateChangesignalingStateChangeselectedCandidatePairreconnectvideoStall
diagnostic events are emitted by the connection lifecycle. stats events are collected automatically while telemetry is enabled.Session Management
Access the current session ID:Session Viewing (Subscribe)
You can let other clients watch an active realtime session as read-only viewers using the subscribe feature. The producer session exposes asubscribeToken that viewers use to connect.
Getting a Subscribe Token
After connecting, the producer’ssubscribeToken is automatically populated:
Subscribing to a Session
Viewers use the subscribe token to receive the transformed video stream in read-only mode:Subscribe clients are receive-only — they cannot send prompts or modify the session. The subscriber sees exactly what the producer’s
onRemoteStream receives.Cleanup
Always disconnect when done to free up resources:Complete Example
Here’s a full application with all features:Best Practices
Use model properties for video constraints
Use model properties for video constraints
Always use the model’s
fps, width, and height properties when calling getUserMedia to ensure optimal performance and compatibility.Enable prompt enhancement
Enable prompt enhancement
For best results, keep
enhance: true (default) to let Decart’s AI enhance your prompts. Only disable it if you need exact prompt control.Handle connection state changes
Handle connection state changes
Always listen to
connectionChange events to update your UI and handle reconnection logic gracefully.Clean up properly
Clean up properly
Always call
disconnect() and stop media tracks when done to avoid memory leaks and unnecessary resource usage.API Reference
client.realtime.connect(stream, options)
Connects to the realtime transformation service.
Parameters:
stream: MediaStream | null- MediaStream from getUserMedia, ornullfor Avatar Liveoptions.model: ModelDefinition- Realtime model frommodels.realtime()options.onRemoteStream: (stream: MediaStream) => void- Callback for transformed video streamoptions.initialState.prompt: { text: string; enhance?: boolean }- Initial transformation promptoptions.initialState.image: Blob | File | string- Portrait image for Avatar Live (passed viainitialState)
Promise<RealtimeClient> - Connected realtime client instance
realtimeClient.setPrompt(prompt, options?)
Changes the transformation style.
Parameters:
prompt: string- Text description of desired styleoptions.enhance?: boolean- Whether to enhance the prompt (default: true)
realtimeClient.set(input)
Updates the prompt, reference image, or both atomically.
Parameters:
input: SetInput- Object with at least one of:prompt?: string- Text description of desired styleenhance?: boolean- Whether to enhance the prompt (default: true)image?: Blob | File | string | null- Reference image, ornullto clear
Promise<void>
realtimeClient.setImage(image)
Sets a reference image to guide the transformation. For Mirage, this guides style transformation. For Lucy, this sets a character reference for identity transformation, allowing you to transform yourself into a different character.
Parameters:
image: Blob | File | string- Image as a Blob, File object, or URL string
Promise<void>
realtimeClient.isConnected()
Check if currently connected.
Returns: boolean
realtimeClient.getConnectionState()
Get current connection state.
Returns: "connected" | "connecting" | "generating" | "reconnecting" | "disconnected"
realtimeClient.sessionId
The ID of the current realtime inference session.
Type: string | null
realtimeClient.subscribeToken
An opaque token that can be shared with other clients to let them watch this session in read-only mode via client.realtime.subscribe().
Type: string | null
realtimeClient.disconnect()
Closes the connection and cleans up resources.
Avatar Live Methods
These methods are only available when using thelive_avatar model.
realtimeClient.playAudio(audio)
Sends audio to animate the avatar.
Parameters:
audio: Blob | File | ArrayBuffer- Audio data to play
Promise<void> - Resolves when audio finishes playing
client.realtime.subscribe(options)
Connects to an existing realtime session as a read-only viewer.
Parameters:
options.token: string- Subscribe token from the producer’srealtimeClient.subscribeTokenoptions.onRemoteStream: (stream: MediaStream) => void- Callback for the video stream
Promise<RealTimeSubscribeClient> - Connected subscribe client
The subscribe client exposes:
isConnected()- Check connection statusgetConnectionState()- Get current statedisconnect()- Close the connectionon(event, listener)/off(event, listener)- Listen toconnectionChangeanderrorevents
Events
connectionChange
Fired when connection state changes.
Callback: (state: "connected" | "connecting" | "generating" | "reconnecting" | "disconnected") => void
error
Fired when an error occurs.
Callback: (error: DecartSDKError) => void
generationTick
Fired periodically during generation with billing information. Use this to track session duration and display usage to users.
Callback: (data: { seconds: number }) => void
stats
Fired continuously with parsed WebRTC transport/media metrics.
Callback: (stats: WebRTCStats) => void
diagnostic
Fired for typed connection lifecycle diagnostics.
Callback: (event: DiagnosticEvent) => void