Camera setup
Always use the model’s built-in constraints when requesting camera access. Each model defines thefps, width, and height it expects — passing these directly avoids scaling artifacts and wasted bandwidth.
Handling constraint failures
Not every device supports every resolution. Useideal constraints as a fallback when targeting a wide range of hardware:
Front vs back camera
On mobile devices, specify thefacingMode to select the camera:
Front-camera mirroring
For selfie streams, pre-flip the input withmirror. Server-baked pixels (watermarks, overlays) then come out in display orientation, and the output renders as-is.
"auto"mirrors when the input track reportsfacingMode: "user".- Pass
truewhen your app already knows the camera is front-facing (desktop webcams often don’t reportfacingMode).
Connection management
Connect once, update prompts
Establishing a WebRTC connection takes a few hundred milliseconds. Don’t reconnect just to change the style or prompt — useset() or setPrompt() instead:
When to reconnect
Reconnect only when you need to:- Switch models (e.g., from Lucy Restyle Live to Lucy 2.1) — each model runs on a different pipeline
- Switch cameras — the stream changes, so you need a new connection
- Recover from a failed connection after auto-reconnect gives up
Track connection state
Always listen toconnectionChange events to update your UI:
Prompt strategy
Use prompt enhancement
Enableenhance: true (the default) to let Decart expand short prompts into detailed descriptions. This dramatically improves output quality for simple inputs:
Atomic updates with set()
Since set() replaces the entire state, always include every field you want to keep. When using Lucy 2.1 with both a prompt and reference image, include both in every call:
Debounce rapid prompt changes
If your UI lets users type prompts in a text field, debounce the input to avoid sending dozens of rapid updates:Error handling
Listen for errors
Always register an error handler. Without one, connection failures go unnoticed:Auto-reconnect
The SDK automatically reconnects when an unexpected disconnection occurs (e.g., network interruption). It retries with exponential backoff up to 5 times:- Connection drops → state moves to
"reconnecting" - SDK retries with increasing delays
- If reconnection succeeds → state moves back to
"generating" - If all retries fail → state moves to
"disconnected"and anerrorevent fires
reconnecting state.
Wrap setup in try/catch
Camera access and connection can both fail. Catch errors early:Cleanup
Always release resources when the session ends or the component unmounts:Client-side authentication
Never expose your permanent API key in client-side code. Use short-lived client tokens instead:1
Create a backend endpoint
2
Fetch and use the token in the browser
Client tokens only prevent new connections after expiry. Active WebRTC sessions continue working even after the token expires.
Firewall and network configuration
Realtime integrations need outbound access to Decart’s API, signaling, diagnostics, and media endpoints.Domains to allow
Staging environments use
turn.stage-decart.com and api.stage-decart.com instead.
Ports and protocols
UDP traffic and proxy configuration
- Allow outbound UDP traffic on port 7882.
- Allow TURN over UDP on port 3478.
- Do not force media through an HTTP or HTTPS proxy that cannot pass UDP if you want the lowest-latency path.
- For SNI or transparent proxies, allow the domains above and do not TLS-intercept
turn.decart.ai; decrypting that traffic breaks the connection.
Mobile considerations
React Native / Expo
React Native realtime runs on LiveKit’s React Native stack — plainreact-native-webrtc is not supported.
- Install the LiveKit packages and register globals.
registerGlobals()must run before your app/router entrypoint so the SDK can reach WebRTC:
@livekit/react-native-expo-plugin and @config-plugins/react-native-webrtc config plugins to app.json, then run npx expo prebuild. LiveKit does not run in Expo Go.
- Select VP8 with
preferredVideoCodec. React Native works best with VP8. Set it as an option — the SDK negotiates the codec, so there’s no manual SDP rewriting:
- Size the camera with
resolveFpsNumber. Use the model’s dimensions and resolve its FPS descriptor to a number for native capture:
-
Browser-only features are rejected.
mirror,debugQuality, and the deep connectivity preflight fail withUNSUPPORTED_PLATFORM_FEATUREon React Native. Mirror the local preview with LiveKit’s<RTCView mirror>instead. - Handle app lifecycle. Disconnect when backgrounded, reconnect when foregrounded:
Battery and bandwidth
Realtime WebRTC streaming consumes significant resources on mobile:- Disconnect when not visible. Use app lifecycle events to pause streaming in the background.
- Match camera constraints to model. Don’t request 4K when the model expects 720p — this wastes encoding power and bandwidth.
- Use front camera when possible. Front cameras typically have lower resolution, which reduces encoding overhead.
Session tracking
Use thegenerationTick event to track session duration and display billing information to users:
Quick reference
Next steps
Lucy 2.1 Guide
Character transformation with reference images
Reference Image Guide
Best practices for character and style reference images
JavaScript SDK
Full SDK reference for realtime features
Mobile App
Complete Expo walkthrough