视频录制+压缩+合并+清除沙盒缓存

news/2024/7/7 18:50:14

-(void)AVCaptureVideo{

    

    //创建视频设备(摄像头前,后)

    NSArray *devices = [AVCaptureDevicedevicesWithMediaType:AVMediaTypeVideo];

    //初始化一个摄像头输入设备(first是后置摄像头,last是前置摄像头)

    AVCaptureDeviceInput *inputVideo = [AVCaptureDeviceInputdeviceInputWithDevice:[devices firstObject] error:NULL];

    //创建麦克风设备

    AVCaptureDevice *deviceAudio = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeAudio];

    //初始化麦克风输入设备

    AVCaptureDeviceInput *inputAudio = [AVCaptureDeviceInputdeviceInputWithDevice:deviceAudioerror:NULL];

    

    //初始化一个movie的文件输出

    AVCaptureMovieFileOutput *output = [[AVCaptureMovieFileOutputalloc] init];

    self.output = output;//保存output,方便下面操作

    

    //初始化一个会话

    AVCaptureSession *session = [[AVCaptureSessionalloc] init];

    

    //将输入输出设备添加到会话中

    if ([sessioncanAddInput:inputVideo]) {

        [session addInput:inputVideo];

    }

    if ([sessioncanAddInput:inputAudio]) {

        [session addInput:inputAudio];

    }

    if ([sessioncanAddOutput:output]) {

        [session addOutput:output];

    }

    

    

    //添加一个视频预览图层,设置大小,添加到控制器view的图层上

    //创建一个预览涂层

    AVCaptureVideoPreviewLayer *preLayer = [AVCaptureVideoPreviewLayerlayerWithSession:session];

    //设置图层的大小

    preLayer.frame =self.view.bounds;

    //添加到view

    [self.view.layeraddSublayer:preLayer];

    

    //开始会话

    [session startRunning];

    

}


#pragma mark ==============

#pragma mark ===录制按钮======

- (void)clickVideoBtn:(UIButton *)sender {

    //判断是否在录制,如果在录制,就停止,并设置按钮title

    if ([self.outputisRecording]) {

      [self.outputstopRecording];

        


   [sender setTitle:@"录制"forState:UIControlStateNormal];

    return;

    }

    

    //设置按钮的title

    [sender setTitle:@"停止"forState:UIControlStateNormal];

    

    //设置录制视频保存的路径

    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,

                                                NSUserDomainMask, YES).lastObjectstringByAppendingPathComponent:[NSStringstringWithFormat:@"%@.mov",[NSDatedate]]];

    


     //转为视频保存的url

     NSURL *url  = [NSURLfileURLWithPath:path];

    

//    UISaveVideoAtPathToSavedPhotosAlbum(path, nil, nil, nil);

    

    //开始录制,并设置控制器为录制的代理

    [self.outputstartRecordingToOutputFileURL:urlrecordingDelegate:self];

}



//清楚缓存

- (void)clickClearMemory{

    

   NSString *path = [LBClearCacheToolgetCacheSizeWithFilePath: [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject]];

    

    UIAlertController *alert=[UIAlertControlleralertControllerWithTitle:[NSStringstringWithFormat:@"确定清除%@缓存吗?",path]message:nilpreferredStyle:UIAlertControllerStyleActionSheet];

    //创建一个取消和一个确定按钮

    UIAlertAction *actionCancle=[UIAlertActionactionWithTitle:@"取消"style:UIAlertActionStyleCancelhandler:nil];

    //因为需要点击确定按钮后改变文字的值,所以需要在确定按钮这个block里面进行相应的操作

    UIAlertAction *actionOk=[UIAlertActionactionWithTitle:@"确定"style:UIAlertActionStyleDestructivehandler:^(UIAlertAction *_Nonnull action) {

        

        //清楚缓存

        BOOL isSuccess = [LBClearCacheToolclearCacheWithFilePath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject]];

        if (isSuccess) {

            [MBProgressHUDshowSuccess:@"清楚成功"];

            

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                

                [MBProgressHUDhideAllHUDsForView:self.viewanimated:YES];

            });

        }

        

        

        

    }   ];

    //将取消和确定按钮添加进弹框控制器

    [alert addAction:actionCancle];

    [alert addAction:actionOk];

    //添加一个文本框到弹框控制器

    

    //显示弹框控制器

    [selfpresentViewController:alert animated:YEScompletion:nil];

    

}


#pragma mark - AVCaptureFileOutputRecordingDelegate

 //录制完成代理

- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error

{

    [MBProgressHUDshowSuccess:@"录制完成"];

    

    [selfsetAlertView:outputFileURL];

    

}


#pragma mark ==============

#pragma mark ===输入框======

-(void)setAlertView:(NSURL *)inPutUrl{

    

    UIAlertController *alert = [UIAlertControlleralertControllerWithTitle:@"输入视频名称"message:@""preferredStyle:(UIAlertControllerStyleAlert)];

    

    [alert addTextFieldWithConfigurationHandler:^(UITextField*textField) {

        

        textField.text = [NSStringstringWithFormat:@"%@",[NSDatedate]];

        

        [textField addTarget:selfaction:@selector(changValue:)forControlEvents:(UIControlEventEditingChanged)];

        

        self.videoName = textField.text;

        

    }];

    

    UIAlertAction *ok = [UIAlertActionactionWithTitle:@"确定"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction *_Nonnull action) {

        

        [selfZIPVideo:inPutUrl VideoName:self.videoName];

    }];

    

    [alert addAction:ok];

    

    [selfpresentViewController:alert animated:YEScompletion:nil];


}



#pragma mark ==============

#pragma mark ===视频压缩======

- (void) lowQuailtyWithInputURL:(NSURL*)inputURL

                      outputURL:(NSURL*)outputURL

                   blockHandler:(void (^)(AVAssetExportSession*))handler

{

    AVURLAsset *asset = [AVURLAssetURLAssetWithURL:inputURL options:nil];

    AVAssetExportSession *session = [[AVAssetExportSessionalloc] initWithAsset:asset    presetName:AVAssetExportPresetMediumQuality];

    session.outputURL = outputURL;

    session.outputFileType =AVFileTypeQuickTimeMovie;

    [session exportAsynchronouslyWithCompletionHandler:^(void)

     {

         handler(session);

     }];

}

-(void)ZIPVideo:(NSURL *)inputURl VideoName:(NSString *)videoName{

    

    //设置录制视频保存的路径

    NSString *outpath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,

                                                            NSUserDomainMask, YES).lastObjectstringByAppendingPathComponent:[NSStringstringWithFormat:@"%@.mov",videoName]];

    

    //转为视频保存的url

    NSURL *outurl  = [NSURLfileURLWithPath:outpath];

    

    //path添加到数组中(合并视频)

    [self.videoPathArrayaddObject:outpath];

    

    [selflowQuailtyWithInputURL:inputURl outputURL:outurl blockHandler:^(AVAssetExportSession *session)

     {

         if (session.status ==AVAssetExportSessionStatusCompleted)

         {

             NSLog(@"压缩成功");

             

         }

         else

         {

             NSLog(@"压缩失败");

             

         }

     }];

}


#pragma mark ==============

#pragma mark ===监听textfield======

-(void)changValue:(UITextField *)text{

    

    self.videoName = text.text;

    

}


//视频合并按钮

-(void)clickMergeButton{

    

    [selfmergeAndExportVideos:self.videoPathArraywithOutPath:[selfvideoPath]];

}

#pragma mark =====下面是合成视频的方法===========

- (void)mergeAndExportVideos:(NSArray*)videosPathArray withOutPath:(NSString*)outpath{

    if (videosPathArray.count ==0) {

        [MBProgressHUDshowError:@"请录制视频"];

        return;

    }

    

    [MBProgressHUDshowMessage:@"合并中..."toView:self.view];

    

    AVMutableComposition *mixComposition = [[AVMutableCompositionalloc] init];

    

    AVMutableCompositionTrack *audioTrack = [mixCompositionaddMutableTrackWithMediaType:AVMediaTypeAudio

                                                                       preferredTrackID:kCMPersistentTrackID_Invalid];

    AVMutableCompositionTrack *videoTrack = [mixCompositionaddMutableTrackWithMediaType:AVMediaTypeVideo

                                                                       preferredTrackID:kCMPersistentTrackID_Invalid];


  //视频旋转270(视频合并后默认旋转了-90)详情请参考(http://www.cnblogs.com/alby/p/4610077.html)

    videoTrack.preferredTransform =CGAffineTransformMake(0,1.0, -1.0,0, 0,0);

    

    CMTime totalDuration =kCMTimeZero;

    for (int i =0; i < videosPathArray.count; i++) {

        AVURLAsset *asset = [AVURLAssetassetWithURL:[NSURLfileURLWithPath:videosPathArray[i]]];


        NSError *erroraudio =nil;

        //获取AVAsset中的音频或者视频

        AVAssetTrack *assetAudioTrack = [[assettracksWithMediaType:AVMediaTypeAudio]firstObject];

        

        

        

        //向通道内加入音频或者视频

        [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)

                            ofTrack:assetAudioTrack

                             atTime:totalDuration

                              error:&erroraudio];

        

//        NSLog(@"erroraudio:%@",erroraudio);

        NSError *errorVideo =nil;

        AVAssetTrack *assetVideoTrack = [[assettracksWithMediaType:AVMediaTypeVideo]firstObject];

        [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)

                            ofTrack:assetVideoTrack

                             atTime:totalDuration

                              error:&errorVideo];

        

//        NSLog(@"errorVideo:%@",errorVideo);

        totalDuration = CMTimeAdd(totalDuration, asset.duration);

    }

    

    NSURL *mergeFileURL = [NSURLfileURLWithPath:outpath];

    AVAssetExportSession *exporter = [[AVAssetExportSessionalloc] initWithAsset:mixComposition

                                                                     presetName:AVAssetExportPresetMediumQuality];

    exporter.outputURL = mergeFileURL;

    exporter.outputFileType =AVFileTypeQuickTimeMovie;

    exporter.shouldOptimizeForNetworkUse =YES;

    [exporter exportAsynchronouslyWithCompletionHandler:^{

        

        if (exporter.error !=nil) {

            dispatch_async(dispatch_get_main_queue(), ^{

                [MBProgressHUDhideHUDForView:self.view];

                

                [MBProgressHUDshowSuccess:@"合并失败"];

            });

            NSLog(@"合并失败");

            

        }else{

            

            dispatch_async(dispatch_get_main_queue(), ^{

                [MBProgressHUDhideHUDForView:self.view];

               

                [MBProgressHUDshowSuccess:@"合并成功"];

            });

            

            NSLog(@"合并成功");

        }

        //保存到相册

//        UISaveVideoAtPathToSavedPhotosAlbum([mergeFileURL path], nil, nil, nil);

        

    }];

}


//路径

- (NSString *)videoPath {

    NSString *basePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)firstObject];

    NSString *moviePath = [basePathstringByAppendingPathComponent:[NSStringstringWithFormat:@"qqq%@.mov",[NSDatedate]]];

    return moviePath;

}





http://lihuaxi.xjx100.cn/news/235243.html

相关文章

长连接及在Node中的应用——HTTP/1.1 keep-alive

HTTP请求都要经过TCP三次握手建立连接&#xff0c;四次分手断开连&#xff0c;如果每个HTTP请求都要建立TCP连接的话是极其费时的&#xff0c;因此HTTP/1.1中浏览器默认开启了Connection: keep-alive。 请求头中的这个属性的作用可以在请求完成后&#xff0c;保持TCP连接一段时…

iOS使用Charts框架绘制—饼状图

作者&#xff1a;jianshu_wl 原文地址&#xff1a;http://www.jianshu.com/p/45194d861b21 首先先看一下效果: 一、创建饼状图对象 创建饼状图对象用到类是PieChartView.h, 代码如下: self.pieChartView [[PieChartView alloc] init]; self.pieChartView.backgroundColor Bg…

iOS封装HTTPS双向和单向验证

1.HttpsUtil (1) 对双向和单向验证的封装 #import <Foundation/Foundation.h> #import "AFNetworking.h" interface HttpsUtil : NSObject // 双向认证 (void)configHTTPSessionManager:(AFHTTPSessionManager *)manager serverCers:(NSArray *) serverCerNam…

乐视云计算被列入失信名单;三星华为达成和解;Python3 采用率超 84%丨Q新闻

本周要闻&#xff1a;三星华为达成和解&#xff1b;乐视云计算被列入失信名单&#xff1b;小米宣布成立技术委员会&#xff1b;支付宝小程序向个人开发者开放公测&#xff1b;Flutter 1.2 发布&#xff1b;Python3 采用率超 84%&#xff1b;调查称最受雇主欢迎的语言是 Go&…

做一款仿映客的直播App?看我就够了

来源&#xff1a;JIAAIR 链接&#xff1a;http://www.jianshu.com/p/5b1341e97757 一、直播现状简介 1.技术实现层面&#xff1a; 技术相对都比较成熟&#xff0c;设备也都支持硬编码。IOS还提供现成的 Video ToolBox框架&#xff0c;可以对摄像头和流媒体数据结构进行处理&am…

OC封装时间选择器

#import <UIKit/UIKit.h> protocol TimeDatePickerViewDelegate <NSObject> //必须实现的两个协议 required - (void)changeTime : (NSDate *)date;//当时改变时出发 - (void)daterMine : (NSDate *)date;//更确定时间 end interface TimeDatePickerView :UIView /…

蓝桥杯 扑克序列(全排列)

扑克序列 A A 2 2 3 3 4 4&#xff0c; 一共4对扑克牌。请你把它们排成一行。要求&#xff1a;两个A中间有1张牌&#xff0c;两个2之间有2张牌&#xff0c;两个3之间有3张牌&#xff0c;两个4之间有4张牌。 请填写出所有符合要求的排列中&#xff0c;字典序最小的那个。 例如&a…

runLoop和runtime的分析

一.RunLoop: Runloop是事件接收和分发机制的一个实现。 Runloop提供了一种异步执行代码的机制&#xff0c;不能并行执行任务。 在主队列中&#xff0c;Main RunLoop直接配合任务的执行&#xff0c;负责处理UI事件、定时器以及其他内核相关事件。 (1).RunLoop的主要目的&#…