LiveKitClient 2.0.12

LiveKitClient 2.0.12

Hiroshi 维护。



 
依赖项
LiveKitWebRTC= 125.6422.03
SwiftProtobuf>= 0
Logging>= 0
 

  • LiveKit
The LiveKit icon, the name of the repository and some sample code in the background.

LiveKit 的 iOS/macOS Swift SDK

使用此 SDK 将实时视频、音频和数据功能添加到您的 Swift 应用中。通过连接到自托管或云托管的 LiveKit 服务器,您可以快速构建类似交互式直播或视频通话的应用程序,这仅需要几行代码。

文档和示例应用程序

注意

Swift SDK 的第 2 版与第 1 版有破坏性更改。请阅读 迁移指南,以了解详细的变化概述。

文档和指南位于 https://docs.livekit.io

有一个 iOS/macOS Swift UI 示例应用程序 的完整源代码。

要查看最小示例,请访问此存储库 👉 Swift SDK 示例

安装

LiveKit 的 Swift 版本作为 Swift 包提供。

Package.swift

将依赖项添加到您的目标

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

XCode

转到项目设置 -> Swift 包。

添加一个新的包并输入: https://github.com/livekit/client-sdk-swift

iOS 使用

LiveKit 提供了一个基于 UIKit 的 VideoView 类来渲染视频轨道。订阅的音频轨道将自动播放。

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
        }
    }
}

屏幕共享

请参阅 iOS 屏幕共享说明

集成说明

线程安全

由于 VideoView 是一个 UI 组件,所有操作(读取/写入属性等)都必须在 main 线程上执行。

其他核心类可以从任何线程访问。

委托将在 SDK 的内部线程上调用。请确保对您应用程序的 UI 元素的所有访问都是从主线程进行的,例如,通过使用 @MainActorDispatchQueue.main.async

内存管理

建议使用 weak var 保存由 SDK 创建和管理的对象的引用,例如 ParticipantTrackPublication 等。当 Room 断开连接时,这些对象将变得无效,并由 SDK 释放。对这些对象的强引用将阻止释放 Room 和其他内部对象。

VideoView.track 属性不保留强引用,因此不需要将其设置为 nil

音频会话管理

连接时,LiveKit 将自动管理底层的 AVAudioSession。会话默认设置为 playback 类别。当发布本地流时,它将切换到 playAndRecord。通常,它将选择合理的默认值并正确执行。

但是,如果您想自定义此行为,请覆盖 AudioManager.customConfigureAudioSessionFunc 以自定义底层的会话。请参阅 此处 的默认行为示例。

iOS 模拟器限制

  • 不支持通过 iOS 模拟器发布相机轨道。

滚动视图性能

建议关闭屏幕外的VideoView渲染,通过将isEnabled属性设置为false来达到目的,当它将再次出现时将其设置为true,以节省CPU资源。

据报道,UICollectionViewDelegatewillDisplay / didEndDisplaying对于此目的不可靠。具体来说,在某些iOS版本中,即使单元格可见,也可能调用didEndDisplaying

以下是不使用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.

要查看完整示例,请参阅👉 UIKit Minimal Example

常见问题

如何以60 FPS发布摄像头?

  • 通过调用LocalVideoTrack.createCameraTrack(options: CameraCaptureOptions(fps: 60))创建一个LocalVideoTrack
  • 使用LocalParticipant.publish(videoTrack: track, publishOptions: VideoPublishOptions(encoding: VideoEncoding(maxFps: 60)))进行发布。

已知问题

避免在macOS Catalina上崩溃

如果您要将应用程序针对macOS Catalina,请确保执行以下操作以避免崩溃(ReplayKit找不到)

  1. 明确将"ReplayKit.framework"添加到"构建阶段" > "链接二进制与库"部分
  2. 将其设置为可选

replykit

  • 我不确定为什么目前ReplayKit需要这样做。
  • 如果您针对macOS 11.0+,则不需要这样做。

获取帮助/贡献

请加入我们的Slack以从我们的开发人员/社区成员那里获得帮助。我们欢迎您的贡献(PRs),并且在那里可以讨论细节。


LiveKit生态系统
实时SDKsReact组件 · JavaScript · iOS/macOS · Android · Flutter · React Native · Rust · Python · Unity (web) · Unity (beta)
服务器APIsNode.js · Golang · Ruby · Java/Kotlin · Python · Rust · PHP (社区)
代理框架Python · Playground
服务Livekit服务器 · Egress · Ingress · SIP
资源文档 · 示例应用程序 · · 自托管 · CLI