视频上传 AVComposition URL 崩溃问题解决

问题描述

  • 场景:视频上传

在使用 PHImageManager 中的如下方法获取视频路径的时候,如果选择的是慢动作视频就会引起如下崩溃:
-[AVComposition URL]: unrecognized selector sent to instance 0x2821c8f40

- (PHImageRequestID)requestAVAssetForVideo:(PHAsset *)asset options:(nullable PHVideoRequestOptions *)options resultHandler:(void (^)(AVAsset *__nullable asset, AVAudioMix *__nullable audioMix, NSDictionary *__nullable info))resultHandler

这是因为 asset 对象是 AVComposition 的对象,AVComposition 继承自 AVAsset ,在该类中没有 URL 属性,就会造成 unrecognized selector sent to instance 0x2821c8f40 的错误

一般的视频返回的都是 AVURLAsset 对象,在使用 asset 的时候需要强制转换下 ((AVURLAsset *)asset).URL 就可以获取 URL。

如果选择的是手机拍摄的慢动作视频,就会造成崩溃,也就是 asset 对象变成了 AVComposition 的实例,而不是 AVURLAsset 的实例。

有关 AVComposition 的介绍 https://www.jianshu.com/p/6ecae3de4344

解决办法

将 AVComposition 对象导出成AVURLAsset视频保存在手机里就可以获取 URL

  • ObjC
+ (void)convertAvcompositionToAvasset:(AVComposition *)composition completion:(void (^)(AVAsset *asset))completion {
    // 导出视频
    AVAssetExportSession *exporter = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
    // 生成一个文件路径
    NSInteger randNumber = arc4random();
    NSString *exportPath = [NSTemporaryDirectory() stringByAppendingString:[NSString stringWithFormat:@"%ldvideo.mov", randNumber]];
    NSURL *exportURL = [NSURL fileURLWithPath:exportPath];
    // 导出
    if (exporter) {
        exporter.outputURL = exportURL;  // 设置路径
        exporter.outputFileType = AVFileTypeQuickTimeMovie;
        exporter.shouldOptimizeForNetworkUse = YES;
        [exporter exportAsynchronouslyWithCompletionHandler:^{
            dispatch_async(dispatch_get_main_queue(), ^{
                if (AVAssetExportSessionStatusCompleted == exporter.status) {   // 导出完成
                    NSURL *URL = exporter.outputURL;
                    AVAsset *avAsset = [AVAsset assetWithURL:URL];
                    if (completion) {
                        completion(avAsset);
                    }
                } else {
                    if (completion) {
                        completion(nil);
                    }
                }
            });
        }];
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (completion) {
                completion(nil);
            }
        });
    }
}
  • Swift
func ConvertAvcompositionToAvasset(avComp: AVComposition, completion:@escaping (_ avasset: AVAsset) -> Void){
        let exporter = AVAssetExportSession(asset: avComp, presetName: AVAssetExportPresetHighestQuality)
        let randNum:Int = Int(arc4random())
        //Generating Export Path
        let exportPath: NSString = NSTemporaryDirectory().appendingFormat("\(randNum)"+"video.mov") as NSString
        let exportUrl: NSURL = NSURL.fileURL(withPath: exportPath as String) as NSURL
        //SettingUp Export Path as URL
        exporter?.outputURL = exportUrl as URL
        exporter?.outputFileType = AVFileTypeQuickTimeMovie
        exporter?.shouldOptimizeForNetworkUse = true
        exporter?.exportAsynchronously(completionHandler: {() -> Void in
            DispatchQueue.main.async(execute: {() -> Void in
                if exporter?.status == .completed {
                    let URL: URL? = exporter?.outputURL
                    let Avasset:AVAsset = AVAsset(url: URL!)
                    completion(Avasset)
                }
                else if exporter?.status == .failed{
                    print("Failed")

                }
            })
        }) }

参考

https://stackoverflow.com/questions/32081057/how-to-convert-an-avmutablevideocomposition-to-an-avasset

你可能感兴趣的:(视频上传 AVComposition URL 崩溃问题解决)