Skip to main content
LocalVideoTrack represents a local video track that captures video from device cameras or other video sources like screen sharing. It manages video capture through a VideoCapturer and provides methods for muting/unmuting and video processing.

Creating a Track

Create a local video track using static factory methods for different video sources:

Camera Track

let cameraTrack = LocalVideoTrack.createCameraTrack(
    name: "camera",
    options: CameraCaptureOptions(),
    reportStatistics: false
)

createCameraTrack

Static factory method to create a camera video track.
name
String?
default:"Track.cameraName"
The name of the video track. Defaults to "camera".
options
CameraCaptureOptions?
default:"nil"
Camera capture configuration options. If nil, default options are used.See CameraCaptureOptions for settings:
  • position: Camera position (.front or .back)
  • preferredFormat: Preferred capture format
  • dimensions: Capture dimensions
  • fps: Target frames per second
reportStatistics
Bool
default:"false"
Whether to collect and report statistics for this track
processor
VideoProcessor?
default:"nil"
Optional video processor for effects like background blur, virtual backgrounds, etc.
Returns: A new LocalVideoTrack instance configured for camera capture.

Properties

capturer

public internal(set) var capturer: VideoCapturer
The VideoCapturer instance managing video capture for this track. This could be a CameraCapturer, ScreenCapturer, or custom capturer implementation.

processor

public var processor: VideoProcessor?
Optional video processor for applying effects to captured video frames. Set this to add background blur, virtual backgrounds, filters, or other custom video processing. Example:
let backgroundBlur = BackgroundBlurProcessor()
videoTrack.processor = backgroundBlur

publishOptions

public var publishOptions: TrackPublishOptions?
The options used when this track was published, or nil if not yet published.

publishState

public var publishState: Track.PublishState
The current publish state of the track:
  • .unpublished: Track has not been published
  • .published: Track is currently published

Inherited Properties

From the base Track class:
  • name: The track name
  • sid: The server-assigned track ID (available after publishing)
  • kind: Always .video for video tracks
  • source: Track source (.camera, .screenShareVideo, etc.)
  • isMuted: Whether the track is currently muted
  • trackState: Current state (.started or .stopped)
  • dimensions: Current video dimensions
  • videoFrame: The last captured video frame
  • statistics: Real-time statistics if reportStatistics is enabled

Methods

mute()

Mutes the video track by stopping video capture.
public func mute() async throws
Muting stops video transmission without destroying the track. The track remains published but sends black frames. Example:
try await videoTrack.mute()

unmute()

Unmutes the video track by resuming video capture.
public func unmute() async throws
Example:
try await videoTrack.unmute()

add(videoRenderer:)

Adds a VideoRenderer to receive video frames from this track.
public func add(videoRenderer: VideoRenderer)
videoRenderer
VideoRenderer
An object conforming to the VideoRenderer protocol that will receive video frames
This is typically a VideoView for display, but can also be custom renderers for processing or recording. Example:
let videoView = VideoView()
videoTrack.add(videoRenderer: videoView)

remove(videoRenderer:)

Removes a previously added VideoRenderer.
public func remove(videoRenderer: VideoRenderer)
videoRenderer
VideoRenderer
The renderer to remove

clone()

Creates a clone of this video track sharing the same VideoCapturer.
public func clone() -> LocalVideoTrack
This allows publishing the same video source multiple times with different encoding parameters. Returns: A new LocalVideoTrack instance sharing the same capturer. Example:
let primaryTrack = LocalVideoTrack.createCameraTrack()
let secondaryTrack = primaryTrack.clone()

// Publish with different quality settings
try await room.localParticipant.publish(
    track: primaryTrack,
    options: TrackPublishOptions(videoQuality: .high)
)

try await room.localParticipant.publish(
    track: secondaryTrack,
    options: TrackPublishOptions(videoQuality: .low)
)

start()

Starts video capture. Inherited from Track.
public func start() async throws
This starts the underlying VideoCapturer and is typically called automatically when publishing.

stop()

Stops video capture. Inherited from Track.
public func stop() async throws

set(reportStatistics:)

Enables or disables statistics reporting at runtime.
public func set(reportStatistics: Bool) async
reportStatistics
Bool
true to enable statistics collection, false to disable

Track Lifecycle

  1. Creation: Create track using createCameraTrack() or other factory methods
  2. Publishing: Publish track via LocalParticipant.publish(track:options:)
  3. Capturing: Track automatically starts capturing when published
  4. Muting/Unmuting: Use mute() and unmute() to control video transmission
  5. Processing: Optionally set a processor for video effects
  6. Unpublishing: Unpublish via LocalParticipant.unpublish(track:)
  7. Cleanup: Track stops capturing when deallocated

Camera Control

For camera tracks, access camera-specific controls through the capturer:
if let cameraCapturer = videoTrack.capturer as? CameraCapturer {
    // Switch camera
    try await cameraCapturer.switchCameraPosition()
    
    // Set specific position
    try await cameraCapturer.set(cameraPosition: .front)
    
    // Update capture options
    let newOptions = CameraCaptureOptions(
        position: .back,
        dimensions: .h1080_169
    )
    try await cameraCapturer.set(options: newOptions)
}

Video Processing

Add video processing by setting the processor property:
// Create track with processor
let processor = MyVideoProcessor()
let track = LocalVideoTrack.createCameraTrack(
    processor: processor
)

// Or set processor later
track.processor = BackgroundBlurProcessor()

// Remove processor
track.processor = nil

Thread Safety

LocalVideoTrack is @unchecked Sendable and thread-safe. All public methods can be called from any thread.

Example Usage

// Create camera track with custom options
let options = CameraCaptureOptions(
    position: .front,
    dimensions: .h720_169,
    fps: 30
)

let videoTrack = LocalVideoTrack.createCameraTrack(
    name: "front-camera",
    options: options,
    reportStatistics: true
)

// Add to view for preview
let previewView = VideoView()
videoTrack.add(videoRenderer: previewView)

// Publish the track
try await room.localParticipant.publish(
    track: videoTrack,
    options: TrackPublishOptions(
        videoEncoding: .h720_169,
        simulcast: true
    )
)

// Apply video processing
let blurProcessor = BackgroundBlurProcessor()
videoTrack.processor = blurProcessor

// Switch camera
if let camera = videoTrack.capturer as? CameraCapturer {
    try await camera.switchCameraPosition()
}

// Mute when needed
try await videoTrack.mute()

See Also

Build docs developers (and LLMs) love