2010-11-13 8 views
7

Sto assemblando un gruppo di videoclip filmati su iPhone in modalità verticale. Per assemblare li sto prendendo approccio diretto come segue:come controllare l'orientamento del video assemblato con AVMutableComposition

AVURLAsset per entrare in possesso dei diversi video poi spintoni questi in un AVMutableCompositionTrack e poi mettere questo in un AVMutableComposition quale sto esportazione di file con AVAssetExportSession

mio il problema è che quando vengo a visualizzare il video in una UIWebView, appare in modalità orizzontale. Tuttavia, se visualizzo una delle viste componente che compaiono in vista verticale. Qualcuno sa come risolvere l'orientamento. Ho provato a fare confusione con AVMutableComposition naturalSize, modificando la larghezza e l'altezza, ma questo ha fatto sembrare la mia gente corta e grassa! (Mentre dalla loro parte)

Grazie in anticipo per eventuali pensieri/suggerimenti

Tudor

+0

chiunque nemmeno come originale orientamento è memorizzato? – Tudor

+0

C'è una proprietà originalTransform sulla traccia di asset che è possibile eseguire la query impostata in determinate circostanze. – Hunter

risposta

11

Setup una composizione video che gestirà ruotare + scala:

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

Se si utilizza la fotocamera frontale, è consigliabile creare un'altra trasformazione per specchiare il video, come fa l'app per fotocamera integrata. – Hunter

+0

quale tipo di classe è 'trasformatore'? –

+0

mi dispiace - copia/incolla errore. Quella linea era inutile (cancellata ora) – Adam

9

Ecco un po 'di codice che regolata la rotazione utilizzando la trasformazione preferita:

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

Ho cercato di utilizzare questo snippet di codice nella mia applicazione in cui unisco alcuni video clip in un video ed esportarlo usando 'AVAssetExportSession'. Tuttavia, ottengo un errore quando imposto la proprietà 'videoComposition' di' AVAssetExportSession' nella mia istanza di 'AVMutableVideoComposition'. Sai come usare il tuo codice quando esporti il ​​film? Ho creato una domanda qui e se hai tempo, vuoi darci un'occhiata? http://stackoverflow.com/questions/16385017/error-when-using-avassetexportsession-with-video-composition-set – simonbs

+0

@simonbs sei riuscito a farlo funzionare? –

11

Se tutto che vogliamo è preservare voi orientamento il video si può decidere di assegnare il valore AVMutableCompositionTrack prefferedTransition da AVAssetTrack come questo:

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

Questo è il modo più conveniente. Grazie! – AlexeyVMP

+2

Questo non sembra funzionare se la composizione contiene tracce con orientamenti diversi ... –

+0

Perché è solo lastObject che viene preso in considerazione. Questa è semplificazione del problema, non soluzione per tutti i casi. – Marcin

Problemi correlati