2013-03-26 68 views
10

Moim celem jest skomponowanie zestawu klipów nagranych z kamery i wyeksportowanie ich w określonym preferowanym rozmiarze. Oczywiście przed eksportowaniem należy obrócić orientację wideo.Transformacja nie działa w AVMutableVideoComposition podczas eksportowania

Robię to poprzez komponowanie AVMutableComposition z tablicy klipów wideo, przechowywanych w avAssets poniżej. Mogę je skomponować dobrze i wyeksportować. Jednak przekształcenie rotacji, które ustawiam w AVMutableVideoComposition, nie jest honorowane. Jeśli użyję tej samej transformacji i ustawię ją na właściwości preferredTransform ścieżki wideo, to działa. W obu przypadkach wideo rendering nie jest honorowany. To tak, jakby eksporter całkowicie zignorował wideoComposition. Jakieś pomysły, co może się wydarzyć?

Mam uruchomioną sesję AVCaptureSession, ale wyłączyłem ją przed eksportowaniem i nie miało to żadnego znaczenia. Jestem całkiem nowy w programowaniu na iOS, więc może to być coś, co nie ma podstaw. :)

Mój kod:

-(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"); 
    } 
}]; 

} 

Odpowiedz

9

Ok zorientowaliśmy się, zamieszczanie tutaj, aby pomagać innym ludziom nie tracić czasu, że ja.

Problem polega na tym, że jeśli używasz AVAssetExportPresetPassthrough na AVExportSession, eksporter zignoruje instrukcje dotyczące kompozycji wideo. Spodziewałem się, że przynajmniej uhonoruje instrukcje dotyczące kompozycji wideo podczas przechodzenia przez format itp., Ale najwyraźniej to nie działa. Po tym, jak wypełniłem błąd w dokumentacji, można go znaleźć w Technical Q&A.

+4

Jakie było rozwiązanie? – jpswain

+1

jak to rozwiązałeś? – MAMN84

+0

Aby rozwiązać ten problem, użyj innego ustawienia niż AVAssetExportPresetPassthrough, które ma sens w przypadku Twojej aplikacji. – BooTooMany