2014-12-23 7 views
5

Sto cercando di unire due video che ottengo dopo aver registrato utilizzando la fotocamera come UIImagePickerController. Sono riuscito a combinare i video in uno solo, ma ho qualche problema con l'orientamento dei video.Video non in rotazione utilizzando AVMutableVideoCompositionLayerInstruction

Come ho capito con UIImagePickerController è che tutti i video vengono catturati in orizzontale, ciò significa che i video registrati in verticale vengono ruotati di 90 °.

Dopo ogni registrazione aggiungo il nuovo video a una serie

func imagePickerController(picker: UIImagePickerController!, didFinishPickingMediaWithInfo info:NSDictionary) { 
    let tempImage = info[UIImagePickerControllerMediaURL] as NSURL 
    videos.append(tempImage) 
    let pathString = tempImage.relativePath 
    self.dismissViewControllerAnimated(true, completion: {}) 
} 

Poi quando voglio unire vado attraverso ogni video e creare un'istruzione e aggiunge le istruzioni per un altro array

var composition = AVMutableComposition() 
let trackVideo:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID()) 
let trackAudio:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID()) 
var insertTime = kCMTimeZero 

for i in 0...(videos.count-1){ 
    let moviePathUrl = videos[i] 
    let sourceAsset = AVURLAsset(URL: moviePathUrl, options: nil) 

    let tracks = sourceAsset.tracksWithMediaType(AVMediaTypeVideo) 
    let audios = sourceAsset.tracksWithMediaType(AVMediaTypeAudio) 

    if tracks.count > 0{ 
     var videoDuration = CMTimeRangeMake(kCMTimeZero, sourceAsset.duration); 

     let assetTrack:AVAssetTrack = tracks[0] as AVAssetTrack 
     let assetTrackAudio:AVAssetTrack = audios[0] as AVAssetTrack 

     trackVideo.insertTimeRange(videoDuration, ofTrack: assetTrack, atTime: insertTime, error: nil) 
     trackAudio.insertTimeRange(videoDuration, ofTrack: assetTrackAudio, atTime: insertTime, error: nil) 

     //Rotate 
     var rotater = AVMutableVideoCompositionLayerInstruction(assetTrack: assetTrack) 
     rotater.setTransform(assetTrack.preferredTransform, atTime: insertTime) 
     rotater.setOpacity(0.0, atTime: CMTimeAdd(insertTime, sourceAsset.duration)) 
     instructions.append(rotater) 

     //Resize 
     var resizer = AVMutableVideoCompositionLayerInstruction(assetTrack: assetTrack) 
     resizer.setCropRectangle(CGRectMake(0, 0, 300, 300), atTime: insertTime) 
     instructions.append(resizer) 

     insertTime = CMTimeAdd(insertTime, sourceAsset.duration) 

    } 
} 

Quando ho creato tutte le istruzioni, le aggiungo all'istruzione principale e creo la sessione di esportazione.

var instruction = AVMutableVideoCompositionInstruction(); 
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, insertTime); 

instruction.layerInstructions = instructions; 
var mainCompositionInst = AVMutableVideoComposition() 
mainCompositionInst.instructions = NSArray(object: instruction) 

mainCompositionInst.frameDuration = CMTimeMake(1, 60); 
mainCompositionInst.renderSize = CGSizeMake(300, 300); 

var exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) 
exporter.videoComposition = mainCompositionInst; 

Cosa mi manca?

risposta

5

Provate ad usare trackVideo nel inizializzatore per la vostra istruzione livello in modo che userà s' trackID piuttosto che la AVMutableCompositionTrack la fonte del bene trackID

Aggiornamento:

Hai solo bisogno di un AVMutableVideoCompositionLayerInstruction, quindi dichiararlo prima loop con il parametro . Quindi, su ogni iterazione del ciclo, imposta le proprietà necessarie dell'istruzione di livello (trasformazione, ritaglio di ritaglio) per la risorsa video corrente con cui stai lavorando. Stai controllando il modo in cui il contenuto del video nella traccia di composizione deve essere visualizzato ad ogni ora di inserimento.

Al termine, posizionare il singolo layerInstruction nell'array delle istruzioni e utilizzarlo nella composizione del video.

var layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: trackVideo) 
for i in 0...(videos.count-1){ 
    //...your other code here 

    layerInstruction.setTransform(assetTrack.preferredTransform, atTime: insertTime) 
    layerInstruction.setCropRectangle(CGRectMake(0, 0, 300, 300), atTime: insertTime) 
} 

var instruction = AVMutableVideoCompositionInstruction(); 
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, insertTime); 

instruction.layerInstructions = NSArray(object: layerInstruction); 
var mainCompositionInst = AVMutableVideoComposition() 
mainCompositionInst.instructions = NSArray(object: instruction) 
+0

Ancora lo stesso problema, nessuna differenza –

+0

In realtà, penso che tu abbia solo bisogno di una istanza di 'rotater'. C'è solo una traccia di composizione video, quindi è necessario dichiarare 'rotater' al di fuori del ciclo e impostare la trasformazione da applicare all'ora di inizio di ogni nuovo video. Se si concatenano video, non è necessario impostare l'opacità su 0. Il prossimo verrà mostrato. – jlw

+0

Se ho capito bene, creo la rotazione usando trackVideo subito prima del ciclo. Poi all'interno del loop ho impostato la trasformazione proprio come facevo prima. Questo non funziona neanche. :/ –

1

Hai due livelli. È necessario applicare le istruzioni di rotazione a entrambi i livelli nella composizione. Quello che stai facendo qui è applicare le istruzioni di rotazione a una sola di esse. Ottieni un riferimento a entrambi gli elementi nella composizione del video e applica istruzioni separate ai due livelli.

+0

Non è quello che sto già facendo? Ho aggiunto più del mio codice alla mia domanda –

1

Si può semplicemente utilizzare questo semplice codice, funziona per me:

var assetVideoTrack = (sourceAsset.tracksWithMediaType(AVMediaTypeVideo)).last as! AVAssetTrack 

    var compositionVideoTrack = (composition.tracksWithMediaType(AVMediaTypeVideo)).last as! AVMutableCompositionTrack 

    if (assetVideoTrack.playable && compositionVideoTrack.playable) { 

     compositionVideoTrack.preferredTransform = assetVideoTrack.preferredTransform 
    } 
Problemi correlati