123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- //
- // UIViewController+YOUPAIVideo.m
- // MSYOUPAI
- //
- // Created by admin on 2022/3/5.
- // Copyright © 2022 MS. All rights reserved.
- //
- #import "UIViewController+YOUPAIVideo.h"
- #import "NSDate+formatter.h"
- typedef void(^MovEncodeToMpegToolResultBlock)(NSURL *mp4FileUrl, NSData *mp4Data, NSError *error);
- typedef enum : NSUInteger {
- ExportPresetLowQuality, //低质量 可以通过移动网络分享
- ExportPresetMediumQuality, //中等质量 可以通过WIFI网络分享
- ExportPresetHighestQuality, //高等质量
- ExportPreset640x480,
- ExportPreset960x540,
- ExportPreset1280x720, //720pHD
- ExportPreset1920x1080, //1080pHD
- ExportPreset3840x2160,
- } ExportPresetQuality;
- @implementation UIViewController (YOUPAIVideo)
- /**
- 选择视频
- */
- -(void)youpaifTZSelectVideo:(YOUPAIVideoWillSelectBlock)willSelect
- didSelect:(YOUPAIVideoDidSelectBlock)didSelect{
-
- TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:9 columnNumber:4 delegate:nil];
- if (willSelect){
- willSelect(imagePickerVc);
- }
- else{
- [LCTZImageConfigHelper setDefaultTZImageConfig:imagePickerVc];
- imagePickerVc.allowTakePicture = YES; // 在内部显示拍照按钮
- imagePickerVc.allowPickingVideo = YES;//是否允许选择视频
- imagePickerVc.allowPickingImage = NO;//是否允许选择照片
- imagePickerVc.allowPickingOriginalPhoto = NO;//是否选择原图
- imagePickerVc.showSelectedIndex = YES; //显示图片序号
- imagePickerVc.sortAscendingByModificationDate = YES;//按时间倒序排列图片
- }
-
-
- [imagePickerVc setDidFinishPickingVideoHandle:^(UIImage *coverImage, PHAsset *asset) {
-
- PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
- options.version = PHVideoRequestOptionsVersionOriginal;
- options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
- options.networkAccessAllowed = YES;
- [ZCHUDHelper showWithStatus:@"读取中..."];
- [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:nil resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
-
- if (asset == nil) {
- NSError *error = [NSError errorWithDomain:@"无效视频" code:-1 userInfo:nil];
- if (didSelect){
- didSelect(nil,nil,error);
- }
- [ZCHUDHelper dismiss];
- return;
- }else{
- AVURLAsset *urlAsser = ( AVURLAsset *)asset;
- [UIViewController convertMovToMp4FromAVURLAsset:urlAsser
- andAVAssetExportPresetQuality:ExportPresetHighestQuality andMovEncodeToMpegToolResultBlock:^(NSURL *mp4FileUrl, NSData *mp4Data, NSError *error) {
- [ZCHUDHelper dismiss];
- if (error == nil){
- if (didSelect){
- AVURLAsset *mp4Asser = [AVURLAsset assetWithURL:mp4FileUrl];
-
- didSelect(coverImage,mp4Asser,nil);
- }
- }else{
- if (didSelect){
- didSelect(nil,nil,error);
- }
- }
- }];
-
-
- }
- }];
-
- }];
-
- [self presentViewController:imagePickerVc animated:YES completion:nil];
- }
- /**
- avplayer 播放视频
- */
- -(void)youpaifAVPlayer:(NSURL*)path {
-
- __block NSString *playurl = [path absoluteString];
- if ([NSThread isMainThread]) {
-
- if([playurl hasPrefix:@"://"])
- {
- playurl = [NSString stringWithFormat:@"file://%@",path];
- }
- NSURL * url = [NSURL URLWithString:playurl];
- AVPlayerViewController *moviePlayer=[[AVPlayerViewController alloc]init];
- moviePlayer.player = [AVPlayer playerWithURL:url];
- [moviePlayer.player play];
- [self presentViewController:moviePlayer animated:YES completion:^{
-
- }];
-
- } else {
- dispatch_sync(dispatch_get_main_queue(), ^{
- if([playurl hasPrefix:@"://"])
- {
- playurl = [NSString stringWithFormat:@"file://%@",path];
- }
- NSURL * url = [NSURL URLWithString:playurl];
- AVPlayerViewController *moviePlayer=[[AVPlayerViewController alloc]init];
- moviePlayer.player = [AVPlayer playerWithURL:url];
- [moviePlayer.player play];
- [self presentViewController:moviePlayer animated:YES completion:^{
-
- }];
- });
- }
-
- }
- /**
- 裁剪视频
- */
- -(void)youpaifCutVideo:(AVURLAsset *)asset
- start:(CGFloat)startTime
- end:(CGFloat)endTime
- completion:(YOUPAIVideoDidCutBlock)completion{
-
- NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
- NSString *outputFilePath = [NSString stringWithFormat:@"%@/MediaTool%@.mp4", docDirPath , [UIViewController getCurrentTime]];
- NSURL *outputFileUrl = [NSURL fileURLWithPath:outputFilePath];
-
- NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset];
- if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality])
- {
-
- AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
- initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
- NSURL *outputURL = outputFileUrl;
- exportSession.outputURL = outputURL;
- exportSession.outputFileType = AVFileTypeMPEG4;
- exportSession.shouldOptimizeForNetworkUse = YES;
-
- CMTime start = CMTimeMakeWithSeconds(startTime, asset.duration.timescale);
- CMTime duration = CMTimeMakeWithSeconds(endTime,asset.duration.timescale);
- CMTimeRange range = CMTimeRangeMake(start, duration);
- exportSession.timeRange = range;
-
- [exportSession exportAsynchronouslyWithCompletionHandler:^{
-
- switch ([exportSession status]) {
- case AVAssetExportSessionStatusFailed:
- {
- completion(nil, 0, [exportSession error]);
- }
- break;
- case AVAssetExportSessionStatusCancelled:
- {
- NSError *error = [NSError errorWithDomain:@"已取消" code:-1 userInfo:nil];
- completion(nil, 0, error);
- }
- break;
- case AVAssetExportSessionStatusCompleted:
- {
- completion(outputURL, endTime, nil);
- }
- break;
- default:
- {
- NSError *error = [NSError errorWithDomain:@"裁剪失败" code:-1 userInfo:nil];
- completion(outputURL, 0, error);
- } break;
- }
- }];
- }
- }
- /**
- 获取上传信息
- */
- -(void)youpaifVideoSts:(NSString*)type
- sts:(YOUPAIVideoDidStsBlock)completion{
-
- [LCHttpHelper requestWithURLString:STS parameters:@{@"type":type} needToken:YES type:HttpRequestTypePost success:^(id responseObject) {
- NSDictionary* dict = (NSDictionary*)responseObject;
- NSInteger code = [[dict objectForKey:@"code"] integerValue];
- if (code==0) {
- YOUPAILZStsModel *model = [YOUPAILZStsModel mj_objectWithKeyValues:[dict objectForKey:@"data"]];
- if (completion) {
- completion(model,nil);
- }
- }
- } failure:^(NSError *error) {
- if (completion) {
- completion(nil,error);
- }
- }];
- }
- //获取当地时间
- + (NSString *)getCurrentTime {
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateFormat:@"HH:mm:ss"];
- NSString *dateTime = [formatter stringFromDate:[NSDate date]];
- return dateTime;
- }
- #pragma mark ### MOV转码MP4
- + (void)convertMovToMp4FromAVURLAsset:(AVURLAsset*)urlAsset
- andAVAssetExportPresetQuality:(ExportPresetQuality)exportQuality
- andMovEncodeToMpegToolResultBlock:(MovEncodeToMpegToolResultBlock)movEncodeToMpegToolResultBlock {
- AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:urlAsset.URL options:nil];
-
- NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
-
- // 查询是否有匹配的预设
- if ([compatiblePresets containsObject:[self getAVAssetExportPresetQuality:exportQuality]]) {
-
- // 在Documents目录下创建一个名为FileData的文件夹
- NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"Cache/VideoData"];
-
- NSFileManager *fileManager = [NSFileManager defaultManager];
- BOOL isDir = FALSE;
- BOOL isDirExist = [fileManager fileExistsAtPath:path isDirectory:&isDir];
- if(!(isDirExist && isDir)) {
- BOOL bCreateDir = [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
- if(!bCreateDir){
- NSLog(@"创建文件夹失败!%@",path);
- }
- NSLog(@"创建文件夹成功,文件路径%@",path);
- }
-
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
- [formatter setDateFormat:@"yyyyMMddHHmmss"]; //每次启动后都保存一个新的文件中
- NSString *dateStr = [formatter stringFromDate:[NSDate date]];
-
- NSString *resultPath = [path stringByAppendingFormat:@"/%@.mp4",dateStr];
- NSLog(@"resultFileName = %@",dateStr);
- AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:avAsset
- presetName:[self getAVAssetExportPresetQuality:exportQuality]];
- exportSession.outputURL = [NSURL fileURLWithPath:resultPath];
- exportSession.outputFileType = AVFileTypeMPEG4;
- exportSession.shouldOptimizeForNetworkUse = YES;
-
- [exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
- switch (exportSession.status) {
- case AVAssetExportSessionStatusUnknown: {
- NSError *error = [NSError errorWithDomain:@"ConvertMovToMp4ErrorDomain"
- code:10001
- userInfo:@{NSLocalizedDescriptionKey:@"AVAssetExportSessionStatusUnknown"}];
- movEncodeToMpegToolResultBlock(nil, nil , error);
- }
- break;
- case AVAssetExportSessionStatusWaiting: {
- NSError *error = [NSError errorWithDomain:@"ConvertMovToMp4ErrorDomain"
- code:10002
- userInfo:@{NSLocalizedDescriptionKey:@"AVAssetExportSessionStatusWaiting"}];
- movEncodeToMpegToolResultBlock(nil, nil , error);
- }
- break;
- case AVAssetExportSessionStatusExporting: {
- NSError *error = [NSError errorWithDomain:@"ConvertMovToMp4ErrorDomain"
- code:10003
- userInfo:@{NSLocalizedDescriptionKey:@"AVAssetExportSessionStatusExporting"}];
- movEncodeToMpegToolResultBlock(nil, nil , error);
- }
- break;
- case AVAssetExportSessionStatusCompleted: {
- NSData *mp4Data = [NSData dataWithContentsOfURL:exportSession.outputURL];
- movEncodeToMpegToolResultBlock(exportSession.outputURL, mp4Data , nil);
- }
- break;
- case AVAssetExportSessionStatusFailed: {
- NSError *error = [NSError errorWithDomain:@"ConvertMovToMp4ErrorDomain"
- code:10005
- userInfo:@{NSLocalizedDescriptionKey:@"AVAssetExportSessionStatusFailed"}];
- movEncodeToMpegToolResultBlock(nil, nil , error);
- }
- break;
- case AVAssetExportSessionStatusCancelled: {
- NSError *error = [NSError errorWithDomain:@"ConvertMovToMp4ErrorDomain"
- code:10006
- userInfo:@{NSLocalizedDescriptionKey:@"AVAssetExportSessionStatusCancelled"}];
- movEncodeToMpegToolResultBlock(nil, nil , error);
- }
- break;
- }
- }];
- }
- else{
- NSError *error = [NSError errorWithDomain:@"ConvertMovToMp4ErrorDomain"
- code:10007
- userInfo:@{NSLocalizedDescriptionKey:@"AVAssetExportSessionStatusNoPreset"}];
- movEncodeToMpegToolResultBlock(nil, nil , error);
- }
- }
- /*
- AVAssetExportPresetLowQuality 低质量 可以通过移动网络分享
- AVAssetExportPresetMediumQuality 中等质量 可以通过WIFI网络分享
- AVAssetExportPresetHighestQuality 高等质量
- AVAssetExportPreset640x480
- AVAssetExportPreset960x540
- AVAssetExportPreset1280x720 720pHD
- AVAssetExportPreset1920x1080 1080pHD
- AVAssetExportPreset3840x2160
- */
- + (NSString *const )getAVAssetExportPresetQuality:(ExportPresetQuality)exportPreset {
- switch (exportPreset) {
- case ExportPresetLowQuality:
- return AVAssetExportPresetLowQuality;
- case ExportPresetMediumQuality:
- return AVAssetExportPresetMediumQuality;
- case ExportPresetHighestQuality:
- return AVAssetExportPresetHighestQuality;
- case ExportPreset640x480:
- return AVAssetExportPreset640x480;
- case ExportPreset960x540:
- return AVAssetExportPreset960x540;
- case ExportPreset1280x720:
- return AVAssetExportPreset1280x720;
- case ExportPreset1920x1080:
- return AVAssetExportPreset1920x1080;
- case ExportPreset3840x2160:
- return AVAssetExportPreset3840x2160;
- }
- }
- @end
|