Search code examples
androidspeech-recognitionvoice-recognitionspeech

SpeechRecognizer not Hearing After First Result


I am using SpeechRecognizer and RecognizerIntent in Android to implement speech recognition. My aim is to restart listening to speech after my speech recognizer displays the results on the screen. For that purpose, I am using the following code.

The problem is, the first time runs fine and displays the results but after it starts listening for the second time (called from onResults method), it does not hear what is being spoken for some reason. Then it gives a ERROR_SPEECH_TIMEOUT error, which means there was no speech input. On Logcat, I can see it entering onReadyForSpeech() but somehow, it won't hear what I am saying.

Does anyone know why this might happen? Does it keep listening after it returns a result? Is it correct to call startListening again explicitly?

public class VR extends Activity implements RecognitionListener {


    private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
    private TextView vrtext;
    private SpeechRecognizer speech = null;
    private Intent intent;
    private String TAG = "VR";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.vr);

        vrtext = (TextView) findViewById(R.id.vrtext);  

    }

    @Override
    public void onResume()
    {
        listen();
        super.onResume();
    }

    private void listen()
    {
        speech = SpeechRecognizer.createSpeechRecognizer(this);
        speech.setRecognitionListener(this);
        intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en");
        intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName());
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
        intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 3);

        speech.startListening(intent);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // TODO Auto-generated method stub

        if(speech != null)
        {
            speech.destroy();
            Log.i(TAG,"destroy");
        }

    }

    public void onBeginningOfSpeech() {
        // TODO Auto-generated method stub
        Log.i(TAG, "onbeginningofspeech");
    }

    public void onBufferReceived(byte[] arg0) {
        // TODO Auto-generated method stub
        //Log.i(TAG, "onbufferreceived");
    }

    public void onEndOfSpeech() {
        // TODO Auto-generated method stub
        Log.i(TAG, "onendofspeech");
    }

    public void onError(int arg0) {
        // TODO Auto-generated method stub
        Log.i(TAG, "error code: " + arg0);
    }

    public void onEvent(int arg0, Bundle arg1) {
        // TODO Auto-generated method stub
        Log.i(TAG, "onevent");
    }

    public void onPartialResults(Bundle arg0) {
        // TODO Auto-generated method stub
        Log.i(TAG, "onpartialresults");
    }

    public void onReadyForSpeech(Bundle arg0) {
        // TODO Auto-generated method stub
        Log.i(TAG, "onreadyforspeech");
    }

    public void onResults(Bundle arg0) {
        // TODO Auto-generated method stub
        Log.i(TAG, "onresults");
        ArrayList<String> matches = arg0.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
        String s = "";
        for (String result:matches)
            s += result + "\n";

        vrtext.setText(s);

        speech.startListening(intent);

    }

    public void onRmsChanged(float arg0) {
        // TODO Auto-generated method stub
        //Log.i(TAG, "onrmschanged");
    }

}

Solution

  • "Does it keep listening after it returns a result?" No

    "Is it correct to call startListening again explicitly?" Yes.

    Also, if you want to keep the recognition happening continuously, you should call startListening again if some errors occur like this:

    @Override
    public void onError(int errorCode)
    {
        if ((errorCode == SpeechRecognizer.ERROR_NO_MATCH)
                || (errorCode == SpeechRecognizer.ERROR_SPEECH_TIMEOUT))
        {
            Log.d(TAG, "didn't recognize anything");
            // keep going
            recognizeSpeechDirectly();
        }
        else
        {
            Log.d(TAG,
                    "FAILED "
                            + SpeechRecognitionUtil
                                    .diagnoseErrorCode(errorCode));
        }
    }
    

    Check out my code for using SpeechRecognizer to detect a certain spoken word here.