我正在尝试创建从用户相册中选择的视频的缩小版本。输出的最大尺寸为 720p。因此,在检索视频时,我使用.mediumQualityFormat
as the deliveryMode
。如果用户设备中不存在原始视频或其中等质量版本,这会导致 iOS 从 iCloud 检索 720p 视频。
let videoRequestOptions = PHVideoRequestOptions()
videoRequestOptions.deliveryMode = .mediumQualityFormat
videoRequestOptions.isNetworkAccessAllowed = true
PHImageManager.default().requestAVAsset(forVideo: asset, options: videoRequestOptions) { (asset, audioMix, info) in
// Proceess the asset
}
问题是,当我使用AVAssetExportSession
要创建资产的缩小版本,如果资产是中等变体而不是原始版本,则导出过程会立即失败并出现以下错误:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-17507), NSLocalizedDescription=İşlem tamamlanamadı, NSUnderlyingError=0x283bbcf60 {Error Domain=NSOSStatusErrorDomain Code=-17507 "(null)"}}
我在任何地方都找不到有关此错误含义的任何信息。
当我设置deliveryMode
财产给.auto
or .highQualityFormat
,一切正常。
当我检查资产 URL 时,我注意到当从 iCloud 检索视频时,其文件名有一个“.medium”后缀,如下例所示:
file:///var/mobile/Media/PhotoData/Metadata/PhotoData/CPLAssets/group338/191B2348-5E19-4A8E-B15C-A843F9F7B5A3.medium.MP4
奇怪的是,如果我使用FileManager
要将此 url 中的视频复制到另一个目录,请创建一个新目录AVAsset
从该文件,并在创建时使用该资产AVExportSession
例如,问题就消失了。
如果有人能够提供有关问题所在的一些见解,我将非常感激。
这就是我使用的方式AVAssetExportSession
创建原始视频的缩小版本。
let originalVideoURL = // The url of the asset retrieved from requestAVAsset
let outputVideoPath = NSTemporaryDirectory() + "encodedVideo.mp4"
let outputVideoURL = URL(fileURLWithPath: outputVideoPath)
guard
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality),
let videoTrack = asset.tracks(withMediaType: .video).first else {
// Error handling
return
}
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = scaledSize // How this is calculated is irrelevant
videoComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
let transform = videoTrack.preferredTransform
layerInstruction.setTransform(transform, at: .zero)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(start: .zero, duration: asset.duration)
instruction.layerInstructions = [layerInstruction]
videoComposition.instructions = [instruction]
exportSession.videoComposition = videoComposition
exportSession.outputURL = outputVideoURL
exportSession.outputFileType = .mp4
exportSession.shouldOptimizeForNetworkUse = true
exportSession.exportAsynchronously(completionHandler: {[weak self] in
guard let self = self else { return }
if let url = exportSession.outputURL, exportSession.status == .completed {
// Works for local videos
} else {
// Fails with error code 17507 when loading videos with delivery size "Medium"
}
})