Offline-Spracherkennung in Android (JellyBean)

78

Es sieht so aus, als hätte Google die Offline-Spracherkennung von Google Now für Apps von Drittanbietern verfügbar gemacht. Es wird von der App Utter verwendet .

Hat jemand Implementierungen gesehen, wie einfache Sprachbefehle mit dieser Offline-Sprachaufzeichnung ausgeführt werden können? Verwenden Sie nur die reguläre SpeechRecognizer-API und sie funktioniert automatisch?

Geld
quelle
1
Solange wir die Sprache herunterladen, müssen wir unseren Code nicht ändern?
Ruchir Baronia

Antworten:

72

Google hat die Offline-Erkennung in diesem Suchupdate stillschweigend aktiviert, es sind jedoch (noch) keine API oder zusätzlichen Parameter in der SpeechRecognizer-Klasse verfügbar . {Siehe Bearbeiten am Ende dieses Beitrags} Die Funktionalität ist ohne zusätzliche Codierung verfügbar. Das Gerät des Benutzers muss jedoch korrekt konfiguriert sein, damit es funktioniert. Hier liegt das Problem, und ich würde mir vorstellen, warum viele Entwickler Nehmen wir an, sie vermissen etwas.

Außerdem hat Google bestimmte Jelly Bean-Geräte aufgrund von Hardwareeinschränkungen daran gehindert, die Offline-Erkennung zu verwenden. Für welche Geräte dies gilt, ist nicht dokumentiert. Tatsächlich ist nichts dokumentiert. Die Konfiguration der Funktionen für den Benutzer hat sich (für sie) als Versuch und Irrtum erwiesen. Es funktioniert für einige sofort - Für diejenigen, die es nicht tun, ist dies der 'Leitfaden', den ich ihnen zur Verfügung stelle.

  1. Stellen Sie sicher, dass der Standard-Android-Spracherkenner auf Google und nicht auf Samsung / Vlingo eingestellt ist
  2. Deinstallieren Sie alle Offline-Erkennungsdateien, die Sie bereits in den Google Sprachsucheinstellungen installiert haben
  3. Gehen Sie zu Ihren Android-Anwendungseinstellungen und prüfen Sie, ob Sie die Updates für die Anwendungen Google Search und Google Voice Search deinstallieren können.
  4. Wenn Sie dies nicht tun können, gehen Sie zum Play Store und prüfen Sie, ob Sie dort die Option haben.
  5. Neustart (wenn Sie 2, 3 oder 4 erreicht haben)
  6. Aktualisieren Sie die Google-Suche und die Google-Sprachsuche im Play Store (wenn Sie 3 oder 4 erreicht haben oder wenn ein Update trotzdem verfügbar ist).
  7. Neustart (wenn Sie 6 erreicht haben)
  8. Installieren Sie die Offline-Sprachdateien von English UK
  9. Starten Sie neu
  10. Verwenden Sie äußerste! mit einer Verbindung
  11. Wechseln Sie in den Flugzeugmodus und probieren Sie es aus
  12. Sobald es funktioniert, sollte auch die Offline-Erkennung anderer Sprachen wie Englisch (USA) funktionieren.

BEARBEITEN: Das vorübergehende Ändern des Gebietsschemas des Geräts auf Englisch in Großbritannien scheint dies ebenfalls zu starten, damit es für einige funktioniert.

Einige Nutzer gaben an, dass sie noch einige Male neu starten mussten, bevor es funktionieren würde, aber sie alle gelangen schließlich dorthin, oft unerklärlich zu dem Auslöser, dessen Schlüssel sich in der Google Search APK befinden , also nicht im öffentlichen Bereich oder ein Teil von AOSP .

Soweit ich feststellen kann, testet Google die Verfügbarkeit einer Verbindung, bevor entschieden wird, ob die Offline- oder Online-Erkennung verwendet wird. Wenn eine Verbindung anfänglich verfügbar ist, aber vor der Antwort verloren geht, gibt Google einen Verbindungsfehler aus und greift nicht auf Offline zurück. Nebenbei bemerkt, wenn eine Anfrage für die netzwerksynthetisierte Stimme gestellt wurde, wird kein Fehler angezeigt, wenn dies fehlschlägt - Sie erhalten Stille.

Das Google Search-Update hat keine zusätzlichen Funktionen in Google Now aktiviert. Wenn Sie versuchen, es ohne Internetverbindung zu verwenden, tritt ein Fehler auf. Ich erwähne dies, als ich mich fragte, ob die Fähigkeit so leise zurückgezogen werden würde, wie es schien, und daher in der Produktion nicht als verlässlich angesehen werden sollte.

Wenn Sie beabsichtigen, die SpeechRecognizer-Klasse zu verwenden, seien Sie gewarnt, es ist ein ziemlich schwerwiegender Fehler damit verbunden, für dessen Behandlung Ihre eigene Implementierung erforderlich ist.

Wenn nicht speziell offline = true angefordert werden kann , ist es unmöglich, diese Funktion zu steuern, ohne die Datenverbindung zu manipulieren. Müll. Sie erhalten Hunderte von Benutzer-E-Mails, in denen Sie gefragt werden, warum Sie etwas so Einfaches nicht aktiviert haben!

BEARBEITEN: Seit API-Level 23 wurde ein neuer Parameter EXTRA_PREFER_OFFLINE hinzugefügt, an den sich der Google-Erkennungsdienst anscheinend zu halten scheint.

Hoffe das oben genannte hilft.

Brandall
quelle
Das funktioniert gut für mich und es war sehr einfach zu implementieren. Ich habe dieses Beispiel hier als Ausgangspunkt verwendet. jameselsey.co.uk/blogs/techblog/…
rmooney
@brandall Ich frage mich, ob ich die Sprache auswählen kann, in der ich die Erkennung durchführe. Die Offline-Sprachdatei unterstützt jetzt meine Sprache (Vietnamesisch)! Ich möchte eine App erstellen, die Offline-Spracherkennung für meine Sprache (Vietnamesisch) ausführt! Ist das möglich?? Herzlichen Dank!
Truongnm
1
@truongmn - Hilft das? stackoverflow.com/q/10538791/1256219 Wenn nicht, stellen Sie eine neue Frage und verlinken Sie mich damit. Ich werde sehen, ob ich helfen kann
Brandall
Auf meinem Samsung Galaxy Grand Prime mit Kitkat 4.4 musste ich die Google Search- (und Google+) Apps im Anwendungsmanager deaktivieren, dann "Hintergrunddaten einschränken" aktivieren (oder sicherstellen, dass keine Verbindung verfügbar war) und erneut aktivieren die Google Search (und Google+) Apps (möglicherweise musste ich auch alle Daten für diese Apps löschen, bevor ich sie deaktivierte). Während ich versucht hatte, "Hintergrunddaten einschränken" zu aktivieren, während diese Apps aktiviert waren, wurde das Mikrofon im Dialer nicht angezeigt. Anscheinend erzwingt das erneute Aktivieren ohne Verbindung (oder eingeschränkt) die Verwendung von Offline.
Shelby Moore III
Hallo hilf mir auf diesem stackoverflow.com/questions/32866239/…
Raos
20

Ich möchte den Leitfaden verbessern, den die Antwort https://stackoverflow.com/a/17674655/2987828 mit Bildern an die Benutzer sendet. Es ist der Satz "Für diejenigen, die es nicht tun, ist dies der 'Leitfaden', den ich ihnen zur Verfügung stelle." das möchte ich verbessern.

Der Benutzer sollte auf die vier in diesen Bildern blau hervorgehobenen Schaltflächen klicken:

Gehen Sie zu Ihren Android-Anwendungseinstellungen, wählen Sie Sprachen und geben Sie ein. Einstellungen der Google Voice-Eingabe bearbeiten, Wählen Sie Download Offline-Spracherkennung, Wählen Sie Ihre Sprachen auf der Registerkarte ALL.

Dann kann der Benutzer beliebige Sprachen auswählen. Wenn der Download abgeschlossen ist, sollte er die Verbindung zum Netzwerk trennen und dann auf die Schaltfläche "Mikrofon" der Tastatur klicken.

Es funktionierte für mich (Android 4.1.2), dann funktionierte die Spracherkennung sofort, ohne neu zu starten. Ich kann jetzt Anweisungen an die Shell von Terminal Emulator diktieren! Auf einem Padfone 2 von ASUS ist es offline doppelt schneller als online.

Diese Bilder werden unter cc by-sa 3.0 lizenziert, wobei die Zuordnung zu stackoverflow.com/a/21329845/2987828 erforderlich ist. Sie können diese Bilder daher an einer beliebigen Stelle zusammen mit dieser Zuordnung hinzufügen.

(Dies ist die Standardrichtlinie aller Bilder und Texte auf stackoverflow.com)

user2987828
quelle
18

Eine einfache und flexible Offline-Erkennung unter Android wird von CMUSphinx implementiert, einem Open-Source-Toolkit zur Spracherkennung. Es funktioniert rein offline, schnell und konfigurierbar. Es kann beispielsweise kontinuierlich nach Schlüsselwörtern suchen.

Den neuesten Code und das neueste Tutorial finden Sie hier .

Update 2019 : Die Zeit vergeht schnell, CMUSphinx ist nicht mehr so ​​genau. Ich empfehle stattdessen das Kaldi Toolkit. Die Demo ist da .

Nikolay Shmyrev
quelle
1
Ich habe gerade eine Demo ausprobiert und sie funktioniert ziemlich gut. Schnell und einfach zu bedienen.
Micer
2
Hallo, funktioniert CMUSphinx auch für Englisch mit indischem Akzent?
Luzifer
1
@Kedarnath es scheint, dass es ganz oben auf ihrer Liste steht, siehe die Umfrage hier: cmusphinx.sourceforge.net
Jerther
Danke, versuche es jetzt!
Herman
Funktioniert es für Arabisch? Kennen Sie jemanden, der für Arabisch funktioniert?
Youssef Sherif
7

Kurz gesagt, ich habe nicht die Implementierung, sondern die Erklärung.

Google hat die Offline-Spracherkennung für Apps von Drittanbietern nicht verfügbar gemacht. Die Offline-Erkennung ist nur über die Tastatur zugänglich. Ben Randall (der Entwickler von Äußersten!) Erklärt seine Problemumgehung in einem Artikel bei Android Police:

Ich hatte meine eigene Tastatur implementiert und wechselte zwischen Google Voice Typing und der Standardtastatur des Benutzers mit einem unsichtbaren Bearbeitungstextfeld und transparenten Aktivitäten, um die Eingabe zu erhalten. Schmutziger Hack!

Dies war die einzige Möglichkeit, da die Offline-Sprachtypisierung nur von einem IME oder einer Systemanwendung ausgelöst werden konnte (das war mein Root-Hack). Die andere Art der Erkennungs-API… hat sie nicht ausgelöst und ist nur mit einem Serverfehler fehlgeschlagen. … Ich habe viel Arbeit für die Problemumgehung verschwendet! Aber zumindest war ich bereit für die Implementierung ...

Von Utter! Behauptet, die erste Nicht-IME-App zu sein, die die Offline-Spracherkennung in Jelly Bean nutzt

Leon Joosse
quelle
4
Ich dachte, das hat er vor dem letzten Update getan. Nach Ihrem Zitat: "Randall erklärte weiter, dass Utter! Jetzt SpeechRecognizer verwendet, der aktualisiert wurde, sodass Entwickler die Offline-Erkennung in einer Reihe von Anwendungen verwenden können, während für Recognizerintent, den vorherigen Offline-Spracheingabecode, ein gültiges IME-Token erforderlich war."
Rmooney
3

Ich habe meinen Sprachdienst erfolgreich mit Offline-Funktionen implementiert, indem ich onPartialResults offline und onResults online verwendet habe.

P. Stresow
quelle
Kann ich bitte mehr darüber wissen? Ich habe hier einen
Raos
2

Ich habe mich damit befasst und festgestellt, dass Sie das Offline-Paket für Ihre Sprache installieren müssen. Meine Spracheinstellung war "Español (Estados Unidos)", aber es gibt kein Offline-Paket für diese Sprache. Als ich die gesamte Netzwerkverbindung deaktivierte, erhielt ich von RecognizerIntent eine Warnung, dass Google nicht erreicht werden kann, und ändere die Sprache in "Englisch (USA)" (weil ich bereits das Offline-Paket habe) und startete den RecognizerIntent, der gerade funktioniert hat.

Tasten: Spracheinstellung == Offline-Spracherkennungspaket

Akino
quelle
Kann ich wissen, welches Gerät Sie verwendet haben? Unterstützt es eher als Google-Gerät. Wie Samsung, Asus usw. Ich arbeite daran und offline nicht in anderen Geräten zu unterstützen.
Raos
1

Es ist anscheinend möglich, die Offline-Spracherkennung manuell zu installieren, indem die Dateien direkt heruntergeladen und manuell an den richtigen Speicherorten installiert werden. Ich denke, dies ist nur eine Möglichkeit, die Hardwareanforderungen von Google zu umgehen. Ich persönlich musste jedoch nicht neu starten oder so, sondern wechselte einfach nach Großbritannien und wieder zurück.

Riju Chatterjee
quelle
0

Das Arbeitsbeispiel ist unten angegeben.

MyService.class

public class MyService extends Service implements SpeechDelegate, Speech.stopDueToDelay {

  public static SpeechDelegate delegate;

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    //TODO do something useful
    try {
      if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
        ((AudioManager) Objects.requireNonNull(
          getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    Speech.init(this);
    delegate = this;
    Speech.getInstance().setListener(this);

    if (Speech.getInstance().isListening()) {
      Speech.getInstance().stopListening();
    } else {
      System.setProperty("rx.unsafe-disable", "True");
      RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
        if (granted) { // Always true pre-M
          try {
            Speech.getInstance().stopTextToSpeech();
            Speech.getInstance().startListening(null, this);
          } catch (SpeechRecognitionNotAvailable exc) {
            //showSpeechNotSupportedDialog();

          } catch (GoogleVoiceTypingDisabledException exc) {
            //showEnableGoogleVoiceTyping();
          }
        } else {
          Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
        }
      });
    }
    return Service.START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
    //TODO for communication return IBinder implementation
    return null;
  }

  @Override
  public void onStartOfSpeech() {
  }

  @Override
  public void onSpeechRmsChanged(float value) {

  }

  @Override
  public void onSpeechPartialResults(List<String> results) {
    for (String partial : results) {
      Log.d("Result", partial+"");
    }
  }

  @Override
  public void onSpeechResult(String result) {
    Log.d("Result", result+"");
    if (!TextUtils.isEmpty(result)) {
      Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
    }
  }

  @Override
  public void onSpecifiedCommandPronounced(String event) {
    try {
      if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
        ((AudioManager) Objects.requireNonNull(
          getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    if (Speech.getInstance().isListening()) {
      Speech.getInstance().stopListening();
    } else {
      RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
        if (granted) { // Always true pre-M
          try {
            Speech.getInstance().stopTextToSpeech();
            Speech.getInstance().startListening(null, this);
          } catch (SpeechRecognitionNotAvailable exc) {
            //showSpeechNotSupportedDialog();

          } catch (GoogleVoiceTypingDisabledException exc) {
            //showEnableGoogleVoiceTyping();
          }
        } else {
          Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
        }
      });
    }
  }


  @Override
  public void onTaskRemoved(Intent rootIntent) {
    //Restarting the service if it is removed.
    PendingIntent service =
      PendingIntent.getService(getApplicationContext(), new Random().nextInt(),
        new Intent(getApplicationContext(), MyService.class), PendingIntent.FLAG_ONE_SHOT);

    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    assert alarmManager != null;
    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
    super.onTaskRemoved(rootIntent);
  }
}

Für mehr Details,

https://github.com/sachinvarma/Speech-Recognizer

Hoffe das wird jemandem in Zukunft helfen.

Sachin Varma
quelle