在 AVAudioEngine 用于输入后使用 AVAudioPlayer 播放声音

Playing a sound with AVAudioPlayer after AVAudioEngine has been utilized for input

我有一个应用程序涉及类似 Alexa 的数字助理。

我们使用 AVAudioEngine 成功地接收了我们的 Speech-To-Text 引擎的输入,然后使用 NLP 我们将该文本解释为请求并响应。

一旦我们收到命令,我们就会确认该命令带有音频,通过 AVAudioPlayer 播放。

这在我们的模拟器上不是问题,但在设备上我们注意到如果我们在 AVAudioEngine 初始化后的任何时间播放声音,音频不会在设备上播放。这些功能不会失败,我们的 audioPlayerDidFinishPlaying 在适当的时间触发,但听不到任何声音。

如果我们在应用程序首次启动时播放音频而不初始化录音,音频播放正常。如果我们停止录音并等待一到几秒后播放音频文件,则听不到任何声音。

我们需要能够在识别命令时停止输入,播放音频文件作为响应,然后继续录制。

我们做错了什么?

AVAudioEngine实例化和去初始化:

实例化:

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

取消初始化:

public func stopListening() {
    if audioEngine.isRunning {
        audioEngine.stop()
    }
    //Other code to stop recognition service
}

音频播放器:

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")
    }
}

问题出在 audioSession.record 会阻止其他音频输出。您可以使用 .playAndRecord 而不是 .record:

try audioSession.setCategory(.playAndRecord, mode: .measurement, options: .duckOthers)

如果您在收听时需要 .record 的值,您可以在 stopListening 方法中编辑 audioSession