利用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{

}

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

  1. java 视频添加音乐_视频编辑时如何添加背景音乐?具体教程?

    最近好多朋友才开始接触视频编辑软件,在学习的过程中,发现自己制作视频时好多方法都弄不明白,在制作视频时,想要给平淡无奇的视频添加一段自己喜欢的音乐,但是不知道具体用什么方法,小编就为大家带来视频编辑时 ...

  2. foobar2000 ios版怎么添加音乐_抖音怎么设置说完话后再放音乐 视频先配音后半段添加背景音乐...

    看到一个段子,双十一最该打折的是什么,答:双手.哈哈,昨天双十一购物狂欢,看到消息说双11当天全国处理亿快件,再创历史新高,也是辛苦各位快递员了.好啦,回归主题,继续给大家带来视频编辑教程.网上有很多 ...

  3. 手把手教你如何给视频快速消音并添加背景音乐

    如果我们想要把视频文件批量地添加自己喜欢的解说或者背景音乐的话,需要怎么操作呢?其实方法并不难,感兴趣的小伙伴们跟我一起来看看具体的操作方法和步骤吧. 一.我们需要先在"固乔科技" ...

  4. [Python MoviePy 音视频开发零基础到实战] 一、用6条代码为你的视频裁剪以及添加水印

    一.MoviePy 安装及配置 在 Python 有一个音视频开发模块 MoviePy,MoviePy 依赖于 FFmepg,使用 MoviePy 可以对音视频进行编辑:例如视频合成.视频处理.视频特 ...

  5. iOS视频裁剪小工具——VideoTailor

    最近在写swift,顺便写个小工具练练手.VideoTailor是对AVFoundation框架的封装,可以方便的裁剪视频区域以及时长,并允许指定输出视频的码率等参数. 0x00 如何使用 Video ...

  6. php封装多段mp4,解决ffmpeg将多段视频裁剪拼接后卡顿现象

    合并 将下载的ts流名称按照顺序记录在一个txt文件中,然后使用命令 ffmpeg.exe -f concat -i ./your.txt -c copy ./output.mkv ffmpeg.ex ...

  7. IOS视频编辑功能详解上篇-添加水印

    前言 用代码在简单视频编辑中,主要就是加美颜.水印(贴图).视频截取.视频拼接.音视频的处理,在美颜中,使用GPUImage即可实现多种滤镜.磨皮美颜的功能,并且可以脸部识别实时美颜等功能,这个有很多 ...

  8. IOS视频编辑,视频美颜,视频添加水印

    前言 用代码在简单视频编辑中,主要就是加美颜.水印(贴图).视频截取.视频拼接.音视频的处理,在美颜中,使用GPUImage即可实现多种滤镜.磨皮美颜的功能,并且可以脸部识别实时美颜等功能,这个有很多 ...

  9. IOS视频编辑,视频裁剪,视频拼接,音频处理,视频处理

    前言 用代码在简单视频编辑中,主要就是加美颜.水印(贴图).视频截取.视频拼接.音视频的处理,在美颜中,使用GPUImage即可实现多种滤镜.磨皮美颜的功能,并且可以脸部识别实时美颜等功能,这个有很多 ...

  10. IOS视频编辑功能详解下篇-视频裁剪、视频拼接、音视频的处理

    转自:http://www.hudongdong.com/ios/550.html 前言 用代码在简单视频编辑中,主要就是加美颜.水印(贴图).视频截取.视频拼接.音视频的处理,在美颜中,使用GPUI ...

最新文章

  1. java stream 转 file_java 中 byte[]、File、InputStream 互相转换
  2. nanomsg:ZeroMQ作者用C语言新写的消息队列库
  3. 探秘Hadoop生态12:分布式日志收集系统Flume
  4. mysql修改的值子查询语句_MySQL的SQL语句 - 数据操作语句(13)- 子查询(13)
  5. 二元函数泰勒公式例题_考研.泰勒公式的理解与运用.一次全懂
  6. Android性能专项测试之Systrace工具
  7. web项目移动端在线预览(excel在线预览)
  8. vivado simulation仿真(38译码器实现)
  9. 工程量计算专用工具-支持灌注桩、搅拌桩、格构柱
  10. X200 BIOS 黑屏
  11. office转pdf(在线预览)思路(java示例)
  12. 马云的电影,丁磊的饭局
  13. 运用腾讯云实现QQ语音通话
  14. 康考迪亚大学 计算机科学,康考迪亚大学 Concordia University
  15. TIM腾讯聊天(即时通信 IM)(咨询客服业务)
  16. 浩方cs全是虚拟服务器,在浩方里面的CS1.5 如何建立服务器
  17. pygame实现雷电游戏雏形开发
  18. PointCNN 论文阅读笔记
  19. 【容斥】[ZJOI2016] 小星星
  20. 进入BIOS+制作u盘启动盘+将u盘启动盘设置为开机首选方法

热门文章

  1. 记静下心来从头学习PLC编程以及用C#开发OPC client 与PLC 交互
  2. 极速PDF编辑器提示缺少字体如何解决
  3. unity2021游戏引擎安装激活并汉化
  4. Unity怎么变中文
  5. 【九天教您南方cass 9.1】 09 提取坐标的几种方法
  6. android网页生成pdf,Android生成pdf
  7. 高校后勤管理系统Java项目-基于SSM
  8. 基于springboot的医院门诊管理系统
  9. 微计算机最常用的输入法,输入无极限 最常用五款拼音输入法横评
  10. XAP部署错误代码大全