video不使用AVMutableVideoCompositionLayerInstruction旋转

我试图合并使用相机作为UIImagePickerController录制后得到的两个video。 我已经成功地将video合并成一个,但是我对video的方向有一些问题。

正如我已经明白它与UIImagePickerController是所有的video捕捉横向,这意味着以纵向logging的video旋转90°。

每次录制后,我将新video添加到数组中

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

然后,当我想要合并时,我会遍历每个video并创build一条指令,并将指令添加到另一个数组

 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) } } 

当我创build了所有的指令后,我将它们添加到主指令中并创build导出会话。

 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; 

我错过了什么?

尝试在初始化程序中为您的图层指令使用trackVideo ,以便使用AVMutableCompositionTracktrackID而不是源资产的trackID

更新:

你只需要一个AVMutableVideoCompositionLayerInstruction ,所以在以AVMutableCompositionTrack为参数的循环之前声明它。 然后在循环的每次迭代中,为正在使用的当前video资源设置图层指令(变换,裁剪矩形)的必要属性。 您正在控制如何在每个插入时间显示合成音轨中的video内容。

最后,将单层指令放置在指令数组中,并在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) 

你有两层。 您需要将旋转指令应用于合成中的两个图层。 你在这里做的只是将旋转指令应用到其中的一个。 获得对video合成中的两个元素的引用,并向两个图层应用单独的指令。

你可以使用这个简单的代码,它适用于我:

  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 }