The LiveKit Swift SDK provides full support for macOS applications with powerful screen and window capture capabilities.
Minimum version: macOS 10.15+ (Catalina)
For screen capture features: macOS 12.3+ (Monterey)
VideoView
The SDK provides an NSView-based VideoView class for rendering video tracks on macOS:
import LiveKit
import Cocoa
class RoomViewController : NSViewController {
lazy var remoteVideoView: VideoView = {
let videoView = VideoView ()
view. addSubview (videoView)
return videoView
}()
lazy var localVideoView: VideoView = {
let videoView = VideoView ()
view. addSubview (videoView)
return videoView
}()
}
Video Rendering
macOS supports two rendering modes:
Metal Rendering (default): Hardware-accelerated rendering
AVSampleBuffer Rendering : Alternative rendering mode
videoView. renderMode = . metal // or .sampleBuffer
Layout Options
// Control how video fits within the view
videoView. layoutMode = . fill // .fill or .fit
// Mirror video
videoView. mirrorMode = . auto // .auto, .mirror, or .off
// Rotation override
videoView. rotationOverride = . r90
Camera Capture
Basic Camera Usage
// Enable camera with default options
try await room. localParticipant . setCamera ( enabled : true )
// Custom camera options
let options = CameraCaptureOptions (
dimensions : . h1080_169 ,
fps : 30
)
try await room. localParticipant . setCamera ( enabled : true , captureOptions : options)
Continuity Camera (macOS 13+)
On macOS 13+, Continuity Camera allows using your iPhone as a webcam:
let devices = try await CameraCapturer. captureDevices ()
let continuityCameras = devices. filter { device in
if #available ( macOS 14.0 , * ) {
return device. deviceType == . continuityCamera
}
return false
}
External Cameras
let devices = try await CameraCapturer. captureDevices ()
let externalCameras = devices. filter { device in
if #available ( macOS 14.0 , * ) {
return device. deviceType == . external
}
return false
}
See DeviceManager.swift:40 for device discovery.
Screen Sharing
macOS provides powerful screen sharing capabilities using ScreenCaptureKit (macOS 12.3+).
Display Capture
Capture an entire display:
// Get main display
let mainDisplay = try await MacOSScreenCapturer. mainDisplaySource ()
// Create screen share track
let screenTrack = LocalVideoTrack. createMacOSScreenShareTrack (
source : mainDisplay,
options : ScreenShareCaptureOptions (
dimensions : . h1080_169 ,
fps : 30 ,
showCursor : true
)
)
// Publish the track
try await room. localParticipant . publish ( videoTrack : screenTrack)
Window Capture
Capture a specific window:
// Get all available windows
let windows = try await MacOSScreenCapturer. windowSources ()
// Filter windows (e.g., exclude current app)
let otherAppWindows = windows. filter { ! $0 . isCurrentApplication }
// Select a window
if let window = otherAppWindows. first {
let screenTrack = LocalVideoTrack. createMacOSScreenShareTrack (
source : window,
options : ScreenShareCaptureOptions (
dimensions : . h1080_169 ,
fps : 30 ,
showCursor : true
)
)
try await room. localParticipant . publish ( videoTrack : screenTrack)
}
See MacOSScreenCapturer.swift:28 for implementation details.
Screen Share Options
let options = ScreenShareCaptureOptions (
dimensions : . h1080_169 , // Target resolution
fps : 30 , // Frame rate
showCursor : true , // Show/hide cursor
appAudio : true , // Capture app audio (macOS 13+)
includeCurrentApplication : false , // Include/exclude current app windows
excludeWindowIDs : [ 12345 ] // Exclude specific windows by ID
)
Enumerating Capture Sources
// Get all displays
let displays = try await MacOSScreenCapturer. displaySources ()
// Get all windows
let windows = try await MacOSScreenCapturer. windowSources ()
// Get all sources (displays + windows)
let allSources = try await MacOSScreenCapturer. sources ( for : . any )
// Include current application windows
let allSourcesIncludingCurrent = try await MacOSScreenCapturer. sources (
for : . any ,
includeCurrentApplication : true
)
for window in windows {
print ( "Window ID: \( window. windowID ) " )
print ( "Title: \( window. title ?? "No title" ) " )
print ( "Frame: \( window. frame ) " )
print ( "Layer: \( window. windowLayer ) " )
print ( "On screen: \( window. isOnScreen ) " )
if let app = window.owningApplication {
print ( "App: \( app. applicationName ) " )
print ( "Bundle ID: \( app. bundleIdentifier ) " )
}
}
Excluding Windows
Exclude specific windows from capture:
// Get window IDs to exclude
let windowIDsToExclude: [ UInt32 ] = [ 12345 , 67890 ]
let options = ScreenShareCaptureOptions (
excludeWindowIDs : windowIDsToExclude
)
let display = try await MacOSScreenCapturer. mainDisplaySource ()
let screenTrack = LocalVideoTrack. createMacOSScreenShareTrack (
source : display,
options : options
)
App Audio Capture (macOS 13+)
On macOS 13+, you can capture system audio:
let options = ScreenShareCaptureOptions (
appAudio : true
)
let display = try await MacOSScreenCapturer. mainDisplaySource ()
let screenTrack = LocalVideoTrack. createMacOSScreenShareTrack (
source : display,
options : options
)
try await room. localParticipant . publish ( videoTrack : screenTrack)
Captured app audio is mixed with the microphone track using AudioManager.shared.mixer.
Audio Management
macOS uses Core Audio for audio management:
Audio Devices
import AVFoundation
// Get available audio input devices
let devices = AVCaptureDevice. devices ( for : . audio )
for device in devices {
print ( "Device: \( device. localizedName ) " )
}
Audio Configuration
Unlike iOS, macOS does not use AVAudioSession. Audio routing is handled at the system level.
// Audio engine management
AudioManager. shared . setRecordingAlwaysPreparedMode ( true )
Permissions
macOS requires explicit permissions for camera, microphone, and screen recording.
Info.plist Entries
Add these keys to your Info.plist:
< key > NSCameraUsageDescription </ key >
< string > This app needs camera access for video calls </ string >
< key > NSMicrophoneUsageDescription </ key >
< string > This app needs microphone access for audio calls </ string >
Screen Recording Permission
For screen capture, macOS requires screen recording permission. The system will automatically prompt the user when screen capture is initiated.
To check permission status:
import ScreenCaptureKit
if #available ( macOS 12.3 , * ) {
// Attempt to get shareable content
// Will prompt for permission if not granted
do {
let content = try await SCShareableContent. excludingDesktopWindows (
false ,
onScreenWindowsOnly : true
)
// Permission granted
} catch {
// Permission denied or error
}
}
macOS Catalina Support
If targeting macOS Catalina (10.15), configure ReplayKit as optional:
Go to Build Phases → Link Binary with Libraries
Add ReplayKit.framework
Set it to Optional
This prevents crashes on Catalina where ReplayKit may not be available.
SwiftUI Integration
The SDK provides SwiftUI components for macOS:
import SwiftUI
import LiveKit
struct VideoCallView : View {
@StateObject var room = Room ()
var body: some View {
VStack {
if let videoTrack = room.remoteParticipants. first ? .videoTracks. first ? .track {
SwiftUIVideoView (videoTrack)
. frame ( maxWidth : . infinity , maxHeight : . infinity )
}
}
. onAppear {
Task {
try await room. connect ( url : url, token : token)
}
}
}
}
Thread Safety
VideoView is a UI component and must be accessed from the main thread .
// Correct: Update VideoView on main thread
DispatchQueue. main . async {
videoView. track = track
}
// Or use MainActor
Task { @MainActor in
videoView. track = track
}
Building and Testing
# Build for macOS
xcodebuild build -scheme LiveKit -destination 'platform=macOS'
# Run tests
xcodebuild test -scheme LiveKit -only-testing LiveKitCoreTests -destination 'platform=macOS'
Example Projects
Next Steps
Screen Sharing Learn about advanced screen capture features
SwiftUI Components Use SwiftUI components in your app