ARKit – sceneView 以 120 fps 渲染其内容(但我需要 30 fps)

ARKit – sceneView renders its content at 120 fps (but I need 30 fps)

我正在开发 ARKit 应用以及 Vision/AVKit 框架。我的应用程序识别用于控制视频的手势(“胜利”、“好”、“拳头”手势)。所以我使用 MLModel 对我的手势进行分类。

应用程序运行良好,但视图内容以 120 fps 呈现。我不需要这样的帧率。这对我的应用程序来说太多了,对 CPU 来说是一个沉重的负担。我尝试使用 SceneKit 的实例 属性:

将帧速率降低到 30 fps
var preferredFramesPerSecond: Int { get set }

但我的帧速率仍然相同 – 120 fps。

这是我的制作方法:

import UIKit
import AVKit
import SceneKit
import ARKit
import Vision

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView! 
    var avPlayerView = AVPlayerViewController()
    private let player = AVQueuePlayer()
    let clips = ["AA", "BB", "CC"]
    private var token: NSKeyValueObservation?
    var number: Int = 0
    var once: Bool = true    
    let dispatchQueueML = DispatchQueue(label: "net.aaa.iii") 
    var visionRequests = [VNRequest]()

    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self
        sceneView.showsStatistics = true
        sceneView.preferredFramesPerSecond = 30     // HERE IT GOES
        sceneView.rendersContinuously = true
    
        let scene = SCNScene()
        sceneView.scene = scene
        sceneView.scene.background.contents = UIColor.black.withAlphaComponent(0)
    
        guard let selectedModel = try? VNCoreMLModel(for: handsModel().model) else {
            fatalError("Couldn't load a model.")
        }
    
        let classificationRequest = VNCoreMLRequest(model: selectedModel, 
                                        completionHandler: classificationCompleteHandler)
        classificationRequest.imageCropAndScaleOption = VNImageCropAndScaleOption.centerCrop
        visionRequests = [classificationRequest]       
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.addAllVideosToPlayer()
        present(avPlayerView, animated: true,
                            completion: { self.player.play() })
    
        let configuration = ARWorldTrackingConfiguration()
        configuration.isAutoFocusEnabled = false
        sceneView.session.run(configuration)
    }

    func addAllVideosToPlayer() {
        avPlayerView.player = player
        // .........................
    }
    func toggleNextVideo() {
        // ..............
    }
    func togglePreviousVideo() {
        // ..............
    }

    // ..............................
    // ..............................

    DispatchQueue.main.async {
        if (topPredictionScore != nil && topPredictionScore! > 0.01) {  
            if (topPredictionName == "FistGesture") && (self.once == false) {
                self.once = true
            }
            if (topPredictionName == "OkeyGesture") && (self.once == true) {
                self.toggleNextVideo()
                self.once = false
            }
        }
    }
}

Apple 是这样说的:

SceneKit chooses an actual frame rate that is as close as possible to your preferred frame rate based on the capabilities of the screen the view is displayed on. The actual frame rate is usually a factor of the maximum refresh rate of the screen to provide a consistent frame rate.

For example, if the maximum refresh rate of the screen is 60 fps, that is also the highest frame rate the view sets as the actual frame rate. However, if you ask for a lower frame rate, SceneKit might choose 30, 20, 15 or some other factor to be the actual frame rate. For this reason, you want to choose a frame rate that your app can consistently maintain. The default value is 60 fps.

如何将视图的帧率降低到 30 fps?

我解决了这个问题。 SceneKit 目前不允许更改帧速率 – 它具有固定的 120 fps。所以我改用 SpriteKit 框架——它允许我使用 30 fps.

以下是我的代码中的更改:

import SpriteKit

class ViewController: UIViewController, ARSKViewDelegate {

    @IBOutlet weak var sceneView: ARSKView!
    // ....................

    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self
        sceneView.preferredFramesPerSecond = 30     // NOW IT WORKS 

        let scene = SKScene()
        sceneView.presentScene(scene)
    }
    // ..................
}