AVCaptureVideoPreviewLayer 并从相机位置预览

问题描述 投票:0回答:5

我正在开发一个允许用户拍照的应用程序。 我已经开始使用苹果提供的 AVCam 但我实际上遇到了问题 只是我无法将相机层放置在我想要的位置,但它会自动放置在视图的中心

enter image description here

在左侧您可以看到我实际拥有的东西,在右侧您可以看到我想要拥有的东西。 包含来自相机的预览的视图是一个

UIView
子类,这是代码

class AVPreviewView : UIView {
    override class func layerClass() -> AnyClass {
        return AVCaptureVideoPreviewLayer.self
    }
    func session () -> AVCaptureSession {
        return (self.layer as AVCaptureVideoPreviewLayer).session
    }

    func setSession(session : AVCaptureSession) -> Void {
        (self.layer as AVCaptureVideoPreviewLayer).session = session;
        (self.layer as AVCaptureVideoPreviewLayer).videoGravity = AVLayerVideoGravityResizeAspect;

    }
}

如有任何帮助,我们将不胜感激

swift sdk ios8 avcapture
5个回答
11
投票

首先获取您的屏幕尺寸,以便计算宽高比

    let screenWidth = UIScreen.mainScreen().bounds.size.width
    let screenHeight = UIScreen.mainScreen().bounds.size.height
    var aspectRatio: CGFloat = 1.0

    var viewFinderHeight: CGFloat = 0.0
    var viewFinderWidth: CGFloat = 0.0
    var viewFinderMarginLeft: CGFloat = 0.0
    var viewFinderMarginTop: CGFlaot = 0.0

现在计算预览图层的大小。

    func setSession(session : AVCaptureSession) -> Void {

        if screenWidth > screenHeight {
            aspectRatio = screenHeight / screenWidth * aspectRatio
            viewFinderWidth = self.bounds.width
            viewFinderHeight = self.bounds.height * aspectRatio
            viewFinderMarginTop *= aspectRatio
        } else {
            aspectRatio = screenWidth / screenHeight
            viewFinderWidth = self.bounds.width * aspectRatio
            viewFinderHeight = self.bounds.height
            viewFinderMarginLeft *= aspectRatio
        }

        (self.layer as AVCaptureVideoPreviewLayer).session = session;

将图层的

videoGravity
设置为
AVLayerVideoGravityResizeAspectFill
,以便图层拉伸以填充给定的自定义视图。

        (self.layer as AVCaptureVideoPreviewLayer).videoGravity = AVLayerVideoGravityResizeAspectFill;

最后,将预览图层的框架设置为上面计算的值以及您喜欢的任何偏移量。

        (self.layer as AVCaptureVideoPreviewLayer).frame = CGRectMake(viewFinderMarginLeft, viewFinderMarginTop, viewFinderWidth, viewFinderHeight)

    }

这可能需要一些调整,因为我还没有进行现场测试,但您应该能够创建一个更灵活的 VideoPreviewArea,由 APPreviewView 的边界分隔。


3
投票

您看到的不是图层的定位,而是视图/图层的纵横比与相机的纵横比不匹配,因此它使用

videoGravity
属性和纵横比填充它(其中始终意味着居中)

创建图层时,调整其大小,使纵横比正确,然后随意放置。 或者,在这种情况下,将视图大小调整为正确的宽高比,然后可以随意定位视图。


2
投票

我遇到了类似的问题,我这样做解决了它:

 previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
                previewLayer.anchorPoint = videoLayer.bounds.origin
                previewLayer.frame = CGRect(x: videoLayer.bounds.origin.x, y: videoLayer.bounds.origin.y, width: videoLayer.frame.size.width, height: videoLayer.frame.size.height)
                videoLayer.layer.addSublayer(previewLayer)
                captureSession.startRunning()

希望这能有所帮助:)


1
投票

我遇到了这个问题,即使代码可以工作,提供的代码也没有解决问题。我一直在使用界面生成器构建我的应用程序。

在属性检查器中的扩展边缘下有一些设置,所有视图都可以在顶部栏和底部栏下扩展。我的设置检查了这些,这导致视图定位的计算失败。

utilities navigator

延伸边缘设置:

extend edges settings


0
投票

我通过使用以下方法解决了这个问题:

// Calculate the aspect ratio of the output.
let previewLayerAspectRatio = (videoDataOutput.videoSettings["Height"] as! CGFloat)
    / (videoDataOutput.videoSettings["Width"] as! CGFloat)

此计算可以在相机设置期间完成。使用

AVLayerVideoGravity.resizeAspect
时,它会返回预览的真实宽高比。然后您可以像这样设置
previewLayer
的大小:

view.layer.insertSublayer(previewLayer, at: 0)
previewLayer.frame = CGRect(x: 0, y: view.safeAreaInsets.top, 
    width: view.frame.width, height: view.frame.width * previewLayerAspectRatio)

结果正是 OP 所期望的:大约 4:3 的预览与安全区域的顶部对齐。

© www.soinside.com 2019 - 2024. All rights reserved.