Iphone AVCaptureSession前摄像头方向
我正在使用Iphone AVCaptureSession前摄像头方向,iphone,ios,objective-c,avfoundation,avassetwriter,Iphone,Ios,Objective C,Avfoundation,Avassetwriter,我正在使用AVCaptureSession录制视频,使用AVAssetWriterInput我正在将视频写入文件。 我的问题是视频方向,使用appleRosyWriter示例,我可以变换AVAssetWriterInput,使视频方向正确 - (CGFloat)angleOffsetFromPortraitOrientationToOrientation:(AVCaptureVideoOrientation)orientation { CGFloat angle = 0.0;
AVCaptureSession
录制视频,使用AVAssetWriterInput
我正在将视频写入文件。我的问题是视频方向,使用apple
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
会发生变化,并且前凸轮和后凸轮的方向不同
因此,我可能需要调整前后凸轮的初始方向之间的差异。我真的不想每次用户切换摄像头时都改变连接的方向,因为正如苹果公司所说的那样,这会影响性能(事实上,当我这样做时,它看起来很糟糕), 因此,苹果建议使用
AVAssetWriterInput
transform
属性来更改输出方向,但我不确定是否可以使用transform
,因为我想让用户在录制时切换相机,但我无法在开始编写后更改transform
(它崩溃了)
有什么办法可以解决这个问题吗?因为前摄像头的图像是镜像的,所以你也需要镜像变换。实现这一点的函数只是用-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;
}
这不是最简单的方法,但我认为如果你截取帧并执行你自己的变换,它肯定会起作用。您不需要任何UIView,因为AVFoundation允许直接访问和操作其帧(如果需要,您可以在写入文件时使用自己的缓冲区进行替换)。我看到的唯一缺点是性能。在旧设备和高分辨率上,即使只是翻转图像也可能非常慢 如果这会影响性能,则可以原样保存视频,并为每个帧保留单独的方向阵列。保存视频后,重新打开它,对每个帧执行变换,然后将其保存到新文件中。我也做过类似的事情,它确实有效 另一方面,
AVAssetWriterInput
的transform
属性仅适用于iPhone。比如说,如果你用AVFoundation录制了一段视频,并将其上传到某个地方,然后在浏览器中观看,那么视频的方向将是错误的。因此,如果您正在寻求一个彻底的解决方案,那么您自己的转型就是一条出路
如果你经常做视频/图像处理(例如,翻转/旋转),考虑OpenCV库。学习需要一些时间,但它是值得的。
再次思考,我不确定我是否可以使用AvassetWriteInput转换,我想让用户在录制时切换相机,但我无法在开始写入后更改AvassetWriteInput转换(它崩溃),因此我想我别无选择,只能更改AVCaptureConnection方向(我知道这会影响性能),你不这么认为吗?如果它能工作,应该不会太糟糕。这里更好的问题是,当样本的分辨率不同时会发生什么。无论如何,如果你更换相机,你可以开始一个新的视频,然后在用户停止录制时将它们全部添加到一起。。