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覆盖更新的时候,路径会更改。所以我们要重新获取一下路径。只能存储文件的名字就可以了。