iosswiftavfoundationavkit

AVCaptureSession.addInput(_:) is very slow when trying to record video


I'm working on a camera app that allows users to take photos and videos (with sound). While testing, I realized that if the user is on a FaceTime call and tries to use the camera, it stops working. The video feed is frozen and throws runtime errors like the following:

AVError(_nsError: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (561017449), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x300723240 {Error Domain=NSOSStatusErrorDomain Code=561017449 "(null)" UserInfo={AVErrorFourCharCode='!pri'}}})

After digging, I found out that the culprit is trying to activate the microphone on my AVCaptureSession like this:

if let audioDevice = AVCaptureDevice.default(for: .audio),
   let audioDeviceInput = try? AVCaptureDeviceInput(device: audioDevice),
   session.canAddInput(audioDeviceInput) {
       session.addInput(audioDeviceInput)
}

The change seemed easy: remove that bit of code from the AVCaptureSession setup logic, and just move it to right before the user tries to record a video. The problem is that if I do that the camera works as expected but there's a significant delay between the user tapping the button and the video to start recording, the camera feed even blanks for a second. If the microphone setup code is done when I'm setting up the AVCaptureSession, there's no delay whatsoever when the user taps the record button.

I've tried to run that code inside (and outside) the DispatchQueue I use to handle all the camera logic and nothing changed. I also tried to add it between session.beginConfiguration() and session.commitConfiguration() and it didn't change a thing either.


Solution

  • I ended up solving this issue by using two AVCaptureSessions. I have the one with the video feed always running, and only when the user taps the record button I start the audio one.

    That way, the recording is instant, and the microphone issues when not recording are gone because the session is not running, so the microphone is not active.

    As a bonus, now I also can run haptic feedback on the controls because the AVCaptureSession that handles the microphone is not running!