使用此 SDK 将实时视频、音频和数据功能添加到您的 Swift 应用程序中。通过连接到 LiveKit 云服务或自托管服务器,您只需几行代码即可快速构建多模态 AI、直播或视频通话等应用程序。
注意
Swift SDK 的版本 2 包含与版本 1 的不兼容变更。请阅读迁移指南,详细了解变更内容。
文档和指南位于 https://docs.livekit.io。
这里有iOS/macOS Swift UI 示例应用的完整源代码。
如需查看最简示例,请访问此仓库 👉 Swift SDK 示例
LiveKit for Swift 以 Swift Package 的形式提供。
添加依赖项,并添加到您的 target 中
let package = Package(
...
dependencies: [
.package(name: "LiveKit", url: "https://github.com/livekit/client-sdk-swift.git", .upToNextMajor("2.1.1")),
],
targets: [
.target(
name: "MyApp",
dependencies: ["LiveKit"]
)
]
}
转到 “Project Settings -> Swift Packages”。
添加一个新的 package 并输入:https://github.com/livekit/client-sdk-swift
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"
Task {
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 {
// 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 {
self.localVideoView.track = track
}
}
func room(_: Room, participant _: RemoteParticipant, didSubscribeTrack publication: RemoteTrackPublication) {
guard let track = publication.track as? VideoTrack else { return }
DispatchQueue.main.async {
self.remoteVideoView.track = track
}
}
}
请参阅 iOS 屏幕共享说明。
由于 VideoView
是一个 UI 组件,因此所有操作(读/写属性等)都必须从 main
线程执行。
可以从任何线程访问其他核心类。
委托将在 SDK 的内部线程上调用。请确保从主线程访问应用程序的 UI 元素,例如使用 @MainActor
或 DispatchQueue.main.async
。
建议在使用 weak var 时存储对 SDK 创建和管理的对象(如 Participant
、TrackPublication
等)的引用。当 Room
断开连接时,这些对象将失效,并会被 SDK 释放。保持对这些对象的强引用将阻止释放 Room
和其他内部对象。
VideoView.track
属性不持有强引用,因此不需要将其设置为 nil
。
LiveKit 将在连接时自动管理底层的 AVAudioSession
。会话将默认设置为 playback
类别。当发布本地流时,它将切换到 playAndRecord
。一般来说,它会选择合理的默认值并执行正确的操作。
但是,如果您想自定义此行为,您可以覆盖 AudioManager.customConfigureAudioSessionFunc
以自行管理底层会话。请参阅 此处的示例 以了解默认行为。
要与 CallKit 集成以实现后台触发的来电,LiveKit 的音频会话必须与 CallKit 的音频会话同步
import LiveKitWebRTC
添加到您的 CallProvider 文件。CXProviderDelegate
实现中,添加以下内容func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession){
LKRTCAudioSession.sharedInstance().audioSessionDidActivate(audioSession)
// ...
}
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
LKRTCAudioSession.sharedInstance().audioSessionDidDeactivate(audioSession)
// ...
}
建议关闭滚动到屏幕外且不可见的 VideoView
的渲染,方法是将 isEnabled
属性设置为 false
,并在重新出现时设置为 true
,以节省 CPU 资源。
据报告,UICollectionViewDelegate
的 willDisplay
/ 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
LocalVideoTrack.createCameraTrack(options: CameraCaptureOptions(fps: 60))
创建 LocalVideoTrack
。LocalParticipant.publish(videoTrack: track, publishOptions: VideoPublishOptions(encoding: VideoEncoding(maxFps: 60)))
发布。如果您的应用程序的目标是 macOS Catalina,请确保执行以下操作以避免崩溃(找不到 ReplayKit)
请加入我们的 Slack 以获得我们开发人员/社区成员的帮助。我们欢迎您的贡献(PR),详细信息可以在那里讨论。
LiveKit 生态系统 | |
---|---|
LiveKit SDK | 浏览器 · iOS/macOS/visionOS · Android · Flutter · React Native · Rust · Node.js · Python · Unity · Unity (WebGL) |
服务器 API | Node.js · Golang · Ruby · Java/Kotlin · Python · Rust · PHP (社区) · .NET (社区) |
UI 组件 | React · Android Compose · SwiftUI |
代理框架 | Python · Node.js · Playground |
服务 | LiveKit 服务器 · Egress · Ingress · SIP |
资源 | 文档 · 示例应用 · 云服务 · 自托管 · CLI |