For some reason the AVAssetTrack nominalFrameRate is always 30 for high speed videos. 120 FPS and 240 FPS videos' nominalFrameRate property is always 30. However, 60 FPS videos' nominalFrameRate is 60. I'm reading in the video url through the PHPickerViewController. I have a configuration for the picker set up as follows.
configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
configuration.filter = .videos
configuration.selectionLimit = 0
and the gathering of the picker results as follows
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
for result in results {
var currentVideo = Video()
let provider = result.itemProvider
provider.loadFileRepresentation(forTypeIdentifier: "public.movie") { url, error in
guard error == nil else {
return
}
guard let url = url else {return}
// create a new filename
let fileName = "\(Int(Date().timeIntervalSince1970)).\(url.pathExtension)"
let newUrl = URL(fileURLWithPath: NSTemporaryDirectory() + fileName)
// copy item to APP Storage
try? FileManager.default.copyItem(at: url, to: newUrl)
currentVideo.url = newUrl.absoluteString
self.parent.selectedVideos.append(currentVideo)
}
}
// Set isPresented to false because picking has finished.
parent.isPresented = false
}
I'm creating an AVAsset and AVAssetTrack to check the FPS of the video as follows.
var asset: AVAsset? = AVAsset(url: url)
if let asset = asset,
let videoTrack = try? await asset.loadTracks(withMediaType: .video).last {
let size = try? await videoTrack.load(.naturalSize)
let fps = try? await videoTrack.load(.nominalFrameRate)
let duration = try? await test.load(.duration)
print(fps) // This shows 30 for 120 fps and 240 fps videos
}
I'm not sure if there's some other configuration that needs to be set to handle high speed videos or what. I'm really confused.
I figured it out. The issue was the way I was creating the AVAssets. Instead of pulling them in from a copied url I used the localIdentifiers to fetch the assets with a defined set of options. The code below works for obtaining the correct FPS for a selected asset.
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
let identifiers = results.compactMap(\.assetIdentifier)
let assets = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
if (assets.count == 0) {
parent.isPresented = false
return
}
var assetArray: [PHAsset] = []
for i in 0...(assets.count - 1) {
assetArray.append(assets[i])
}
let options = PHVideoRequestOptions()
options.version = .original
for asset in assetArray {
PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { avAsset, avAudioMix, info in
var currentVideo = Video()
currentVideo.asset = avAsset
self.parent.selectedVideos.append(currentVideo)
}
}
// Set isPresented to false because picking has finished.
parent.isPresented = false
}
I hope this helps!