Swift 4 Capture Photo,photoOutput 返回 nil

Posted

技术标签:

【中文标题】Swift 4 Capture Photo,photoOutput 返回 nil【英文标题】:Swift 4 Capture Photo, photoOutput returns nil 【发布时间】:2018-03-09 17:47:36 【问题描述】:

目前我有两个不同的视图控制器和一个在它们之间切换的按钮。 我希望能够在每个设备上拍摄设备输入的照片。

我目前能够拍摄后置摄像头的照片以进行处理并且效果很好,但是当我尝试在另一个控制器中为第二个视图编写相同的代码时,照片输出返回 nil,但是当我记录每个设备,它仍然显示前后摄像头。

我对 swift 还很陌生,不知道为什么会这样。

ViewController 类、viewDidLoad 和变量:

class AddUserController: UIViewController , AVCaptureVideoDataOutputSampleBufferDelegate , UITextFieldDelegate

   //variable for captureing video feed
   var captureSessionFront = AVCaptureSession()
   //variable for rendering camera to the view
   var videoPreviewLayer: AVCaptureVideoPreviewLayer?

   var frontCamera: AVCaptureDevice?
   var backCamera: AVCaptureDevice?
   var currentCamera2: AVCaptureDevice?
   var PhotoOutputFront: AVCapturePhotoOutput?
   var cameraPreviewLayer2: AVCaptureVideoPreviewLayer?

   var tempImage: UIImage?

   var tempstring: String?

   private var maskLayer = [CAShapeLayer]()



   @IBOutlet weak var textField: UITextField!

   //button action to save the user to the collection
   @IBAction func saveFaceBtn(_ sender: Any) 
       let settings = AVCapturePhotoSettings()
       PhotoOutputFront?.capturePhoto(with: settings, delegate: self)
       //print(PhotoOutputFront!)
   

   override func viewDidLoad() 
       super.viewDidLoad()
       // Do any additional setup after loading the view, typically from a nib.

       //hide keyboard
       self.textField.delegate = self

       //video capture functions
       setupCaptureSession()
       setupDevice()
       setupInputOutput()
       setupPreview()
       startRunningCaptureSession()

功能:

func setupCaptureSession() 
       captureSessionFront.sessionPreset = AVCaptureSession.Preset.photo
   
func setupDevice() 

       //discover devices
       let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(
           deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera],
           mediaType: AVMediaType.video,
           position: AVCaptureDevice.Position.unspecified)

       //find devices and check if frint or back cameras discovered
       let devices = deviceDiscoverySession.devices

       for device in devices
           print(device)
           if device.position == AVCaptureDevice.Position.front
               frontCamera = device

            else if device.position == AVCaptureDevice.Position.back
               backCamera = device
           
       

       currentCamera2 = frontCamera

   

   func setupInputOutput() 

       do
       

           let captureDeviceInput2 = try AVCaptureDeviceInput(device: currentCamera2!)

           captureSessionFront.addInput(captureDeviceInput2)
           PhotoOutputFront?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
           print(PhotoOutputFront)
       
       catch
       
           print(error)
       
   

   func setupPreview() 
       cameraPreviewLayer2 = AVCaptureVideoPreviewLayer(session: captureSessionFront)
       cameraPreviewLayer2?.videoGravity = AVLayerVideoGravity.resizeAspectFill
       cameraPreviewLayer2?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
       cameraPreviewLayer2?.frame = self.view.frame
       self.view.layer.insertSublayer(cameraPreviewLayer2!, at: 0)
   

   func startRunningCaptureSession() 
       captureSessionFront.startRunning()
   

保存拍摄照片的扩展程序:

extension AddUserController: AVCapturePhotoCaptureDelegate 

   func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) 
       print("before if let")
       if let imageData = photo.fileDataRepresentation()
           tempImage = UIImage(data: imageData)
           print(tempImage!)

           //check to see if name is empty
           let tempstring = self.textField.text
           if(tempstring != nil || tempstring != "")

               print(tempstring!)
               //addPhotoToCollection()
           


       
   


它必须是设置输入输出的东西,但我不确定我哪里出错了,因为这段代码适用于我的主视图控制器中的后置摄像头。我认为这与此功能有关,因为在我的其他控制器“PhotoOutput”中不返回零。在这里,“PhotoOutputFront”返回 nil。

view    func setupInputOutput() 

       do
       

           let captureDeviceInput2 = try AVCaptureDeviceInput(device: currentCamera2!)

           captureSessionFront.addInput(captureDeviceInput2)
           PhotoOutputFront?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
           print(PhotoOutputFront)
       
       catch
       
           print(error)
       
   

任何帮助将不胜感激。提前致谢!

【问题讨论】:

【参考方案1】:

问题是我没有将捕获设备添加为捕获会话的输入,也没有添加捕获会话的输出。

希望这可以帮助其他在使用 avcapture 设备时遇到问题的人。 :)

func setupInputOutput() 

       do
       

           let captureDeviceInput2 = try AVCaptureDeviceInput(device: currentCamera2!)

           captureSessionFront.addInput(captureDeviceInput2)
           PhotoOutputFront = AVCapturePhotoOutput()
           PhotoOutputFront?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
           captureSessionFront.addOutput(PhotoOutputFront!)
       
       catch
       
           print(error)
       
   

【讨论】:

【参考方案2】:

添加输出:

if captureSessionFront?.canAddOutput(PhotoOutputFront) 
  let settings = AVCapturePhotoSettings()
  let previewPixelType = 
  settings.__availablePreviewPhotoPixelFormatTypes.first!
  let previewFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
                   kCVPixelBufferWidthKey as String: 160,
                   kCVPixelBufferHeightKey as String: 160]
  settings.previewPhotoFormat = previewFormat
  settings.isHighResolutionPhotoEnabled = 
  PhotoOutputFront.isHighResolutionCaptureEnabled
  PhotoOutputFront.setPreparedPhotoSettingsArray([settings], completionHandler:  (finished, anError) in
    guard let error = anError else  return 
    debugPrint("Failed to set photo settings with: \(error.localizedDescription)")
  )
  captureSessionFront.addOutput(PhotoOutputFront)

在添加输出之前,添加输入:

if captureSessionFront.canAddInput(captureDeviceInput2) 
    captureSessionFront.addInput(captureDeviceInput2)

【讨论】:

以上是关于Swift 4 Capture Photo,photoOutput 返回 nil的主要内容,如果未能解决你的问题,请参考以下文章

UIPanGestureRecognizer Swift Capture 相对翻译

如何停止 MediaStore.ACTION_IMAGE_CAPTURE 复制图片

场景删除后 Reality Capture API 结果可用性

NSKeyedArchiver 返回 nil Swift 4.2

如果在 ON 子句中使用 OR,MySQL 将不会在 JOIN 中使用可用索引

如果在函数中创建,为啥 Tkinter 图像不显示?