I am getting an application crash of my app when I am using mic in my case Microsoft Teams on the background and trying to record an audio inside of my app.
Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: IsFormatSampleRateAndChannelCountValid(format)'
Please refer to the code below:
func startRecording() {
// Clear all previous session data and cancel task
if recognitionTask != nil {
recognitionTask?.cancel()
recognitionTask = nil
}
// Create instance of audio session to record voice
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSession.Category.record, mode: AVAudioSession.Mode.measurement, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
} catch {
print("audioSession properties weren't set because of an error.")
}
self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
let inputNode = audioEngine.inputNode
guard let recognitionRequest = recognitionRequest else {
fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")
}
recognitionRequest.shouldReportPartialResults = true
self.recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in
var isFinal = false
if result != nil {
self.textField.text = result?.bestTranscription.formattedString
isFinal = (result?.isFinal)!
}
if error != nil || isFinal {
self.audioEngine.stop()
inputNode.removeTap(onBus: 0)
self.recognitionRequest = nil
self.recognitionTask = nil
self.micButton.isEnabled = true
}
})
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
self.recognitionRequest?.append(buffer)
}
self.audioEngine.prepare()
do {
try self.audioEngine.start()
} catch {
print("audioEngine couldn't start because of an error.")
}
self.textField.text = ""
}
I am pretty sure that the problem is somewhere here, but not sure how to fix it.
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
self.recognitionRequest?.append(buffer)
}
So the app was crashing because I didn't applied the correct microphone channel.
Create a protocol on the top of your code after the imports to represent an error in the file where u have:
let audioEngine = AVAudioEngine()
protocol FeedbackViewDelegate : AnyObject {
func showFeedbackError(title: String, message: String)
func audioDidStart(forType type : FeedbackViewType)
}
In the beginning add the return of boolean in your function
func startRecording() -> Bool {
}
Add this line of code in the sharedInstance
catch
part (it will prevent crash)
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSession.Category.playAndRecord, mode: AVAudioSession.Mode.measurement, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
} catch {
print("audioSession properties weren't set because of an error.")
delegate?.showFeedbackError(title: "Sorry", message: "Mic is busy")
return false
}
Return above will prevent code to be executed.
Create an extension in the view controller
extension codeFileName : FeedbackViewDelegate {
func showFeedbackError(title: String, message: String) {
}
}
(there is a millions of examples in the web) inside of the function you can create an alert and in "in" part use self