I have an app that involves an Alexa like digital assistant.
We are successfully receiving input for our Speech-To-Text engine with AVAudioEngine, and then using NLP we are interpreting that text into requests and responding.
Once we receive a command, we acknowledge that command with audio, played through AVAudioPlayer.
This wasn't a problem on our simulators, but on device we have noticed that if we play a sound any time after the AVAudioEngine has been initialized, the audio does not play on the device. The functions do not fail, and our audioPlayerDidFinishPlaying
fires at the appropriate time, but no audio is heard.
If we play audio when the app first launches without initializing the recording, the audio plays fine. If we stop the recording and wait one to many seconds later to play an audio file, no audio is ever heard.
We need to be able to stop the input when a command is recognized, play an audio file in response, and then resume recording.
What are we doing wrong?
AVAudioEngine instantiation and de-initialization:
Instantiation:
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
} catch {
validatePermissions()
}
let inputNode = audioEngine.inputNode
De-initialization:
public func stopListening() {
if audioEngine.isRunning {
audioEngine.stop()
}
//Other code to stop recognition service
}
Audio Player:
func playAudio() {
let path = Bundle.main.path(forResource: fileName, ofType:nil)!
let url = URL(fileURLWithPath: path)
do {
myAudioPlayer = try AVAudioPlayer(contentsOf: url)
myAudioPlayer.delegate = self
myAudioPlayer.play()
} catch {
print("Error playing audio")
}
}
The problem is with the audioSession
, with .record
it prevents other audio outputs. You can use .playAndRecord
instead of .record
:
try audioSession.setCategory(.playAndRecord, mode: .measurement, options: .duckOthers)
You can edit audioSession
in your stopListening
method if you need a value of .record
while listening.