admin管理员组

文章数量:1313616

I'm working on an iOS app using AVFoundation to handle real time video capture and object detection. However, I’ve encountered a frustrating issue when switching between the Wide and Ultra Wide cameras while the torch is ON.

Issue:

  • If the torch is ON and I switch from the Wide to the Ultra Wide camera, the camera completely freezes
  • If the Ultra Wide camera is active and I try to turn ON the torch, the camera freezes as well
  • The iPhone Camera app allows using the torch with Ultra Wide while recording video, so this should be possible via AVFoundation
  1. Is this a known limitation of AVFoundation or is there a workaround to enable the torch on Ultra-Wide?
  2. How does Apple’s default Camera app manage to enable the torch with Ultra Wide without crashing?
  3. What’s the correct approach to avoid the camera freezing when toggling between Wide and Ultra Wide with the torch active?
  4. Is there a proper way to synchronize torch activation with camera switching in AVFoundation?

Current Code (Torch + Camera Switch)

@IBAction func ultrawideCameraTapped(_ sender: Any?) {
    DispatchQueue.global(qos: .userInitiated).async { [weak self] in
        guard let self = self else { return }

        let isSwitchingToUltraWide = !self.isUsingFisheyeCamera
        let cameraType: AVCaptureDevice.DeviceType = isSwitchingToUltraWide ? .builtInUltraWideCamera : .builtInWideAngleCamera
        let cameraName = isSwitchingToUltraWide ? "Ultra Wide" : "Wide"

        guard let selectedCamera = AVCaptureDevice.default(cameraType, for: .video, position: .back) else {
            DispatchQueue.main.async {
                self.showAlert(title: "Camera Error", message: "\(cameraName) camera is not available on this device.")
            }
            return
        }

        do {
            let currentInput = self.videoCapture.captureSession.inputs.first as? AVCaptureDeviceInput

            self.videoCapture.captureSession.beginConfiguration()

            // If switching to Ultra-Wide with Torch ON, attempt workaround
            if isSwitchingToUltraWide && self.isFlashlightOn {
                self.forceEnableTorchThroughWide()
            }

            if let currentInput = currentInput {
                self.videoCapture.captureSession.removeInput(currentInput)
            }

            let videoInput = try AVCaptureDeviceInput(device: selectedCamera)
            self.videoCapture.captureSession.addInput(videoInput)

            self.videoCapture.captureSessionmitConfiguration()

            self.videoCapture.updateVideoOrientation()

            DispatchQueue.main.async {
                if let barButton = sender as? UIBarButtonItem {
                    barButton.title = isSwitchingToUltraWide ? "Wide" : "Ultra Wide"
                    barButton.tintColor = isSwitchingToUltraWide ? UIColor.systemGreen : UIColor.white
                }
                print("Switched to \(cameraName) camera.")
            }

            self.isUsingFisheyeCamera.toggle()
        } catch {
            DispatchQueue.main.async {
                self.showAlert(title: "Camera Error", message: "Failed to switch to \(cameraName) camera: \(error.localizedDescription)")
            }
        }
    }
}

func forceEnableTorchThroughWide() {
    DispatchQueue.global(qos: .userInitiated).async {
        guard let wideCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back), wideCamera.hasTorch else {
            DispatchQueue.main.async {
                self.showAlert(title: "Torch Error", message: "Torch is not available on this device.")
            }
            return
        }

        do {
            try wideCamera.lockForConfiguration()
            wideCamera.torchMode = .on
            self.isFlashlightOn = true
            wideCamera.unlockForConfiguration()
        } catch {
            DispatchQueue.main.async {
                self.showAlert(title: "Torch Error", message: "Error while forcing torch through Wide Camera: \(error.localizedDescription)")
            }
        }
    }
}

本文标签: