2010-11-13 3 views
7

Ich stelle eine Reihe von Videoclips zusammen, die auf dem iPhone im Hochformat aufgenommen wurden. Zur Montage ihnen, dass ich geradliniger Ansatz nehme wie folgt:Wie steuere ich die Ausrichtung des mit AVMutableComposition erstellten Videos?

AVURLAsset halten, die verschiedenen Videos zu bekommen diese dann in einem AVMutableCompositionTrack schubsen und dann diese in eine AVMutableComposition setzen, die ich den Export mit AVAssetExportSession

Datei My Problem ist, dass wenn ich komme, um das Video in einem UIWebView anzuzeigen, erscheint es im Querformatmodus. Wenn ich jedoch eine der Komponentenansichten betrachte, erscheinen sie in der Hochformatansicht. Kann jemand die Orientierung sortieren? Ich habe versucht, mit der AVMutableComposition naturalSize herumzuspielen, indem ich die Breite und Höhe verändert habe, aber das hat meine Leute nur kurz und fett aussehen lassen! (Während auf ihrer Seite)

Vielen Dank im Voraus für alle Gedanken/Vorschläge

Tudor

+0

jemand einmal wissen, wie ursprüngliche Ausrichtung gespeichert? – Tudor

+0

Es gibt eine originalTransform -Eigenschaft auf der Asset-Spur, die Sie abfragen können und die unter bestimmten Umständen festgelegt ist. – Hunter

Antwort

11

Einrichtung einer Videokomposition, die + Skala drehen Griff:

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

Wenn Sie die Frontkamera verwenden, sollten Sie auch eine andere Transformation durchführen, um das Video zu spiegeln, wie es bei der integrierten Kamera-App der Fall ist. – Hunter

+0

Welcher Klassentyp ist "Transformator"? –

+0

Entschuldigung - Fehler beim Kopieren/Einfügen. Diese Zeile war unnötig (jetzt gelöscht) – Adam

9

Hier einige Code, der angepasst die Drehung unter Verwendung der bevorzugten Transformation:

// 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

Ich habe versucht, dieses Code-Snippet in meiner Anwendung zu verwenden, wo ich einige Videoclips in ein Video zusammenführe und es mit 'AVAssetExportSession' exportiere. Allerdings bekomme ich einen Fehler, wenn ich die Eigenschaft 'videoComposition' der' AVAssetExportSession' auf meine Instanz von 'AVMutableVideoComposition' setze. Weißt du, wie du deinen Code beim Exportieren des Films verwendest? Ich habe hier eine Frage gestellt und wenn Sie Zeit haben, sehen Sie sich das bitte an? http://stackoverflow.com/questions/16385017/error-when-using-avassexportsession-with-video-composition-set – simonbs

+0

@simonbs konnten Sie es zum Funktionieren bringen? –

11

Wenn alles Sie wollen, ist Sie Video Orientierung erhalten Sie möglicherweise AVMutableCompositionTrack prefferedTransition Wert von AVAssetTrack wie folgt vergeben:

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

Dies ist der bequemste Weg. Vielen Dank! – AlexeyVMP

+2

Das scheint nicht zu funktionieren, wenn die Komposition Spuren mit unterschiedlichen Ausrichtungen enthält ... –

+0

Weil nur lastObject berücksichtigt wird. Dies ist eine Vereinfachung des Problems und keine Lösung für alle Fälle. – Marcin