2013-03-26 3 views
10

Моя цель - составить набор клипов, записанных с камеры, и экспортировать их с определенным предпочтительным размером. Конечно, перед экспортом ориентацию видео нужно поворачивать.Преобразование не работает в AVMutableVideoComposition при экспорте

Я делаю это, создавая AVMutableComposition из массива видеоклипов, хранящихся в avAssets ниже. Я могу составить их в порядке и экспортировать. Однако преобразование вращения, которое я устанавливаю на AVMutableVideoComposition, не соблюдается. Если я использую одно и то же преобразование и устанавливаю его на свойстве preferredTransform видеодорожки, он работает. В обоих случаях видео renderSize не выполняется. Это как если бы экспортер полностью игнорировал видеокомпозицию. Любые идеи, что может произойти?

У меня есть работа AVCaptureSession, но я отключил ее перед экспортом, и это не имело никакого значения. Я довольно новичок в программировании на iOS, так что может быть, я пропустил что-то основное. :)

Мой код:

-(void) finalRecord{ 
NSError *error = nil; 

AVMutableComposition *composition = [AVMutableComposition composition]; 

AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
NSLog(@"Video track id is %d", [compositionVideoTrack trackID]); 

AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 

// avAssets hold the video clips to be composited 
int pieces = [avAssets count]; 

CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_2); 
// [compositionVideoTrack setPreferredTransform:transform]; 

for (int i = 0; i<pieces; i++) { 

    AVURLAsset *sourceAsset = [avAssets objectAtIndex:i]; 

    AVAssetTrack *sourceVideoTrack = [[sourceAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    AVAssetTrack *sourceAudioTrack = [[sourceAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 

    [timeRanges addObject:[NSValue valueWithCMTimeRange:CMTimeRangeMake(kCMTimeZero, sourceAsset.duration)]]; 
    [videoTracks addObject:sourceVideoTrack]; 
    [audioTracks addObject:sourceAudioTrack]; 
} 

[compositionVideoTrack insertTimeRanges:timeRanges ofTracks:videoTracks atTime:kCMTimeZero error:&error]; 
[compositionAudioTrack insertTimeRanges:timeRanges ofTracks:audioTracks atTime:kCMTimeZero error:&error]; 

AVMutableVideoCompositionInstruction *vtemp = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
vtemp.timeRange = CMTimeRangeMake(kCMTimeZero, [composition duration]); 
NSLog(@"\nInstruction vtemp's time range is %f %f", CMTimeGetSeconds(vtemp.timeRange.start), 
     CMTimeGetSeconds(vtemp.timeRange.duration)); 

// Also tried videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack  
AVMutableVideoCompositionLayerInstruction *vLayerInstruction = [AVMutableVideoCompositionLayerInstruction 
                   videoCompositionLayerInstructionWithAssetTrack:composition.tracks[0]]; 
[vLayerInstruction setTransform:transform atTime:kCMTimeZero]; 
vtemp.layerInstructions = @[vLayerInstruction]; 

AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 
videoComposition.renderSize = CGSizeMake(320.0, 240.0); 
videoComposition.frameDuration = CMTimeMake(1,30); 

videoComposition.instructions = @[vtemp]; 

AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:composition presetName:gVideoExportQuality]; 

NSParameterAssert(exporter != nil); 
exporter.videoComposition = videoComposition; 
exporter.outputFileType = AVFileTypeQuickTimeMovie; 

NSString *rootName = [[self captureManager] tempFileRoot]; 

NSString *temp = [NSString stringWithFormat:@"%@%@.mov", NSTemporaryDirectory(), rootName]; 
exporter.outputURL = [NSURL fileURLWithPath:temp ]; 

[exporter exportAsynchronouslyWithCompletionHandler:^{ 
    switch ([exporter status]) { 
     case AVAssetExportSessionStatusFailed: 
      NSLog(@"Export failed: %@", [exporter error]); 
      break; 
     case AVAssetExportSessionStatusCancelled: 
      NSLog(@"Export canceled"); 
      break; 
     case AVAssetExportSessionStatusCompleted: 
      NSLog(@"Export successfully"); 
      [self exportFile:exporter.outputURL]; 
      [self.delegate recordingEndedWithFile:exporter.outputURL]; 
      isExporting = FALSE; 
      [[[self captureManager] session] startRunning]; 
      break; 
     default: 
      break; 
    } 
    if (exporter.status != AVAssetExportSessionStatusCompleted){ 
     NSLog(@"Retry export"); 
    } 
}]; 

} 

ответ

9

Хорошо понял это и размещение здесь, чтобы помочь другим людям не тратить время, что я сделал.

Проблема заключается в том, что если вы используете AVAssetExportPresetPassthrough на AVExportSession, то экспортер будет игнорировать инструкции по составлению видео. Я ожидал, что он, по крайней мере, будет соблюдать инструкции по составлению видео, проходя через формат и т. Д., Но, по-видимому, это не так, как это работает. После того как я заполнил ошибку документации, вы можете найти ее в Technical Q&A.

+4

Так каково было решение? – jpswain

+1

как вы его решили? – MAMN84

+0

Чтобы решить эту проблему, используйте другую настройку, отличную от AVAssetExportPresetPassthrough, которая имеет смысл для вашего приложения. – BooTooMany

Смежные вопросы