AVCaptureVideoPreviewLayer and preview from camera position

偶尔善良 提交于 2019-12-03 21:40:40

First get your screen size so you can calculate the aspect ratio

    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

Now calculate the size of the preview layer.

    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;

Set the layer's videoGravity to AVLayerVideoGravityResizeAspectFill so that the layer stretches to fill given your custom view.

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

Finally, set the frame of your preview layer to the values calculated above with any offset that you like.

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

    }

This may take some tweaking since I haven't tested it live, but you should be able to create a more flexible VideoPreviewArea delimited by the bounds of your APPreviewView.

What you're seeing isn't the layer being positioned as much as it is the aspect of the view/layer doesn't match the aspect ratio of the camera, so it's using the videoGravity property and aspect filling it (which always implies centered)

When you create the layer, size it so that the aspect ratio is correct, then position it at will. Or, in this case, resize the view to the correct aspect ratio, then the view can be positioned at will.

I had a similar problem I fix it doing this:

 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.addSubview(previewLayer)
                //                previewLayer.
                videoLayer.layer.addSublayer(previewLayer)
                captureSession.startRunning()

Hope this can help :)

Abishek Gokal

I ran into this problem and the code provided did not fix the situation even though the code was working. I have been building my app using the interface builder.

In the the attributes inspector there under extend edges there are settings which all the view to be extended under tops bars and under bottom bars. My settings had these checked which was throwing off calculations for the positioning of the view.

Extend edges settings:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!