Reputation: 1
I want my app to recognize speech from the microphone and allow audio in the background to keep playing.
My app recognizes speech coming in through the microphone and converts it to text. When my app launches it shuts down any audio playing in the background.
Is it possible to let the background audio continue to play while my app listens for speech using the microphone?
Stripped down code:
import UIKit
import Speech
class ViewController: UIViewController {
public private(set) var isRecording = false
private var audioEngine: AVAudioEngine!
private var inputNode: AVAudioInputNode!
private var audioSession: AVAudioSession!
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
override func viewDidLoad() {
super.viewDidLoad()
}
override public func viewDidAppear(_ animated: Bool) {
checkPermissions()
startRecording()
isRecording.toggle()
}
private func startRecording() {
guard let recognizer = SFSpeechRecognizer(), recognizer.isAvailable else {
handleError(withMessage: "Speech recognizer not available.")
return
}
recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
recognitionRequest!.shouldReportPartialResults = true
recognizer.recognitionTask(with: recognitionRequest!) { (result, error) in
guard error == nil else { self.handleError(withMessage: error!.localizedDescription); return }
guard let result = result else { return }
print(result.bestTranscription.segments)
}
audioEngine = AVAudioEngine()
inputNode = audioEngine.inputNode
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, _) in
self.recognitionRequest?.append(buffer)
}
audioEngine.prepare()
do {
audioSession = AVAudioSession.sharedInstance()
try audioSession.setCategory(.record, mode: .spokenAudio, options: .duckOthers)
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
try audioEngine.start()
} catch {
handleError(withMessage: error.localizedDescription)
}
}
private func checkPermissions() {
SFSpeechRecognizer.requestAuthorization { authStatus in
DispatchQueue.main.async {
switch authStatus {
case .authorized: break
default: self.handlePermissionFailed()
}
}
}
}
private func handlePermissionFailed() {
// Present an alert asking the user to change their settings.
let ac = UIAlertController(title: "This app must have access to speech recognition to work.",
message: "Please consider updating your settings.",
preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Open settings", style: .default) { _ in
let url = URL(string: UIApplication.openSettingsURLString)!
UIApplication.shared.open(url)
})
ac.addAction(UIAlertAction(title: "Close", style: .cancel))
present(ac, animated: true)
}
private func handleError(withMessage message: String) {
// Present an alert.
let ac = UIAlertController(title: "An error occured", message: message, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}
When I run my app and there is audio running in the background my app pauses the audio. I tried exiting my app and restarting the audio but when I return to my app it once again pauses the background audio. I would like the audio to keep playing while my app is using the microphone to listen.
I tried removing "options: .duckOthers" but it made no difference.
I believe what I want to do is possible. Shazam, for instance, can play a song on the speaker and simultaneously use the microphone to listen to it and identify it.
Upvotes: 0
Views: 687