Skip to main content
The Room class is the main entry point for connecting to a LiveKit server. It manages the connection state, participants, tracks, and provides delegate callbacks for room events.

Creating a Room

Create a Room instance with optional configuration:
let room = Room(
    delegate: self,
    connectOptions: ConnectOptions(),
    roomOptions: RoomOptions()
)

Room Options

Configure room behavior with RoomOptions:
let roomOptions = RoomOptions(
    defaultCameraCaptureOptions: CameraCaptureOptions(),
    defaultAudioCaptureOptions: AudioCaptureOptions(),
    defaultVideoPublishOptions: VideoPublishOptions(),
    defaultAudioPublishOptions: AudioPublishOptions(),
    adaptiveStream: true,
    reportRemoteTrackStatistics: true,
    suspendLocalVideoTracksInBackground: true
)

Connecting to a Room

Connect to a LiveKit room using a URL and token:
try await room.connect(
    url: "wss://your-livekit-server.com",
    token: "your-jwt-token"
)
The connect method is asynchronous and throws errors if connection fails. Always wrap it in a do-catch block or handle errors appropriately.

Connection Options

You can specify ConnectOptions to control connection behavior:
let connectOptions = ConnectOptions(
    enableMicrophone: true  // Auto-publish microphone on connect
)

try await room.connect(
    url: "wss://your-livekit-server.com",
    token: "your-jwt-token",
    connectOptions: connectOptions
)

Connection Lifecycle

The room connection goes through several states defined by ConnectionState:
  • disconnected - Not connected to the room
  • connecting - Attempting to connect
  • connected - Successfully connected
  • reconnecting - Connection lost, attempting to reconnect
  • disconnecting - Disconnecting from the room
Monitor connection state changes:
class MyViewController: RoomDelegate {
    func room(_ room: Room, didUpdate connectionState: ConnectionState, oldValue: ConnectionState) {
        switch connectionState {
        case .connected:
            print("Connected to room")
        case .reconnecting:
            print("Connection lost, reconnecting...")
        case .disconnected:
            print("Disconnected from room")
        default:
            break
        }
    }
}
The SDK automatically handles reconnection when the connection is lost. It will attempt to restore the session and re-establish track subscriptions.

Room Properties

Access room information and participants:
// Room metadata
room.sid                    // Server-assigned room ID
room.name                   // Room name
room.metadata               // Room metadata
room.serverVersion          // LiveKit server version
room.serverRegion           // Server region code

// Connection info
room.connectionState        // Current connection state
room.url                    // User-provided URL
room.connectedUrl           // Actual connected URL (may include region)

// Participants
room.localParticipant       // Local participant
room.remoteParticipants     // Dictionary of remote participants [Identity: RemoteParticipant]
room.activeSpeakers         // Array of currently speaking participants

// Room statistics
room.participantCount       // Total number of participants
room.publishersCount        // Number of publishing participants
room.maxParticipants        // Maximum allowed participants
room.isRecording            // Whether room is being recorded

Disconnecting

Disconnect from the room:
await room.disconnect()
The disconnect process:
  1. Sends a leave message to the server
  2. Stops all local tracks
  3. Cleans up remote participants and tracks
  4. Resets connection state to disconnected
Always call disconnect() when leaving a room to properly clean up resources and notify the server.

Room Events

Implement the RoomDelegate protocol to receive room events:
@objc protocol RoomDelegate {
    // Connection events
    optional func room(_ room: Room, didUpdate connectionState: ConnectionState, oldValue: ConnectionState)
    
    // Participant events
    optional func room(_ room: Room, participantDidJoin participant: RemoteParticipant)
    optional func room(_ room: Room, participantDidDisconnect participant: RemoteParticipant)
    
    // Track publication events
    optional func room(_ room: Room, participant: Participant, didPublishTrack publication: TrackPublication)
    optional func room(_ room: Room, participant: Participant, didUnpublishTrack publication: TrackPublication)
    
    // Track subscription events (remote tracks only)
    optional func room(_ room: Room, participant: RemoteParticipant, didSubscribeTrack publication: RemoteTrackPublication)
    optional func room(_ room: Room, participant: RemoteParticipant, didUnsubscribeTrack publication: RemoteTrackPublication)
    
    // Data events
    optional func room(_ room: Room, participant: RemoteParticipant?, didReceiveData data: Data, topic: String?)
    
    // Metadata events
    optional func room(_ room: Room, didUpdateMetadata metadata: String)
    optional func room(_ room: Room, participant: Participant, didUpdateMetadata metadata: String)
    
    // Recording events
    optional func room(_ room: Room, didUpdateIsRecording isRecording: Bool)
}

Example Implementation

class RoomManager: RoomDelegate {
    let room = Room()
    
    init() {
        room.delegates.add(delegate: self)
    }
    
    func room(_ room: Room, participantDidJoin participant: RemoteParticipant) {
        print("Participant joined: \(participant.identity ?? "unknown")")
        participant.delegates.add(delegate: self)
    }
    
    func room(_ room: Room, participant: RemoteParticipant, didSubscribeTrack publication: RemoteTrackPublication) {
        print("Subscribed to track: \(publication.name)")
        
        if let videoTrack = publication.track as? VideoTrack {
            // Attach to video view
            videoTrack.add(videoRenderer: videoView)
        }
    }
    
    func room(_ room: Room, participant: RemoteParticipant?, didReceiveData data: Data, topic: String?) {
        print("Received data on topic: \(topic ?? "default")")
    }
}

MulticastDelegate

The Room uses MulticastDelegate to support multiple delegates:
// Add a delegate
room.delegates.add(delegate: myDelegate)

// Remove a delegate
room.delegates.remove(delegate: myDelegate)
This allows multiple components to observe room events simultaneously.

SwiftUI Integration

The Room conforms to ObservableObject for SwiftUI integration:
struct RoomView: View {
    @StateObject var room = Room()
    
    var body: some View {
        VStack {
            Text("Connection: \(room.connectionState)")
            Text("Participants: \(room.participantCount)")
            
            ForEach(Array(room.remoteParticipants.values)) { participant in
                ParticipantView(participant: participant)
            }
        }
        .task {
            try? await room.connect(url: url, token: token)
        }
    }
}

Best Practices

  1. Always handle connection errors: Wrap connect() in try-catch blocks
  2. Disconnect when done: Call disconnect() to clean up resources
  3. Monitor connection state: Handle reconnection scenarios gracefully
  4. Use delegates: Add room and participant delegates early to avoid missing events
  5. Check permissions: Verify participant permissions before attempting operations

Build docs developers (and LLMs) love