如何录制 ARKit 场景但排除 UI 元素?

Posted

技术标签:

【中文标题】如何录制 ARKit 场景但排除 UI 元素?【英文标题】:How can I record an ARKit scene but exclude UI elements? 【发布时间】:2021-08-18 09:13:35 【问题描述】:

我正在使用带有 Scenekit 的 ARKit 进行渲染。我想让用户捕捉 AR 会话的视频,以便他们可以将其保存到照片中或分享。

目前我为此使用ARVideoKit,但性能仍有待改进,而且我遇到了一些难以解决的错误。我发现的其他库也好不到哪里去。

ReplayKit 似乎是理想的解决方案,但它记录了我的整个应用程序,包括用户界面。有没有办法让 ReplayKit 只记录 AR 内容而排除用户界面?

【问题讨论】:

【参考方案1】:

您可以为此使用ReplayKit,但它的文档记录不是很好。关键是您将所有 UI 元素呈现在一个单独的 UIWindow 中,该 UIWindow 覆盖在包含 AR 内容的主要 UIWindow 之上。 ReplayKit 只记录主窗口,因此使用这种结构,用户界面元素不会显示在记录中。

虽然可能有更好的方法来执行此操作,但这里有一个示例,说明了我如何为基于 SwiftUI 的应用程序设置此窗口结构。这里我使用UIWindow.level属性将AR内容标记为主窗口,同时将UI放到自己的更高级别的辅助窗口中:

class SceneDelegate: UIResponder, UIWindowSceneDelegate 

    var arWindow: UIWindow?    
    var uiWindow: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options 
        if let windowScene = scene as? UIWindowScene 
            // Create a window for the AR content.
            // This is the main window. 
            let arWindow = UIWindow(windowScene: windowScene)
            self.arWindow = arWindow
            arWindow.windowLevel = .normal
            
            // Add your AR view controller here or set the view controller lazily
            // when you actually need to show AR content
            let vc = UIViewController() 
            arWindow.rootViewController = vc
            

            // Now create a window for the UI
            let uiWindow = UIWindow(windowScene: windowScene)
            self.uiWindow = uiWindow
            // Setting the level makes this window's content be excluded from replaykit
            uiWindow.windowLevel = UIWindow.Level(UIWindow.Level.normal.rawValue + 1)
            uiWindow.isOpaque = false
            
            // Render your SwiftUI based user interface
            let content = MyUserInterfaceView()
                .background(Color.clear)
            
            let hosting = UIHostingController(rootView: content)
            hosting.view.backgroundColor = .clear
            hosting.view.isOpaque = false
            uiWindow.rootViewController = hosting
            
            uiWindow.makeKeyAndVisible()
        
    

我的应用会延迟初始化 AR 内容,因此我只需在需要显示时更新 arWindow.viewController

几点说明:

这种方法要求您将 AR 视图控制器与用户界面的其余部分分开。在许多情况下,这是一个简单的更改,但对于更复杂的应用程序可能会涉及很多。

请记住,在您将 AR 内容和布局拆分到各自的窗口后,您在 AR 视图控制器上的任何用户事件处理程序和手势识别器可能不再按预期工作。

我通过在我的主布局中使用透明代理视图控制器来解决这个问题,它将用户事件转发到真正的 AR 视图控制器

这种方法不是 ARKit 特有的。它也应该适用于普通的 SceneKit 应用、Metal 应用和传统应用。

与某些第三方录制库不同,ReplayKit 在录制屏幕时会提示用户。

我真的很喜欢这个功能,因为它让用户可以轻松选择是否要录制麦克风。您可能会发现它会妨碍您,因此第三方录音库仍有用例。

ReplayKit 还提供了一个很好的内置用户界面,用于修剪和保存录制的视频。

【讨论】:

我很想试试这个。能否报告最终视频的比特率和分辨率? 快速测试,12.9 英寸 iPad 横屏:1920x1440, 30277 kb/s, 54.95 fps。对于 iPhone 12 纵向:888x1920、18537 kb/s、59.54 fps

以上是关于如何录制 ARKit 场景但排除 UI 元素?的主要内容,如果未能解决你的问题,请参考以下文章

JQuery UI Datepicker - MaxDate 排除禁用天数

jQuery为空但排除某个元素

查找具有相同类但排除单击的元素的所有元素? [复制]

为某些元素设置动画时遇到问题 UIView 将排除其他元素

查找 transcluded 指令的子元素,但排除其自己的嵌套指令子元素

如何从分析查询中排除选择分区?