视频不使用AVMutableVideoCompositionLayerInstruction旋转

Osk*_*son 5 avfoundation ios swift

我正在尝试将使用相机作为UIImagePickerController录制后录制的两个视频合并.我已成功将视频合并为一个,但我对视频的方向有一些问题.

正如我所知,UIImagePickerController的所有视频都是以横向拍摄的,这意味着以纵向录制的视频会旋转90°.

每次录制后,我都会将新视频添加到阵列中

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

然后当我想要合并时,我会浏览每个视频并创建一条指令并将指令添加到另一个数组中

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)

    }
}
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

jlw*_*jlw 6

尝试trackVideo在初始化程序中使用图层指令,这样它将使用AVMutableCompositionTrack's trackID而不是源资源trackID

更新:

您只需要一个AVMutableVideoCompositionLayerInstruction,因此在循环之前使用AVMutableCompositionTrackas参数声明它.然后在循环的每次迭代中,为您正在使用的当前视频资产设置图层指令(transform,crop rect)的必要属性.您正在控制在每次插入时应如何显示合成轨道中的视频内容.

最后,将单个layerInstruction放在指令数组中,并在视频合成中使用它.

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)
Run Code Online (Sandbox Code Playgroud)