• Stars
    star
    145
  • Rank 245,219 (Top 5 %)
  • Language
    Swift
  • License
    Apache License 2.0
  • Created over 3 years ago
  • Updated 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

LiveKit Swift Client SDK. Easily build live audio or video experiences into your mobile app, game or website.
The LiveKit icon, the name of the repository and some sample code in the background.

iOS/macOS Swift SDK for LiveKit

Use this SDK to add real-time video, audio and data features to your Swift app. By connecting to a self- or cloud-hosted LiveKit server, you can quickly build applications like interactive live streaming or video calls with just a few lines of code.

Docs & Example app

Docs and guides are at https://docs.livekit.io.

There is full source code of a iOS/macOS Swift UI Example App.

For minimal examples view this repo 👉 Swift SDK Examples

Installation

LiveKit for Swift is available as a Swift Package.

Package.swift

Add the dependency and also to your target

let package = Package(
  ...
  dependencies: [
    .package(name: "LiveKit", url: "https://github.com/livekit/client-sdk-swift.git", .upToNextMajor("1.0.0")),
  ],
  targets: [
    .target(
      name: "MyApp",
      dependencies: ["LiveKit"]
    )
  ]
}

XCode

Go to Project Settings -> Swift Packages.

Add a new package and enter: https://github.com/livekit/client-sdk-swift

iOS Usage

LiveKit provides an UIKit based VideoView class that renders video tracks. Subscribed audio tracks are automatically played.

import LiveKit
import UIKit

class RoomViewController: UIViewController {

    lazy var room = Room(delegate: self)

    lazy var remoteVideoView: VideoView = {
        let videoView = VideoView()
        view.addSubview(videoView)
        // additional initialization ...
        return videoView
    }()

    lazy var localVideoView: VideoView = {
        let videoView = VideoView()
        view.addSubview(videoView)
        // additional initialization ...
        return videoView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        let url: String = "ws://your_host"
        let token: String = "your_jwt_token"

        room.connect(url, token).then { room in

            // Publish camera & mic
            room.localParticipant?.setCamera(enabled: true)
            room.localParticipant?.setMicrophone(enabled: true)

        }.catch { error in
            // failed to connect
        }
    }
}

extension RoomViewController: RoomDelegate {

    func room(_ room: Room, localParticipant: LocalParticipant, didPublish publication: LocalTrackPublication) {
        guard let track = publication?.track as? VideoTrack else {
            return
        }
        DispatchQueue.main.async {
            localVideoView.track = track
        }
    }

    func room(_ room: Room, participant: RemoteParticipant, didSubscribe publication: RemoteTrackPublication, track: Track) {
        guard let track = track as? VideoTrack else {
          return
        }
        DispatchQueue.main.async {
            remoteVideoView.track = track
        }
    }
}

Screen Sharing

See iOS Screen Sharing instructions.

Integration Notes

Thread safety

Since VideoView is a UI component, all operations (read/write properties etc) must be performed from the main thread.

Other core classes can be accessed from any thread.

Delegates will be called on the SDK's internal thread. Make sure any access to the UI is within the main thread, for example by using DispatchQueue.main.async.

Memory management

It is recommended to use weak var when storing references to objects created and managed by the SDK, such as Participant, TrackPublication etc. These objects are invalid when the Room disconnects, and will be released by the SDK. Holding strong reference to these objects will prevent releasing Room and other internal objects.

VideoView.track property does not hold strong reference, so it's not required to set it to nil.

AudioSession management

LiveKit will automatically manage the underlying AVAudioSession while connected. The session will be set to playback category by default. When a local stream is published, it'll be switched to playAndRecord. In general, it'll pick sane defaults and do the right thing.

However, if you'd like to customize this behavior, you would override AudioManager.customConfigureAudioSessionFunc to manage the underlying session on your own. See example here for the default behavior.

iOS Simulator limitations

  • Currently, VideoView will use OpenGL for iOS Simulator.
  • Publishing the camera track is not supported by iOS Simulator.

ScrollView performance

It is recommended to turn off rendering of VideoViews that scroll off the screen and isn't visible by setting false to isEnabled property and true when it will re-appear to save CPU resources.

UICollectionViewDelegate's willDisplay / didEndDisplaying has been reported to be unreliable for this purpose. Specifically, in some iOS versions didEndDisplaying could get invoked even when the cell is visible.

The following is an alternative method to using willDisplay / didEndDisplaying :

// 1. define a weak-reference set for all cells
private var allCells = NSHashTable<ParticipantCell>.weakObjects()
// in UICollectionViewDataSource...
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ParticipantCell.reuseIdentifier, for: indexPath)

    if let cell = cell as? ParticipantCell {
        // 2. keep weak reference to the cell
        allCells.add(cell)

        // configure cell etc...
    }

    return cell
}
// 3. define a func to re-compute and update isEnabled property for cells that visibility changed
func reComputeVideoViewEnabled() {

    let visibleCells = collectionView.visibleCells.compactMap { $0 as? ParticipantCell }
    let offScreenCells = allCells.allObjects.filter { !visibleCells.contains($0) }

    for cell in visibleCells.filter({ !$0.videoView.isEnabled }) {
        print("enabling cell#\(cell.hashValue)")
        cell.videoView.isEnabled = true
    }

    for cell in offScreenCells.filter({ $0.videoView.isEnabled }) {
        print("disabling cell#\(cell.hashValue)")
        cell.videoView.isEnabled = false
    }
}
// 4. set a timer to invoke the func
self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { [weak self] _ in
    self?.reComputeVideoViewEnabled()
})

// alternatively, you can call `reComputeVideoViewEnabled` whenever cell visibility changes (such as scrollViewDidScroll(_:)),
// but this will be harder to track all cases such as cell reload etc.

For the full example, see 👉 UIKit Minimal Example

Frequently asked questions

Mic privacy indicator (orange dot) remains on even after muting audio track

You will need to un-publish the LocalAudioTrack for the indicator to turn off. More discussion here #140

How to publish camera in 60 FPS ?

  • Create a LocalVideoTrack by calling LocalVideoTrack.createCameraTrack(options: CameraCaptureOptions(fps: 60)).
  • Publish with LocalParticipant.publishVideoTrack(track: track, publishOptions: VideoPublishOptions(encoding: VideoEncoding(maxFps: 60))).

Known issues

Avoid crashes on macOS Catalina

If your app is targeting macOS Catalina, make sure to do the following to avoid crash (ReplayKit not found):

  1. Explicitly add "ReplayKit.framework" to the Build Phases > Link Binary with Libraries section
  2. Set it to Optional

replykit

  • I am not sure why this is required for ReplayKit at the moment.
  • If you are targeting macOS 11.0+, this is not required.

Getting help / Contributing

Please join us on Slack to get help from our devs / community members. We welcome your contributions(PRs) and details can be discussed there.


LiveKit Ecosystem
Client SDKsComponents · JavaScript · iOS/macOS · Android · Flutter · React Native · Rust · Python · Unity (web) · Unity (beta)
Server SDKsNode.js · Golang · Ruby · Java/Kotlin · PHP (community) · Python (community)
ServicesLivekit server · Egress · Ingress
ResourcesDocs · Example apps · Cloud · Self-hosting · CLI

More Repositories

1

livekit

End-to-end stack for WebRTC. SFU media server and SDKs.
Go
6,715
star
2

client-sdk-js

LiveKit browser client SDK (javascript)
TypeScript
273
star
3

client-sdk-flutter

Flutter Client SDK for LiveKit
Dart
197
star
4

livekit-react

React component and library for LiveKit
TypeScript
166
star
5

server-sdk-go

Client and server SDK for Golang
Go
164
star
6

livekit-cli

Command line interface to LiveKit
Go
154
star
7

client-sdk-android

LiveKit SDK for Android
Kotlin
138
star
8

egress

Export and record WebRTC sessions and tracks
Go
137
star
9

rust-sdks

LiveKit real-time SDK and server API for Rust
Rust
119
star
10

agents

Build real-time multimodal AI applications 🤖🎙️📹
Python
111
star
11

components-js

Official open source React components and examples for building with LiveKit.
TypeScript
104
star
12

server-sdk-js

JS Server SDK to LiveKit
TypeScript
100
star
13

client-sdk-react-native

TypeScript
80
star
14

protocol

LiveKit protocol. Protobuf definitions for LiveKit's signaling protocol
Go
58
star
15

ingress

Ingest streams (RTMP/WHIP) or files (HLS, MP4) to LiveKit WebRTC
Go
48
star
16

sip

SIP to WebRTC bridge for LiveKit
Go
46
star
17

client-sdk-unity-web

Client SDK for Unity WebGL
C#
42
star
18

python-sdks

LiveKit real-time SDK and server API for Python
Python
38
star
19

livekit-helm

LiveKit Helm charts
Smarty
36
star
20

livekit-recorder

Go
31
star
21

livekit-server-sdk-python

LiveKit Server SDK for Python
Python
25
star
22

server-sdk-kotlin

Kotlin
24
star
23

track-processors-js

TypeScript
23
star
24

client-example-swift

Example app for LiveKit Swift SDK 👉 https://github.com/livekit/client-sdk-swift
Swift
21
star
25

server-sdk-ruby

LiveKit Server SDK for Ruby
Ruby
20
star
26

client-sdk-unity

C#
20
star
27

psrpc

Go
17
star
28

meet

Open source video conferencing app built on LiveKit Components, LiveKit Cloud, and Next.js.
TypeScript
16
star
29

client-unity-demo

Demo for LiveKit Unity SDK
C#
11
star
30

client-sdk-cpp

C++
11
star
31

WebRTC-swift

Swift package for WebRTC
Objective-C
10
star
32

agents-playground

TypeScript
9
star
33

deploy

Resources for deploying LiveKit
Go
8
star
34

livekit-docs

JavaScript
8
star
35

chrometester

A livekit tester to simulate a subscriber in a room, uses headless Chromium
JavaScript
8
star
36

nats-test

benchmarking app that emulates our usage patterns
Go
7
star
37

mediatransportutil

Media transport utilities
Go
5
star
38

webrtc-vmaf

VMAF benchmarking tool for WebRTC codecs
Python
4
star
39

client-example-collection-swift

A collection of small examples for the LiveKit Swift SDK 👉 https://github.com/livekit/client-sdk-swift
Swift
3
star
40

webrtc-chrome

Fork of Google's WebRTC repo, with LiveKit patches.
C++
3
star
41

rtcscore-go

Library to calculate Mean Opinion Score(MOS)
Go
2
star
42

ios-test-apps

Swift
1
star
43

gstreamer

C
1
star
44

mageutil

Go
1
star
45

components-android

Kotlin
1
star
46

gst-plugins

Go
1
star