视频无法使用AVMutableVideoCompositionLayerInstruction旋转 [英] Video not rotating using AVMutableVideoCompositionLayerInstruction

查看:86
本文介绍了视频无法使用AVMutableVideoCompositionLayerInstruction旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to merge two videos I get after recording using the camera as a UIImagePickerController. I've succeeded with combining the videos into one but I have some problems with the orientation of the videos.

正如我所知,UIImagePickerController是所有视频在横向捕捉,这意味着以纵向录制的视频旋转90°。

As I've understood it with the UIImagePickerController is that all videos are captured in landscape, this means that the videos recorded in portrait are rotated 90°.

每次录制后我将新视频添加到阵列

After each recording I add the new video to an 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: {})
}

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

Then when I want to merge I go through each video and create an instruction and adds the instruction to another 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)

    }
}

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

When I've created all the instructions I add them to the main instruction and create the export session.

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 ,这样它将使用 AVMutableCompositionTrack trackID 而不是源资产的 trackID

Try using trackVideo in the initializer for your layer Instruction so it will use the AVMutableCompositionTrack's trackID rather than the source asset's trackID

更新:

你只需要一个 AVMutableVideoCompositionLayerInstruction ,所以在循环前用 AVMutableCompositionTrack 作为参数。然后在循环的每次迭代中,为您正在使用的当前视频资产设置图层指令(transform,crop rect)的必要属性。您正在控制合成轨道中视频内容在每次插入时的显示方式。

You only need one AVMutableVideoCompositionLayerInstruction, so declare it before the loop with the AVMutableCompositionTrack as the parameter. Then on each iteration of the loop, set the necessary properties of the layer instruction (transform, crop rect) for the current video asset you're working with. You're controlling how the video content in the composition track should be displayed at each insert time.

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

At the end, place the single layerInstruction in the instructions array, and use that in the video composition.

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)

这篇关于视频无法使用AVMutableVideoCompositionLayerInstruction旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆