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

标签 ios swiftui scenekit arkit replaykit

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

目前我正在使用ARVideoKit为此,但性能仍有待提高,而且我遇到了一些难以解决的错误。我发现的其他库也没有更好。

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

最佳答案

您可以使用ReplayKit为此,但它没有很好的记录。关键是您在一个单独的 UIWindow 中渲染所有 UI 元素,该 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 View Controller 与用户界面的其余部分分开。在许多情况下,这是一个简单的更改,但对于更复杂的应用程序来说可能会非常复杂。

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

    我通过在主布局中使用透明代理 View Controller 来解决这个问题,该 Controller 将用户事件转发到真实的 AR View Controller

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

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

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

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

关于ios - 如何录制 ARKit 场景但排除 UI 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67767374/

相关文章:

swift - 我如何在 Xcode 11 Playground 中使用图像?

swift - SceneKit 导入的 COLLADA 框不是 "Lit"

ios - 调用 UIViewController 并且永远不会被释放

ios - 在iOS上运行Flutter项目时出现重新定义错误

swift - WKWebView - 从 SwiftUI TextFields 更新 HTML 标签

ios - 为什么空 SceneKit 场景具有高多边形数?

ios - 从触摸位置快速获取 SCNNode 环境中的矢量

ios - 如何更改状态栏背景的颜色?

android - 如何在 Ubuntu 上模拟 iOS、Windows Phone 和黑莓

SwiftUI/.onDelete 从嵌套数组中删除列表中的子 OutlineGroup 行