2010-11-13 9 views
7

Pobiegam kilka klipów wideo nakręconych na iPhone'a w trybie portretu. Aby zmontować je Biorę proste podejście następująco:Jak kontrolować orientację wideo zmontowanego z AVMutableComposition

AVURLAsset zdobyć z różnych filmów następnie popychając je w na AVMutableCompositionTrack a potem to ująć w AVMutableComposition który mam wywozu do pliku z AVAssetExportSession

My Problem polega na tym, że kiedy przychodzę do wyświetlania wideo w UIWebView, pojawia się w trybie poziomym. Jeśli jednak zobaczę dowolny widok komponentu, będą one wyświetlane w widoku pionowym. Czy ktoś wie, jak uporządkować orientację? Próbowałem się bawić z AVMutableComposition naturalSize zmieniając szerokość i wysokość wokół, ale to właśnie sprawiło, że moi ludzie wyglądali na krótko i grubo! (Podczas gdy na ich stronie)

Dzięki z góry za wszelkie myśli/sugestie

Tudorów

+0

ktoś wie nawet, jak oryginalna orientacja jest przechowywane? – Tudor

+0

Istnieje własność originalTransform na torze zasobów, które można ustawić w pewnych okolicznościach. – Hunter

Odpowiedz

11

Konfiguracja kompozycja wideo, które zajmują się obracać + skalę:

AVMutableVideoComposition* videoComposition = [[AVMutableVideoComposition videoComposition]retain]; 
videoComposition.renderSize = CGSizeMake(320, 240); 
videoComposition.frameDuration = CMTimeMake(1, 30); 

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30)); 

AVMutableVideoCompositionLayerInstruction* rotator = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]]; 
CGAffineTransform translateToCenter = CGAffineTransformMakeTranslation(0,-320);  
CGAffineTransform rotateBy90Degrees = CGAffineTransformMakeRotation(M_PI_2); 
CGAffineTransform shrinkWidth = CGAffineTransformMakeScale(0.66, 1); // needed because Apple does a "stretch" by default - really, we should find and undo apple's stretch - I suspect it'll be a CALayer defaultTransform, or UIView property causing this 
CGAffineTransform finalTransform = CGAffineTransformConcat(shrinkWidth, CGAffineTransformConcat(translateToCenter, rotateBy90Degrees)); 
[rotator setTransform:finalTransform atTime:kCMTimeZero]; 

instruction.layerInstructions = [NSArray arrayWithObject: rotator]; 
videoComposition.instructions = [NSArray arrayWithObject: instruction]; 
+0

Jeśli korzystasz z kamery skierowanej do przodu, będziesz również chciał wymyślić kolejną transformację do odbicia lustrzanego wideo, tak jak ma to miejsce w przypadku wbudowanej aplikacji aparatu fotograficznego. – Hunter

+0

jaki typ klasy to "transformator"? –

+0

przepraszam - skopiuj/wklej błąd. Ta linia była niepotrzebna (teraz usunięta). – Adam

9

Oto niektóre kod, który regulowany obrót przy użyciu korzystnej transformacji:

// our composition, with one video and one audio track 
AVMutableComposition* composition = [AVMutableComposition composition]; 
AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 

// loop through all the clips, adding them to our track and inserting composition instructions 
NSDictionary* options = @{ AVURLAssetPreferPreciseDurationAndTimingKey: @YES }; 
CMTime insertionPoint = kCMTimeZero; 
NSMutableArray* instructions = [NSMutableArray array]; 
NSError* error = nil; 
for (NSURL* outputFileURL in self.movieFileURLs) { 
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:outputFileURL options:options]; 

    // insert this clip's video track into our composition 
    NSArray *videoAssetTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; 
    AVAssetTrack *videoAssetTrack = (videoAssetTracks.count > 0 ? [videoAssetTracks objectAtIndex:0] : nil); 
    [videoTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, asset.duration) ofTrack:videoAssetTrack atTime:insertionPoint error:&error]; 

    // create a layer instruction at the start of this clip to apply the preferred transform to correct orientation issues 
    AVMutableVideoCompositionLayerInstruction *instruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoAssetTrack]; 
    [instruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero]; 

    // create the composition instructions for the range of this clip 
    AVMutableVideoCompositionInstruction * videoTrackInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
    videoTrackInstruction.timeRange = CMTimeRangeMake(insertionPoint, asset.duration); 
    videoTrackInstruction.layerInstructions = @[instruction]; 
    [instructions addObject:videoTrackInstruction]; 

    // insert this clip's audio track into our composition 
    NSArray *audioAssetTracks = [asset tracksWithMediaType:AVMediaTypeAudio]; 
    AVAssetTrack *audioAssetTrack = (audioAssetTracks.count > 0 ? [audioAssetTracks objectAtIndex:0] : nil); 
    [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:audioAssetTrack atTime:insertionPoint error:nil]; 

    // advance the insertion point to the end of the clip 
    insertionPoint = CMTimeAdd(insertionPoint, asset.duration); 
} 

// create our video composition which will be assigned to the player item 
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 
videoComposition.instructions = instructions; 
videoComposition.frameDuration = CMTimeMake(1, videoTrack.naturalTimeScale); 
videoComposition.renderSize = videoTrack.naturalSize; 
_videoComposition = videoComposition; 
+1

Próbowałem użyć tego fragmentu kodu w mojej aplikacji, w której łączę niektóre klipy wideo w jeden film i eksportuję go za pomocą 'AVAssetExportSession'. Jednak pojawia się błąd, gdy ustawię właściwość 'videoComposition' parametru' AVAssetExportSession' na moje wystąpienie 'AVMutableVideoComposition'. Czy wiesz, jak użyć swojego kodu podczas eksportowania filmu? Stworzyłem tu pytanie, a jeśli masz czas, czy możesz go obejrzeć? http://stackoverflow.com/questions/16385017/error-when-using-avassetexportsession-w-video-composition-set – simonbs

+0

@imonbs byłeś w stanie go uruchomić działa? –

11

Jeśli wszystkie chcesz, to cię zachować orientację wideo może chcesz przypisać wartość AVMutableCompositionTrack prefferedTransition z AVAssetTrack tak:

AVAssetTrack *videoAssetTrack= [[videoAsset tracksWithMediaType:AVMediaTypeVideo] lastObject]; 

AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
[videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:videoAssetTrack atTime:kCMTimeZero error:&error]; 

videoCompositionTrack.preferredTransform = videoAssetTrack.preferredTransform; 
+0

To najwygodniejszy sposób. Dzięki! – AlexeyVMP

+2

To nie wygląda na to, że działa, jeśli kompozycja zawiera utwory o różnych orientacjach ... –

+0

Ponieważ jest brany pod uwagę tylko obiekt lastObject. To jest uproszczenie problemu, a nie rozwiązanie dla wszystkich przypadków. – Marcin