简体   繁体   English

Swift 4 Capture Photo,photoOutput返回nil

[英]Swift 4 Capture Photo, photoOutput returns nil

Currently I have two different view controllers and a button that switches between them. 目前,我有两个不同的视图控制器和一个在它们之间切换的按钮。 On each of them I want to be able to snap a photo of the device input. 我希望在每张照片上都能拍摄到设备输入的照片。

I currently am able to snap a Photo of the back camera for processing and that works perfectly, however when i tried writing the same code in the other controller for the second view, the photo output returns nil, but when I log each device, it still shows front and back camera. 目前,我可以拍摄后置摄像头的照片以进行处理,并且效果很好,但是当我尝试在第二个视图的另一个控制器中编写相同的代码时,照片输出将返回nil,但是当我记录每个设备时,仍然显示前后摄像头。

I am fairly new to swift and not sure why this is happening. 我是新手,不知道为什么会这样。

ViewController class, viewDidLoad and variables: 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()

Functions: 职能:

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 which saves the captured photo: 扩展名,用于保存捕获的照片:

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()
           }


       }
   }

}

It must be something setting up the Input Output, but I'm not sure where I went wrong as this code works for the back camera in my main viewcontroller. 必须设置输入输出,但是我不确定哪里出了问题,因为此代码适用于我的主视图控制器中的后置摄像头。 I think it has to do with this function as in my other controller "PhotoOutput"doesn't return nil. 我认为这与该功能有关,因为在我的其他控制器“ PhotoOutput”中不会返回nil。 Where as here, "PhotoOutputFront" returns nil. 此处“ 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)
       }
   }

Any help would be greatly appreciated. 任何帮助将不胜感激。 Thanks in advance! 提前致谢!

The problem was that I was not adding the capture device as an input to the capture session as well as not adding the output of my capture session. 问题是我没有将捕获设备添加为捕获会话的输入,也没有添加捕获会话的输出。

Hope this helps anyone else who was having trouble with avcapture devices. 希望这对使用捕获设备遇到麻烦的其他人有所帮助。 :) :)

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)
       }
   }

Add the output: 添加输出:

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)
}

Before adding the output, add the input: 在添加输出之前,请添加输入:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM