2012-05-29 141 views
11

我最近发现了一个使用AVMutableComposition的问题,我正在寻找这方面的一些见解。AVMutableComposition旋转视频

我希望能够以两种方向录制视频 - 横向左右。当我以右侧风格录制视频(主页按钮位于右侧)时,它们会被添加到合成中并以正确的方向播放。但是,如果我按方向左侧(左侧的主页按钮)录制,则会将这些剪辑上下颠倒。

但是,如果它们插入到作品中,它们只会颠倒播放。否则,他们会以正确的方向玩。为什么构图逆转了横向拍摄的剪辑的旋转?我怎样才能解决这个问题?任何帮助表示赞赏!

+0

我也注意到还有,无论我做什么,这是发生。设置预先录制的方向,尝试旋转等。如果单独播放第一个剪辑,则曲目正面向上播放,但只要将其合并为合成作品,则会颠倒翻转。 – bgoers

回答

27

这里是一个稍微容易的方式,如果你只是想保持原来的旋转。

// Grab the source track from AVURLAsset for example. 
AVAssetTrack *assetVideoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].lastObject; 

// Grab the composition video track from AVMutableComposition you already made. 
AVMutableCompositionTrack *compositionVideoTrack = [composition tracksWithMediaType:AVMediaTypeVideo].lastObject; 

// Apply the original transform.  
if (assetVideoTrack && compositionVideoTrack) { 
    [compositionVideoTrack setPreferredTransform:assetVideoTrack.preferredTransform]; 
} 

// Export... 
+0

这个解决方案完美的为我保留原来的旋转。 – Brad

+0

在swift中转换时无法工作? – 2015-10-09 05:38:09

+1

如果在合成中有多个曲目具有不同的变换,您不能简单地设置每个曲目的变换,您需要进行不同的补偿。 –

8

解决了我的问题。终于能够旋转轨道并将其翻译成框架。奇迹般有效。

//setting up the first video based on previous recording 
    CMTimeRange videoDuration = CMTimeRangeMake(kCMTimeZero, [self.previousRecording duration]); 
    AVAssetTrack *clipVideoTrack = [[self.previousRecording tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    AVAssetTrack *clipAudioTrack = [[self.previousRecording tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 
    [compositionVideoTrack insertTimeRange:videoDuration ofTrack:clipVideoTrack atTime:nextClipStartTime error:nil]; 
    [compositionAudioTrack insertTimeRange:videoDuration ofTrack:clipAudioTrack atTime:nextClipStartTime error:nil]; 

    //our first track instruction - set up the instruction layer, then check the orientation of the track 
    //if the track is in landscape-left mode, it needs to be rotated 180 degrees (PI) 
    AVMutableVideoCompositionLayerInstruction *firstTrackInstruction = 
     [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack]; 

    if([self orientationForTrack:clipVideoTrack] == UIDeviceOrientationLandscapeLeft) { 
     CGAffineTransform rotation = CGAffineTransformMakeRotation(M_PI); 
     CGAffineTransform translateToCenter = CGAffineTransformMakeTranslation(640, 480); 
     CGAffineTransform mixedTransform = CGAffineTransformConcat(rotation, translateToCenter); 
     [firstTrackInstruction setTransform:mixedTransform atTime:kCMTimeZero]; 
    } 
+0

嗨bgoers ....我也有同样的问题...我用你的代码,但我越来越错误[自我orientationForTrack:clipVideoTrack](方法未找到)可以请你帮我在这... – ask123

+0

这是我自己定义的方法来确定轨道的方向。它将AVAssetTrack作为参数,然后使用首选方向。我改变了一下,但这应该有助于http://stackoverflow.com/a/6046421/1415949 – bgoers

+0

什么是'[self orientationForTrack:]'?它的实现是什么? –

0

我认为答案肯定是最好的选择,但它只是部分正确的。实际上,为了使其工作,我们还必须调整导出的渲染大小,翻转纵向轨道自然大小的高度和宽度。

我只是测试它,我也举AVFoundation编程指南 - 编辑部分,这说明实行什么是@dizy的答案,但有提到除了实际建议:

所有AVAssetTrack对象都有一个preferredTransform包含该资产追踪的​​方向信息的财产。只要资产轨道显示在屏幕上,就会应用此转换。在前面的代码中,将图层指令的变换设置为资产轨道的变换,以便在您调整渲染大小后,新构图中的视频将正确显示

的代码应该是这样的一个,然后(只是两行补充):

// Grab the source track from AVURLAsset for example. 
AVAssetTrack *assetVideoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].lastObject; 

// Grab the composition video track from AVMutableComposition you already made. 
AVMutableCompositionTrack *compositionVideoTrack = [composition tracksWithMediaType:AVMediaTypeVideo].lastObject; 

// Apply the original transform.  
if (assetVideoTrack && compositionVideoTrack) { 
    [compositionVideoTrack setPreferredTransform:assetVideoTrack.preferredTransform]; 
} 

flippedSize = CGSize(compositionVideoTrack.naturalSize.height, compositionVideoTrack.naturalSize.width); 
composition.renderSize = flippedSize; 

// Export..