Native Swift SDK for Decart AI - Real-time video processing and AI generation for iOS & macOS.
Decart iOS SDK provides two primary APIs:
- RealtimeManager - Real-time video processing with WebRTC streaming
- ProcessClient - Batch image and video generation
Both APIs leverage modern Swift concurrency (async/await) with type-safe interfaces and comprehensive error handling.
- Real-time video processing with WebRTC
- Batch image and video generation
- Native Swift with modern concurrency (async/await)
- AsyncStream events for reactive state management
- Type-safe API with compile-time guarantees
- iOS 15+ and macOS 12+ support
- SwiftUI ready
Add to your Package.swift:
dependencies: [
.package(url: "https://github.com/decartai/decart-ios.git", from: "0.0.4")
]Or in Xcode:
- File → Add Package Dependencies
- Enter:
https://github.com/decartai/decart-ios - Select version and add to target
Stream video with real-time AI processing using WebRTC:
import DecartSDK
let config = DecartConfiguration(apiKey: "your-api-key")
let client = DecartClient(decartConfiguration: config)
let model: RealtimeModel = .mirage
let modelConfig = Models.realtime(model)
let realtimeManager = try client.createRealtimeManager(
options: RealtimeConfiguration(
model: modelConfig,
initialState: ModelState(prompt: Prompt(text: "Lego World"))
)
)
// Listen to connection events
Task {
for await state in realtimeManager.events {
switch state {
case .connected:
print("Connected")
case .disconnected:
print("Disconnected")
case .error:
print("Connection error")
default:
break
}
}
}
// Create video source and camera capture
let videoSource = realtimeManager.createVideoSource()
let capture = RealtimeCapture(model: modelConfig, videoSource: videoSource)
try await capture.startCapture()
// Create local stream and connect
let videoTrack = realtimeManager.createVideoTrack(source: videoSource, trackId: "video0")
let localStream = RealtimeMediaStream(videoTrack: videoTrack, id: .localStream)
let remoteStream = try await realtimeManager.connect(localStream: localStream)
// Update prompt in real-time
realtimeManager.setPrompt(Prompt(text: "Anime World"))
// Send reference image (base64) to the realtime session
try await realtimeManager.setImageBase64(
imageBase64String,
prompt: "Use this as reference",
enhance: true
)
// Cleanup
await capture.stopCapture()
await realtimeManager.disconnect()Generate images from text prompts:
import DecartSDK
let config = DecartConfiguration(apiKey: "your-api-key")
let client = DecartClient(decartConfiguration: config)
let input = try TextToImageInput(prompt: "Retro robot in neon city")
let processClient = try client.createProcessClient(
model: .lucy_pro_t2i,
input: input
)
let imageData = try await processClient.process()
let image = UIImage(data: imageData)Transform images with AI:
import DecartSDK
let config = DecartConfiguration(apiKey: "your-api-key")
let client = DecartClient(decartConfiguration: config)
let imageData = try Data(contentsOf: referenceImageURL)
let fileInput = try FileInput.image(data: imageData)
let input = try ImageToImageInput(prompt: "Make it cyberpunk", data: fileInput)
let processClient = try client.createProcessClient(
model: .lucy_pro_i2i,
input: input
)
let resultData = try await processClient.process()
let image = UIImage(data: resultData)Generate videos from reference images:
import DecartSDK
let config = DecartConfiguration(apiKey: "your-api-key")
let client = DecartClient(decartConfiguration: config)
let imageData = try Data(contentsOf: referenceImageURL)
let fileInput = try FileInput.image(data: imageData)
let input = try ImageToVideoInput(prompt: "Make it dance", data: fileInput)
let processClient = try client.createProcessClient(
model: .lucy_pro_i2v,
input: input
)
let videoData = try await processClient.process()
try videoData.write(to: outputURL)Transform videos with AI:
import DecartSDK
let config = DecartConfiguration(apiKey: "your-api-key")
let client = DecartClient(decartConfiguration: config)
let videoData = try Data(contentsOf: referenceVideoURL)
let fileInput = try FileInput.video(data: videoData)
let input = try VideoToVideoInput(prompt: "Apply anime style", data: fileInput)
let processClient = try client.createProcessClient(
model: .lucy_pro_v2v,
input: input
)
let resultData = try await processClient.process()
try resultData.write(to: outputURL)let config = DecartConfiguration(
baseURL: "https://api3.decart.ai", // Optional
apiKey: "your-api-key"
)let client = DecartClient(decartConfiguration: config)
// Create realtime manager
func createRealtimeManager(options: RealtimeConfiguration) throws -> RealtimeManager
// Create process clients
func createProcessClient(model: ImageModel, input: TextToImageInput) throws -> ProcessClient
func createProcessClient(model: ImageModel, input: ImageToImageInput) throws -> ProcessClient
func createProcessClient(model: VideoModel, input: TextToVideoInput) throws -> ProcessClient
func createProcessClient(model: VideoModel, input: ImageToVideoInput) throws -> ProcessClient
func createProcessClient(model: VideoModel, input: VideoToVideoInput) throws -> ProcessClientfunc connect(localStream: RealtimeMediaStream) async throws -> RealtimeMediaStream
func disconnect() async
func setPrompt(_ prompt: Prompt)
func setImageBase64(_ imageBase64: String?, prompt: String?, enhance: Bool?, timeout: TimeInterval?) async throws
func getStats() async -> RTCStatisticsReport?
let events: AsyncStream<DecartRealtimeConnectionState>
// States: .idle, .connecting, .connected, .disconnected, .errorfunc process() async throws -> DataRealtime Models:
RealtimeModel.mirageRealtimeModel.mirage_v2RealtimeModel.lucy_v2v_720p_rt
Image Models:
ImageModel.lucy_pro_t2i- Text to imageImageModel.lucy_pro_i2i- Image to image
Video Models:
VideoModel.lucy_pro_t2v- Text to videoVideoModel.lucy_pro_i2v- Image to videoVideoModel.lucy_pro_v2v- Video to videoVideoModel.lucy_dev_i2v- Image to video (dev)VideoModel.lucy_fast_v2v- Fast video to video
// Text-based inputs
TextToImageInput(prompt: String, seed: Int?, resolution: ProResolution?)
TextToVideoInput(prompt: String, seed: Int?, resolution: ProResolution?)
// File-based inputs
ImageToImageInput(prompt: String, data: FileInput, seed: Int?)
ImageToVideoInput(prompt: String, data: FileInput, seed: Int?)
VideoToVideoInput(prompt: String, data: FileInput, seed: Int?)
// File input helpers
FileInput.image(data: Data, filename: String)
FileInput.video(data: Data, filename: String)
FileInput.from(data: Data, uniformType: UTType?)RealtimeConfiguration(
model: ModelDefinition,
initialState: ModelState,
connection: ConnectionConfig, // Optional
media: MediaConfig // Optional
)
// Connection config
ConnectionConfig(
iceServers: [String],
connectionTimeout: Int32,
pingInterval: Int32
)
// Media config
MediaConfig(
video: VideoConfig
)
// Video config
VideoConfig(
maxBitrate: Int,
minBitrate: Int,
maxFramerate: Int,
preferredCodec: String // "VP8" or "H264"
)- iOS 15.0+ / macOS 12.0+
- Swift 5.9+
- Xcode 15.0+
Configure these in your Xcode scheme (Edit Scheme → Run → Environment Variables):
| Variable | Required | Description |
|---|---|---|
DECART_API_KEY |
Yes | Your Decart API key from platform.decart.ai |
DECART_DEFAULT_PROMPT |
No | Default prompt for realtime sessions (defaults to "Simpsons") |
ENABLE_DECART_SDK_DUBUG_LOGS |
No | Set to YES to enable verbose SDK logging |
- WebRTC - WebRTC framework for iOS/macOS
MIT License - see LICENSE for details.