it-swarm.com.de

Zeitüberschreitung bei der Google-Spracherkennung

Ich entwickle eine Android-Anwendung, die auf der Spracherkennung basiert.

Bis heute hat alles gut und zeitnah funktioniert, z. Ich würde mit der Spracherkennung beginnen, sprechen und innerhalb von 1 bis 2 Sekunden habe die Anwendung die Ergebnisse erhalten.

Es war eine sehr akzeptable Benutzererfahrung.

Dann muss ich heute zehn oder mehr Sekunden warten, bis die Erkennungsergebnisse verfügbar sind.

Ich habe versucht, die folgenden EXTRAS einzustellen, von denen kein Unterschied erkennbar ist

RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS
RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS
RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS

Ich habe meine Bewerbung ständig geändert, jedoch hat sich keine der Änderungen auf den Spracherkenner bezogen.

Gibt es eine Methode, mit der ich die Zeit zwischen dem Umschalten der Spracherkennung von onBeginningOfSpeech() auf onResults() reduzieren kann?

Hier ist ein Beispiel, wie lange es dauert

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()
25
Hector

EDIT - Wurde anscheinend in der kommenden Version vom August 2016 behoben Sie können die Beta testen, um zu bestätigen.

Dies ist ein Fehler bei der Veröffentlichung von Google 'Now' V6.0.23. * Und bleibt in der neuesten Version V6.1.28 bestehen. *

Seit der Veröffentlichung von V5.11.34. * Wurde die Implementierung von SpeechRecognizer von Google mit Fehlern geplagt.

Sie können this Gist verwenden, um viele davon zu replizieren.

Sie können diesen BugRecognitionListener verwenden, um einige von ihnen zu umgehen.

Ich habe diese direkt dem Now-Team gemeldet, sie sind sich dessen bewusst, aber bis jetzt ist noch nichts behoben worden. Es gibt keinen externen Bug-Tracker für Google Now, da er nicht Teil von AOSP ist. Daher kann ich nichts fürchten.

Der jüngste Fehler, den Sie detailliert beschreiben, macht die Implementierung unbrauchbar. Wenn Sie richtig darauf hinweisen, werden die Parameter zur Steuerung der Spracheingabezeitpunkte ignoriert. Was laut der Dokumentation

Abhängig von der Erkennungsimplementierung sind diese Werte kann keine Wirkung haben.

ist etwas, was wir erwarten sollten ......

Die Erkennung wird unbegrenzt fortgesetzt, wenn Sie nicht sprechen oder einen erkennbaren Ton erzeugen.

Ich arbeite gerade an einem Projekt, um diesen neuen Fehler und alle anderen zu replizieren, die ich hier weiterleiten und in Kürze hier verlinken werde.

EDIT - Ich hatte gehofft, eine Problemumgehung erstellen zu können, bei der die Erkennung von partiellen oder instabilen Ergebnissen als Auslöser verwendet wurde, um zu wissen, dass der Benutzer immer noch spricht. Sobald sie aufgehört hatten, konnte ich recognizer.stopListening() nach einer festgelegten Zeit manuell aufrufen.

Leider ist stopListening() auch defekt und stoppt die Erkennung nicht wirklich. Daher gibt es keine Problemumgehung.

Versuche, das Erkennungsprogramm zu zerstören und sich nur auf die Teilergebnisse bis zu diesem Punkt zu verlassen (wenn das Erkennungsprogramm onResults() nicht aufgerufen wird), konnten keine zuverlässige Implementierung erzeugen, es sei denn, Sie sind simple Schlüsselworterkennung .

Wir können nichts tun, bis Google dies behoben hat. Sie können sich nur per E-Mail an [email protected] melden, um das Problem zu melden, und hoffen, dass das Volumen, das sie erhalten, ihnen einen Nudge gibt .....

20
brandall

HINWEIS! Dies funktioniert nur im Online-Modus. Aktivieren Sie den Diktatmodus und deaktivieren Sie Teilergebnisse:

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

Im Diktiermodus ruft speechRecognizer noch immer onPartialResults() auf. Sie sollten jedoch die Teilergebnisse als Endergebnis behandeln. 

7
vladbph

UPDATE:

Für den Fall, dass jemand Probleme beim Einrichten der Spracherkennung hat, können Sie Droid-Sprachbibliothek verwenden, das ich zur Behebung des Zeitlimits bei Android entwickelt habe. 


Meine App war vollständig von der Spracherkennungsfunktion abhängig, und Google hat eine Bombe abgeworfen. Nach dem Aussehen der Dinge glaube ich, dass dies nicht in naher Zukunft behoben werden würde.

Ich habe vorerst eine Lösung gefunden, um die Sprachergebnisse wie beabsichtigt durch die Google-Spracherkennung zu liefern.

Hinweis: Dieser Ansatz unterscheidet sich geringfügig von den oben genannten Lösungen.

Der Hauptzweck dieser Methode besteht darin, sicherzustellen, dass die gesamten vom Benutzer geäußerten Wörter bei onPartialResults () erfasst werden. 

Wenn ein Benutzer in einer bestimmten Instanz mehr als ein einzelnes Wort spricht, ist die Antwortzeit im Normalfall zu schnell, und bei Teilergebnissen wird häufig nicht nur das erste Wort, sondern nicht das vollständige Ergebnis angezeigt. 

Um sicherzustellen, dass jedes einzelne Wort bei onPartialResults () abgefangen wird, wird ein Handler eingeführt, um die Pausenverzögerung des Benutzers zu überprüfen und die Ergebnisse zu filtern. Beachten Sie auch, dass das Ergebnis-Array von onPartialResults () meist nur ein einzelnes Element enthält.

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);
3
Vikram Ezhil

Die beste Lösung für die Lösung, die ich gefunden habe (bis Google den Fehler behebt), bestand darin, die Informationen zur Google App-App aufzurufen und dann auf "Updates deinstallieren" zu klicken. Dadurch werden alle an dieser App vorgenommenen Aktualisierungen entfernt, die direkte Auswirkungen auf die Spracherkennung haben, und sie im Wesentlichen an den Hersteller zurücksenden.

** Möglicherweise ist es eine gute Idee, die automatischen Updates zu stoppen, bis wir wissen, dass es Updates gibt. Es tut uns leid...

2
Shai Herman

UPDATE: Bei meinen heutigen Tests scheint dieser Fehler endgültig behoben worden zu sein und ist nicht mehr erforderlich. Verlassen, falls es in Zukunft wieder pleite wird. Bei meinen Tests funktioniert das Sprach-Timeout normal.

Ok, ich weiß, das ist SEHR UGLY, aber es scheint mit onPartialResults zu funktionieren (ich verstehe die Problematik mit onPartialResults, aber ich habe es ein paar Mal versucht und es ist etwas, bis Google diesen lächerlichen Fehler behebt!) noch (ich werde und gebe Ergebnisse zurück, da ich dies in einer App verwenden werde), aber ich war verzweifelt an einer Lösung interessiert. Im Grunde verwende ich onRmsChanged, um auszulösen, dass der Benutzer mit dem Sprechen fertig ist, vorausgesetzt, wenn die RmsDb für 2 Sekunden unter peak und kein onPartialResults fällt, sind wir fertig.

Das Einzige, was ich nicht mag, ist, dass SR zerstört einen doppelten Piepston macht. FWIW und YMMV. Bitte posten Sie Verbesserungsvorschläge!

HINWEIS: Wenn Sie dies wiederholt verwenden, vergessen Sie nicht, bBegin und fPeak zurückzusetzen! Außerdem müssen Sie SR neu erstellen (entweder onStartCommand oder den Dienst stoppen und starten.) 

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's 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;
    }
}
1
John Smith

Lösung nur für offline:

Ich bin auf das gleiche Problem gestoßen (Android-System benötigte 25 Sekunden, um die Abschrift der Rede über onPartialResults() zu erhalten, nachdem onEndOfSpeech() ausgelöst wurde.

Ich habe den folgenden Code ausprobiert und es hat funktioniert: 

Intent.putExtra
(
    RecognizerIntent.EXTRA_PREFER_OFFLINE,
    true
);

Diese Lösung funktioniert für meine App und möglicherweise für Sie, wenn Sie den Online-Modus nicht verwenden (ich habe das Sprachpaket über die Telefoneinstellung heruntergeladen).

0
Antoine Nguyen