AgoraARKit
使应用能够直播 AR 视频流。 ARKit 使用设备的摄像头和运动传感器将虚拟内容投影到用户的现实世界中。Agora.io,提供了一个 视频 SDK 用于构建实时视频和音频通信应用。通过结合 Agora.io 的视频 SDK 和 ARKit,它使开发人员能够创建跨多个用例的许多不同应用程序。
此库提供了带有托管用户界面的三个类
- 大厅:预通道 UIView,允许用户定义他们的频道名称和角色(广播者和观众)
- ARBroadcaster:在直播中广播用户的 AR 视图
- ARAudience:查看远程用户的 AR 会话。
设备要求
AgoraARKit 至少需要 iOS 12.2 版本,并支持以下设备
- iPhone 6S 或更高版本
- iPhone SE
- iPad (2017)
- 所有 iPad Pro 型号
iOS 12.2 可从 Apple 开发者网站下载。
依赖关系
AgoraARKit 依赖于 Agora.io 视频SDK 和 ARVideoKit。
支持
快速入门指南
要开始使用AgoraARVideoKit,请按照以下步骤进行:
使用 CocoaPods 设置
- 将其添加到您的 podfile 文件中
pod 'AgoraARKit'
- 在终端中,导航到您的项目文件夹,然后
pod install
- 将
NSCameraUsageDescription
、NSMicrophoneUsageDescription
、NSPhotoLibraryAddUsageDescription
和NSPhotoLibraryUsageDescription
添加到 plist 文件中,并简要说明。后两个权限由 ARVideoKit 的存储照片/视频功能所必需。
手动设置
- 将
AgoraARKit
目录中的所有文件添加到您的项目中。 - 导入
ARVideoKit
和Agora.io Video SDK
库 - 将
NSCameraUsageDescription
和NSMicrophoneUsageDescription
添加到 plist 文件中,并简要说明(参见示例项目获取示例)
实现
- 导入 AgoraARKit 及其依赖项后,打开您的
ViewController.swift
文件并添加以下代码
import AgoraARKit
- 然后设置您的
ViewController
类继承自AgoraLobbyVC
,并使用loadView
方法设置 Agora App Id。如果您想为 Lobby 视图设置自定义图像,请使用bannerImage
属性进行设置。
override func loadView() {
super.loadView()
AgoraARKit.agoraAppId = ""
// set the banner image within the initial view
if let agoraLogo = UIImage(named: "ar-support-icon") {
self.bannerImage = agoraLogo
}
}
自定义功能:
自定义AgoraARKit类是可扩展的,因此您可以子类化它们以按需自定义。
大厅视图控制器
因为我们已经从AgoraLobbyVC
继承了,所以在我们的ViewController
中覆盖joinSession
和createSession
方法来设置观众和广播视图的图像。
观众视图中自定义图像
@IBAction override func joinSession() {
if let channelName = self.userInput.text {
if channelName != "" {
let arAudienceVC = ARAudience()
if let exitBtnImage = UIImage(named: "exit") {
arAudienceVC.backBtnImage = exitBtnImage
}
arAudienceVC.channelName = channelName
arAudienceVC.modalPresentationStyle = .fullScreen
self.present(arAudienceVC, animated: true, completion: nil)
} else {
// TODO: add visible msg to user
print("unable to join a broadcast without a channel name")
}
}
}
广播视图中自定义图像
@IBAction override func createSession() {
if let channelName = self.userInput.text {
if channelName != "" {
let arBroadcastVC = ARBroadcaster()
if let exitBtnImage = UIImage(named: "exit") {
arBroadcastVC.backBtnImage = exitBtnImage
}
if let micBtnImage = UIImage(named: "mic"),
let muteBtnImage = UIImage(named: "mute"),
let watermakerImage = UIImage(named: "agora-logo") {
arBroadcastVC.micBtnImage = micBtnImage
arBroadcastVC.muteBtnImage = muteBtnImage
arBroadcastVC.watermarkImage = watermakerImage
}
arBroadcastVC.channelName = channelName
arBroadcastVC.modalPresentationStyle = .fullScreen
self.present(arBroadcastVC, animated: true, completion: nil)
} else {
// TODO: add visible msg to user
print("unable to launch a broadcast without a channel name")
}
}
}
AR广播器
AR广播器是一个UIViewController,它实现了ARKit会话和渲染代理,以及Agora RTC引擎代理方法。有关每个代理的完整列表,请参阅ARKit文档。
当前的ARBroadcaster
类设置为WorldTracking
,但可以很容易地更新为正面对话。以下是一个扩展了ARKit的FaceTracking
的示例,并增加了对多个广播器的支持。
import ARKit
class FaceBroadcaster : ARBroadcaster {
// placements dictionary
var faceNodes: [UUID:SCNNode] = [:] // Dictionary of faces
override func viewDidLoad() {
super.viewDidLoad()
}
override func setARConfiguration() {
print("setARConfiguration") // Configure ARKit Session
let configuration = ARFaceTrackingConfiguration()
configuration.isLightEstimationEnabled = true
// run the config to start the ARSession
self.sceneView.session.run(configuration)
self.arvkRenderer?.prepare(configuration)
}
// anchor detection
override func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
super.renderer(renderer, didAdd: node, for: anchor)
guard let sceneView = renderer as? ARSCNView, anchor is ARFaceAnchor else { return }
/*
Write depth but not color and render before other objects.
This causes the geometry to occlude other SceneKit content
while showing the camera view beneath, creating the illusion
that real-world faces are obscuring virtual 3D objects.
*/
let faceGeometry = ARSCNFaceGeometry(device: sceneView.device!)!
faceGeometry.firstMaterial!.colorBufferWriteMask = []
let occlusionNode = SCNNode(geometry: faceGeometry)
occlusionNode.renderingOrder = -1
let contentNode = SCNNode()
contentNode.addChildNode(occlusionNode)
node.addChildNode(contentNode)
faceNodes[anchor.identifier] = node
}
}
...