【问题标题】:Scale of AVCaptureVideoPreviewLayerAVCaptureVideoPreviewLayer 的比例
【发布时间】:2017-12-16 22:04:24
【问题描述】:

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

视图如下所示:

视图(白色)称为ScanView,我想让图像预览的大小与ScanView 相同并将其居中。

代码sn-p:

感谢您的每一个帮助!

【问题讨论】:

  • 你对image preview 的意思,在你的代码中我没有看到类似的东西。你的意思是video
  • 是的,对不起,我的错

标签: ios swift video avfoundation preview


【解决方案1】:

这是一个可行的解决方案:

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 做了以下约束:

结果如下:

【讨论】:

  • 我试过了,但它不起作用。没有名为“translatesAutoresizingMaskIntoConstaints”的视频成员
  • 我明白了。我编辑提供了一个类来强制子层的自动调整大小,现在试试
  • 我添加了它并查看:imgur.com/a/fhfrQ。它没有调整到“scanView”边界的宽度和高度。
  • 与以前的结果相同。我不知道如何改变它。我只需要更改子层的宽度并将其在 scanView 视图中居中,但它不起作用
  • 你能告诉我如何添加输出吗?我想扫描二维码,但我这样做的方式不起作用
【解决方案2】:

我和 Philip Dz 有同样的问题。最后通过将setupVideo() 函数从viewDidLoad 移动到viewDidAppear 来解决这个问题:

  • 在 viewDidLoad 中调用 setupVideo()

  • 在 viewDidAppear 中调用 setupVideo():

【讨论】:

  • 在尝试了一些其他解决方案之后,这是一个可行的解决方案!
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多