iOS 视频截取
一、背景
因为最近有个需求,关于视频截取的,这篇文章将遇到的问题总结一下,希望以后做到这种需求的iOSer,可以帮助到。
需求是这样的:
1、从本地图库里拿到视频;
2、对视频进行截取;
3、上传服务器;
二、问题描述与解决
1.1 本地视频录制,有三种方式:普通视频录制、延时摄影和慢动作。使用photos.framework 是可以拿到这些资源的,都是存储在PHAsset里面。(关于photos.framwork这个框架,以后我会专门说,这里想了解知识的可以去搜。)
1.2 当我拿到PHAsset,通过
[[PHCachingImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"%@",asset);
if (completion) {
completion(urlAsset);
}
}];
这个api,可以得到AVFoundation框架下的AVAsset对象,(关于AVFoundation框架,需要补充知识的也请先自行查找),需要注意的是,这block在子线程。这里提一下AVAsset,他是一个抽象类,我们需要注意的是他有两个子类,一个是AVURLAsset,还有一个是AVComposition。AVURLAsset是我们读取资源时候要用到,里面包含URL。而AVComposition是做视频处理时候用到的,它包含视频轨和音轨。我做视频截取时候,用到一个第三方,SAVideoRangeSlider这个是一个处理视频拆分的slider,他有个方法:
- (void)getMovieFrame:(NSURL *)videoUrl;
这里,需要传递一个视频url,然后就可以分割为一帧一帧的图片。
啰嗦了这么多,问题出现,如下:
VideoCutOutDemo[56533:8168439] -[AVComposition URL]: unrecognized selector sent to instance 0x1c02210c0
运行,直接挂了,说找不到[AVComposition URL]方法,这是崩了的根本原因。我发现只有一个视频崩掉,点其他视频并不报错,就是我之前录制的慢动作视频。所以,我打印了一下asset,发现原因,慢动作视频返回的是AVComposition类型(这里面包含视频轨和音轨),里面确实没有url的属性,所以找不到getter方法,挂了。而其他视频是AVURLAsset,所以没事。
解决方法:上面代码有一个地方,要传入一个options,我们可以通过这个options处理一下。
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
options.version = PHVideoRequestOptionsVersionOriginal;
typedef NS_ENUM(NSInteger, PHVideoRequestOptionsVersion) {
PHVideoRequestOptionsVersionCurrent = 0, // version with edits (aka adjustments) rendered or unadjusted version if there is no edits
PHVideoRequestOptionsVersionOriginal // original version
} PHOTOS_ENUM_AVAILABLE_IOS_TVOS(8_0, 10_0);
默认是PHVideoRequestOptionsVersionCurrent,这个是可以播放,慢动作视频,也是默认的设置;PHVideoRequestOptionsVersionOriginal是将慢动作视频变为正常视频。这样打印asset时候,返回的是AVURLAsset,这样就可以截取了。
注意:
这个解决方法,是有一定问题的,就是如果你们老板或者产品非要慢动作视频的截取,我还不知道咋搞,苹果自带的视频编辑是可以处理的。我下载的其他app对于慢动作的截取,就是我这种方式,如果哪位大神看了,可以教我一下,不胜感激。
2.视频截取
直接调用VideoManager中的方法
/**
根据时间裁剪
@param avAsset avAsset
@param startTime 起始时间
@param endTime 结束时间
@param completion 回调视频url
*/
+ (void)cutVideoWithAVAsset:(AVAsset *)avAsset startTime:(CGFloat)startTime endTime:(CGFloat)endTime completion:(outputBlock)completion;
具体方法的实现过程,在该方法里面看就可以了。
3.上传服务器
方法最终回调的是url ,我们上传服务器,将url转化为data格式,上传服务器的。这个完全根据实际需求和逻辑决定。
整个demo,在这。
这文章目的可以交流,学习。