AVCaptureVideoPreviewLayer的规模

4
我目前正在为我的Swift应用程序开发QR扫描视图。我想将VideoPreview居中在我的视图中间。
视图如下所示: Image of the View I'm working on 该视图(白色)称为ScanView,我想使图像预览与ScanView大小相同,并将其居中。
代码片段: Setup of my VideoDevice 感谢您的帮助!

你所说的“图像预览”,在你的代码中我没有看到类似的东西。你是指“视频”吗? - mugx
对不起,我的错。 - Philip Dz
3个回答

7
这里有一个可行的解决方案:
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://dev59.com/DF0Z5IYBdhLWcg3wyy11#35642852
        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实现:

图片描述在此处输入

这里是结果:

图片描述在此处输入


我尝试了,但它不起作用。没有名为“translatesAutoresizingMaskIntoConstaints”的video成员。 - Philip Dz
我明白了。我编辑后提供了一个类来强制子层自动调整大小,请现在尝试。 - mugx
我已经添加了它并查看:https://imgur.com/a/fhfrQ。它没有调整为“scanView”边界的宽度和高度。 - Philip Dz
与之前的结果相同。我不知道如何更改它。我只需要更改子层的宽度并将其居中在scanView视图中,但它不起作用。 - Philip Dz
添加了 AVCaptureVideoDataOutputSampleBufferDelegate + AVCaptureVideoDataOutput - mugx
显示剩余9条评论

4
我有一个类似于Philip Dz的问题。最终将setupVideo()函数从viewDidLoad移动到viewDidAppear中解决了该问题:
  • viewDidLoad中调用setupVideo()

enter image description here

  • viewDidAppear中调用setupVideo()

enter image description here


尝试了一些其他的解决方案后,这个是有效的! - smmelzer

0

也许我来晚了一点,但我刚刚实现了QRScanner,并且根据运行视频流的设备可以进行缩放。这是通过AVCaptureDevice.videoZoomFactor属性实现的。因此,为了增强小方形QRScanner的用户体验,可以通过在self.session?.startRunning()之前插入以下行device.zoomFactor = min(YOUR_ZOOM_FACTOR_VALUE, device.activeFormat.videoMaxZoomFactor)来略微修改上面的代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接