【问题标题】:AVCapturePhotoOutput - settings may not be reusedAVCapturePhotoOutput - 不能重复使用设置
【发布时间】:2019-01-08 02:57:10
【问题描述】:

我正在运行 ios 12 swift 4.2。

我已经实现了一个基本的摄像头捕获会话,并且正在单击其中的图像。一切都很好,直到我在自动/开/关模式之间切换闪光灯。单击第一张照片然后更改闪光模式后,应用程序崩溃并出现错误:

[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] Settings may not be re-used'

以下是相机实现:

var captureSession: AVCaptureSession!
var videoPreviewLayer: AVCaptureVideoPreviewLayer!
var capturePhotoOutput: AVCapturePhotoOutput!
let capturePhotoSettings = AVCapturePhotoSettings()


var previewView: UIView!


override func viewDidLoad() {
    startCameraSession()
    setupCaptureOutput()
}

@objc // Tap on a button to capture
func takePhotoOnTap() {
    guard let capturePhotoOutput = self.capturePhotoOutput else { return }

    capturePhotoSettings.isAutoStillImageStabilizationEnabled = true
    capturePhotoSettings.isHighResolutionPhotoEnabled = true
    capturePhotoSettings.flashMode = .auto
    let _ = getSettings(camera: captureDevice!, flashMode: spotmiCameraOptions.flashMode)
    capturePhotoOutput.capturePhoto(with: capturePhotoSettings, delegate: self)
}


    //This is a delegate method from the button
func toggleFlash(mode: FlashMode) {

    switch mode {
    case .auto:
        capturePhotoSettings.flashMode = .auto
    case .enabled:
        capturePhotoSettings.flashMode = .on
    case .disabled:
        capturePhotoSettings.flashMode = .off
    }

}


func setupCaptureOutput() {
    capturePhotoOutput = AVCapturePhotoOutput()
    capturePhotoOutput.isHighResolutionCaptureEnabled = true
    captureSession.addOutput(capturePhotoOutput)
}

func startCameraSession() {

    let captureDevice = AVCaptureDevice.default(.builtInDualCamera, for: AVMediaType.video, position: .back)

    do {
        let input = try AVCaptureDeviceInput(device: captureDevice!)
        captureSession = AVCaptureSession()
        captureSession.addInput(input)
        videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        videoPreviewLayer.videoGravity = .resizeAspectFill
        videoPreviewLayer.frame = self.view.layer.bounds
        camcontainer.layer.addSublayer(videoPreviewLayer)
        captureSession.startRunning()
    } catch {
        print(error.localizedDescription)
    }


}

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {
    guard error == nil, let sampleBuffer = photoSampleBuffer else {
        print("error capturing photo due to \(String(describing: error?.localizedDescription))")
        return
    }
    guard let imageData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer) else  { return }

    let capturedImage = UIImage(data: imageData, scale: 1.0)
    if let image = capturedImage {
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
    }
}

    func getSettings(camera: AVCaptureDevice, flashMode: FlashMode) -> AVCapturePhotoSettings {
    let settings = capturePhotoSettings

    if camera.hasFlash {
        switch flashMode {
//            case .auto: settings.flashMode = .auto
        case .enabled: settings.flashMode = .on
        case .disabled: settings.flashMode = .off
        default: settings.flashMode = .auto
        }
    }
    return settings
}

我真的不知道如何准确地重复使用captureSettings 并每次使用不同的闪存模式进行更改。我经历了几个问题,但它们主要是关于手电筒的。我正在寻找闪光灯。

非常感谢任何帮助。

【问题讨论】:

    标签: ios swift camera avfoundation avcapturesession


    【解决方案1】:

    AVCapturePhotoSettings对象是唯一的,不能重复使用,所以每次使用这种方法都需要获取新的设置:

    func getSettings(camera: AVCaptureDevice, flashMode: CurrentFlashMode) -> AVCapturePhotoSettings {
        let settings = AVCapturePhotoSettings()
    
        if camera.hasFlash {
            switch flashMode {
               case .auto: settings.flashMode = .auto
               case .on: settings.flashMode = .on
               default: settings.flashMode = .off
            }
        }
        return settings
    }
    

    如您所见,lockConfiguration 是不需要的。

    CurrentFlashModeenum,创建它是为了保持清晰:

    枚举 CurrentFlashMode { 关闭案例 案例 案例自动 }

    然后在拍照时简单地使用它:

     @IBAction func captureButtonPressed(_ sender: UIButton) {
            let currentSettings = getSettings(camera: currentCamera, flashMode: currentFlashMode)
            photoOutput.capturePhoto(with: currentSettings, delegate: self)
        }
    

    【讨论】:

    • 感谢您的回答。如果你能看到,那就是我在这里所做的。
    • 创建您正在使用全局变量的“AVCapturePhotoSettings()”的新对象
    【解决方案2】:

    引用AVCapturePhotoSettings doc,见最后重要部分:

    总结

    用于单个照片拍摄请求的功能和设置规范。

    声明

    类 AVCapturePhotoSettings : NSObject 讨论

    要拍摄照片,您需要创建并配置一个 AVCapturePhotoSettings 对象,然后将其传递给 AVCapturePhotoOutput capturePhoto(with:delegate:) 方法。 AVCapturePhotoSettings 实例可以包含任何设置组合,无论该组合对于给定的捕获会话是否有效。当您通过将照片设置对象传递给 AVCapturePhotoOutputcapturePhoto(with:delegate:) 方法来启动捕获时,照片捕获输出会验证您的设置以确保确定性行为。例如, flashMode 设置必须指定存在于照片输出的 supportedFlashModes 数组中的值。详细的验证规则,请参见下面的每个属性说明。

    重要

    重复使用 AVCapturePhotoSettings 实例进行多次捕获是非法的。如果设置对象的 uniqueID 值与任何以前使用的设置对象的值匹配,则调用 capturePhoto(with:delegate:) 方法会引发异常 (invalidArgumentException)。 To reuse a specific combination of settings, use the init(from:) 初始化器,用于从现有照片设置对象创建一个新的、唯一的 AVCapturePhotoSettings 实例。

    和你一样的问题:this github issue

    【讨论】:

    • 嘿,我知道这一点。但也有我感到困惑的地方。我的意思是我应该如何实现它?我应该每次都分配新的设置吗?我该怎么做?
    • 你能解释一下那里到底发生了什么吗?您每次都在生成新设置。如果我是正确的?那么完成块发生了什么
    • 这不是我的代码,我想你只需使用AVCapturePhotoSettings.init 再试一次,忽略块的东西,看看它是否适合你。
    猜你喜欢
    • 2014-07-07
    • 1970-01-01
    • 2016-10-18
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 2018-03-10
    • 1970-01-01
    相关资源
    最近更新 更多