AVCaptureVideoPreviewLayer的比例

时间:2017-12-16 22:04:25

标签: ios swift video avfoundation preview

我目前正在Swift应用程序中处理QR扫描视图。 我希望将VideoPreview置于视图的中间位置。

视图如下所示:

Image of the View I'm working on

视图(白色)名为ScanView,我想让图片预览的尺寸与ScanView相同,并将其置于其中。

代码段:

Setup of my VideoDevice

感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

这是一个有效的解决方案:

import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureMetadataOutputObjectsDelegate {
  @IBOutlet weak var innerView: UIView!
  var session: AVCaptureSession?
  var input: AVCaptureDeviceInput?
  var previewLayer: AVCaptureVideoPreviewLayer?

  override func viewDidLoad() {
    super.viewDidLoad()
    createSession()
  }

  override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.previewLayer?.frame.size = self.innerView.frame.size
  }

  private func createSession() {
    do {
      self.session = AVCaptureSession()
      if let device = AVCaptureDevice.default(for: AVMediaType.video) {
        self.input = try AVCaptureDeviceInput(device: device)
        self.session?.addInput(self.input!)
        self.previewLayer = AVCaptureVideoPreviewLayer(session: self.session!)
        self.previewLayer?.frame.size = self.innerView.frame.size
        self.previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
        self.innerView.layer.addSublayer(self.previewLayer!)

        //______ 1. solution with Video camera ______//
        let videoOutput = AVCaptureVideoDataOutput()
        videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue.main)
        self.session?.canAddOutput(videoOutput)
        self.session?.addOutput(videoOutput)
        self.session?.startRunning()

        //______ 2. solution with QR code ______//
        let videoOutput = AVCaptureMetadataOutput()
        videoOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        self.session?.canAddOutput(videoOutput)
        self.session?.addOutput(videoOutput)
        // explanation here: https://stackoverflow.com/a/35642852/2450755
        videoOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]
        self.session?.startRunning()
      }
    } catch _ {
    }
  }

  //MARK: AVCaptureVideoDataOutputSampleBufferDelegate
  public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    if let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
        let cameraImage = CIImage(cvPixelBuffer: pixelBuffer)
        // awesome stuff here
    }
  }

  //MARK: AVCaptureMetadataOutputObjectsDelegate
  func setMetadataObjectsDelegate(_ objectsDelegate: AVCaptureMetadataOutputObjectsDelegate?, queue objectsCallbackQueue: DispatchQueue?) {

  }
}

要求:

  • 设置:Privacy - Camera Usage Description
  • innerView必须初始化,我在Storyboard中做了以下约束:

enter image description here

这里的结果是:

enter image description here

答案 1 :(得分:2)

我也有像Philip Dz一样的问题。最后,通过将setupVideo()函数从viewDidLoad移到viewDidAppear来解决此问题:

  • 在viewDidLoad中调用setupVideo()

enter image description here

  • 在viewDidAppear中调用setupVideo():

enter image description here

答案 2 :(得分:0)

也许我有点晚了,但我刚刚实施了 QRScanner,并且根据运行视频流的设备可以缩放。这是通过 AVCaptureDevice.videoZoomFactor 属性实现的。所以,为了增强小方型QRScanner的用户体验,可以稍微修改上面的代码,在device.zoomFactor = min(YOUR_ZOOM_FACTOR_VALUE, device.activeFormat.videoMaxZoomFactor)

之前插入下面这行self.session?.startRunning()