首页 > 解决方案 > 如何录制 ARKit 场景但排除 UI 元素?

问题描述

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

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

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

标签: iosswiftuiscenekitarkitreplaykit

解决方案


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

虽然可能有更好的方法来做到这一点,但这里有一个示例,说明了我如何为基于 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 还提供了一个很好的内置用户界面,用于修剪和保存录制的视频。


推荐阅读