iOS 录视频,相册选择视频,视频压缩,存储本地文件,播放,上传
工程中用到了这部分的功能,也纠结了几天后做完了,现在总结下这部分的东西。
先说描述下需求:
(1)从相册取视频、录视频;
(2)视频转码为mp4;
(3)存储在文件中,覆盖更新后也能读取视频
(4)视频的播放
注意:在iOS9之后需要在plist文件中添加一些限制
Privacy - Microphone Usage Description App需要您的同意,才能访问麦克风
Privacy - Photo Library Usage Description “App需要您的同意,才能访问相册”
Privacy - Camera Usage Description “App需要您的同意,才能访问相机”
Privacy - Media Library Usage Description “App需要您的同意,才能访问媒体资源库”
导入的库文件
#import <MobileCoreServices/MobileCoreServices.h>
#import <AVFoundation/AVFoundation.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import <MediaPlayer/MediaPlayer.h>
使用的UIImagePickerController <UIImagePickerControllerDelegate,UINavigationControllerDelegate>
一、读取本地的视频,并播放
注意:添加本地视频的方法:
读取地址:
NSString *str = [[NSBundle mainBundle] resourcePath];
NSString *filePath = [NSString stringWithFormat:@“%@%@",str,@"/123.mp4"];
NSURL *sourceMovieURL = [NSURL fileURLWithPath:filePath];
- (void)playVideowithUrl:(NSURL *)url{
AVAsset *movieAsset = [AVURLAsset URLAssetWithURL:url options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:movieAsset];
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.frame = CGRectMake(0, 230,300, 150);
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
[self.view.layer addSublayer:playerLayer];
playerLayer.backgroundColor = [UIColor blueColor].CGColor;
[player play];
}
二、调用相机,相册获取视频
//点击视频录制的按钮
- (IBAction)videoButtonClick:(UIButton *)sender {
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"视频" preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction * firstAction = [UIAlertAction actionWithTitle:@"从相册获取视频" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self choosevideo];
}];
UIAlertAction * secondAction = [UIAlertAction actionWithTitle:@"录制视频" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self openLocalCamera];
}];
[alert addAction:firstAction];
[alert addAction:secondAction];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)choosevideo
{
UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;//sourcetype有三种分别是camera,photoLibrary和photoAlbum
NSArray *availableMedia = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];//Camera所支持的Media格式都有哪些,共有两个分别是@"public.image",@"public.movie"
ipc.mediaTypes = [NSArray arrayWithObject:availableMedia[1]];//设置媒体类型为public.movie
[self presentViewController:ipc animated:YES completion:nil];
ipc.delegate = self;//设置委托
}
- (void)openLocalCamera{
UIImagePickerController * picker = [[UIImagePickerController alloc]init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
//录制视频时长,默认10s
picker.videoMaximumDuration = 20;
//相机类型(拍照、录像...)这里表示我们打开相机支持的是相机和录像两个功能。
picker.mediaTypes = @[(NSString *)kUTTypeMovie];
picker.delegate = self;
picker.videoQuality = UIImagePickerControllerQualityTypeHigh;
//设置摄像头模式(拍照,录制视频)为相机模式
// UIImagePickerControllerCameraCaptureModeVideo 这个是设置为视频模式
picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
[self presentViewController:picker animated:YES completion:nil];
}
#pragma mark UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//如果是视频资源
NSURL *sourceURL = info[UIImagePickerControllerMediaURL];
NSLog(@"%@",[NSString stringWithFormat:@"%f s", [self getVideoLength:sourceURL]]);
NSLog(@"%@", [NSString stringWithFormat:@"%.2f kb", [self getFileSize:[sourceURL path]]]);
self.videoImage.image = [self thumbnailImageForVideo:sourceURL atTime:1];
self.videoUrl = sourceURL;
NSURL *newVideoUrl ; //一般.mp4
[picker dismissViewControllerAnimated:YES completion:^{}];
[self compressedVideoOtherMethodWithURL:sourceURL compressionType:@"AVAssetExportPresetMediumQuality"];
}
- (void)compressedVideoOtherMethodWithURL:(NSURL *)url compressionType:(NSString *)compressionType {
NSString *resultPath;
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
// 所支持的压缩格式中是否有 所选的压缩格式
if ([compatiblePresets containsObject:compressionType]) {
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:avAsset presetName:compressionType];
NSDateFormatter *formater = [[NSDateFormatter alloc] init];// 用时间, 给文件重新命名, 防止视频存储覆盖,
[formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
NSFileManager *manager = [NSFileManager defaultManager];
BOOL isExists = [manager fileExistsAtPath:CompressionVideoPaht];
if (!isExists) {
[manager createDirectoryAtPath:CompressionVideoPaht withIntermediateDirectories:YES attributes:nil error:nil];
}
NSInteger num = random()%1000;
resultPath = [CompressionVideoPaht stringByAppendingPathComponent:[NSString stringWithFormat:@"outputJFVideo-%@.mov",[NSNumber numberWithInteger:num]]];
[useDefault setValue:[NSNumber numberWithInteger:num] forKey:@"videoRandom"];
[useDefault synchronize];
NSLog(@"resultPath = %@",resultPath);
exportSession.outputURL = [NSURL fileURLWithPath:resultPath];
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void)
{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
NSData *data = [NSData dataWithContentsOfFile:resultPath];
float memorySize = (float)data.length / 1024 / 1024;
NSLog(@"视频压缩后大小 %f", memorySize);
self.fileVideoImage.image = [self thumbnailImageForVideo:[NSURL fileURLWithPath:resultPath] atTime:1];
[self playVideowithUrl:[NSURL fileURLWithPath:resultPath]];
} else {
NSLog(@"压缩失败");
}
}];
} else {
NSLog(@"不支持 %@ 格式的压缩", compressionType);
}
}
注意播放压缩后导出会有一个文件的存储地址。如果我们用到了数据库,会在数据库中的一个字段下存储这个文件的路径,这样就会有一个文件的路径,但是不能存储绝对路径。因为在app覆盖更新的时候,路径会更改。所以我们要重新获取一下路径。只能存储文件的名字就可以了。