从ARSession实时上传帧到firebase存储

问题描述 投票:0回答:1

我正在尝试将帧从 ARSession 实时流式传输到 Firebase 存储。在将帧发送到 firebase 之前,会对帧进行一些预处理。应用程序的流程如下。

frameCount
变量用于命名数据库中的图像文件。我希望图像在拍摄时按顺序命名。文件正在上传成功,问题是:

  1. 它不是实时的,因为 upload() 是异步运行的,需要一些时间
  2. 图片没有按顺序上传。我希望它们以与捕获时相同的顺序上传。异步部分正在做一些与
    count
    变量无关的事情。经过几个小时的调试,我发现对于不同的帧多次使用相同的
    count
    值。上传无处不在。
    frameCount
    达到 100,但上传滞后于 5-10。然后,当我停止会话时,上传部分继续但顺序随机。例如,它会上传文件 98.jpg,下一个文件是 5.jpg
    var frameCount = 0
    
    func session(_ session: ARSession, didUpdate frame: ARFrame) {
        frameCount += 1
        DispatchQueue.async{
            process(frame: frame, count: frameCount)
        }
    }

    func process(frame: ARFrame, count: Int){
        // all the processing happens here to get jpg data of the image
       var imgData = ...
       var fileURL = writeToFile(imageData: imgData, count: count)
       upload(fileURL: fileURL, count: count)
    }

func writeToFile(imageData: Data, count: Int)-> URL{
    jpgFileURL = try getDirectory().appendingPathComponent("\(count).jpg")
    try jpgData.write(to: jpgFileURL!)
    return jpgFileURL
}
func upload(fileURL: URL, count: Int){
    let imageFileRef = storageRef.child("\(count).jpg")
    imageFileRef.putFile(from: fileURL) // this part runs asynchronously
}

我已经尝试了 DispatchQueues、await/async 关键字、TaskGroups 等的多种变体,但似乎没有任何效果。在核心,我只想增加

frameCount
,将数据写入文件,然后按顺序上传。下一帧的管道应该叠加在前一帧的执行之上,并等待它成功上传。

swift firebase firebase-storage arkit swift-concurrency
1个回答
0
投票

如果不出意外,您要确保不要在闭包中引用可变属性。因此,例如,您想要引用

frameCount
的副本。要复制它,请使用“捕获列表”。所以而不是……

dispatchQueue.async {
    process(frame: frame, count: frameCount)
}

而是使用……

dispatchQueue.async { [frameCount] in
    process(frame: frame, count: frameCount)
}

这仍然不会按顺序上传它们,但它会确保它们至少具有

frameCount
的当前唯一值,因此被正确命名。


现在,我不知道你正在处理多少帧,但这很容易遭受“线程爆炸”,一旦积压超过 64 帧,它可能会表现得很奇怪。您可能希望将其限制为某个合理的数字。你可以用

OperationQueue
做到这一点:

var frameCount = 0
let operationQueue: OperationQueue = {
    let queue = OperationQueue()
    queue.name = "frame.queue"
    queue.maxConcurrentOperationCount = 6
    return queue
}()
    
func session(_ session: ARSession, didUpdate frame: ARFrame) {
    frameCount += 1
    operationQueue.addOperation { [frameCount] in
        process(frame: frame, count: frameCount)
    }
}

或者 Swift 并发:

var frameCount = 0
    
func session(_ session: ARSession, didUpdate frame: ARFrame) {
    frameCount += 1
    Task.detached { [frameCount] in
        process(frame: frame, count: frameCount)
    }
}

也有办法让它按顺序运行(按顺序,一次一个),但这会使它运行得更慢。我打赌你已经跟不上你的“实时”目标,让这个异步任务串行运行可能只会让情况变得更糟。

© www.soinside.com 2019 - 2024. All rights reserved.