自 Google App 版本 6 起 Android 语音识别器速度变慢

标签 android speech-recognition

我的应用程序使用 Android 的 SpeechRecognizer 类,并且直到几天前一直在多种设备上正常运行。在我的三星 S3 和 LG-E980 上,应用程序突然变得非常慢。我的其他设备不受影响。出现该问题的原因是 onBeginningOfSpeech 和 onEndOfSpeech 之间有大约 7 秒的等待时间。 我尝试过互联网上其他具有源代码的应用程序,但结果相同。 有人知道最近的软件更改可能会导致此问题吗? 我的三星 S3 运行的是 Android 5.0.1 运行良好的三星运行的是 4.1.2

键盘麦克风没有延迟。

最佳答案

我非常确定这是由于 Google 应用(Google 搜索)版本 6 造成的。我在使用以下代码测试 9 台设备后发现了这一点:

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");
    }
}

此代码是自包含的,不需要任何 XML 布局。

不要忘记添加

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

到您的 list 。

此外,Google App 版本 3 支持离线语音识别。版本 4 没有。我没有版本 5,无法判断。 6.0.23.21版本确实支持离线,但是速度很慢。 问题是从 onBeginningOfSpeech 到 onEndOfSpeech 所需的时间。语音停止后,它会持续等待大约 5 秒,然后确定不再有语音并继续识别(在线和离线)。即使将 EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS 参数设置为零或负数,也会被忽略。

我的三部手机安装了 Google 应用版本 6,但我能够在所有手机上恢复到之前的版本,问题就消失了。

还有一个与 ERROR 7 相关的问题,我用 bool 标志processingSpeech 解决了这个问题。

关于自 Google App 版本 6 起 Android 语音识别器速度变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38116149/

相关文章:

android - 语音识别在几秒钟后停止收听

android - React Native Android 中的 Gif 支持

android - 带有屏幕旋转的 Fragment 上的 DialogFragment

android - X 分钟 Y 秒前

Powershell可以说话,但如果我说话,它可以写吗?

ios - 将 Microsoft Project Oxford 语音识别从 Objective-C 转换为 SWIFT

android - Android 中的 AlwaysOnHotwordDetector 示例

android - `canvas.clipRect` 和 `Region.Op.REPLACE` 的最佳替代方案是什么?

java - Android 蓝牙-MAC 地址

Python pocketsphinx RequestError : missing PocketSphinx module: ensure that PocketSphinx is set up correctly