最近,开始注意到一些资产在从照片库导入时没有显示。问题中的资产存储在iCloud中,没有缓存在设备上。我相信这是一个iOS 14问题,因为我从未在iOS 13上经历过这个问题。(我不能100%肯定,因为我无法在iOS 13上推出我的个人设备)。
以下是我在iOS 14所做的工作
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
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")
}
}然后,我为匹配的
请求一个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
}
}Problem:通常,当资产来自iCloud时,我将不会有videoTrack。avAsset.duration也将是0.0。
我会看到下载的进展,但我将落在最后的警卫声明。有时,一旦该资产被下载并无法加载videoTrack,重试就会立即失败(它不会再次尝试加载该资产,似乎它已损坏)。这将落在最后的守卫声明中。
我注意到使用deliveryMode = .highQualityFormat在PHVideoRequestOptions上工作,但我宁愿只下载720 p视频,而不是高质量的视频。
我想我在这里做错了什么。我应该从phAsset那里得到PHPickerResult吗?任何指针/帮助都将不胜感激。我创建了这个回购程序来复制https://github.com/SwiftRabbit/RequestAVAssetIssues/tree/main/RequestAVAssetIssues。不复制100%,必须是iCloud视频,不再在设备上。
补充说明/尝试:
PHImageManager
的AVPlayerItem。
发布于 2020-12-24 16:56:49
我在我的iPad上录制了一段视频,等待它与iCloud同步,然后在2016年的iPhone SE上请求AVAsset。为了说明这一点,我在github上创建了一个回购程序。这是一个客观的C项目,但结论应该是相同的Swift。回购的主要部分是在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返回的结果:
H 111 avAsset的曲目数为0H 212G 213
通过使用result.itemProvider loadFileRepresentationForTypeIdentifier,您可以强制将视频从iCloud下载到设备。结果如下:
H 124 avAsset的音轨数是1H 225G 226
完整的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秒的信息可能是您在应用程序中所需的全部信息,因为它意味着视频至少有一个音轨。
编辑2:通过使用options:nil,我使用了隐式networkAccessAllowed = NO。通过编辑,我把它写得很清楚。它还可能给出一个持续时间为0.0和轨道0的解释。如果允许网络访问,但网络连接失败怎么办?然后,您仍然可以为phAsset.duration获得有意义的值(来自早期的iCloud同步),但对于avAsset却没有活动值。
https://stackoverflow.com/questions/64090158
复制相似问题