Challenges with AVFoundation Not Honouring Locked Exposure Settings

For our application, we are aiming to have full control over setting and locking the camera exposure settings when taking a video. We’re working with Apple’s AVFoundation framework for a range of devices, but most of the development is focused on the iPad 8 front camera. The manual settings are specific to our use, so we aim to use the custom exposure mode with e.g ISO = 100, exposureDuration = 1/60, and a fixed white balance. The duration, ISO, and white balance are all set in advance of recording, but when we begin we can see that something is still adjusting and compensating for lighting changes. We then also tried locking the exposure mode after setting the custom values, but there appears to be a delay in this lock taking effect. While tracking the ISO during a recording, we see that the ISO values change in the first second of the recording, leading to oversaturated images, despite our efforts to keep it locked.

This is our attempt to lock the settings using custom mode, which we don’t adjust ourselves during the recording, but it does not work as expected:

func setCameraSettings(newValueISO: Float, newValueDuration: CMTime){
        do {
        try cameraDevice?.lockForConfiguration()
            cameraDevice?.automaticallyAdjustsVideoHDREnabled = false
            cameraDevice?.setExposureModeCustom(duration: newValueDuration, iso: newValueISO, completionHandler: { [self] _ in
            cameraDevice?.setWhiteBalanceModeLocked(with: cameraDevice!.deviceWhiteBalanceGains)
            
            
                if ((cameraDevice!.isFocusModeSupported(.locked)))  {
                    do {
                        cameraDevice!.focusMode = .locked
                        debugPrint("Focus mode set to locked.")
                    }
                }
        cameraDevice?.unlockForConfiguration()
        
        })
        
        } catch {
            debugPrint("Error adjusting the exposure")
            cameraDevice?.unlockForConfiguration()
            
        }
    }

We then tried to lock the exposure mode after setting the custom values, but it then changes during the first second of the recording. We also explicitly tried setting exposureTargetBias to 0, but this made no difference.

func setCameraSettings(newValueISO: Float, newValueDuration: CMTime){
        guard let camera = cameraDevice else { return }
        
        do {
            if camera.isExposureModeSupported(.custom) {
                do {
                    try camera.lockForConfiguration()


                    let customExposureBias: Float = 0
                    //camera.setExposureTargetBias(customExposureBias, completionHandler: nil)
                    if camera.isExposureModeSupported(.custom) {
                        camera.setExposureModeCustom(duration: newValueDuration, iso: newValueISO) { [weak camera ] _ in
                            guard let camera = camera else { return }
                            if camera.isExposureModeSupported(.locked) {
                                camera.exposureMode = .locked
                            }
                            
                        }
                    }
                    camera.unlockForConfiguration()
                    print("Exposure settings locked with custom values.")
                } catch {
                    print("Failed to lock configuration for capture device: \(error.localizedDescription)")
                    camera.unlockForConfiguration()
                }
            } else {
                print("Custom exposure mode is not supported.")
            }
        }
    }

We would very much appreciate input on how to keep the manually selected camera settings fixed throughout the video recording.