4

AVCaptureSession用来录制视频,AVAssetWriterInput我正在将视频写入文件。
我的问题是视频方向,使用苹果RosyWriter示例,我可以转换视频, AVAssetWriterInput以便视频处于正确的方向。

- (CGFloat)angleOffsetFromPortraitOrientationToOrientation:(AVCaptureVideoOrientation)orientation
{
    CGFloat angle = 0.0;

    switch (orientation) {
        case AVCaptureVideoOrientationPortrait:
            angle = 0.0;
            break;
        case AVCaptureVideoOrientationPortraitUpsideDown:
            angle = M_PI;
            break;
        case AVCaptureVideoOrientationLandscapeRight:
            angle = -M_PI_2;
            break;
        case AVCaptureVideoOrientationLandscapeLeft:
            angle = M_PI_2;
            break;
        default:
            break;
    }

    return angle;
}

- (CGAffineTransform)transformFromCurrentVideoOrientationToOrientation:(AVCaptureVideoOrientation)orientation
{
    CGAffineTransform transform = CGAffineTransformIdentity;

    // Calculate offsets from an arbitrary reference orientation (portrait)
    CGFloat orientationAngleOffset = [self angleOffsetFromPortraitOrientationToOrientation:orientation];
    CGFloat videoOrientationAngleOffset = [self angleOffsetFromPortraitOrientationToOrientation:self.videoOrientation];

    // Find the difference in angle between the passed in orientation and the current video orientation
    CGFloat angleOffset = orientationAngleOffset - videoOrientationAngleOffset;
    transform = CGAffineTransformMakeRotation(angleOffset);

    return transform;
}  

问题在于前置摄像头方向,在用户更改为前置摄像头后,使用此代码将不起作用。

似乎导致问题的原因是当我将凸轮更改为前面时,这些AVCaptureConnection变化并且我为前凸轮和后凸轮获得了不同的方向。

所以也许我需要调整前后凸轮初始方向之间的差异。
我真的不想在每次用户切换摄像头时更改连接的方向,因为正如 Apple 所说的那样它会损害性能(而且当我这样做时确实看起来很糟糕),所以 Apple 建议使用该AVAssetWriterInput transform属性来更改输出方向,但是我不确定我是否可以使用transform,因为我想让用户在录制时切换相机,但transform在我开始写作后我无法更改(它崩溃了)......

任何想法如何解决这个问题?

4

2 回答 2

1

由于来自前置摄像头的图像是镜像的,因此您还需要镜像转换。执行此操作的功能只是用 -1 缩放其中一个维度。尝试玩这个:

transform = CGAffineTransformConcat(CGAffineTransformMakeRotation(angle), CGAffineTransformMakeScale(1.0, -1.0));

注意可能的排列是(除了角度)X比例因子是-1和或交换顺序concat

编辑:解释

AVCaptureSession 将返回不像您的设备那样旋转的图像数据,我自然相信那将是横向或横向。如果您需要视频具有正确的方向,具体取决于您持有设备的方式,您需要对其应用一些变换,在大多数情况下,只需应用一些旋转就足够了。但是,前置摄像头是一种特殊情况,因为它会在您仍在接收非镜像帧时模拟镜像。因此,您的视频似乎是上下颠倒或左右或所有其他组合,具体取决于您应用的旋转方式,因此正如您所说“我尝试了很多角度,但我就是无法得到对的...”。同样,要模拟镜像效果,您应该将其中一个轴缩放 -1。

编辑:交换方向(来自评论)

这只是一个想法,我认为这是一个很好的想法。。根本不要使用资产转换,自己做。创建一个具有您希望视频大小的视图,然后使用您需要的所有转换、剪辑和内容模式为其创建一个图像视图子视图。从您获得的示例中创建图像,将它们设置为图像视图并从视图中获取图层快照。然后将快照发送给资产编写器。

我知道你在这里想的是“开销”。嗯,我不这么认为。由于视图和图像视图在 CPU 上进行转换,资产编写器也是如此,所以您所做的就是取消其内部转换并使用您自己的系统。如果你愿意尝试这个,我非常想听听你的结果。

获取图层图像:

- (UIImage *)imageFromLayer:(CALayer *)layer {
    UIGraphicsBeginImageContext([layer frame].size);
    [layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return outputImage;
}
于 2013-06-12T10:17:49.553 回答
0

不是最简单的方法,但我认为如果您截取帧并执行自己的转换,它肯定会起作用。您不需要任何 UIView - AVFoundation 允许直接访问和操作其框架(如果需要,您可以在写入文件时替换为自己的缓冲区)。我看到的唯一缺点是性能。在旧设备和高分辨率下,即使只是翻转图像也可能非常慢。

如果这确实会影响性能,您可以按原样保存视频,并为每帧保留一个单独的方向数组。保存视频后,重新打开它,对每一帧执行转换,然后将其保存到新文件中。我做过类似的事情,它确实有效。

附带说明,AVAssetWriterInputtransform属性仅适用于 iPhone。例如,如果您使用 AVFoundation 录制视频并将其上传到某处并在浏览器中观看,那么它将有错误的方向。因此,如果您正在寻求彻底的解决方案,那么您自己的转变就是要走的路。

如果您经常进行视频/图像处理(例如,在这种情况下,翻转/旋转),请考虑使用 OpenCV 库。学习需要一些时间,但这是值得的。

于 2013-06-21T03:29:02.490 回答