有了声网 UIKit 程序包,(ios视频直播)推流直播 AR 会话就会变得非常简单。下面我会教大家怎么通过简单几步将一个 AR 场景推流到声网。
前期准备
设置
首先,我们在 Xcode 中创建一个单视图的 iOS 新项目,然后把声网 UIKit 程序包添加进去。
我们可以按照这个步骤添加程序包:打开并选择File > Swift Packages > Add Package Dependency
,然后把这个链接粘贴到 Swift 包中:
GitHub GitHub - AgoraIO-Community/iOS-UIKit: Swift package and CocoaPod to simply... Swift package and CocoaPod to simply integrate Agora Video Calling or Live Video Streaming to your iOS or macOS app with just a few lines of code. - GitHub - AgoraIO-Community/iOS-UIKit: Swift pack...
这个程序包的最新版本(2021年11月23日)是4.0.0-preview.8
。这里我们使用的版本是 SDK 4.x preview,同时示例库里还有一个配置好声网 video SDK 3.x 的这个例子的可用版本。
我们还需要添加 ARVideoKit,这是一个 Swift 包,它可以帮我们从 SceneKit 视图中捕捉音频和视频。
GitHub GitHub - AFathi/ARVideoKit: Capture & record ARKit videos 📹, photos 🌄,... Capture & record ARKit videos 📹, photos 🌄, Live Photos 🎇, and GIFs 🎆. - GitHub - AFathi/ARVideoKit: Capture & record ARKit videos 📹, photos 🌄, Live Photos 🎇, and GIFs 🎆.
如果你想了解更多信息,可以在这里找到所有示例项目:
这些程序包都安装完成后,接下来就要添加摄像头和麦克风访问权限啦。如果不知道怎么添加,可以点击下面的链接查看 Apple 的文档哦:
搭建 UI
我们只需要在 App 上添加两个视图:
- Augmented Reality SceneKit 视图(
ARSCNView
) - 设置为
.collection
样式的 Agora UIKit 视图
我们示例的是一个常见的 SceneKit 视图,只需要先创建一个填充屏幕的 ARSCNView,然后在摄像头前( [0, 0, -3]
位置)放置一个立方体。
SceneKit
我们可以像下面这样设置 SceneKit 视图:
// Initialise and frame SceneKit view
self.sceneView = ARSCNView()
self.view.addSubview(sceneView)
self.view.sendSubviewToBack(sceneView)
sceneView.translatesAutoresizingMaskIntoConstraints = false
sceneView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
sceneView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
sceneView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
sceneView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
// Add cube to SceneKit
let node = SCNNode(
geometry: SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0.3)
)
node.position.z = -3
sceneView.scene.rootNode.addChildNode(node)
以上所有代码段都来自 ViewController 类的函数。
接下来,我们在 ARVideoKit 中搭建 AR Recorder。因为这个类包裹了 ARSCNView,所以它可以抓取适合的镜头以及 SceneKit 帧并把它们合并起来。
// setup ARViewRecorder
self.arvkRenderer = RecordAR(ARSceneKit: self.sceneView)
self.arvkRenderer?.renderAR = self // Set the renderer's delegate
// Configure the renderer to always render the scene
self.arvkRenderer?.onlyRenderWhileRecording = false
// Configure ARKit content mode. Default is .auto
self.arvkRenderer?.contentMode = .aspectFill
// Set the UIViewController orientations
self.arvkRenderer?.inputViewOrientations = [.portrait]
self.arvkRenderer?.enableAudio = false
在上面的示例里,我们把 renderAR 委托设置成 self,但这里的 self 指的是 ViewController
实例。
我们要把 RenderARDelegate 协议添加到 ViewController 中,还要添加给我们提供视频帧的委托方法:
extension ViewController: RenderARDelegate {
// MARK: ARVideoKit Renderer
open func frame(
didRender buffer: CVPixelBuffer, with time: CMTime,
using rawBuffer: CVPixelBuffer
) {
// Create AgoraVideoFrame, and push to Agora engine.
// This part will be filled in later.
}
}
ARKit 会话的最后一步是配置和启动 AR 会话。我一般会把这一步放进 viewDidAppear
函数。因为我们只想要一个基础的 AR 会话,所以使用 ARWorldTrackingConfiguration
这个基础配置就完全 OK :
open func setARConfiguration() {
let configuration = ARWorldTrackingConfiguration()
// run the config to start the ARSession
self.arvkRenderer?.prepare(configuration)
}
一般来说我们会调用 self.sceneView.session.run(configuration)
来启动会话。但因为我们把它包裹在一个 RecordAR
对象中,所以可以直接在 arvkRenderer
对象上调用这个函数。
声网 UIKit
现在我们要使用UIKit 加入声网视频频道。记得告诉引擎我们会使用外部摄像头,要不然 UIKit 会打开默认的内置摄像头。
我们要在 AgoraSettings 中对已调用的 externalVideoSettings 接口进行设置。这个属性不但能告诉引擎我们要使用外部视频源,还能告诉引擎外部视频源的一些细节,包括视频源是否是纹理视频数据以及它是否被编码。
这里我们使用的是纹理视频数据,而且源码没有被编码。我们不想要翻转摄像头的标识,所以要像下面这样创建设置属性:
var agSettings = AgoraSettings()
agSettings.externalVideoSettings = AgoraSettings.ExternalVideoSettings(
enabled: true, texture: true, encoded: false
)
agSettings.enabledButtons = [.cameraButton, .micButton]
然后创建一个 AgoraVideoViewer 的实例,并按照上面说的以及前面提到的 .collection
样式设置。
let agoraView = AgoraVideoViewer(
connectionData: AgoraConnectionData(
appId: <#Agora App ID#>,
appToken: <#Agora Token or nil#>
),
style: .collection,
agoraSettings: agSettings
)
接下来用 AgoraVideoViewer 填充视图并加入频道,同时在 ViewController 中保持对 agoraView 的引用。
agoraView.fills(view: self.view)
agoraView.join(channel: "test", as: .broadcaster)
self.agoraView = agoraView
推送帧给声网
此时AR 场景在背景里正确渲染。任何人如果使用摄像头加入同一个频道,都会显示在视图上方。因为我们的设备没有推送任何内容,所以加入的摄像头画面不会传到远程用户端。
回到之前提到的视频帧委托方法,我们需要创建一个 AgoraVideoFrame 对象,为视频帧配置格式、像素缓冲和时间戳。
extension ViewController: RenderARDelegate {
// MARK: ARVideoKit Renderer
open func frame(
didRender buffer: CVPixelBuffer, with time: CMTime,
using rawBuffer: CVPixelBuffer
) {
// Create a new AgoraVideoFrame
let videoFrame = AgoraVideoFrame()
videoFrame.format = 12 // format 12 means iOS texture (CVPixelBufferRef)
videoFrame.textureBuf = buffer // set the texture buffer to our CVPixelBuffer
videoFrame.time = time // assign the timestamp
// Push the AgoraVideoFrame to the Agora engine
self.agoraView?.agkit.pushExternalVideoFrame(videoFrame)
}
}
然后,通过 AgoraVideoViewer
类抓取 AgoraRtcEngineKit
实例,把视频帧推送过去。
音频
如果你想在 SceneKit 中推流音频,还需要额外进行一些设置:
- 把 UIKit 中的 externalAudioSettings 设置为启用状态。
- 把 ARWorldTrackingConfiguration 中的 providesAudioData 设置为True。
- 添加 ARSessionDelegate 函数 didOutputAudioSampleBuffer。
- 在 Agora 引擎实例上调用 pushExternalAudioFrameSampleBuffer。
总结
你可以用这个新的视频流 App 在 iOS 系统上使用 SceneKit 推流 AR 场景,还可以在任何一个配置了兼容声网 SDK 的设备上观看这个场景。
测试
用下面的 UIKit 3.x 或 4.x SDK 试用这个实例。
因为 ARVideoKit 有一些与设备方向相关的 bug,所以这次的实例我推荐只在(ios视频直播)设备直立(竖屏)时尝试。
其他资源
- 想了解更多使用声网 SDK 搭建应用的信息,请查看声网 Video Call 快速指南和 API Reference。
原文作者:Max Cobb
原文链接:https://www.agora.io/en/blog/augmented-reality-streaming-with-agora-uikit-on-ios/