Ios 在不删除previewLayer的情况下开始新的captureSession

Ios 在不删除previewLayer的情况下开始新的captureSession,ios,swift,avcapturesession,Ios,Swift,Avcapturesession,我正在为CameraView创建一个customView,它工作得很好,但是我现在正在从后摄像头更改为前摄像头。我现在已经通过下面的步骤完成了。然而,这似乎创造了一个糟糕的用户体验,它删除了previewLayer(屏幕变为白色),然后正确显示前摄像头。有没有一种方法可以创造更好的用户体验,在显示新会话之前,不要在1秒内将所有内容都变成白色 切换摄像头 func switchCamera() { if usingbackCamera == true { endSessio

我正在为CameraView创建一个customView,它工作得很好,但是我现在正在从后摄像头更改为前摄像头。我现在已经通过下面的步骤完成了。然而,这似乎创造了一个糟糕的用户体验,它删除了previewLayer(屏幕变为白色),然后正确显示前摄像头。有没有一种方法可以创造更好的用户体验,在显示新会话之前,不要在1秒内将所有内容都变成白色

切换摄像头

func switchCamera() {
    if usingbackCamera == true {
        endSession()
        beginSession(frontCamera!)
        usingbackCamera = false
        self.cameraView.bringSubviewToFront(actionView)

    } else {
        endSession()
        beginSession(backCamera!)
        usingbackCamera = true
        self.cameraView.bringSubviewToFront(actionView)
    }
}
开始会话

func beginSession(device: AVCaptureDevice) {

    do {
        captureSession.addInput(try AVCaptureDeviceInput(device: device))
        self.previewLayer?.removeFromSuperlayer()
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

        self.cameraView.layer.addSublayer(previewLayer!)

        previewLayer?.frame = self.cameraView.bounds
        captureSession.startRunning()

        stillImageOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]
        if captureSession.canAddOutput(stillImageOutput) {
            captureSession.addOutput(stillImageOutput)
        }
        if captureSession.canAddOutput(videoOutput) {
            captureSession.addOutput(videoOutput)
        }



    } catch let err as NSError {
        print(err)
    }

}
func endSession() {
    self.previewLayer?.removeFromSuperlayer()
    captureSession.stopRunning()
    captureSession = AVCaptureSession()

}
结束会话

func beginSession(device: AVCaptureDevice) {

    do {
        captureSession.addInput(try AVCaptureDeviceInput(device: device))
        self.previewLayer?.removeFromSuperlayer()
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

        self.cameraView.layer.addSublayer(previewLayer!)

        previewLayer?.frame = self.cameraView.bounds
        captureSession.startRunning()

        stillImageOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]
        if captureSession.canAddOutput(stillImageOutput) {
            captureSession.addOutput(stillImageOutput)
        }
        if captureSession.canAddOutput(videoOutput) {
            captureSession.addOutput(videoOutput)
        }



    } catch let err as NSError {
        print(err)
    }

}
func endSession() {
    self.previewLayer?.removeFromSuperlayer()
    captureSession.stopRunning()
    captureSession = AVCaptureSession()

}
拍照

func takePicture() {


    if let videoConnection = stillImageOutput.connectionWithMediaType(AVMediaTypeVideo){
        videoConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
        stillImageOutput.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: {
            (sampleBuffer, error) in


                let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
                let dataProvider  = CGDataProviderCreateWithCFData(imageData)
                let cgImageRef = CGImageCreateWithJPEGDataProvider(dataProvider, nil, true, CGColorRenderingIntent.RenderingIntentDefault)

                let image = UIImage(CGImage: cgImageRef!, scale: 1.0, orientation: UIImageOrientation.Right)

                self.previewImageView.image = image
                self.previewImageView.hidden = false
                self.cameraView.bringSubviewToFront(self.previewImageView)





        })
    }


}

我认为在更改输入设备时不必删除预览层。 该层已绑定到会话,您只需停止会话,删除原始输入并添加新输入,然后再次启动会话

我通过自定义渲染创建捕获视图,但我认为过程将是相同的

捕获片段:

    for output in session.outputs {
        if let capture = output as? AVCaptureStillImageOutput{
            for connection in (capture.connections as! [AVCaptureConnection]){
                for port in (connection.inputPorts as! [AVCaptureInputPort]){
                    if port.mediaType == AVMediaTypeVideo{
                        capture.captureStillImageAsynchronouslyFromConnection(connection, completionHandler: {(buffer, err) -> Void in
                            if err != nil{
                                print(err)
                            }
                            let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
                            guard let image = CIImage(data: imageData) else{
                                completion(nil)
                                return
                            }
                            let rotatedImage = image.imageByApplyingTransform(CGAffineTransformMakeRotation(-CGFloat(M_PI_2)))
                        })
                    }
                }
            }
        }
    }

从后摄像头切换到前摄像头时,无需停止captureSession并再次启动它,反之亦然

您所需要做的就是删除旧的捕获会话输入,添加新的捕获会话输入以及在开始/提交会话配置块之间的所有输入

下面是一个粗略的例子:

  func switchCamera() {
    //begin configuration changes
    captureSession.beginConfiguration()

    //remove the previous inputs
    let inputs = captureSession.inputs as! [AVCaptureInput]
    for oldInput:AVCaptureInput in inputs {
        captureSession.removeInput(oldInput)
    }

    //add the new input
    if usingbackCamera == true {
        addInput(frontCamera!)
        usingbackCamera = false
        self.cameraView.bringSubviewToFront(actionView)

    }
    else {
        addInput(backCamera!)
        usingbackCamera = true
        self.cameraView.bringSubviewToFront(actionView)
    }

    //end the configuration
    captureSession.commitConfiguration()
}


func addInput(device: AVCaptureDevice) {

    do {
        captureSession.addInput(try AVCaptureDeviceInput(device: device))

    } catch let err as NSError {
        print(err)
    }

}

这很好,但是切换相机后,拍摄的照片返回
空样本缓冲区。“
你是说样本缓冲区为空还是图像数据?我改变主意了,这是我真正的建议。从session.outputs中查找输出,但不是从您声明的stillImageOutput实例中查找。您能否提供一个片段作为答案,我不确定您的意思?endConfiguration不是captureSessionCorrect@PeterPik的成员,它应该是
commitConfiguration
,没有使用Xcode直接在这里输入,我忘记了它是
commitConfiguration
而不是
endConfiguration