Coder Social home page Coder Social logo

floschliep / livekit-swift Goto Github PK

View Code? Open in Web Editor NEW

This project forked from livekit/client-sdk-swift

0.0 0.0 0.0 2.33 MB

LiveKit Swift Client SDK. Easily build live audio or video experiences into your mobile app, game or website.

Home Page: https://livekit.io

License: Apache License 2.0

Shell 0.03% Ruby 0.10% C 0.06% Objective-C 0.08% Swift 99.66% Makefile 0.07%

livekit-swift's Introduction

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

Note

Version 2 of the Swift SDK contains breaking changes from Version 1. Read the migration guide for a detailed overview of what has changed.

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("2.0.4")),
  ],
  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 = "ws://your_host"
        let token = "your_jwt_token"

        do {
            try await room.connect(url: url, token: token)
            // Connection successful...

            // Publishing camera & mic...
            try await room.localParticipant.setCamera(enabled: true)
            try await room.localParticipant.setMicrophone(enabled: true)
        } catch let error in {
            // Failed to connect
        }
    }
}

extension RoomViewController: RoomDelegate {

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

    func room(_: Room, participant _: RemoteParticipant, didSubscribeTrack publication: RemoteTrackPublication) {
        guard let track = publication?.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 your app's UI elements are from the main thread, for example by using @MainActor or 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

  • 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

How to publish camera in 60 FPS ?

  • Create a LocalVideoTrack by calling LocalVideoTrack.createCameraTrack(options: CameraCaptureOptions(fps: 60)).
  • Publish with LocalParticipant.publish(videoTrack: 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
Real-time SDKsReact ComponentsJavaScriptiOS/macOSAndroidFlutterReact NativeRustPythonUnity (web)Unity (beta)
Server APIsNode.jsGolangRubyJava/KotlinPythonRustPHP (community)
Agents FrameworksPythonPlayground
ServicesLivekit serverEgressIngressSIP
ResourcesDocsExample appsCloudSelf-hostingCLI

livekit-swift's People

Contributors

hiroshihorie avatar davidzhao avatar dsa avatar davidliu avatar ocupe avatar cloudwebrtc avatar amseddi avatar floschliep avatar janoskranczler avatar hoord avatar ronnyf avatar creativecbr avatar iamcr avatar own2pwn avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    馃枛 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 馃搳馃搱馃帀

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google 鉂わ笍 Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.