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

How can I record an ARKit scene but exclude UI elements?

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

目前我正在为此使用 ARVideoKit,但性能还有待改进,我 运行 遇到了一些难以解决的错误。我发现的其他图书馆也好不到哪儿去。

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

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

虽然可能有更好的方法来执行此操作,但这里是我如何为基于 SwiftUI 的应用程序设置此 window 结构的示例。这里我使用 UIWindow.level 属性 将 AR 内容标记为主要 window,同时将 UI 放入其更高级别的次要 window:

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 内容和布局拆分为它们自己的 windows 后,AR 视图控制器上的任何用户事件处理程序和手势识别器可能不再按预期工作.

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

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

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

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

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