代码之家  ›  专栏  ›  技术社区  ›  Aakash Dave

avcapturephotooutput-设置不能重复使用

  •  0
  • Aakash Dave  · 技术社区  · 7 年前

    我正在运行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 每次使用不同的闪光模式时都要更换。我已经回答了几个问题,但主要是关于手电筒的问题。我在找闪光灯。

    任何帮助都非常感谢。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Pratap    7 年前

    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 不需要。

    CurrentFlashMode enum ,这是为了保持清楚:

    枚举当前FlashMode{ 断案 案 案例自动 }

    然后在拍摄照片时使用它:

     @IBAction func captureButtonPressed(_ sender: UIButton) {
            let currentSettings = getSettings(camera: currentCamera, flashMode: currentFlashMode)
            photoOutput.capturePhoto(with: currentSettings, delegate: self)
        }
    
        2
  •  0
  •   Ethan    7 年前

    引用 AVCapturePhotoSettings 医生,见最后一个重要部分:

    总结

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

    宣言

    类avCapturePhotosettings:nsObject 讨论

    要拍摄照片,请创建并配置一个avCapturePhotosettings对象,然后将其传递给avCapturePhotoOutput CapturePhoto(with:delegate:)方法。 avCapturePhotosettings实例可以包含任何设置组合,而不管该组合是否对给定的捕获会话有效。当您通过将照片设置对象传递给avCapturePhotoOutputCapturePhoto(with:delegate:)方法来启动捕获时,照片捕获输出将验证您的设置以确保确定性行为。例如,flashmode设置必须指定照片输出__的受支持的flashmode s数组中存在的值。有关详细的验证规则,请参阅下面的每个属性说明。

    重要的

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

    和你一样的问题: this github issue