AVFoundation 旋转屏幕 - Obj C

csw*_*285 1 transform objective-c video-processing avfoundation ios

我正在努力改变视频的方向。它以纵向记录,然后以横向保存。更改变换只会使视频在横向视频中旋转。在这个带有 M_PI_2 的例子中,它消失了,因为它旋转了屏幕或平面。但是如果我把它改成 M_PI_2/2 或者它看起来是歪的。我知道 AVFoundation 默认情况下会这样做。我该如何改变?我从本教程中得到了很多这样的代码:https : //www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos 但使用 AVMutableVideoCompositionLayerInstruction 不起作用。

AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                    preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime insertTime = kCMTimeZero;
for(AVAsset *videoAsset in self.videoArray){
    [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:insertTime error:nil];
    // Updating the insertTime for the next insert
    insertTime = CMTimeAdd(insertTime, videoAsset.duration);
}
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(M_PI_2);
videoTrack.preferredTransform = rotationTransform;

// 3.1 - Create AVMutableVideoCompositionInstruction
AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruction.timeRange = videoTrack.timeRange;

// 3.2 - Create an AVMutableVideoCompositionLayerInstruction for the video track and fix the orientation.
AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
AVAssetTrack *videoAssetTrack = [[videoTrack.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

UIImageOrientation videoAssetOrientation_  = UIImageOrientationUp;
BOOL isVideoAssetPortrait_  = NO;

CGAffineTransform videoTransform = videoAssetTrack.preferredTransform;
if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0) {
    videoAssetOrientation_ = UIImageOrientationRight;
    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0) {
    videoAssetOrientation_ =  UIImageOrientationLeft;
    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {
    videoAssetOrientation_ =  UIImageOrientationUp;
}
if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {
    videoAssetOrientation_ = UIImageOrientationDown;
}

//CGAffineTransform rotationTransform = videoAssetTrack.preferredTransform;

[videolayerInstruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero];
[videolayerInstruction setOpacity:0.0 atTime:videoTrack.timeRange.duration];
Run Code Online (Sandbox Code Playgroud)

有没有办法设置锚点或进行我自己的变换?

zho*_*lei 5

查看https://developer.apple.com/library/content/qa/qa1744/_index.html,这是使用 AVFoundation 设置视频方向的官方解释。简单地说,您需要使用 AVMutableVideoCompositionLayerInstruction 对象来修改变换以应用于视频合成中的给定轨道。
然后让我们谈谈您应该应用的转换。有很多人建议使用 AVAssetTrack 的 preferredTransform。在大多数情况下,它是有效的,您应该使用它来获取 assetTrack 的视频方向。但有时 preferredTransform 可能缺少 tx(ty) 的值(如果您不知道 tx(ty) 是什么,则应查看 Apple API 参考中的 CGAffineTransform)或 tx(ty) 的值不准确,从而导致视频定位错误。
所以主要思想是:使用preferredTransform来确定原始视频方向并进行自己的变换。
这是获取轨道方向的代码:

- (UIInterfaceOrientation)orientationForTrack:(AVAsset *)asset {
    UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait;
    NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];

    if([tracks count] > 0) {
        AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
        CGAffineTransform t = videoTrack.preferredTransform;

        // Portrait
        if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0) {
            orientation = UIInterfaceOrientationPortrait;
        }
        // PortraitUpsideDown
        if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0) {
            orientation = UIInterfaceOrientationPortraitUpsideDown;
        }
        // LandscapeRight
        if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0) {
            orientation = UIInterfaceOrientationLandscapeRight;
        }
        // LandscapeLeft
        if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0) {
            orientation = UIInterfaceOrientationLandscapeLeft;
        }
    }
    return orientation;
}
Run Code Online (Sandbox Code Playgroud)

以及用于获取所需转换以应用的代码:

- (CGAffineTransform)transformBasedOnAsset:(AVAsset *)asset {
    UIInterfaceOrientation orientation = [AVUtilities orientationForTrack:asset];
    AVAssetTrack *assetTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0];
    CGSize naturalSize = assetTrack.naturalSize;
    CGAffineTransform finalTranform;
    switch (orientation) {
        case UIInterfaceOrientationLandscapeLeft:
            finalTranform = CGAffineTransformMake(-1, 0, 0, -1, naturalSize.width, naturalSize.height);
            break;
        case UIInterfaceOrientationLandscapeRight:
            finalTranform = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
            break;
        case UIInterfaceOrientationPortrait:
            finalTranform = CGAffineTransformMake(0, 1, -1, 0, naturalSize.height, 0);
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            finalTranform = CGAffineTransformMake(0, -1, 1, 0, 0, naturalSize.width);
            break;
        default:
            break;
    }
    return finalTranform;
}
Run Code Online (Sandbox Code Playgroud)

如果您感到困惑,我建议您先拍摄不同方向的视频,然后使用 NSStringFromCGAffineTransform() 或其他方法打印出视频的 preferredTransform 以查看详细信息。