如何使用AVFoundation结合不同方向的video剪辑

我正在尝试将几个video剪辑合并为一个使用AVFoundation。 我可以使用下面的代码使用AVMutableComposition创build一个video

AVMutableComposition *composition = [AVMutableComposition composition]; AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; CMTime startTime = kCMTimeZero; /*videoClipPaths is a array of paths of the video clips recorded*/ //for loop to combine clips into a single video for (NSInteger i=0; i < [videoClipPaths count]; i++) { NSString *path = (NSString*)[videoClipPaths objectAtIndex:i]; NSURL *url = [[NSURL alloc] initFileURLWithPath:path]; AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil]; [url release]; AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; AVAssetTrack *audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; //set the orientation if(i == 0) { [compositionVideoTrack setPreferredTransform:videoTrack.preferredTransform]; } ok = [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration]) ofTrack:videoTrack atTime:startTime error:nil]; ok = [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration]) ofTrack:audioTrack atTime:startTime error:nil]; startTime = CMTimeAdd(startTime, [asset duration]); } //export the combined video NSString *combinedPath = /* path of the combined video*/; NSURL *url = [[NSURL alloc] initFileURLWithPath: combinedPath]; AVAssetExportSession *exporter = [[[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPreset640x480] autorelease]; exporter.outputURL = url; [url release]; exporter.outputFileType = [[exporter supportedFileTypes] objectAtIndex:0]; [exporter exportAsynchronouslyWithCompletionHandler:^(void){[self combineVideoFinished:exporter.outputURL status:exporter.status error:exporter.error];}]; 

如果所有video剪辑都以相同方向(纵向或横向)录制,上面的代码可以正常工作。 但是,如果我在剪辑中混合了方向,则最终的video会将其一部分向右(或向左)旋转90度。

我想知道是否有办法将所有剪辑转换为相同的方向(例如第一个剪辑的方向),同时组成它们。 从我从AVMutableVideoCompositionLayerInstruction看起来可以用来转换AVAsset ,但我不知道如何创build和应用几个不同的层指令到相应的剪辑,然后在组成( AVMutableComposition* )中使用,

任何帮助,将不胜感激!

这就是我所做的。 然后我使用AVAssetExportSession创build实际的文件。 但是我警告你,CGAffineTransforms有时会被应用得很晚,所以在video转换之前你会看到一到两个原始的。 我不知道为什么会发生这种情况,不同的video组合会产生预期的结果,但有时候会closures。

 AVMutableComposition *composition = [AVMutableComposition composition]; AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; videoComposition.frameDuration = CMTimeMake(1,30); videoComposition.renderScale = 1.0; AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack]; // Get only paths the user selected NSMutableArray *array = [NSMutableArray array]; for(NSString* string in videoPathArray){ if(![string isEqualToString:@""]){ [array addObject:string]; } self.videoPathArray = array; float time = 0; for (int i = 0; i<self.videoPathArray.count; i++) { AVURLAsset *sourceAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[videoPathArray objectAtIndex:i]] options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]]; NSError *error = nil; BOOL ok = NO; AVAssetTrack *sourceVideoTrack = [[sourceAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; CGSize temp = CGSizeApplyAffineTransform(sourceVideoTrack.naturalSize, sourceVideoTrack.preferredTransform); CGSize size = CGSizeMake(fabsf(temp.width), fabsf(temp.height)); CGAffineTransform transform = sourceVideoTrack.preferredTransform; videoComposition.renderSize = sourceVideoTrack.naturalSize; if (size.width > size.height) { [layerInstruction setTransform:transform atTime:CMTimeMakeWithSeconds(time, 30)]; } else { float s = size.width/size.height; CGAffineTransform new = CGAffineTransformConcat(transform, CGAffineTransformMakeScale(s,s)); float x = (size.height - size.width*s)/2; CGAffineTransform newer = CGAffineTransformConcat(new, CGAffineTransformMakeTranslation(x, 0)); [layerInstruction setTransform:newer atTime:CMTimeMakeWithSeconds(time, 30)]; } ok = [compositionVideoTrack insertTimeRange:sourceVideoTrack.timeRange ofTrack:sourceVideoTrack atTime:[composition duration] error:&error]; if (!ok) { // Deal with the error. NSLog(@"something went wrong"); } NSLog(@"\n source asset duration is %f \n source vid track timerange is %f %f \n composition duration is %f \n composition vid track time range is %f %f",CMTimeGetSeconds([sourceAsset duration]), CMTimeGetSeconds(sourceVideoTrack.timeRange.start),CMTimeGetSeconds(sourceVideoTrack.timeRange.duration),CMTimeGetSeconds([composition duration]), CMTimeGetSeconds(compositionVideoTrack.timeRange.start),CMTimeGetSeconds(compositionVideoTrack.timeRange.duration)); time += CMTimeGetSeconds(sourceVideoTrack.timeRange.duration); } instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction]; instruction.timeRange = compositionVideoTrack.timeRange; videoComposition.instructions = [NSArray arrayWithObject:instruction]; 

这就是我所做的。 然后我使用AVAssetExportSession创build实际的文件。 但是我警告你,CGAffineTransforms有时会被应用得很晚,所以在video转换之前你会看到一到两个原始的。 我不知道为什么会发生这种情况,不同的video组合会产生预期的结果,但有时候会closures。