2014-12-23 3 views
5

Ich versuche, zwei Videos zusammenzuführen, die ich nach der Aufnahme mit der Kamera als UIImagePickerController bekomme. Es ist mir gelungen, die Videos zu einem zu kombinieren, aber ich habe einige Probleme mit der Ausrichtung der Videos.Video dreht sich nicht mit AVMutableVideoCompositionLayerInstruction

Wie ich es mit dem UIImagePickerController verstanden habe, dass alle Videos im Querformat aufgenommen werden, bedeutet dies, dass die im Hochformat aufgenommenen Videos um 90 ° gedreht sind.

Nach jeder Aufnahme füge ich das neue Video zu einem Array

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

Dann, wenn ich will ich durch jedes Video gehen verschmelzen und eine Anweisung und fügt den Befehl zu einem anderen 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) 

    } 
} 
erstellen

Wenn ich alle Anweisungen erstellt habe, füge ich sie der Hauptanweisung hinzu und erstelle die Exportsitzung.

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; 

Was fehlt mir?

Antwort

5

Versuchen trackVideo in dem Initialisierer für Ihre Schicht Anweisung verwendet, so dass es die AVMutableCompositionTrack ‚s trackID eher als die Quelle des Vermögens trackID

Update verwenden wird:

Sie nur eine AVMutableVideoCompositionLayerInstruction benötigen, so erklären sie, bevor die Schleife mit dem AVMutableCompositionTrack als Parameter. Legen Sie dann bei jeder Iteration der Schleife die erforderlichen Eigenschaften der Ebenenanweisung (transform, crop rect) für das aktuelle Video-Asset fest, mit dem Sie arbeiten. Sie steuern, wie der Videoinhalt in der Kompositionsspur bei jedem Einfügen angezeigt werden soll.

Am Ende, legen Sie die Single LayerInstruction im Array Anweisungen und verwenden Sie diese in der Video-Komposition.

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

Immer noch das gleiche Problem, kein Unterschied –

+0

Eigentlich glaube ich, dass Sie nur eine Instanz von 'rotater' brauchen. Da es nur eine Kompositionsspur für Videos gibt, müssen Sie 'rotater' außerhalb der Schleife deklarieren und die Transformation für die Startzeit jedes neuen Videos festlegen. Wenn Sie Videos verketten, müssen Sie die Deckkraft auch nicht auf 0 setzen. Der nächste wird einfach auftauchen. – jlw

+0

Wenn ich dich richtig verstanden habe, erstelle ich das Drehen mit trackVideo direkt vor der Schleife. Dann setze ich innerhalb der Schleife die Transformation genau wie zuvor. Dies funktioniert auch nicht. :/ –

1

Sie haben zwei Schichten. Sie müssen die Rotationsanweisung auf beide Ebenen in der Komposition anwenden. Was Sie hier tun, ist das Anwenden der Rotationsanweisung auf nur einen von ihnen. Erhalten Sie einen Verweis auf beide Elemente in der Videomischung und wenden Sie separate Anweisungen auf die beiden Ebenen an.

+0

Ist das nicht, was ich schon tun? Ich habe mehr von meinem Code zu meiner Frage hinzugefügt –

1

Sie können nur diesen einfachen Code verwenden, es funktioniert für mich:

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 
    }