AVAssetImageGenerator.generateCGImagesAsynchronously 错误的帧
Incorrect Frames by AVAssetImageGenerator.generateCGImagesAsynchronously
根据文档,generateCGImagesAsynchronously
接收一个 NSValue
数组并根据视频和给定时间生成帧,return 将其作为回调。
我使用以下代码生成值列表
var values : [NSValue] = []
let frameDuration = CMTimeMake(1, timeScale)
for i in 0..<duration{
let lastFrameTime = CMTimeMake(Int64(i), timeScale)
let presentationTime = (i == 0) ? lastFrameTime : CMTimeAdd(lastFrameTime, frameDuration)
values.append(NSValue(time: presentationTime))
//Next two lines of codes are just to cross check the output
let image = try! imageGenerator.copyCGImage(at: presentationTime, actualTime: nil)
let imageUrl = FileManagerUtil.getTempFileName(parentFolder: FrameExtractor.EXTRACTED_IMAGE, fileNameWithExtension: "\(Constants.FRAME_SUFFIX)\(i)\(".jpeg")")
}
正如您在上面的代码中看到的,我使用同步方法交叉检查了结果,我可以确认 values
数组包含正确的时间参考。
但是当相同的数组传递给 generateImageAsynchronously
方法时,对于不同的时间戳,我得到相同帧的副本 10 次。也就是说,如果我的视频是 10 秒,那么我会得到 300 帧(30 fps),但第一秒的帧每个重复 10 次。当请求 1 秒时,它类似于 returning 帧 0.1 秒。
P.S: Though synchronous method is working fine, it is taking twice the
time taken by the asynchronous method. May be because it is returning
same frames. But I need it working to check the actual time usages.
不知道为什么,但是当从主线程调用函数时我得到了错误。但是当我从后台线程调用它时,它就开始工作了。
不确定解释,但与 let image = imageGenerator.copyCGImage(at: time, actualTime: nil)
DispatchQueue.global(qos: .background).async {
imageGenerator.generateCGImagesAsynchronously(forTimes: localValue, completionHandler: ({ (startTime, generatedImage, endTime, result, error) in
//Save image to file or perform any task
}))
}
您需要将 requestedTimeToleranceBefore
和 requestedTimeToleranceAfter
设置为您想要的精度,例如 .zero
但这可能会产生额外的延迟和生成图像的成本。
例如:
imageGenerator.requestedTimeToleranceBefore = .zero
imageGenerator.requestedTimeToleranceAfter = .zero
这样你会得到当时的准确帧。
根据文档,generateCGImagesAsynchronously
接收一个 NSValue
数组并根据视频和给定时间生成帧,return 将其作为回调。
我使用以下代码生成值列表
var values : [NSValue] = []
let frameDuration = CMTimeMake(1, timeScale)
for i in 0..<duration{
let lastFrameTime = CMTimeMake(Int64(i), timeScale)
let presentationTime = (i == 0) ? lastFrameTime : CMTimeAdd(lastFrameTime, frameDuration)
values.append(NSValue(time: presentationTime))
//Next two lines of codes are just to cross check the output
let image = try! imageGenerator.copyCGImage(at: presentationTime, actualTime: nil)
let imageUrl = FileManagerUtil.getTempFileName(parentFolder: FrameExtractor.EXTRACTED_IMAGE, fileNameWithExtension: "\(Constants.FRAME_SUFFIX)\(i)\(".jpeg")")
}
正如您在上面的代码中看到的,我使用同步方法交叉检查了结果,我可以确认 values
数组包含正确的时间参考。
但是当相同的数组传递给 generateImageAsynchronously
方法时,对于不同的时间戳,我得到相同帧的副本 10 次。也就是说,如果我的视频是 10 秒,那么我会得到 300 帧(30 fps),但第一秒的帧每个重复 10 次。当请求 1 秒时,它类似于 returning 帧 0.1 秒。
P.S: Though synchronous method is working fine, it is taking twice the time taken by the asynchronous method. May be because it is returning same frames. But I need it working to check the actual time usages.
不知道为什么,但是当从主线程调用函数时我得到了错误。但是当我从后台线程调用它时,它就开始工作了。
不确定解释,但与 let image = imageGenerator.copyCGImage(at: time, actualTime: nil)
DispatchQueue.global(qos: .background).async {
imageGenerator.generateCGImagesAsynchronously(forTimes: localValue, completionHandler: ({ (startTime, generatedImage, endTime, result, error) in
//Save image to file or perform any task
}))
}
您需要将 requestedTimeToleranceBefore
和 requestedTimeToleranceAfter
设置为您想要的精度,例如 .zero
但这可能会产生额外的延迟和生成图像的成本。
例如:
imageGenerator.requestedTimeToleranceBefore = .zero
imageGenerator.requestedTimeToleranceAfter = .zero
这样你会得到当时的准确帧。