AVAssetTrack获取高速视频nominalFrameRate始终为30的问题
问题:AVAssetTrack.nominalFrameRate在120/240FPS高速视频中始终返回30,60FPS视频正常
现象
使用PHPickerViewController读取视频后,通过AVAssetTrack获取nominalFrameRate时,120FPS和240FPS的高速视频始终返回30,但60FPS视频能正确返回60。
相关代码
PHPicker配置
configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared()) configuration.filter = .videos configuration.selectionLimit = 0
选择器结果处理
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 }
帧率检查代码
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 videoTrack.load(.duration) print(fps) // 120/240FPS视频这里输出30 }
解决方案
1. 使用effectiveFrameRate替代nominalFrameRate
高速慢动作视频的nominalFrameRate对应的是播放帧率(比如30FPS,用于慢动作播放),而effectiveFrameRate才是视频实际的采样帧率(即拍摄时的120/240FPS)。修改帧率读取代码:
let fps = try? await videoTrack.load(.effectiveFrameRate) print(fps) // 现在应该能正确返回120/240
2. 通过帧时长计算实际帧率
如果effectiveFrameRate仍无法获取正确值,可以通过视频轨道的minFrameDuration或maxFrameDuration计算真实帧率:
if let frameDuration = try? await videoTrack.load(.minFrameDuration) { let frameRate = Double(frameDuration.timescale) / Double(frameDuration.value) print("实际帧率:\(frameRate)") }
原理:帧率 = 时间刻度(timescale) / 帧时长数值(value)
3. 确保PHPicker获取原始视频文件
默认情况下PHPicker可能返回适配过的视频版本,而非原始文件。修改配置强制获取原始视频:
configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared()) configuration.filter = .videos configuration.selectionLimit = 0 // 添加这行配置 configuration.preferredAssetRepresentationMode = .original
内容的提问来源于stack exchange,提问作者alwaysmemin
相关产品推荐
相关产品推荐

