14

我最近发现了一个使用 AVMutableComposition 的问题,我正在寻找对此的一些见解。

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

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

4

3 回答 3

34

如果您只想保持原始旋转,这是一种稍微简单的方法。

// 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...
于 2014-02-24T05:59:47.897 回答
9

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

    //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];
    }
于 2012-05-30T17:37:23.197 回答
0

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

我刚刚对其进行了测试,并且还引用了 AVFoundation Programming Guide - Editing 部分,该部分建议实施@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..
于 2017-10-01T10:46:59.317 回答