iOS10语音识别“听力”音效

我正在使用新的iOS10框架进行实时语音识别.我使用AVCaptureSession来获取音频.

我有一个“聆听”的嘟嘟声,通知用户他可以开始说话.放置声音的最佳方式是第一次调用captureOutput(:didOutputSampleBuffer ..),但如果我在开始会话后尝试播放声音,则声音将无法播放.没有错误被抛出..它只是默默无法发挥…

我尝试了什么:

>播放系统声音(AudioServicesPlaySystemSound …())
>使用AVPlayer播放资产
>还尝试了主队列上的上述解决方案async / sync

似乎无论我在做什么,触发识别后都不可能触发播放任何类型的音频(不确定它是否特别是AVCaptureSession或SFSpeechAudioBufferRecognitionRequest / SFSpeechRecognitionTask ……)

有任何想法吗? Apple even recommends playing a “listening” sound effect(和Siri一起做)但是我找不到任何参考/示例显示如何实际做到这一点……(他们的“SpeakToMe”示例不播放声音)

>我可以在触发会话之前播放声音,并且它确实有效(在完成播放声音时开始会话)但有时实际上是在识别识别时(主要是在使用BT耳机和从不同的AudioSession切换时)类别 – 我没有完成事件…) – 因为我需要一种方法来播放录音实际开始时的声音,而不是在它触发和交叉手指之前它不会延迟启动它… .

最佳答案 好吧,显然有一堆必须遵循的“规则”才能成功开始语音识别会话,并且只有在识别真正开始之后(之后)才能发挥“聆听”效果.

>会话设置&必须在主队列上调用触发器.所以:

DispatchQueue.main.async {
    speechRequest = SFSpeechAudioBufferRecognitionRequest()
    task = recognizer.recognitionTask(with: speechRequest, delegate: self)
    capture = AVCaptureSession()
    //.....
    shouldHandleRecordingBegan = true
    capture?.startRunning()
}

>“收听”效果应该是通过AVPlayer的播放器,而不是系统声音.
>当我们得到第一个sampleBuffer回调函数时,最安全的地方就是在AVCaptureAudioDataOutputSampleBufferDelegate的代理调用中知道我们肯定会记录的:

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {

    //only once per recognition session
    if shouldHandleRecordingBegan {
        shouldHandleRecordingBegan = false

        player = AVPlayer(url: Bundle.main.url(forResource: "listening", withExtension: "aiff")!)
        player.play()            

        DispatchQueue.main.async {
            //call delegate/handler closure/post notification etc...
        }
    }

    // append buffer to speech recognition
    speechRequest?.appendAudioSampleBuffer(sampleBuffer)
}

>识别效果结束很容易:

var ended = false

if task?.state == .running || task?.state == .starting {
    task?.finish() // or task?.cancel() to cancel and not get results.
    ended = true
}

if true == capture?.isRunning {
    capture?.stopRunning()
}

if ended {
    player = AVPlayer(url: Bundle.main.url(forResource: "done", withExtension: "aiff")!)
    player.play()
}
点赞