我正在使用新的iOS10框架进行实时语音识别。我使用AVCaptureSession
来获取音频。
我有一个"听"发出哔哔声以通知用户他可以开始说话。发出声音的最好方法是在captureOutput(:didOutputSampleBuffer..)
的第一次通话,但是如果我在开始会话后尝试播放声音,那么声音就不会播放。没有错误被抛出..它只是默默无法发挥...
我尝试了什么:
AudioServicesPlaySystemSound...()
)AVPlayer
似乎无论我在做什么,都不可能在触发识别后触发播放任何类型的音频(不确定它是否具体是AVCaptureSession
或SFSpeechAudioBufferRecognitionRequest
/ SFSpeechRecognitionTask
...)
有什么想法吗? Apple even recommends playing a "listening" sound effect(和Siri一起做)但是我找不到任何参考/示例来说明如何实际做到这一点......(他们的" SpeakToMe"示例没有发出声音)
答案 0 :(得分:2)
嗯,显然有很多"规则"必须遵循以便成功开始语音识别会话并播放"听"只有在识别真正之后(之后)才会生效。
会话设置&必须在主队列上调用触发器。所以:
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()
}