AVAssetExportSession导出MP4视频失败

在开发一个相册选择器时,遇到AVAssetExportSession导出MP4视频失败的问题。通过设置AVVideoComposition的instructions进行视频旋转后,导出失败。参考StackOverflow上的解决方案,尝试重新构建AVComposition,解决了导出问题,但导致iPhone录制的MP4视频逆时针旋转90度。最后发现是AVVideoComposition实例的旋转角度设置不当,修正后问题得到解决。
摘要由CSDN通过智能技术生成

前几个月的时候自己动手写了一个相册选择器,如下(UI仿抖音):

今天测试小姐姐说她手机里有一个视频特别奇怪,只要一选择那个视频,就会提示“视频导出失败”,此时的我也是一脸懵逼。二话不说,连上手机调试。这时候发现这个视频的格式跟手机里其他视频的格式不同,这个视频是MP4格式,其他视频是MOV。最后确定这个MP4视频是某安卓手制作的,然后被测试小姐姐保存到自己的iPhone中。

首先说一下我获取视频的过程,使用PHImageManager类进行获取视频资源AVAsset,然后使用AVAssetExportSession类进行导出视频,导出操作之前可以告诉AVAssetExportSession实例一些导出的规格,将这些规格封装在AVVideoComposition实例中,并传递给AVAssetExportSession实例的videoComposition属性。这里我在videoComposition的instructions中提供了旋转角度(参考了TZImagePickerController代码)。

获取相册资源代码如下:

        [SVProgressHUD show];
        PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
        options.version = PHVideoRequestOptionsVersionOriginal;
        options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
        options.networkAccessAllowed = YES;
        
        __weak typeof(self) weakSelf = self;
        options.progressHandler = ^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [SVProgressHUD showProgress:progress status:@"iCloud同步中"];
            });
        };
        
        [[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
            if (asset) {
                AVURLAsset *urlAsset = (AVURLAsset *)asset;
                
                [weakSelf startExportVideoWithVideoAsset:urlAsset presetName:AVAssetExportPresetHighestQuality success:^(NSString *outputPath) {
                    [SVProgressHUD dismiss];
                    [weakSelf dismissViewControllerAnimated:YES completion:nil];
                    if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(didFinishPickVideoUrl:)]) {
                        [weakSelf.delegate didFinishPickVideoUrl:[NSURL fileURLWithPath:outputPath]];
                    }
                } failure:^(NSString *errorMessage, NSError *error) {
                    [SVProgressHUD showErrorWithStatus:errorMessage];
                }];
            
            }else {
                [SVProgressHUD dismiss];
            }
            
        }];
复制代码

封装AVVideoComposition实例,并赋值给AVAssetExportSession实例的videoComposition属性,如下:

- (void)startExportVideoWithVideoAsset:(AVURLAsset *)videoAsset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {

    NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:videoAsset];
    
    if ([presets containsObject:presetName]) {
        AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:presetName];
        NSDateFormatter *formater = [[NSDateFormatter alloc] init];
        [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"];
        NSString *outputPath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/video-%@.mp4", [formater stringFromDate:[NSDate date]]];
        if (videoAsset.URL && videoAsset.URL.lastPathComponent) {
            outputPath = [outputPath stringByReplacingOccurrencesOfString:@".mp4" withString:[NSString stringWithFormat:@"-%@", videoAsset.URL.lastPathComponent]];
        }
         NSLog(@"video outputPath = %@",outputPath);
        session.outputURL = [NSURL fileURLWithPath:outputPath];
        
        // Optimize for network use.
        session.shouldOptimizeForNetworkUse = true;
        
        NSArray *supportedTypeArray = session.supportedFileTypes;
        if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) {
            session.outputFileType = AVFileTypeMPEG4;
        } else if (supportedTypeArray.count == 0) {
            if (failure) {
                failure(@"该视频类型暂不支持导出", nil);
            }
            NSLog(@"No supported file types 视频类型暂不支持导出");
            return;
        } else {
            session.outputFileType = [supportedTypeArray objectAtIndex:0];
        }
        
        if (![[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"]]) {
            [[NSFileManager defaultManager] createDirectoryAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"] withIntermediateDirectories:YES attributes:nil error:nil];
        }
        
        AVMutableVideoComposition *videoComposition = [self fixedCompositionWithAsset:videoAsset];
        if (videoComposition.renderSize.width) {
            // 修正视频转向
            session.videoComposition = videoComposition;
        }
        
        // Begin to export video to the output path asynchronously.
        [session exportAsynchronous
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值