gpt4 book ai didi

ios - 使用 iCloud PHAsset 请求 AVAsset 返回一个没有 VideoTracks 的 AVAsset

转载 作者:行者123 更新时间:2023-12-03 09:25:49 26 4
gpt4 key购买 nike

最近,开始注意到从照片库导入某些 Assets 时未显示它们。有问题的 Assets 存储在 iCloud 中,不会缓存在设备上。
我相信这是 iOS 14 的问题,因为我从未在 iOS 13 上遇到过这个问题。(我不能 100% 确定,因为我无法将我的个人设备推广到 iOS 13)。
这是我在 中所做的事情iOS 14 :

  • 使用新的选取器 View Controller 导入视频 Assets
  • var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
    configuration.filter = PHPickerFilter.videos
    let videoPickerController = PHPickerViewController(configuration: configuration)
    videoPickerController.delegate = self
    present(videoPickerController, animated: true, completion: nil)
  • 我从 [PHPickerResult] 中提取 PHAsset(委托(delegate)方法)
  • func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    picker.dismiss(animated: true, completion: nil)
    guard results.count > 0 else {
    return
    }
    guard let firstPHAssetIdentifier = results.first?.assetIdentifier else {
    fatalError("No asset identifier")
    }
    let fetchOptions = PHFetchOptions()
    guard let phAsset = PHAsset.fetchAssets(withLocalIdentifiers: [firstPHAssetIdentifier], options: fetchOptions).firstObject else {
    fatalError("No matching PHAsset")
    }
    guard phAsset.mediaType == .video else {
    fatalError("Asset not of the video type")
    }
    }
  • 然后,我为匹配的 PHAsset
  • 请求 AVAsset
    let options = PHVideoRequestOptions()
    options.isNetworkAccessAllowed = true
    options.progressHandler = { progress, _, _, _ in
    print("Progress: \(progress)")
    }

    PHCachingImageManager.default().requestAVAsset(forVideo: phAsset, options: options) { [weak self] avAsset, _, info in
    guard info?[PHImageCancelledKey] == nil && info?[PHImageErrorKey] == nil else {
    print("Error or cancelled. Info: \(String(describing: info))")
    return
    }
    guard let avAsset = avAsset else {
    print("Asset is nil. Info: \(String(describing: info))")
    return
    }
    guard let videoTrack = avAsset.tracks(withMediaType: .video).first else {
    print("Cound not extract video track from AvAsset") // <- My issue
    return
    }
    }
    问题 : 通常,当 Assets 来自 iCloud 时,我不会有 videoTrack。 avAsset.duration 也将为 0.0。
    我会看到下载进度,但我会陷入最后的守卫声明。
    有时,一旦资源被下载并且无法加载 videoTrack,重试将立即失败(它不会再次尝试加载资源,看起来它已损坏)。它将落入最后的守卫声明。
    我注意到在 PHVideoRequestOptions 上使用 deliveryMode = .highQualityFormat 可以使它工作,但我宁愿只下载 720p 视频,而不是高质量视频。
    我想我在这里做错了什么。我应该以这种方式从 PHPickerResult 获取 phAsset 吗?任何指针/帮助将不胜感激。
    我创建了这个 repo 来复制 https://github.com/SwiftRabbit/RequestAVAssetIssues/tree/main/RequestAVAssetIssues .不会 100% 复制,并且必须是不再在设备上的 iCloud 视频。
    附加说明/尝试:
  • 我在使用 PHCachingImageManager 和 PHImageManager
  • 时遇到了同样的问题
  • 一些流行的应用程序似乎对某些 Assets 有同样的问题(例如 Instagram、TikTok...)
  • PHCachingImageManager.default().requestPlayerItem 也不起作用。它返回一个不包含任何轨道的 AVPlayerItem。
  • iPhone XS,企业托管设备
  • 最佳答案

    我可以通过在我的 iPad 上录制视频来重现这个问题,等到它同步到 iCloud,然后在我的 iPhone SE 2016 上请求 AVAsset。我在 github 上创建了一个 repo 来说明这一点。这是一个 Objective-C 项目,但结论对于 Swift 应该是一样的。 repo 的重要部分位于 https://github.com/Jan-E/ikyle.me-code-examples/blob/master/Photo%20Picker%20ObjC/Photo%20Picker%20ObjC/PHPickerController.m
    这是我正在使用的代码:

    for (PHAsset *phAsset in assetResults) {
    float recordingDuration = phAsset.duration;
    NSLog(@"recordingDuration %f", recordingDuration);
    NSDate *PHAssetCreationDate = phAsset.creationDate;
    NSLog(@"PHAssetCreationDate %@", PHAssetCreationDate);
    PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
    options.networkAccessAllowed = NO;
    [[PHImageManager defaultManager] requestAVAssetForVideo:phAsset
    options:options
    resultHandler:^(AVAsset *avAsset, AVAudioMix *audioMix, NSDictionary *info) {
    NSURL *videoURL = (NSURL *)[[(AVURLAsset *)avAsset URL] fileReferenceURL];
    NSLog(@"videoURL absoluteString = %@", [videoURL absoluteString]);
    NSLog(@"videoURL relativePath = %@", [videoURL relativePath]);
    AVURLAsset *avUrl = [AVURLAsset assetWithURL:videoURL];
    CMTime time = [avUrl duration];
    float recordingDuration;
    recordingDuration = time.value/time.timescale;
    NSArray *tracks = [avUrl tracksWithMediaType:AVMediaTypeVideo];
    NSLog(@"duration %f, tracks %lu", recordingDuration, (unsigned long)tracks.count);
    }];
    }
    当视频仍然只在 iCloud 上时,这些是 NSLog 返回的结果:
  • phAsset.duration 返回正确的值
  • phAsset.creationDate 返回正确的值
  • avAsset URL 返回 (null)
  • avAsset 的持续时间为 0.0 秒
  • avAsset 的磁道数为 0

  • 通过使用 result.itemProvider loadFileRepresentationForTypeIdentifier您可以强制将视频从 iCloud 下载到设备。那么结果如下:
  • phAsset.duration 返回正确的值
  • phAsset.creationDate 返回正确的值
  • avAsset URL 返回正确的路径
  • avAsset 的持续时间是正确的值
  • avAsset 的磁道数为 1

  • 完整的 NSLog 输出位于 2 次提交中的最后一次下方的 2 条评论中: https://github.com/Jan-E/ikyle.me-code-examples/commit/2d0174c2766abf742b6d76d053abc0a46199358f
    编辑 :请注意,在设备上没有视频的情况下开始的示例中,从 iCloud 下载 1.2GB 视频需要 4:23 分钟 (2020-12-24 15:45:13.669505+0100 - 2020-12-24 15:49 :36.224240+0100)。并非在所有情况下都需要下载。 phAsset.duration 的值为 680.044983 秒的信息可能是您在应用程序中需要的所有信息,因为这意味着视频至少有 1 个轨道。
    编辑 2 : 通过使用 options:nil我使用的是隐式 networkAccessAllowed = NO .通过编辑,我明确表示。它还可以解释持续时间 0.0 和轨迹 0。如果允许网络访问,但网络连接失败怎么办?然后你仍然会得到一个有意义的 phAsset.duration 值(来自早期的 iCloud 同步),但没有 avAsset 的实时值。

    关于ios - 使用 iCloud PHAsset 请求 AVAsset 返回一个没有 VideoTracks 的 AVAsset,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64090158/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com