2

My app uses Android's SpeechRecognizer class, and has been working fine on several devices until a couple days ago. On my Samsung S3 and my LG-E980 the app suddendly become very slow. My other devices are not affected. The problem occurs because there is about a 7 seconds wait between onBeginningOfSpeech and onEndOfSpeech. I have tried other apps with source code on the internet with the same result. Is anybody aware of any recent software change that may be causing this? My Samsung S3 is running Android 5.0.1 The Samsung that works well runs 4.1.2

The keyboard mic does not have delays.

Nikolay Shmyrev
  • 24,897
  • 5
  • 43
  • 87
gastonceron
  • 191
  • 1
  • 11
  • is your code working well on other devices and getting you result / – Sagar Nayak Jun 30 '16 at 07:17
  • 1
    The last two Google 'Now' releases really messed up their `SpeechRecognizer` implementation. Check out the gist linked in this answer http://stackoverflow.com/a/37641803/1256219 - If subclassing the RecognitionListener doesn't solve the problem for you, you'll need to post some code. – brandall Jun 30 '16 at 13:47
  • Yes, it is and now even my LG phone went back to normal. I did a factory reset on the slow Samsung but still remains slow. It may be something on the google servers, but specific to that Samsung model? – gastonceron Jun 30 '16 at 13:49
  • I think that mine is a different problem, though I also on occasion have the error 7 problem, which I have fixed in a similar way as your subclassing suggestion. – gastonceron Jun 30 '16 at 21:45
  • My problem is not that I get an error 7. I get a OnBeginningOfSpeech when I start talking but after I stop talking the program waits about 5 seconds before getting onEndOfSpeech. and receiving the conversion to text shortly after. I will try to make and post a short demo code. – gastonceron Jun 30 '16 at 21:56
  • 1
    http://stackoverflow.com/q/38150312/1256219 - check here. It's not a solution, but I can now replicate the issue since my devices received the update – brandall Jul 01 '16 at 17:28
  • 1
    I have tested 9 devices with different versions of Android and Google App (Aka Google Search) and yes, the response is much slower since Google App version 6. I think it is reasonable to expect Google to fix the problem. In the mean time you can revert to the original version but it is an ugly thing to ask your users to do. – gastonceron Jul 01 '16 at 21:22
  • @gastonceron - Hi, i am also facing this problem. Did you got any success in this. – Gaurav Vachhani Jul 13 '16 at 04:50
  • No, I just abandoned my project which was published on Google Play y and other sites after several months of development. The only fix is to revert Google Search to an older version (not version 6) or to wait for a fix from Google. In the future I will stick to the microphone on the keyboard. – gastonceron Jul 13 '16 at 13:37

1 Answers1

3

I am pretty sure that this is slowdown is due to Google App (Google Search) version 6. I found this after testing 9 devices with the code below:

package com.example.speechtest;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends Activity implements RecognitionListener {
    static String speechTestTag = "SpeechText";
    MyView myView;
    SpeechRecognizer speechRecognizer;
    Intent speechIntent;
    boolean processingSpeech = false;
    long startTime;
    long speechTime;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(BuildConfig.DEBUG) Log.d(speechTestTag, "onCreate");
        myView = new MyView(this);
        setContentView(myView);
        speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
        speechRecognizer.setRecognitionListener(this);
        speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
//      speechIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 1100); // this line is ignored
//      speechIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 0); // this line is ignored
    }

    class MyView extends LinearLayout {
        TextView speechTimeView;
        TextView textView;
        Button talkButton;

        public MyView(Context context) {
            super(context);
            setOrientation(LinearLayout.VERTICAL);
            speechTimeView = new TextView(context);
            speechTimeView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
            textView = new TextView(context);
            textView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
            talkButton = new Button(context);
            talkButton.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
            talkButton.setText("Touch to Talk");
            talkButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(BuildConfig.DEBUG) Log.d(speechTestTag, "talkButton calling startListening - processingSpeech = " + processingSpeech);
                    talkButton.setText("Speak");
                    speechTimeView.setText(" "); //speechTimeView.invalidate();
                    textView.setText(" "); //textView.invalidate();
                    speechRecognizer.startListening(speechIntent);
                }
            });
            addView(speechTimeView);
            addView(textView);
            addView(talkButton);
        }
    }

        @Override
        public void onReadyForSpeech(Bundle params) {
            if(BuildConfig.DEBUG) Log.d(speechTestTag, "onReadyForSpeech");
            processingSpeech = true;
        }

    @Override
    public void onBeginningOfSpeech() {
        if(BuildConfig.DEBUG) Log.d(speechTestTag, "onBeginningOfSpeech");
        startTime = System.currentTimeMillis();
    }

    @Override
    public void onRmsChanged(float rmsdB) {
////        if(BuildConfig.DEBUG) Log.d(speechTestTag, "onRmsChanged - new rmssB = " + rmsdB); // too much of this on some devices
    }

    @Override
    public void onBufferReceived(byte[] buffer) {
        if(BuildConfig.DEBUG) Log.d(speechTestTag, "onBufferReceived");
    }

    @Override
    public void onEndOfSpeech() {
        if(BuildConfig.DEBUG) Log.d(speechTestTag, "onEndOfSpeech");
    long     endTime = System.currentTimeMillis();
        speechTime = endTime - startTime;
        myView.speechTimeView.setText("SpeechTime: " + speechTime + " Milliseconds");
    }

    @Override
    public void onError(int error) {
        if(BuildConfig.DEBUG) Log.d(speechTestTag, "onError error: " + error + " processingSpeech = " + processingSpeech + " speechTime = " + speechTime);
        if(error == 7 && (!processingSpeech || speechTime < 1700)) {
            if(BuildConfig.DEBUG) Log.d(speechTestTag, "onError startListening");
            speechRecognizer.startListening(speechIntent);
        } else {
            if(BuildConfig.DEBUG) Log.d(speechTestTag, "onError displaying error");
            myView.textView.setText("< " + "ERROR " + error + " >");
            myView.talkButton.setText("Touch to Talk");
        }
        processingSpeech = false;
    }

    @Override
    public void onResults(Bundle results) {
        ArrayList<String> recognitionResults = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
        String myResult = recognitionResults.get(0);
        if(BuildConfig.DEBUG) Log.d(speechTestTag, "onResults - <" + myResult + ">");
        myView.textView.setText(myResult);
        myView.talkButton.setText("Touch to Talk");
        processingSpeech = false;
    }

    @Override
    public void onPartialResults(Bundle partialResults) {
        if(BuildConfig.DEBUG) Log.d(speechTestTag, "onPartialResults");
    }

    @Override
    public void onEvent(int eventType, Bundle params) {
        if(BuildConfig.DEBUG) Log.d(speechTestTag, "onEvent");
    }
}

This code is self contained, it does not need any XML layouts.

Do not forget to add

<uses-permission android:name="android.permission.RECORD_AUDIO"/> 

to your manifest.

Also, version 3 of Google App supports off line speech recognition. Version 4 does not. I have not version 5 to be able to tell. Version 6.0.23.21 does support off-line, but it is very slow. The problem is the time it takes from onBeginningOfSpeech to onEndOfSpeech. After the speech stops it keeps waiting for about 5 seconds before deciding that there will be no more speech and proceed with the recognition (both on and off line).The EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS parameter is ignored even if you make it zero or negative.

Three of my phones had Google App version 6, but I was able to revert to a previous version on all of them and the problem went away.

There is another problem with ERROR 7, which I solved with the boolean flag processingSpeech.

gastonceron
  • 191
  • 1
  • 11