前几个月的时候自己动手写了一个相册选择器,如下(UI仿抖音):
首先说一下我获取视频的过程,使用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