Подтвердить что ты не робот

Тайм-аут распознавания речи Google

Я разрабатываю приложение для Android, основанное на распознавании речи.

До сегодняшнего дня все работает нормально и своевременно, например. Я начал бы распознавать речи, говорить, и в течение 1 или 2 секунд максимум приложение получило результаты.

Это был ОЧЕНЬ приемлемый пользовательский интерфейс.

Затем сегодня мне нужно подождать десять или более секунд до того, как будут доступны результаты распознавания.

Я попытался установить следующие ЭКСТРАСЫ, ни одна из которых не делает различимых различий

RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS
RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS
RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS

Я постоянно меняю свое приложение, однако ни одно из этих изменений не было связано с распознавателем речи.

Можно ли использовать какой-либо метод, чтобы сократить время между переключением распознавателя речи с onBeginningOfSpeech() на onResults()?

Вот пример того, сколько времени требуется

07-01 17:50:20.839 24877-24877/com.voice I/Voice: onReadyForSpeech()
07-01 17:50:21.614 24877-24877/com.voice I/Voice: onBeginningOfSpeech()
07-01 17:50:38.163 24877-24877/com.voice I/Voice: onEndOfSpeech()
4b9b3361

Ответ 1

РЕДАКТИРОВАТЬ. По-видимому, он был исправлен в предстоящем выпуске в августе 2016 года. Вы можете проверить бета-версию для подтверждения.

Это ошибка с выпуском Google 'Now' V6.0.23. * и сохраняется в последнем V6.1.28. *

С момента выпуска V5.11.34. * Реализация Google SpeechRecognizer была запутана с ошибками.

Вы можете использовать этот метод, чтобы воспроизвести многие из них.

Вы можете использовать этот BugRecognitionListener, чтобы обойти некоторые из них.

Я сообщил об этом непосредственно команде Now, поэтому они знают, но пока ничего не исправлено. В Google Now нет внешнего трекера ошибок, так как он не является частью AOSP, поэтому ничего страшного не могу.

Самая последняя ошибка, которую вы подробно описываете, делает их реализацию непригодной, как вы правильно указываете, параметры для управления таймингами речевого ввода игнорируются. Что соответствует документации:

Кроме того, в зависимости от реализации распознавателя эти значения может не иметь эффекта.

- это то, что мы должны ожидать......

Признание будет продолжаться бесконечно, если вы не будете говорить или не будете распознавать звук.

В настоящее время я создаю проект для репликации этой новой ошибки и всех остальных, которые я перейду позже и свяжусь здесь в ближайшее время.

EDIT. Я надеялся, что смогу создать обходной путь, который использовал обнаружение частичных или неустойчивых результатов в качестве триггера, чтобы знать, что пользователь все еще говорит. Когда они остановятся, я могу вручную вызвать recognizer.stopListening() через заданный период времени.

К сожалению, stopListening() также ломается и фактически не останавливает распознавание, поэтому для этого не существует обходного пути.

Попытки обойти выше, уничтожить распознаватель и полагаться только на частичные результаты до тех пор, пока эта точка (при уничтожении распознавателя onResults() не вызывается) не смогла обеспечить надежную реализацию, если вы не просто ключевое слово spotting.

Мы ничего не можем сделать, пока Google не исправит это. Ваш единственный выход - отправить email [email protected], сообщив о проблеме, и надеемся, что объем, который они получают, дает им толчок.....

Ответ 2

Внимание! это работает только в онлайн-режиме. Включить режим диктовки и отключить частичные результаты:

intent.putExtra("android.speech.extra.DICTATION_MODE", true);
intent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, false);

В режиме диктовки speechRecognizer все равно вызовет onPartialResults(), однако вы должны рассматривать частичные файлы как окончательные результаты.

Ответ 3

UPDATE:

На всякий случай, если у кого-то возникают проблемы при настройке распознавания речи, вы можете использовать Droid Speech library, которую я создал для преодоления проблема речи в андроиде.


Мое приложение полностью зависело от функции распознавания голоса, и Google бросил бомбу. Похожая на вещи, я считаю, что это не будет исправлено, по крайней мере, в ближайшем будущем.

В настоящее время я нашел решение, чтобы распознавание голоса Google обеспечивало речевые результаты по назначению.

Примечание: Этот подход немного отличается от вышеупомянутых решений.

Основная цель этого метода - убедиться, что все слова, произнесенные пользователем, пойманы в onPartialResults().

В обычных случаях, если пользователь говорит более одного слова в данном экземпляре, время ответа слишком быстрое, а частичные результаты будут чаще, чем не получать только первое слово, а не полный результат.

Итак, чтобы каждое слово было зафиксировано на onPartialResults(), вводится обработчик, чтобы проверить задержку паузы пользователя и затем фильтровать результаты. Также обратите внимание, что массив результатов из onPartialResults() будет чаще, чем не иметь только один элемент.

SpeechRecognizer userSpeech = SpeechRecognizer.createSpeechRecognizer(this);

Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
speechIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName());
speechIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true);
speechIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, ModelData.MAX_VOICE_RESULTS);

Handler checkForUserPauseAndSpeak = new Handler(); 
Boolean speechResultsFound = false;

userSpeech.setRecognitionListener(new RecognitionListener(){

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

    @Override
    public void onResults(Bundle results)
    {
        if(speechResultsFound) return;

        speechResultsFound = true;

        // Speech engine full results (Do whatever you would want with the full results)
    }

    @Override
    public void onReadyForSpeech(Bundle params)
    {
        // NA
    }

    @Override
    public void onPartialResults(Bundle partialResults)
    {
        if(partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).size() > 0 &&
                partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).get(0) != null &&
                !partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).get(0).trim().isEmpty())
        {
            checkForUserPauseAndSpeak.removeCallbacksAndMessages(null);
            checkForUserPauseAndSpeak.postDelayed(new Runnable()
            {
                @Override
                public void run()
                {
                    if(speechResultsFound) return;

                    speechResultsFound = true;

                    // Stop the speech operations
                    userSpeech.destroy();

                    // Speech engine partial results (Do whatever you would want with the partial results)

                }

            }, 1000);
        }
    }

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

    @Override
    public void onError(int error)
    {
        // Error related code
    }

    @Override
    public void onEndOfSpeech()
    {
        // NA
    }

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

    @Override
    public void onBeginningOfSpeech()
    {
        // NA
    }
});

userSpeech.startListening(speechIntent);

Ответ 4

Лучшая работа над решением, которое я нашел (пока Google не исправил ошибку), должен был войти в App App App, а затем нажать кнопку "Удалить обновления" . Это приведет к удалению всех обновлений, сделанных в этом приложении, которые оказывают непосредственное влияние на распознаватель речи, в основном возвращая его на factory.

** Вероятно, прекратить автоматические обновления, пока мы не узнаем, что это исправление. *** Примечание: это решение только для разработчиков, очевидно, если у вас есть приложение в магазине, это не поможет. К сожалению...

Ответ 5

ОБНОВЛЕНИЕ: По состоянию на мое тестирование сегодня, эта ошибка, кажется, была решена окончательно, и это больше не нужно. Оставляя его на случай, если он снова сломается в будущем. Из моих тестов тайм-аут речи работает нормально.

Хорошо, я знаю, что это ОЧЕНЬ УГЛИ, но, похоже, это работает с использованием onPartialResults (я понимаю, что gotchas с onPartialResults, но я пробовал это несколько раз, и это что-то, пока Google не исправляет эту нелепую ошибку!) У меня нет исчерпывающе протестировал его (я верну результаты, так как буду использовать это в приложении), но я отчаянно нуждался в решении. В основном, я использую onRmsChanged для запуска этого пользователя, говорящего, предполагая, что, когда RmsDb падает ниже пика и нет onPartialResults в течение 2 секунд, мы закончили.

Единственное, что мне не нравится в этом, - это уничтожение SR, которое делает двойной звуковой сигнал. FWIW и YMMV. Пожалуйста, внесите любые улучшения!

ПРИМЕЧАНИЕ. Если вы собираетесь использовать это повторно, не забудьте reset bBegin и fPeak! Также вам нужно будет воссоздать SR (либо onStartCommand, либо остановить и запустить сервис.)

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.support.annotation.Nullable;
import android.util.Log;

import java.util.ArrayList;

public class SpeechToTextService extends Service {

    private String TAG = "STT";

    float fPeak;
    boolean bBegin;
    long lCheckTime;
    long lTimeout = 2000;

    @Override
    public void onCreate() {
        super.onCreate();

        bBegin = false;
        fPeak = -999; //Only to be sure it under ambient RmsDb.

        final SpeechRecognizer sr = SpeechRecognizer.createSpeechRecognizer(getApplicationContext());
        sr.setRecognitionListener(new RecognitionListener() {

            @Override
            public void onReadyForSpeech(Bundle bundle) {
                Log.i(TAG, "onReadyForSpeech");
            }

            @Override
            public void onBeginningOfSpeech() {
                bBegin = true;
                Log.i(TAG, "onBeginningOfSpeech");
            }

            @Override
            public void onRmsChanged(float rmsDb) {
                if(bBegin) {
                    if (rmsDb > fPeak) {
                        fPeak = rmsDb;
                        lCheckTime = System.currentTimeMillis();
                    }
                    if (System.currentTimeMillis() > lCheckTime + lTimeout) {
                        Log.i(TAG, "DONE");
                        sr.destroy();
                    }
                }
                //Log.i(TAG, "rmsDB:"+rmsDb);
            }

            @Override
            public void onBufferReceived(byte[] buffer) {
                Log.i(TAG, "onBufferReceived");
            }

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

            @Override
            public void onError(int error) {
                Log.i(TAG, "onError:" + error);
            }

            @Override
            public void onResults(Bundle results) {

                ArrayList data = results.getStringArrayList(
                        SpeechRecognizer.RESULTS_RECOGNITION);

                String sTextFromSpeech;
                if (data != null) {
                    sTextFromSpeech = data.get(0).toString();
                } else {
                    sTextFromSpeech = "";
                }
                Log.i(TAG, "onResults:" + sTextFromSpeech);
            }

            @Override
            public void onPartialResults(Bundle bundle) {

                lCheckTime = System.currentTimeMillis();
                ArrayList data = bundle.getStringArrayList(
                        SpeechRecognizer.RESULTS_RECOGNITION);

                String sTextFromSpeech;
                if (data != null) {
                    sTextFromSpeech = data.get(0).toString();
                } else {
                    sTextFromSpeech = "";
                }
                Log.i(TAG, "onPartialResults:" + sTextFromSpeech);
            }

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

                Log.i(TAG, "onEvent:" + eventType);
            }
        });

        Intent iSRIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        iSRIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
        iSRIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true);
        iSRIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getPackageName());
        iSRIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US");
        iSRIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en-US");
        sr.startListening(iSRIntent);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Ответ 6

Решение только для офлайн:

Я столкнулся с одной и той же проблемой (система Android заняла 25 секунд, чтобы получить транскрипцию речи через onPartialResults() после срабатывания onEndOfSpeech().

Я пробовал следующий код, и он работал:

Intent.putExtra
(
    RecognizerIntent.EXTRA_PREFER_OFFLINE,
    true
);

Это решение работает для моего приложения, и оно может работать для вас, если вы не используете онлайн-режим (я загрузил языковой пакет с помощью настройки телефона).