AVFoundation- 相机切换一次,且仅一次

AVFoundation- Camera Switches Once, And Only Once

我在 Whosebug 上找到了 this great thread here,并用它在 Swift 中编写了我的 switchCamera 函数。

我已经让它工作了,所以当我按下我的按钮时,摄像头会切换到后置摄像头。但是,一旦我再次按下它,它就不会切换回前置摄像头。我在不允许再次切换相机的代码中做错了什么?

一个额外的注意事项:当我翻译上面线程中提到的代码时,我无法在我的 cameraWithPosition() 中 return nil。不确定这是否是导致我的问题的原因。

我的代码:

@IBAction func switchCamera(sender: UIButton) {
    let currentCameraInput: AVCaptureInput = session.inputs[0] as! AVCaptureInput
    session.removeInput(currentCameraInput)

    let newCamera: AVCaptureDevice?
    if(captureDevice!.position == AVCaptureDevicePosition.Back){
        println("Setting new camera with Front")
        newCamera = self.cameraWithPosition(AVCaptureDevicePosition.Front)
    } else {
        println("Setting new camera with Back")
        newCamera = self.cameraWithPosition(AVCaptureDevicePosition.Back)
    }

    let newVideoInput = AVCaptureDeviceInput(device: newCamera!, error: nil)
    if(newVideoInput != nil) {
        session.addInput(newVideoInput)
    } else {
        println("Error creating capture device input")
    }

    session.commitConfiguration()

}

func cameraWithPosition(position: AVCaptureDevicePosition) -> AVCaptureDevice {
    let devices = AVCaptureDevice.devices()
    for device in devices {
            if(device.position == position){
                return device as! AVCaptureDevice
            }
    }
    return AVCaptureDevice()
}

5 分钟后,我 post 解决了这个问题,哈哈。

我的问题是我没有将我的初始 captureDevice 设置为等于我称为 newCamera 的新创建的 AVCaptureDevice。

所以为了解决这个问题,我只是在 switchCamera() 结束时做了这个...

captureDevice! = newCamera!

您实现切换相机的方式很好,并且只有在您只有一个视频 AVCaptureDevice 输入时才有效。考虑具有多个 AVCaptureDevice 输入(音频和视频)的情况。在那种情况下,您不能保证以下行 -:

 let currentCameraInput: AVCaptureInput = session.inputs[0] as! AVCaptureInput
 session.removeInput(currentCameraInput) 

在这种情况下,当您点击 toggleCamera 按钮时,它崩溃并出现以下错误

Couldn't add back facing video input
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** Multiple audio/video AVCaptureInputs are not currently supported.'
*** First throw call stack:
(0x38f2f2a3 0x3725997f 0x39aff977 0x39aff091 0xe943d 0xe7875 0x3a4de0a5 0x3a4de057 0x3a4de035 0x3a4dd8eb 0x3a4ddde1 0x3a4065f1 0x3a3f3801 0x3a3f311b 0x37cad5a3 0x37cad1d3 0x38f04173 0x38f04117 0x38f02f99 0x38e75ebd 0x38e75d49 0x37cac2eb 0x3a4472f9 0xdf1ab 0x36324b20)

为了克服这个问题,我用不同的方式实现了它。所以我在 CameraController.swift 中的切换相机代码看起来像这样 -:

// toggleCamera basic purpose is to toggle the camera from front to back or vice versa as per user selection

func toggleCamera(){
        println("toggleCamera -----")
        var error:NSError?
        var backCameraDevice:AVCaptureDevice?
        var audio:AVCaptureDevice?
        var frontCameraDevice:AVCaptureDevice?
        var rearCamera: AVCaptureInput?
        var frontCamera: AVCaptureInput?
        for device in availableCameraDevices as! [AVCaptureDevice] {
           if device.position == .Back {
            self.backCameraDevice = device
           }
           else if device.position == .Front {
            self.frontCameraDevice = device
           }
        }

        if let validVideoFrontDevice = self.frontCameraDevice {
                self.frontCamera = AVCaptureDeviceInput.deviceInputWithDevice(validVideoFrontDevice, error: &error) as! AVCaptureDeviceInput
        }

        if let validVideoBackDevice = self.backCameraDevice {
                self.rearCamera = AVCaptureDeviceInput.deviceInputWithDevice(validVideoBackDevice, error: &error) as! AVCaptureDeviceInput
        }

        session.beginConfiguration()
        let inputs = session.inputs as! [AVCaptureInput]
        let newCamera: AVCaptureDevice?
        if(currentCameraDevice!.position == AVCaptureDevicePosition.Back){
            println("Setting new camera with Front")
            newCamera = self.frontCameraDevice
            if self.hasFrontCamera {
                if let validBackDevice = self.rearCamera {
                    if contains(inputs, validBackDevice) {
                        session.removeInput(validBackDevice)
                    }
                }
                if let validFrontDevice = self.frontCamera {
                    if !contains(inputs, validFrontDevice) {
                        session.addInput(validFrontDevice)
                    }
                }
            }
        } else {
            println("Setting new camera with Back")
            newCamera = self.backCameraDevice
            if let validFrontDevice = self.frontCamera {
                if contains(inputs, validFrontDevice) {
                    session.removeInput(validFrontDevice)
                }
            }
            if let validBackDevice = self.rearCamera {
                if !contains(inputs, validBackDevice) {
                    session.addInput(validBackDevice)
                }
            }
        }
        session.commitConfiguration()
        if let validError = error {
            println("Device setup error occured \(validError.localizedDescription)")
        }
        currentCameraDevice! = newCamera!
}

    /// The Bool property to determine if current device has front camera.

public var hasFrontCamera: Bool = {
        let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
        for  device in devices  {
            let captureDevice = device as! AVCaptureDevice
            if (captureDevice.position == .Front) {
                return true
            }
        }
        return false
        }()

在我的视图控制器中:

@IBAction func toggleCamera(sender: UIButton) {
    //  toggle the camera side
    println("toggling the camera side")
    self.cameraController.toggleCamera()
}

希望对您有所帮助。 谢谢