4

我正在開發一個使用android SpeechRecognizer的應用程序。我使用它來做簡單的事情。我點擊一個按鈕,我的SpeechRecognizer開始聽,並從我所說的得到了一些結果。可以使SpeechRecognizer更快?

容易吧?那麼,我的問題是我需要快速製作SpeechRecognizer。我的意思是,我點擊我的按鈕,我說「你好」,SpeechRecognizer需要3-4秒的時間才能返回可能結果的數組。我的問題是:

可以使SpeechRecognizer返回結果更快? 或者花費更少的時間來結束聽力意向並開始處理聽力內容? 也許另一種方式來做到這一點?這會有比這更好的表現嗎?

我被檢查庫,我看到這3個參數:

EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS:

的時候,它應該採取我們不再聽到演講考慮 輸入完成後的金額。

EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS

話語的最小長度。

EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS

的時候,我們停止後,聽到講話 考慮輸入可能完成,它應該走量。

http://developer.android.com/intl/es/reference/android/speech/RecognizerIntent.html

我已經嘗試了所有的人,但它不工作,也許我不使用他們分辯。這裏是我的代碼:

public class MainActivity extends Activity { 
private static final String TIME_FORMAT = "%02d:%02d:%02d"; 
private final String TAG = "MainActivity"; 

private StartTimerButton mSpeakButton; 
private CircleProgressBar mCountdownProgressBar; 
private CountDownTimer mCountDownTimer; 
private TextView mTimer; 
private int mRunSeconds = 0; 
private SpeechRecognizer mSpeechRecognizer; 
private Intent mSpeechRecognizerIntent; 
private boolean mIsListening = false; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    mRunSeconds = 0; 
    mTimer = (TextView) findViewById(R.id.timerText); 
    mCountdownProgressBar = (CircleProgressBar) findViewById(R.id.progressBar); 
    mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this); 
    mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 
    mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 
      RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); 
    mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, 
      this.getPackageName()); 

//   mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 
//    1000); 
//  mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 
//    1000); 
//  mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 
//    1000); 

    SpeechRecognitionListener listener = new SpeechRecognitionListener(); 
    mSpeechRecognizer.setRecognitionListener(listener); 
    mSpeakButton = (StartTimerButton) findViewById(R.id.btnSpeak); 
    mSpeakButton.setReadyState(false); 
    mSpeakButton.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      if (mSpeakButton.isReady()) { 
       if (!mIsListening) 
        mSpeechRecognizer.startListening(mSpeechRecognizerIntent); 
      } else 
       mSpeakButton.setReadyState(true); 
     } 
    }); 

}  

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    return true; 
} 

public void onSpeechResults(ArrayList<String> matches) { 
    for (String match : matches) { 

     match = match.toLowerCase(); 
     Log.d(TAG, "Got speech: " + match); 

     if (match.contains("go")) { 
      //Do Something 
      mSpeechRecognizer.stopListening(); 
     } 
     if (match.contains("stop")) { 
      //Do Something 
      mSpeechRecognizer.stopListening(); 
     } 
    } 
} 

protected class SpeechRecognitionListener implements RecognitionListener 
{ 

    @Override 
    public void onBeginningOfSpeech() 
    { 
     //Log.d(TAG, "onBeginingOfSpeech"); 
    } 

    @Override 
    public void onBufferReceived(byte[] buffer) 
    { 

    } 

    @Override 
    public void onEndOfSpeech() 
    { 
     //Log.d(TAG, "onEndOfSpeech"); 
    } 

    @Override 
    public void onError(int error) 
    { 
     mSpeechRecognizer.startListening(mSpeechRecognizerIntent); 

     //Log.d(TAG, "error = " + error); 
    } 

    @Override 
    public void onEvent(int eventType, Bundle params) 
    { 

    } 

    @Override 
    public void onPartialResults(Bundle partialResults) 
    { 
     ArrayList<String> matches = partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); 
     for (String match : matches) { 
      match = match.toLowerCase(); 
      Log.d(TAG, "onPartialResults : " + match); 
     } 
    } 

    @Override 
    public void onReadyForSpeech(Bundle params) 
    { 
     Log.d(TAG, "onReadyForSpeech"); //$NON-NLS-1$ 
    } 

    @Override 
    public void onResults(Bundle results) 
    { 
     //Log.d(TAG, "onResults"); //$NON-NLS-1$ 
     ArrayList<String> matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); 
     onSpeechResults(matches); 
     // matches are the return values of speech recognition engine 
     // Use these values for whatever you wish to do 
    } 

    @Override 
    public void onRmsChanged(float rmsdB) 
    { 
    } 
}} 

謝謝大家爲你的時間!希望有人能幫助我一點:P!

+0

不,請考慮使用更靈活的識別器 –

+0

你能給我一些關於我可以使用的其他識別器的建議嗎? –

回答

2

是的,有可能關閉前,以減少延遲....

你不能改變的,谷歌認爲是在講用戶的結束沉默的時間。 EXTRA_SPEECH_*參數用於工作,現在它們似乎偶爾工作在最佳狀態,或根本不工作。

你可以做的是使用部分結果來檢測你想要的單詞或短語,然後手動關閉識別服務。

下面是如何做到這一點的例子:

public boolean isHelloDetected(@NonNull final Context ctx, @NonNull final Locale loc, @NonNull final Bundle results) { 

     boolean helloDetected = false; 

     if (!results.isEmpty()) { 

      final String hello = ctx.getString(R.string.hello); 

      final ArrayList<String> partialData = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); 

       /* handles empty string bug */ 
      if (partialData != null && !partialData.isEmpty()) { 
       partialData.removeAll(Collections.singleton("")); 

       if (!partialData.isEmpty()) { 
        final ListIterator<String> itr = partialData.listIterator(); 

        String vd; 
        while (itr.hasNext()) { 
         vd = itr.next().toLowerCase(loc).trim(); 

         if (vd.startsWith(hello)) { 
          helloDetected = true; 
          break; 
         } 
        } 
       } 
      } 

      if (!helloDetected) { 
       final ArrayList<String> unstableData = results.getStringArrayList("android.speech.extra.UNSTABLE_TEXT"); 

        /* handles empty string bug */ 
       if (unstableData != null && !unstableData.isEmpty()) { 
        unstableData.removeAll(Collections.singleton("")); 

        if (!unstableData.isEmpty()) { 
         final ListIterator<String> itr = unstableData.listIterator(); 

         String vd; 
         while (itr.hasNext()) { 
          vd = itr.next().toLowerCase(loc).trim(); 

          if (vd.startsWith(hello)) { 
           helloDetected = true; 
           break; 
          } 
         } 
        } 
       } 
      } 
     } 

     return helloDetected; 
    } 

你會每次從onPartialResults()

接收如果返回真的時候運行這個方法,你需要調用stopListening()主線程(可能通過new Handler(Looper.getMainLooper()).post(...

但請注意,一旦您關閉了識別器,您在onResults()中收到的後續和最終結果可能不是包含「你好」。因爲這個詞可能只被歸類爲不穩定。

您需要編寫額外的邏輯以防止在檢測到hello時使用detectHello()(否則您將重複呼叫stopListening()) - 一些簡單的布爾標記可以解決此問題。

最後,使用Collections.singleton("")刪除空字符串是內部錯誤報告details to replicate here的一部分,使用ListIterator對於您的示例而言可能過度殺傷;一個簡單的循環就足夠了。

祝你好運。

+0

嗨@brandall!我已經在昨天添加了「EXTRA_PARTIAL_RESULTS」給我的意圖。我只想抓住一個特定的詞,所以它工作正常。無論如何,你是什麼意思與「EXTRA_SPEECH_ *」?你能告訴我更多一點嗎?只是爲了嘗試改進我的解決方案 我標記你的asnwer是正確的原因,你找到了和我一樣的解決方案!謝謝。順便說一句,你知道如果可以靜音可怕的嗶嗶聲沒有靜音整個AudioStream? –

+1

很高興你解決了它 - 在上面的例子中,使用不穩定的部分結果可以加快速度。 'EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS'和其他人無法正常工作(所有的時間),所以不能依賴。目前沒有任何方法可以通過AudioStream以外的方式將嗶聲靜音 - Google不太可能通過改變此方式來防止濫用「連續識別服務」。看看使用PocketSphinx來做到這一點。 – brandall

+0

目前我將使用Google SpeechRecognizer服務。我沒有學過這麼多的PocketSphinx,但我讀到它不太精確,在這種情況下,我需要儘快得到一個詞的識別。 無論如何,當我的應用程序完成時,我會試一試。檢查我是否可以提供更好的服務。 非常感謝你@brandall! –

相關問題