You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARKit设置preferredFramesPerSecond锁30fps无效如何解决

ARKit固定帧率与稳定截图方案

一、恒定锁定30fps(或更低帧率)的实现

你设置sceneView.preferredFramesPerSecond = 30未生效的核心原因是:ARSCNView的渲染帧率同时受AR会话本身的帧输出速率约束,仅修改SceneKit视图层的帧率配置不会干预ARSession的原生帧推送逻辑,需要同时完成两层配置才能强制锁帧:

  • 配置AR会话的帧率范围(iOS 13及以上版本支持),从帧输出源头限制速率:
let config = ARWorldTrackingConfiguration()
if #available(iOS 13.0, *) {
    config.preferredFrameRateRange = CAFrameRateRange(
        minimum: 30,
        maximum: 30,
        preferred: 30
    )
}
sceneView.session.run(config)
  • 补全视图层的帧率配置,关闭系统自动帧率调节:
sceneView.preferredFramesPerSecond = 30
sceneView.preferredFrameRateRange = CAFrameRateRange(
    minimum: 30,
    maximum: 30,
    preferred: 30
)
sceneView.rendersContinuously = false

注意:如果需要锁定更低帧率,直接替换上述代码里的数值即可,但不建议将帧率设置到15fps以下,会直接导致AR世界跟踪精度下降甚至失准。iOS 13以下系统没有提供强制锁帧的公开API,直接使用下文的动态适配方案即可。

二、动态适配帧率的截图逻辑

不需要专门在启动前1-2秒做帧率探测,直接在session(_:didUpdate:)回调内做简单的计数+时间戳兜底判断,就能在任意运行帧率下稳定保持每秒30次截图,还能自动适配运行过程中的帧率波动:

  • 先在控制器内定义两个辅助变量:
// 帧计数器
private var frameCounter: Int = 0
// 上一次执行截图的时间戳
private var lastSnapshotTime: TimeInterval = 0
  • 在ARSession的帧更新回调内加入判断逻辑:
func session(_ session: ARSession, didUpdate frame: ARFrame) {
    frameCounter += 1
    // 60fps时隔一帧截一次,30fps时每帧都触发,时间戳兜底适配非整数帧率/掉帧场景
    let shouldSnapshot = frameCounter % 2 == 1 
        || (frame.timestamp - lastSnapshotTime) >= 1.0/30.0
    guard shouldSnapshot else { return }

    // 此处写入你的截图逻辑
    // 优先取frame.capturedImage做处理,比调用view.snapshot()的CPU开销低80%以上
    lastSnapshotTime = frame.timestamp
}

这个逻辑不需要提前采样帧率,启动后立刻生效,哪怕运行过程中因为CPU负载变化帧率在30-60fps之间波动,截图频率都会自动调整,始终稳定在每秒30次左右,不会出现重复采样或者采样间隔过长的问题。


内容的提问来源于stack exchange,提问作者martin wotterman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 15:00:55