【问题标题】:DTMF tone in RecognitionListener.onReadyForSpeech() mistaken for speechRecognitionListener.onReadyForSpeech() 中的 DTMF 音调被误认为是语音
【发布时间】:2011-04-20 17:56:42
【问题描述】:

Google 语音搜索从您通过 startActivityForResult() 调用它的那一刻起,直到它的对话框显示,准备好接受您的演讲,都会有很大的延迟。

这要求用户在说话之前总是看着屏幕,等待对话框显示出来。

所以我正在考虑通过实现 RecognitionListener 并在 onReadyForSpeech() 中发出 DTMF 音来生成可听信号而不是对话框,如下面的 sn-p:

  @Override
  public void onReadyForSpeech(Bundle params) {
    Log.d(LCTAG, "Called when the endpointer is ready for the user to start speaking.");
    mToneGenerator.startTone(ToneGenerator.TONE_DTMF_1);
    try {
      Thread.sleep(50);
    } catch (InterruptedException e) {
      Log.e(LCTAG, "InterruptedException while in Thread.sleep(50).");        
      e.printStackTrace();
    } // SystemClock.sleep(50);
    mToneGenerator.stopTone();
  }

音调听起来很美,但...它也被麦克风“听到”,到达语音识别服务并总是产生识别错误ERROR_NO_MATCH

有没有办法解决这个问题?

【问题讨论】:

    标签: android speech-recognition voice-recognition


    【解决方案1】:

    这是一个随机的想法,很可能行不通。

    您可以尝试在播放音调时禁用麦克风(可能通过AudioManager.setMicrophoneMute)吗?

    【讨论】:

    • 好主意 (+1)。我很快实现了它,但它产生了相同的 ERROR_NO_MATCH 识别错误。静音是针对不同的输入流,或者哔声以某种方式通过“本地循环”传递到 SR 服务。
    • 叹气,很遗憾听到这个消息。您可以尝试使用其他设置(可能是输入流音量),但我觉得语音识别会覆盖(或忽略)设置。
    • 我还没能解决问题,但是你的回答是目前为止最好的,所以我接受了。
    • 谢谢,非常感谢。抱歉,我无法提供更多帮助,但如果我偶然遇到解决方案,我会告诉你的!
    【解决方案2】:

    这是我为我工作的代码,放入 RecognitionListener 的 onReadyForSpeech() 回调中。

    private void playSpeechReadyTone(){
        audioManager.setMicrophoneMute(true);
        MediaPlayer mediaPlayer = MediaPlayer.create(JarvisService.this, R.raw.doublebeep);
        mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
    
            @Override
            public void onCompletion(MediaPlayer arg0) {
                audioManager.setMicrophoneMute(false);
            }
        });
        mediaPlayer.start();    
    }
    

    【讨论】:

    • 据我了解setMicrophoneMute()totally unreliable。 IOW,它可能适用于某些手机,但不能保证适用于所有手机。
    【解决方案3】:

    恐怕没有一种简单干净的方法可以做到这一点。正如 srf 指定的那样,您不应该依赖 AudioManager.setMicrophoneMute(boolean),所以,AFAIK,可能的情况是:

    1. 在调用 SpeechRecognizer.startListening(intent) 之前播放音频文件:

      final MediaPlayer mediaPlayer = MediaPlayer.create(JarvisService.this, R.raw.doublebeep);
      mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
      
           @Override
          public void onCompletion(MediaPlayer player) {
              player.release();
              // Safety start Speech Recognizer
              mSpeechRecognizer.startListening(getSpeechRecognizerIntent());
          }
      });
      mediaPlayer.start();
      

    但是,这个解决方案有一个问题......如果在调用 RecognitionListener.onReadyForSpeech 之前可能会收到一个 RecognitionListener.onError(int error) 并且在这种情况下,您仍然每次都播放哔声(这会发生,例如,如果您未连接到 Internet 并且语音识别配置为在线工作)! 此外,您应该管理在音频(双哔)播放期间取消语音识别过程的情况。

    1. 在 onReadyForSpeech 回调中播放音频(阅读原始问题),但使用具有适当值的 RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS。就我而言,我的哔声真的很短(最多 1 秒),我将 RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS 设置为 4/5 秒。

    另请注意,正如谷歌文档所说:

    另请注意,某些值可能会导致不希望的或意外的结果 - 请谨慎使用!此外,根据识别器的实现,这些值可能无效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-06
      • 2010-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-27
      • 2013-04-23
      相关资源
      最近更新 更多