最近,在做有关视频操作的功能。需要从相册选择视频,处理之后再保存到相册。
选择视频:
方式一:用系统的UIImagePickerController
贴代码:
- (void)selectAction{
NSLog(@"从相册选择");
UIImagePickerController *picker=[[UIImagePickerController alloc] init];
picker.delegate=self;
picker.allowsEditing=NO;
picker.videoMaximumDuration = 1.0;//视频最长长度
picker.videoQuality = UIImagePickerControllerQualityTypeMedium;//视频质量
//媒体类型:@"public.movie" 为视频 @"public.image" 为图片
//这里只选择展示视频
picker.mediaTypes = [NSArray arrayWithObjects:@"public.movie", nil];
picker.sourceType= UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[kCurNavController presentViewController:picker animated:YES completion:^{
}];
}
#pragma mark UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
NSString *mediaType=[info objectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:@"public.movie"]){
//如果是视频
NSURL *url = info[UIImagePickerControllerMediaURL];//获得视频的URL
NSLog(@"url %@",url);
self.videoUrl = url;
}
[self dismissViewControllerAnimated:YES completion:nil];
}
选择视频:
方式二:利用三方库TZImagePickerController
贴代码:
- (void)selectThreeKuAction{
TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 columnNumber:4 delegate:nil pushPhotoPickerVc:YES];
//展示相册中的视频
imagePickerVc.allowPickingVideo = YES;
//不展示图片
imagePickerVc.allowPickingImage = NO;
//不显示原图选项
imagePickerVc.allowPickingOriginalPhoto = NO;
//按时间排序
imagePickerVc.sortAscendingByModificationDate = YES;
//选择完视频之后的回调
[imagePickerVc setDidFinishPickingVideoHandle:^(UIImage *coverImage,id asset){
//iOS8以后返回PHAsset
PHAsset *phAsset = asset;
if (phAsset.mediaType == PHAssetMediaTypeVideo) {
//从PHAsset获取相册中视频的url
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
options.version = PHImageRequestOptionsVersionCurrent;
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
PHImageManager *manager = [PHImageManager defaultManager];
[manager requestAVAssetForVideo:phAsset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
AVURLAsset *urlAsset = (AVURLAsset *)asset;
NSURL *url = urlAsset.URL;
self.videoUrl = url;
NSLog(@"%@",url);
}];
}
}];
[kCurNavController presentViewController:imagePickerVc animated:YES completion:nil];
}
以上都得到了视频的URL,之后再操作就方便了。
裁剪视频:
//视频裁剪
- (void)cropWithVideoUrlStr:(NSURL *)videoUrl start:(CGFloat)startTime end:(CGFloat)endTime completion:(void (^)(NSURL *outputURL, Float64 videoDuration, BOOL isSuccess))completionHandle
{
AVURLAsset *asset =[[AVURLAsset alloc] initWithURL:videoUrl options:nil];
//获取视频总时长
Float64 duration = CMTimeGetSeconds(asset.duration);
NSString *outputPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"dafei.mp4"];
NSURL *outputURL = [NSURL fileURLWithPath:outputPath];
//如果文件已经存在,先移除,否则会报无法存储的错误
NSFileManager *manager = [NSFileManager defaultManager];
[manager removeItemAtPath:outputPath error:nil];
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset];
if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality])
{
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
exportSession.outputURL = outputURL;
//视频文件的类型
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
//输出文件是否网络优化
exportSession.shouldOptimizeForNetworkUse = YES;
//要截取的开始时间
CMTime start = CMTimeMakeWithSeconds(startTime, asset.duration.timescale);
//要截取的总时长
CMTime duration = CMTimeMakeWithSeconds(endTime - startTime,asset.duration.timescale);
CMTimeRange range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch ([exportSession status]) {
case AVAssetExportSessionStatusFailed:
{
NSLog(@"合成失败:%@", [[exportSession error] description]);
completionHandle(outputURL, endTime, NO);
}
break;
case AVAssetExportSessionStatusCancelled:
{
completionHandle(outputURL, endTime, NO);
}
break;
case AVAssetExportSessionStatusCompleted:
{
//成功
completionHandle(outputURL, endTime, YES);
}
break;
default:
{
completionHandle(outputURL, endTime, NO);
} break;
}
}];
}
}
处理完视频之后,把视频保存到相册:
方式一:
//保存视频到相册
- (void)writeVideoToPhotoLibrary:(NSURL *)url
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error){
if (error == nil) {
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"视频保存成功" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:alert animated:true completion:nil];
}else{
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"视频保存失败" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:alert animated:true completion:nil];
}
}];
}
保存视频到相册,方式二:用下面这个方法
UISaveVideoAtPathToSavedPhotosAlbum(path, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
// 视频保存回调
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo: (void *)contextInfo {
if (error == nil) {
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"视频保存成功" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:alert animated:true completion:nil];
}else{
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"视频保存失败" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:alert animated:true completion:nil];
}
}