Store your API key securely. Never commit API keys to version control. Use BuildConfig fields, encrypted shared preferences, or fetch ephemeral keys from your backend.
For production Android apps using the Realtime API, fetch short-lived client tokens from your backend instead of embedding your permanent API key in the APK:
// Fetch ephemeral key from your backendval ephemeralKey = fetchTokenFromBackend()// Use it to create the clientval client = DecartClient( context = applicationContext, config = DecartClientConfig(apiKey = ephemeralKey))
See Client Tokens for details on secure client-side authentication.
import ai.decart.sdk.RealtimeModelsRealtimeModels.LUCY_2_RT // Realtime video editing with character referenceRealtimeModels.MIRAGE_V2 // Realtime video restylingRealtimeModels.LIVE_AVATAR // Avatar animation with audio
Previous generation models
RealtimeModels.LUCY_V2V_720P_RT // Realtime video editingRealtimeModels.MIRAGE // Realtime video transformation
Each model exposes properties for optimal camera configuration:
val model = RealtimeModels.LUCY_2_RTprintln(model.fps) // 25println(model.width) // 1280println(model.height) // 704
The SDK uses Kotlin coroutines and Flow for reactive state management:
import kotlinx.coroutines.flow.collectimport kotlinx.coroutines.launch// Realtime connection state as StateFlowlifecycleScope.launch { client.realtime.connectionState.collect { state -> println("Connection: $state") }}// Errors as SharedFlowlifecycleScope.launch { client.realtime.errors.collect { error -> println("Error: ${error.code} — ${error.message}") }}// Queue job progress as Flowclient.queue.submitAndObserve(model, input).collect { update -> when (update) { is QueueJobResult.InProgress -> println("Status: ${update.status}") is QueueJobResult.Completed -> saveVideo(update.data) is QueueJobResult.Failed -> showError(update.error) }}
All realtime state is exposed as Kotlin StateFlow or SharedFlow. Collect them in a lifecycle-aware scope (e.g., lifecycleScope or viewModelScope) to avoid leaks.
Request camera permission at runtime before connecting:
val launcher = rememberLauncherForActivityResult( ActivityResultContracts.RequestPermission()) { granted -> if (granted) { // Start camera and connect }}launcher.launch(Manifest.permission.CAMERA)
Realtime tab — Camera capture + WebRTC streaming with live prompt changes
Video tab — Batch job submission, status updates, and result playback
For a more complete app showcasing real-world use cases — video restyling, 90+ style presets, multiple view modes, and swipe navigation — see the Decart Android Example App.
Build realtime Android experiencesComplete guide with Jetpack Compose examples for camera handling, video transformation, and interactive applications.
Queue API Guide
Batch video processingEdit videos, control motion, and transform videos with typed input classes and Flow-based progress tracking.