欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS视频裁剪、拼接、添加水印、添加背景音乐

程序员文章站 2022-03-08 07:59:43
利用GPUImage,实现视频的操作,GPUImage下载地址:点击打开链接方法声明:///使用AVfoundation添加水印- (void)AVsaveVideoPath:(NSURL*)videoPath WithWaterImg:(UIImage*)img WithInfoDic:(NSDictionary*)infoDic WithFileName:(NSString*)fileName completion:(void(^)(NSURL*outputURL,BOOLisSuccess...

利用GPUImage,实现视频的操作,GPUImage下载地址:点击打开链接

方法声明:

///使用AVfoundation添加水印

- (void)AVsaveVideoPath:(NSURL*)videoPath WithWaterImg:(UIImage*)img WithInfoDic:(NSDictionary*)infoDic WithFileName:(NSString*)fileName completion:(void(^)(NSURL*outputURL,BOOLisSuccess))completionHandle;

//视频合成,添加背景音乐

-(void)addFirstVideo:(NSURL*)firstVideoPath andSecondVideo:(NSURL*)secondVideo withMusic:(NSURL*)musicPath completion:(void(^)(NSURL*outputURL,BOOLisSuccess))completionHandle;

//视频裁剪

- (void)cropWithVideoUrlStr:(NSURL*)videoUrl start:(CGFloat)startTime end:(CGFloat)endTime completion:(void(^)(NSURL*outputURL, Float64 videoDuration,BOOLisSuccess))completionHandle;

以下是具体的实现:

#import"VideoManager.h"

#import<Photos/Photos.h>

#import"GPUImage.h"

@interfaceVideoManager()

{

///GPUImage

    GPUImageMovie *movieFile;

    GPUImageOutput<GPUImageInput> *filter;

    GPUImageMovieWriter *movieWriter;

CADisplayLink* dlink;

 

///AVFoundation

AVAsset* videoAsset;

AVAssetExportSession*exporter;

}

@end

///使用AVfoundation添加水印

- (void)AVsaveVideoPath:(NSURL*)videoPath WithWaterImg:(UIImage*)img WithInfoDic:(NSDictionary*)infoDic WithFileName:(NSString*)fileName completion:(void(^)(NSURL*outputURL,BOOLisSuccess))completionHandle

{

if(!videoPath) {

return;

    }

 

//1 创建AVAsset实例 AVAsset包含了video的所有信息 self.videoUrl输入视频的路径

 

//封面图片

NSDictionary*opts = [NSDictionarydictionaryWithObject:@(YES) forKey:AVURLAssetPreferPreciseDurationAndTimingKey];

videoAsset = [AVURLAssetURLAssetWithURL:videoPath options:opts];//初始化视频媒体文件

 

CMTimestartTime =CMTimeMakeWithSeconds(0.2,600);

CMTimeendTime =CMTimeMakeWithSeconds(videoAsset.duration.value/videoAsset.duration.timescale-0.2, videoAsset.duration.timescale);

 

//声音采集

AVURLAsset* audioAsset = [[AVURLAssetalloc] initWithURL:videoPath options:opts];

 

//2 创建AVMutableComposition实例. apple developer 里边的解释 【AVMutableComposition is a mutable subclass of AVComposition you use when you want to create a new composition from existing assets. You can add and remove tracks, and you can add, remove, and scale time ranges.】

AVMutableComposition*mixComposition = [[AVMutableCompositionalloc] init];

 

//3 视频通道  工程文件中的轨道,有音频轨、视频轨等,里面可以插入各种对应的素材

AVMutableCompositionTrack*videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo

                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];

//把视频轨道数据加入到可变轨道中 这部分可以做视频裁剪TimeRange

[videoTrack insertTimeRange:CMTimeRangeFromTimeToTime(startTime, endTime)

ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]

atTime:kCMTimeZero error:nil];

//音频通道

AVMutableCompositionTrack* audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudiopreferredTrackID:kCMPersistentTrackID_Invalid];

//音频采集通道

AVAssetTrack* audioAssetTrack = [[audioAsset tracksWithMediaType:AVMediaTypeAudio] firstObject];

[audioTrack insertTimeRange:CMTimeRangeFromTimeToTime(startTime, endTime) ofTrack:audioAssetTrack atTime:kCMTimeZero error:nil];

 

//3.1 AVMutableVideoCompositionInstruction 视频轨道中的一个视频,可以缩放、旋转等

AVMutableVideoCompositionInstruction*mainInstruction = [AVMutableVideoCompositionInstructionvideoCompositionInstruction];

mainInstruction.timeRange =CMTimeRangeFromTimeToTime(kCMTimeZero, videoTrack.timeRange.duration);

 

// 3.2 AVMutableVideoCompositionLayerInstruction 一个视频轨道,包含了这个轨道上的所有视频素材

AVMutableVideoCompositionLayerInstruction*videolayerInstruction = [AVMutableVideoCompositionLayerInstructionvideoCompositionLayerInstructionWithAssetTrack:videoTrack];

AVAssetTrack*videoAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

//    UIImageOrientation videoAssetOrientation_  = UIImageOrientationUp;

BOOLisVideoAssetPortrait_  =NO;

CGAffineTransformvideoTransform = videoAssetTrack.preferredTransform;

if(videoTransform.a ==0&& videoTransform.b ==1.0&& videoTransform.c ==-1.0&& videoTransform.d ==0) {

//        videoAssetOrientation_ = UIImageOrientationRight;

isVideoAssetPortrait_ =YES;

    }

if(videoTransform.a ==0&& videoTransform.b ==-1.0&& videoTransform.c ==1.0&& videoTransform.d ==0) {

//        videoAssetOrientation_ =  UIImageOrientationLeft;

isVideoAssetPortrait_ =YES;

    }

//    if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {

//        videoAssetOrientation_ =  UIImageOrientationUp;

//    }

//    if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {

//        videoAssetOrientation_ = UIImageOrientationDown;

//    }

    [videolayerInstruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero];

[videolayerInstruction setOpacity:0.0atTime:endTime];

// 3.3 - Add instructions

mainInstruction.layerInstructions = [NSArrayarrayWithObjects:videolayerInstruction,nil];

//AVMutableVideoComposition:管理所有视频轨道,可以决定最终视频的尺寸,裁剪需要在这里进行

AVMutableVideoComposition*mainCompositionInst = [AVMutableVideoCompositionvideoComposition];

 

CGSizenaturalSize;

if(isVideoAssetPortrait_){

naturalSize =CGSizeMake(videoAssetTrack.naturalSize.height, videoAssetTrack.naturalSize.width);

}else{

        naturalSize = videoAssetTrack.naturalSize;

    }

 

floatrenderWidth, renderHeight;

    renderWidth = naturalSize.width;

    renderHeight = naturalSize.height;

mainCompositionInst.renderSize =CGSizeMake(renderWidth, renderHeight);

mainCompositionInst.renderSize =CGSizeMake(renderWidth, renderHeight);

mainCompositionInst.instructions = [NSArrayarrayWithObject:mainInstruction];

mainCompositionInst.frameDuration =CMTimeMake(1,25);

 

//shuiyin

//[self applyVideoEffectsToComposition:mainCompositionInst WithWaterImg:img WithCoverImage:coverImg WithQustion:question size:CGSizeMake(renderWidth, renderHeight)];

 

//by yangyunfei

[selfapplyVideoEffectsToComposition:mainCompositionInst WithWaterImg:img WithInfoDic:infoDic size:CGSizeMake(renderWidth, renderHeight)];

 

//    //UI操作放到主线程执行

//    dispatch_async(dispatch_get_main_queue(), ^{

//       

//        [self applyVideoEffectsToComposition:mainCompositionInst WithWaterImg:img WithCoverImage:coverImg WithQustion:question size:CGSizeMake(renderWidth, renderHeight)];

//

//    });

 

// 4 - 输出路径

NSArray*paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);

NSString*documentsDirectory = [paths objectAtIndex:0];

 

NSString*myPathDocs =  [documentsDirectory stringByAppendingPathComponent:

[NSStringstringWithFormat:@"%@-%d.mov",fileName,arc4random() %1000]];

//    NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mov",fileName]];

    unlink([myPathDocs UTF8String]);

 

//如果文件已经存在,先移除,否则会报无法存储的错误

NSFileManager*manager = [NSFileManagerdefaultManager];

[manager removeItemAtPath:myPathDocs error:nil];

 

NSURL* videoUrl = [NSURLfileURLWithPath:myPathDocs];

 

dlink = [CADisplayLinkdisplayLinkWithTarget:selfselector:@selector(updateProgress)];

[dlink setFrameInterval:15];

[dlink addToRunLoop:[NSRunLoopcurrentRunLoop] forMode:NSDefaultRunLoopMode];

[dlink setPaused:NO];

 

// 5 - 视频文件输出

exporter = [[AVAssetExportSessionalloc] initWithAsset:mixComposition

presetName:AVAssetExportPresetHighestQuality];

    exporter.outputURL=videoUrl;

exporter.outputFileType =AVFileTypeQuickTimeMovie;

exporter.shouldOptimizeForNetworkUse =YES;

    exporter.videoComposition = mainCompositionInst;

    [exporter exportAsynchronouslyWithCompletionHandler:^{

//        dispatch_async(dispatch_get_main_queue(), ^{

//            //这里是输出视频之后的操作,做你想做的

//            [self exportDidFinish:exporter];

//        });

switch([exporter status]) {

caseAVAssetExportSessionStatusFailed:

            {

NSLog(@"添加水印失败:%@", [[exporter error] description]);

completionHandle(videoUrl,NO);

            }

break;

caseAVAssetExportSessionStatusCancelled:

            {

completionHandle(videoUrl,NO);

            }

break;

caseAVAssetExportSessionStatusCompleted:

            {

//成功

NSLog(@"添加水印成功");

completionHandle(videoUrl,YES);

 

            }

break;

default:

            {

completionHandle(videoUrl,NO);

}break;

        }

    }];

 

}

//添加水印

- (void)applyVideoEffectsToComposition:(AVMutableVideoComposition*)composition WithWaterImg:(UIImage*)img WithCoverImage:(UIImage*)coverImg WithQustion:(NSString*)question  size:(CGSize)size {

 

UIFont*font = [UIFontsystemFontOfSize:30.0];

CATextLayer*subtitle1Text = [[CATextLayeralloc] init];

[subtitle1Text setFontSize:30];

    [subtitle1Text setString:question];

    [subtitle1Text setAlignmentMode:kCAAlignmentCenter];

[subtitle1Text setForegroundColor:[[UIColorwhiteColor]CGColor]];

subtitle1Text.masksToBounds =YES;

subtitle1Text.cornerRadius =23.0f;

[subtitle1Text setBackgroundColor:[UIColorcolorWithRed:0green:0blue:0alpha:0.5].CGColor];

CGSizetextSize = [question sizeWithAttributes:[NSDictionarydictionaryWithObjectsAndKeys:font,NSFontAttributeName,nil]];

[subtitle1Text setFrame:CGRectMake(50,100, textSize.width+20, textSize.height+10)];

 

//水印

CALayer*imgLayer = [CALayerlayer];

imgLayer.contents = (id)img.CGImage;

//    imgLayer.bounds = CGRectMake(0, 0, size.width, size.height);

imgLayer.bounds =CGRectMake(0,0,210,50);

imgLayer.position =CGPointMake(size.width/2.0, size.height/2.0);

 

//第二个水印

CALayer*coverImgLayer = [CALayerlayer];

coverImgLayer.contents = (id)coverImg.CGImage;

//    [coverImgLayer setContentsGravity:@"resizeAspect"];

coverImgLayer.bounds =CGRectMake(50,200,210,50);

coverImgLayer.position =CGPointMake(size.width/4.0, size.height/4.0);

 

// 2 - The usual overlay

CALayer*overlayLayer = [CALayerlayer];

    [overlayLayer addSublayer:subtitle1Text];

    [overlayLayer addSublayer:imgLayer];

overlayLayer.frame =CGRectMake(0,0, size.width, size.height);

[overlayLayer setMasksToBounds:YES];

 

CALayer*parentLayer = [CALayerlayer];

CALayer*videoLayer = [CALayerlayer];

parentLayer.frame =CGRectMake(0,0, size.width, size.height);

videoLayer.frame =CGRectMake(0,0, size.width, size.height);

    [parentLayer addSublayer:videoLayer];

    [parentLayer addSublayer:overlayLayer];

    [parentLayer addSublayer:coverImgLayer];

 

//设置封面

CABasicAnimation*anima = [CABasicAnimationanimationWithKeyPath:@"opacity"];

anima.fromValue = [NSNumbernumberWithFloat:1.0f];

anima.toValue = [NSNumbernumberWithFloat:0.0f];

anima.repeatCount =0;

anima.duration =5.0f;//5s之后消失

[anima setRemovedOnCompletion:NO];

    [anima setFillMode:kCAFillModeForwards];

anima.beginTime =AVCoreAnimationBeginTimeAtZero;

[coverImgLayer addAnimation:anima forKey:@"opacityAniamtion"];

 

composition.animationTool = [AVVideoCompositionCoreAnimationTool

                                videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

 

}

//添加水印

- (void)applyVideoEffectsToComposition:(AVMutableVideoComposition*)composition WithWaterImg:(UIImage*)img  WithInfoDic:(NSDictionary*)infoDic  size:(CGSize)size {

 

CGFloatfontSize =46.0;

CGFloatleftLength =60;

UIFont*font = [UIFontsystemFontOfSize:fontSize];

CATextLayer*nameText = [[CATextLayeralloc] init];

    [nameText setFontSize:fontSize];

[nameText setString:[infoDic objectForKey:@"name"]];

    [nameText setAlignmentMode:kCAAlignmentLeft];

[nameText setForegroundColor:[[UIColorwhiteColor]CGColor]];

CGSizetextSize = [[infoDic objectForKey:@"name"] sizeWithAttributes:[NSDictionarydictionaryWithObjectsAndKeys:font,NSFontAttributeName,nil]];

[nameText setFrame:CGRectMake(leftLength, size.height/2.0+textSize.height/2.0+(28+textSize.height)*2, textSize.width+10, textSize.height+10)];

 

CATextLayer*shengaoText = [[CATextLayeralloc] init];

    [shengaoText setFontSize:fontSize];

NSString*text3 =  [NSStringstringWithFormat:@"%@cm",[infoDic objectForKey:@"shengao"]];

    [shengaoText setString:text3];

    [shengaoText setAlignmentMode:kCAAlignmentLeft];

[shengaoText setForegroundColor:[[UIColorwhiteColor]CGColor]];

CGSizetextSize3 = [text3 sizeWithAttributes:[NSDictionarydictionaryWithObjectsAndKeys:font,NSFontAttributeName,nil]];

[shengaoText setFrame:CGRectMake(leftLength, size.height/2.0+textSize3.height/2.0+28+textSize3.height, textSize3.width+10, textSize3.height+10)];

CATextLayer*tizhongText = [[CATextLayeralloc] init];

    [tizhongText setFontSize:fontSize];

NSString*text2 =  [NSStringstringWithFormat:@"%@kg",[infoDic objectForKey:@"tizhong"]];

    [tizhongText setString:text2];

    [tizhongText setAlignmentMode:kCAAlignmentLeft];

[tizhongText setForegroundColor:[[UIColorwhiteColor]CGColor]];

CGSizetextSize2 = [text2 sizeWithAttributes:[NSDictionarydictionaryWithObjectsAndKeys:font,NSFontAttributeName,nil]];

[tizhongText setFrame:CGRectMake(leftLength, size.height/2.0+textSize2.height/2.0, textSize2.width+10, textSize2.height+10)];

 

CATextLayer*sanText = [[CATextLayeralloc] init];

    [sanText setFontSize:fontSize];

NSString*text4 =  [NSStringstringWithFormat:@"%@-%@-%@",[infoDic objectForKey:@"xiongwei"],[infoDic objectForKey:@"yaowei"],[infoDic objectForKey:@"tunwei"]];

    [sanText setString:text4];

    [sanText setAlignmentMode:kCAAlignmentLeft];

[sanText setForegroundColor:[[UIColorwhiteColor]CGColor]];

CGSizetextSize4 = [text4 sizeWithAttributes:[NSDictionarydictionaryWithObjectsAndKeys:font,NSFontAttributeName,nil]];

[sanText setFrame:CGRectMake(leftLength, size.height/2.0-textSize4.height/2.0-28, textSize4.width+10, textSize4.height+10)];

CATextLayer*xiemaText = [[CATextLayeralloc] init];

    [xiemaText setFontSize:fontSize];

NSString*text5 =  [NSStringstringWithFormat:@"%@",[infoDic objectForKey:@"xiema"]];

    [xiemaText setString:text5];

    [xiemaText setAlignmentMode:kCAAlignmentLeft];

[xiemaText setForegroundColor:[[UIColorwhiteColor]CGColor]];

CGSizetextSize5 = [text5 sizeWithAttributes:[NSDictionarydictionaryWithObjectsAndKeys:font,NSFontAttributeName,nil]];

[xiemaText setFrame:CGRectMake(leftLength, size.height/2.0-textSize4.height/2.0-28-textSize4.height-28, textSize5.width+10, textSize5.height+10)];

//水印

CALayer*imgLayer = [CALayerlayer];

imgLayer.contents = (id)img.CGImage;

imgLayer.bounds =CGRectMake(0,0, img.size.width, img.size.height);

imgLayer.position =CGPointMake(size.width - img.size.width, img.size.height+10);

 

// 2 - The usual overlay

CALayer*overlayLayer = [CALayerlayer];

    [overlayLayer addSublayer:nameText];

    [overlayLayer addSublayer:shengaoText];

    [overlayLayer addSublayer:tizhongText];

    [overlayLayer addSublayer:sanText];

    [overlayLayer addSublayer:xiemaText];

    [overlayLayer addSublayer:imgLayer];

overlayLayer.frame =CGRectMake(0,0, size.width, size.height);

 

CALayer*parentLayer = [CALayerlayer];

CALayer*videoLayer = [CALayerlayer];

parentLayer.frame =CGRectMake(0,0, size.width, size.height);

videoLayer.frame =CGRectMake(0,0, size.width, size.height);

    [parentLayer addSublayer:videoLayer];

    [parentLayer addSublayer:overlayLayer];

 

//设置动画

CABasicAnimation*anima = [CABasicAnimationanimationWithKeyPath:@"opacity"];

anima.fromValue = [NSNumbernumberWithFloat:0.0f];

anima.toValue = [NSNumbernumberWithFloat:1.0f];

anima.repeatCount =0;

anima.duration =3.0f;//5s之后消失

[anima setRemovedOnCompletion:NO];

    [anima setFillMode:kCAFillModeForwards];

anima.beginTime =AVCoreAnimationBeginTimeAtZero;

[overlayLayer addAnimation:anima forKey:@"opacityAniamtion"];

 

composition.animationTool = [AVVideoCompositionCoreAnimationTool

                                videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

 

}

//保存视频到相册

- (void)exportDidFinish:(AVAssetExportSession*)session {

if(session.status ==AVAssetExportSessionStatusCompleted) {

NSURL*outputURL = session.outputURL;

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

            __block PHObjectPlaceholder *placeholder;

if(UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(outputURL.path)) {

NSError*error;

                [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{

                    PHAssetChangeRequest* createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:outputURL];

                    placeholder = [createAssetRequest placeholderForCreatedAsset];

                } error:&error];

if(error) {

//[SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"%@",error]];

                }

else{

//[SVProgressHUD showSuccessWithStatus:@"视频已经保存到相册"];

                }

}else{

//[SVProgressHUD showErrorWithStatus:NSLocalizedString(@"视频保存相册失败,请设置软件读取相册权限", nil)];

            }

        });

    }

}

//视频合成,添加背景音乐

-(void)addFirstVideo:(NSURL*)firstVideoPath andSecondVideo:(NSURL*)secondVideo withMusic:(NSURL*)musicPath completion:(void(^)(NSURL*outputURL,BOOLisSuccess))completionHandle{

 

AVAsset*firstAsset = [AVAssetassetWithURL:firstVideoPath];

AVAsset*secondAsset = [AVAssetassetWithURL:secondVideo];

AVAsset*musciAsset = [AVAssetassetWithURL:musicPath];

 

// 1 - Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.

AVMutableComposition*mixComposition = [[AVMutableCompositionalloc] init];

// 2 - Video track

AVMutableCompositionTrack*firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo

                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];

[firstTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, firstAsset.duration)

ofTrack:[[firstAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];

[firstTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, secondAsset.duration)

ofTrack:[[secondAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:firstAsset.duration error:nil];

 

 

if(musciAsset!=nil){//添加背景音乐

AVMutableCompositionTrack*AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio

                                                                            preferredTrackID:kCMPersistentTrackID_Invalid];

[AudioTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero,CMTimeAdd(firstAsset.duration, secondAsset.duration))

ofTrack:[[musciAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];

}else{//不添加背景音乐

#pragma注意这里需要加上音频轨道信息,否则合成的视频没有声音

//添加 by yang

AVMutableCompositionTrack*AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio

                                                                            preferredTrackID:kCMPersistentTrackID_Invalid];

[AudioTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, firstAsset.duration)

ofTrack:[[firstAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];

[AudioTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, secondAsset.duration)

ofTrack:[[secondAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:firstAsset.duration error:nil];

    }

 

 

// 4 - Get path

NSArray*paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);

NSString*documentsDirectory = [paths objectAtIndex:0];

NSString*myPathDocs =  [documentsDirectory stringByAppendingPathComponent:

[NSStringstringWithFormat:@"mergeVideo-%d.mov",arc4random() %1000]];

//    NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:

//                            [NSString stringWithFormat:@"%@.mov",@"combinVideo"]];

//如果文件已经存在,先移除,否则会报无法存储的错误

NSFileManager*manager = [NSFileManagerdefaultManager];

[manager removeItemAtPath:myPathDocs error:nil];

 

NSURL*videoUrl = [NSURLfileURLWithPath:myPathDocs];

 

// 5 - Create exporter

exporter = [[AVAssetExportSessionalloc] initWithAsset:mixComposition

presetName:AVAssetExportPresetHighestQuality];

    exporter.outputURL=videoUrl;

exporter.outputFileType =AVFileTypeQuickTimeMovie;

exporter.shouldOptimizeForNetworkUse =YES;

    [exporter exportAsynchronouslyWithCompletionHandler:^{

//        dispatch_async(dispatch_get_main_queue(), ^{

//            [self exportDidFinish:exporter];

//        });

switch([exporter status]) {

caseAVAssetExportSessionStatusFailed:

            {

NSLog(@"视频拼接失败:%@", [[exporter error] description]);

completionHandle(videoUrl,NO);

            }

break;

caseAVAssetExportSessionStatusCancelled:

            {

completionHandle(videoUrl,NO);

            }

break;

caseAVAssetExportSessionStatusCompleted:

            {

//成功

NSLog(@"视频拼接成功");

completionHandle(videoUrl,YES);

 

            }

break;

default:

            {

completionHandle(videoUrl,NO);

}break;

        }

    }];

}

//视频裁剪

- (void)cropWithVideoUrlStr:(NSURL*)videoUrl start:(CGFloat)startTime end:(CGFloat)endTime completion:(void(^)(NSURL*outputURL, Float64 videoDuration,BOOLisSuccess))completionHandle

{

AVURLAsset*asset =[[AVURLAssetalloc] initWithURL:videoUrl options:nil];

 

//获取视频总时长

Float64 duration =CMTimeGetSeconds(asset.duration);

 

//NSString *outputPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"dafei.mov"];

NSArray*paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);

NSString*documentsDirectory = [paths objectAtIndex:0];

 

NSString*outputPath =  [documentsDirectory stringByAppendingPathComponent:

[NSStringstringWithFormat:@"dafei-%d.mov",arc4random() %1000]];

 

NSURL*outputURL = [NSURLfileURLWithPath:outputPath];

 

//如果文件已经存在,先移除,否则会报无法存储的错误

NSFileManager*manager = [NSFileManagerdefaultManager];

[manager removeItemAtPath:outputPath error:nil];

 

NSArray*compatiblePresets = [AVAssetExportSessionexportPresetsCompatibleWithAsset:asset];

if([compatiblePresets containsObject:AVAssetExportPresetMediumQuality])

    {

 

AVAssetExportSession*exportSession = [[AVAssetExportSessionalloc]

initWithAsset:asset presetName:AVAssetExportPresetPassthrough];

 

        exportSession.outputURL =  outputURL;

//视频文件的类型

exportSession.outputFileType =AVFileTypeQuickTimeMovie;

//输出文件是否网络优化

exportSession.shouldOptimizeForNetworkUse =YES;

 

//要截取的开始时间

CMTimestart =CMTimeMakeWithSeconds(startTime, asset.duration.timescale);

//要截取的总时长

CMTimeduration =CMTimeMakeWithSeconds(endTime - startTime,asset.duration.timescale);

CMTimeRangerange =CMTimeRangeMake(start, duration);

        exportSession.timeRange = range;

 

        [exportSession exportAsynchronouslyWithCompletionHandler:^{

switch([exportSession status]) {

caseAVAssetExportSessionStatusFailed:

                {

NSLog(@"合成失败:%@", [[exportSession error] description]);

completionHandle(outputURL, endTime,NO);

                }

break;

caseAVAssetExportSessionStatusCancelled:

                {

completionHandle(outputURL, endTime,NO);

                }

break;

caseAVAssetExportSessionStatusCompleted:

                {

//成功

completionHandle(outputURL, endTime,YES);

 

                }

break;

default:

                {

completionHandle(outputURL, endTime,NO);

}break;

            }

        }];

    }

}

//展示进度

- (void)updateProgress{

 

}

 

本文地址:https://blog.csdn.net/qq_21743659/article/details/110126216

相关标签: iso ios