Skip to main content

Screen Capturer

LiveKit provides platform-specific screen capture capabilities for iOS and macOS. The implementation varies based on platform capabilities and requirements.

macOS Screen Capture

MacOSScreenCapturer

Available on macOS 12.3+, MacOSScreenCapturer uses ScreenCaptureKit for high-performance screen and window capture.

Creating a Screen Share Track

// Get the main display
let display = try await MacOSScreenCapturer.mainDisplaySource()

let options = ScreenShareCaptureOptions(
    dimensions: .h1080_169,
    fps: 30,
    showCursor: true
)

let track = LocalVideoTrack.createMacOSScreenShareTrack(
    source: display,
    options: options
)

Enumerating Screen Sources

Display Sources
let displays = try await MacOSScreenCapturer.displaySources()
for display in displays {
    print("Display: \(display.displayID)")
    print("Size: \(display.width)x\(display.height)")
    print("Frame: \(display.frame)")
}
Window Sources
let windows = try await MacOSScreenCapturer.windowSources()
for window in windows {
    print("Window: \(window.title ?? "Untitled")")
    print("App: \(window.owningApplication?.applicationName ?? "Unknown")")
    print("Size: \(window.frame.size)")
    print("On screen: \(window.isOnScreen)")
}
All Sources
let allSources = try await MacOSScreenCapturer.sources(
    for: .any,
    includeCurrentApplication: false
)

Source Types

MacOSDisplay Represents a display/monitor:
PropertyTypeDescription
displayIDCGDirectDisplayIDUnique display identifier
widthIntDisplay width in pixels
heightIntDisplay height in pixels
frameCGRectDisplay frame
MacOSWindow Represents an application window:
PropertyTypeDescription
windowIDCGWindowIDUnique window identifier
frameCGRectWindow frame
titleString?Window title
windowLayerIntWindow layer level
owningApplicationMacOSRunningApplication?Application that owns the window
isOnScreenBoolWhether window is currently visible
isCurrentApplicationBoolWhether window belongs to current app

Capturing Specific Windows

let windows = try await MacOSScreenCapturer.windowSources()

// Find a specific application window
if let window = windows.first(where: { 
    $0.owningApplication?.applicationName == "Safari" 
}) {
    let track = LocalVideoTrack.createMacOSScreenShareTrack(
        source: window,
        options: options
    )
}

Excluding Windows

let windowsToExclude: [UInt32] = [/* window IDs */]

let options = ScreenShareCaptureOptions(
    excludeWindowIDs: windowsToExclude
)

iOS Screen Capture

In-App Screen Capture

For capturing only your app’s content (iOS 11+):
let options = ScreenShareCaptureOptions(
    dimensions: .h1080_169,
    fps: 15
)

let track = LocalVideoTrack.createInAppScreenShareTrack(
    options: options
)

Broadcast Extension (Full Screen)

For full-screen capture including other apps, you need to implement a Broadcast Upload Extension. The SDK automatically uses the broadcast extension if configured:
let options = ScreenShareCaptureOptions(
    useBroadcastExtension: true
)

// The SDK will use the broadcast extension if available
let track = LocalVideoTrack.createScreenShareTrack(
    options: options
)

Screen Share Capture Options

ScreenShareCaptureOptions

Configure screen capture with these properties:
PropertyTypeDefaultDescription
dimensionsDimensions.h1080_169Target capture dimensions
fpsInt30Frames per second
showCursorBooltrueShow cursor in capture (macOS only)
appAudioBoolfalseCapture application audio (macOS 13+)
useBroadcastExtensionBoolautoUse broadcast extension (iOS only)
includeCurrentApplicationBoolfalseInclude own app windows (macOS only)
excludeWindowIDs[UInt32][]Window IDs to exclude (macOS only)
let options = ScreenShareCaptureOptions(
    dimensions: .h1080_169,
    fps: 30,
    showCursor: true,
    appAudio: true,
    includeCurrentApplication: false
)

Capturing Application Audio (macOS 13+)

On macOS 13 and later, you can capture audio from the screen share source:
let options = ScreenShareCaptureOptions(
    appAudio: true
)

let track = LocalVideoTrack.createMacOSScreenShareTrack(
    source: display,
    options: options
)
The audio is automatically routed through AudioManager and mixed with other audio sources.

Frame Resending

When screen content is static, MacOSScreenCapturer automatically resends the last frame at 1 fps to maintain the video stream. This ensures:
  • Continuous video stream even when content doesn’t change
  • Efficient bandwidth usage during static periods
  • Smooth experience for viewers

Platform-Specific Considerations

macOS

  • Requires macOS 12.3+ for ScreenCaptureKit-based capture
  • User must grant screen recording permission in System Preferences
  • Can capture individual windows or entire displays
  • Supports audio capture on macOS 13+
  • Automatically filters out small or system windows

iOS

  • In-app capture only captures your app (iOS 11+)
  • Full-screen capture requires Broadcast Upload Extension
  • User initiates broadcast from Control Center
  • Limited to portrait or landscape orientation

Error Handling

do {
    let display = try await MacOSScreenCapturer.mainDisplaySource()
    let track = LocalVideoTrack.createMacOSScreenShareTrack(
        source: display,
        options: options
    )
    try await track.start()
} catch {
    print("Failed to start screen capture: \(error)")
}
Common errors:
  • deviceNotFound: No screen capture source available
  • invalidState: Screen capture permission not granted
  • Permission errors on macOS if screen recording is not allowed

See Also

Build docs developers (and LLMs) love