4
votes

I'm working on a video recording app, and need to be able to use a bluetooth mic as the audio input (if one is connected).

I have the following code to configure the audio input of an AVCaptureSession:

self.captureSession.usesApplicationAudioSession = YES;
self.captureSession.automaticallyConfiguresApplicationAudioSession = NO;

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];

self.microphone = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
audioInput = [AVCaptureDeviceInput deviceInputWithDevice:self.microphone error:&error];

if ([self.captureSession canAddInput:audioInput])
{
   [self.captureSession addInput:audioInput];
}

The problem is, the bluetooth mic never shows up as an available capture device (although it is paired properly). Printing out [AVCaptureDevice devices] results in:

enter image description here

So, no matter what I do, the audio is always coming from the iPad's built in mic.

1

1 Answers

0
votes

I also ran into this issue in the context of SFSpeechRecognizer. I wanted to record audio from a Bluetooth mic and convert it into text. First I switched the input in AVAudioSession:

// Activate bluetooth devices for recording
try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryRecord, with: [.allowBluetooth])
try? AVAudioSession.sharedInstance().setActive(true)

// Configure a bluetooth device for recording if available
let bluetoothRoutes = [AVAudioSessionPortBluetoothHFP]
let availableInputs = AVAudioSession.sharedInstance().availableInputs
if let bluetoothInput = (availableInputs?.filter{ bluetoothRoutes.contains($0.portType) })?.first {
    try? AVAudioSession.sharedInstance().setPreferredInput(bluetoothInput)
}

But even after setting AVCaptureSession's automaticallyConfiguresApplicationAudioSession property to false, AVCaptureDevice.devices() only showed me the built-in microphone and didn't record any audio from Bluetooth.

I ended up replacing AVCaptureDevice with AVAudioRecorder, which does respect the route change. Now I can record audio into a temporary file, which I pass to SFSpeechRecognizer.