iOS|iOS 视频编辑之视频拼接

原理及步骤:
1、新建一个视频的框架
2、往框架里面添加一条音频轨道和视频轨道
3、把需要拼接的视频片段循环读取出视频和音频部分,并依次插入对应轨道
4、导出视频
代码:

- (void)finalMergeAndExportVideos:(NSArray*)videosPathArray withOutPath:(NSString*)outpath success:(void (^)(void))successBlock{if (videosPathArray.count == 0) {return; }AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init]; AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudiopreferredTrackID:kCMPersistentTrackID_Invalid]; AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideopreferredTrackID:kCMPersistentTrackID_Invalid]; CMTime totalDuration = kCMTimeZero; //用来计算视频大小(不需要可以删掉) CGFloat length = 0; for (int i = 0; i < videosPathArray.count; i++) {AVURLAsset *asset = [AVURLAsset assetWithURL:videosPathArray[i]]; NSError *erroraudio = nil; AVAssetTrack *assetAudioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] firstObject]; [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)ofTrack:assetAudioTrackatTime:totalDurationerror:&erroraudio]; NSError *errorVideo = nil; AVAssetTrack *assetVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo]firstObject]; [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)ofTrack:assetVideoTrackatTime:totalDurationerror:&errorVideo]; //合成的视频方向设置成第一个视频的方向 (不需要可以直接删掉)if (i==0 ) {[videoTrack setPreferredTransform:[MediaManager ssfixedCompositionWithAsset:asset]]; }totalDuration = CMTimeAdd(totalDuration, asset.duration); length +=[NSData dataWithContentsOfFile:self.marr_movies[i]].length/1000000.0; NSLog(@"lenght =============%f", length); }NSString * name = AVAssetExportPresetPassthrough; //视频如果大于5M就压缩(不需要可以删掉) if (length > 5) { name = AVAssetExportPresetMediumQuality; }NSURL *mergeFileURL = [NSURL fileURLWithPath:outpath]; AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixCompositionpresetName:name]; exporter.outputURL = mergeFileURL; exporter.outputFileType = AVFileTypeMPEG4; exporter.shouldOptimizeForNetworkUse = YES; [exporter exportAsynchronouslyWithCompletionHandler:^{if( exporter.status == AVAssetExportSessionStatusCompleted ){//UISaveVideoAtPathToSavedPhotosAlbum(outpath, nil, nil, nil); successBlock(); }else if( exporter.status == AVAssetExportSessionStatusFailed ) { } }]; }

【iOS|iOS 视频编辑之视频拼接】PS:
1、videosPathArray为本地视频片段url的数组:[NSURL fileURLWithPath:path],注意别写成了URLWithString
2、里面有视频方向设置,以后有时间再单独写出来 (方法如下)
// 获取优化后的视频转向信息 + (CGAffineTransform)ssfixedCompositionWithAsset:(AVAsset *)videoAsset { // 视频转向 int degrees = [self degressFromVideoFileWithAsset:videoAsset]; CGAffineTransform translateToCenter; CGAffineTransform mixedTransform; NSArray *tracks = [videoAsset tracksWithMediaType:AVMediaTypeVideo]; AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; if (degrees == 90) { // 顺时针旋转90° translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.height, 0.0); mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2); } else if(degrees == 180){ // 顺时针旋转180° translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.width, videoTrack.naturalSize.height); mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI); } elseif(degrees == 270){ // 顺时针旋转270° translateToCenter = CGAffineTransformMakeTranslation(0.0, videoTrack.naturalSize.width); mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2*3.0); }else{ translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.height, 0.0); mixedTransform = CGAffineTransformRotate(translateToCenter,0); }return mixedTransform; }// 获取视频角度 + (int)degressFromVideoFileWithAsset:(AVAsset *)asset { int degress = 0; NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo]; if([tracks count] > 0) { AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; CGAffineTransform t = videoTrack.preferredTransform; if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){ // Portrait degress = 90; } else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){ // PortraitUpsideDown degress = 270; } else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){ // LandscapeRight degress = 0; } else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){ // LandscapeLeft degress = 180; } } return degress; }

    推荐阅读