【问题标题】:iOS10 Speech Recognition "Listening" sound effectiOS10语音识别“听”音效
【发布时间】:2016-12-12 07:40:33
【问题描述】:

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

我有一个“正在听”的哔声通知用户他可以开始说话了。发出该声音的最佳方式是在第一次致电captureOutput(:didOutputSampleBuffer..) 时,但如果我在开始会话后尝试播放声音,声音就不会播放。并且没有抛出错误..它只是默默地无法播放......

我尝试了什么:

  • 通过系统声音播放 (AudioServicesPlaySystemSound...())
  • 使用AVPlayer 播放资产
  • 还尝试了上述两种解决方案异步/同步主队列

似乎无论我在做什么,触发识别后都无法触发播放任何类型的音频(不确定是具体是AVCaptureSession还是SFSpeechAudioBufferRecognitionRequest/SFSpeechRecognitionTask...)

有什么想法吗? Apple even recommends playing a "listening" sound effect(用 Siri 自己做)但我找不到任何参考/示例来说明如何实际操作...(他们的“SpeakToMe”示例不播放声音)

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

【问题讨论】:

    标签: ios iphone speech-recognition


    【解决方案1】:

    好吧,显然,为了成功开始语音识别会话并仅在识别真正开始(之后)发挥“聆听”效果,必须遵循一系列“规则”。

    1. 必须在主队列上调用会话设置和触发。所以:

      DispatchQueue.main.async {
          speechRequest = SFSpeechAudioBufferRecognitionRequest()
          task = recognizer.recognitionTask(with: speechRequest, delegate: self)
          capture = AVCaptureSession()
          //.....
          shouldHandleRecordingBegan = true
          capture?.startRunning()
      }
      
    2. “聆听”效果应该是通过AVPlayer 播放的,而不是系统声音。

    3. 知道我们肯定录制的最安全的地方是在AVCaptureAudioDataOutputSampleBufferDelegate的委托调用中,当我们得到我们的第一个sampleBuffer回调时:

      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)
      }
      
    4. 识别效果的结束要容易得多:

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

    【讨论】:

      猜你喜欢
      • 2023-03-27
      • 1970-01-01
      • 2016-10-15
      • 2012-07-15
      • 1970-01-01
      • 2013-05-23
      • 2017-06-30
      • 2021-09-12
      相关资源
      最近更新 更多