web-dev-qa-db-fra.com

Reconnaissance vocale hors ligne sous Android (JellyBean)

Il semble que Google ait rendu la reconnaissance vocale hors ligne disponible à partir de Google Now pour les applications tierces. Il est utilisé par l'application nommée Utter .

Quelqu'un a-t-il déjà vu comment mettre en œuvre des commandes vocales simples avec cet enregistrement vocal hors ligne? Utilisez-vous simplement l'API SpeechRecognizer standard et cela fonctionne-t-il automatiquement?

78
rmooney

Google a discrètement activé la reconnaissance hors ligne dans cette mise à jour de la recherche, mais aucune API ni aucun paramètre supplémentaire n'est disponible dans la classe classe SpeechRecognizer . {Voir Editer au bas de cet article} La fonctionnalité est disponible sans codage supplémentaire. Cependant, le périphérique de l'utilisateur doit être configuré correctement pour pouvoir fonctionner. C'est là que réside le problème et j'imagine pourquoi. beaucoup de développeurs pensent qu'ils "manquent quelque chose".

En outre, Google a empêché certains périphériques Jelly Bean d’utiliser la reconnaissance hors ligne en raison de contraintes matérielles. Les périphériques auxquels cela s'applique ne sont pas documentés. En fait, rien n'est documenté. La configuration des fonctionnalités pour l'utilisateur s'est donc révélée être une affaire d'essais et d'erreurs (pour eux). Cela fonctionne tout de suite pour certains - pour ceux qui ne le font pas, c’est le «guide» que je leur fournis.

  1. Assurez-vous que la reconnaissance vocale Android par défaut est définie sur Google, pasSamsung/Vlingo 
  2. Désinstallez tous les fichiers de reconnaissance hors ligne déjà installés Dans les paramètres de Google Voice Search. 
  3. Allez dans les paramètres de votre application Android et voyez si vous pouvez désinstaller Les mises à jour des applications Google Search et Google Voice Search
  4. Si vous ne pouvez pas faire ce qui précède, rendez-vous sur le Play Store pour voir si vous avez le option là-bas.
  5. Redémarrez (si vous avez atteint 2, 3 ou 4)
  6. Mettez à jour Google Search et Google Voice Search à partir du Play Store (sivous avez atteint 3 ou 4 ou si une mise à jour est disponible de toute façon).
  7. Redémarrez (si vous avez atteint 6)
  8. Installer les fichiers de langue hors ligne anglais UK 
  9. Redémarrer
  10. Utilisez utter! Avec une connexion
  11. Basculer en mode avion et l'essayer
  12. Une fois que cela fonctionne, la reconnaissance hors ligne des autres langues, tels que l'anglais américain devrait commencer à travailler aussi.

EDIT: Modifier temporairement les paramètres régionaux de l'appareil en anglais au Royaume-Uni semble également lancer cela pour que cela fonctionne pour certains.

Certains utilisateurs ont indiqué qu’ils devaient encore redémarrer à plusieurs reprises avant de commencer à fonctionner, mais ils y parviennent tous finalement, souvent de manière inexplicablement liée au déclencheur, dont la clé se trouve dans le Google Search APK donc pas dans le domaine public ou une partie de AOSP .

D'après ce que je peux établir, Google teste la disponibilité d'une connexion avant de décider d'utiliser la reconnaissance hors ligne ou en ligne. Si une connexion est disponible initialement mais est perdue avant la réponse, Google fournira une erreur de connexion qui ne sera pas rétablie hors connexion. En remarque, si une requête pour la voix synthétisée sur le réseau a été faite, aucune erreur ne lui est fournie si elle échoue - Vous obtenez le silence.

La mise à jour de Google Search n'a activé aucune fonctionnalité supplémentaire dans Google Now. En fait, si vous essayez de l'utiliser sans connexion Internet, une erreur se produira. Je mentionne cela car je me demandais si la capacité serait retirée aussi discrètement qu'elle est apparue et ne devrait donc pas être utilisée dans la production.

Si vous envisagez de commencer à utiliser la classe SpeechRecognizer, soyez averti, un joli bogue majeur lui est associé; il doit être géré par votre propre implémentation.

Ne pouvant pas spécifiquement demander offline = true, il est impossible de contrôler cette fonctionnalité sans manipuler la connexion de données. Ordures. Des centaines de courriels d’utilisateurs vous demandent pourquoi vous n’avez pas activé quelque chose de si simple!

EDIT: Depuis le niveau 23 de l'API, un nouveau paramètre a été ajouté EXTRA_PREFER_OFFLINE auquel le service de reconnaissance Google semble adhérer.

J'espère que ce qui précède aide.

70
brandall

Je voudrais améliorer le guide que la réponse https://stackoverflow.com/a/17674655/2987828 envoie à ses utilisateurs, avec des images. C’est la phrase "Pour ceux qui ne le savent pas, c’est le" guide "que je leur fournis." que je veux améliorer.

L'utilisateur doit cliquer sur les quatre boutons surlignés en bleu dans ces images:

Go to your Android Application Settings, select Languages and input,edit Settings of Google Voice typing,select Download Offline speech recognition,select your languages in the ALL tab.

Ensuite, l'utilisateur peut sélectionner n'importe quelle langue souhaitée. Une fois le téléchargement terminé, il doit se déconnecter du réseau, puis cliquer sur le bouton "Microphone" du clavier. 

Cela a fonctionné pour moi (Android 4.1.2), puis la reconnaissance de la langue a fonctionné hors de la boîte, sans redémarrage. Je peux maintenant dicter des instructions au shell de l'émulateur de terminal! Et il est deux fois plus rapide hors ligne qu'en ligne, sur un padfone 2 d'ASUS.

Ces images sont sous licence cc by-sa 3.0 avec l'attribution requise pour stackoverflow.com/a/21329845/2987828; vous pouvez donc ajouter ces images n'importe où avec cette attribution.

(Ceci est la politique standard de toutes les images et textes sur stackoverflow.com)

20
user2987828

CMUSphinx, une boîte à outils open source de reconnaissance vocale, implémente une reconnaissance simple et flexible sur Android. Cela fonctionne purement hors ligne, rapide et configurable. Il peut écouter en permanence un mot clé, par exemple. 

Vous pouvez trouver le dernier code et tutoriel ici .

16
Nikolay Shmyrev

En bref, je n'ai pas la mise en œuvre, mais l'explication.

Google n'a pas rendu la reconnaissance vocale hors connexion disponible pour les applications tierces. La reconnaissance hors ligne est uniquement accessible via le clavier. Ben Randall (le développeur de utter!) Explique sa solution de contournement dans un article paru dans Android Police:

J'avais implémenté mon propre clavier et basculais entre Google Voice Typing et le clavier par défaut des utilisateurs avec une édition invisible champ de texte et Activité transparente pour obtenir la saisie. Sale bidouille!

C’était le seul moyen de le faire, car la saisie vocale hors ligne ne pouvait être que déclenché par un IME ou une application système (c'était mon hack racine) . L'autre type d'API de reconnaissance… ne l'a pas déclenché et a juste échoué avec une erreur de serveur. … Beaucoup de travail a été perdu pour moi sur la solution de contournement! Mais au moins j'étais prêt pour la mise en œuvre ...

De Utter! Prétend être la première application non-IME à utiliser la reconnaissance vocale hors ligne dans Jelly Bean

7
Leon Joosse

J'ai implémenté avec succès mon Speech-Service avec des fonctionnalités hors ligne en utilisant onPartialResults en mode hors connexion et onResults en mode connexion.

3
P. Stresow

J'avais affaire à cela et j'ai remarqué que vous deviez installer le paquet hors ligne pour votre langue. Mon paramètre de langue était "Español (États-Unis)" mais il n'y a pas de package hors ligne pour cette langue. Ainsi, lorsque j'ai désactivé toutes les connexions réseau, une alerte de RecognizerIntent m'avertissant que je ne pouvais pas atteindre Google, je change la langue en "Anglais (US)" (parce que j'ai déjà le paquet hors ligne) et lancé le RecognizerIntent, il a juste fonctionné.

Touches: Réglage de la langue == Package de reconnaissance vocale hors ligne

2
Akino

Il est apparemment possible d'installer manuellement la reconnaissance vocale hors ligne en téléchargeant les fichiers directement et en les installant manuellement aux emplacements appropriés. J'imagine que c'est simplement un moyen de contourner les exigences matérielles de Google. Cependant, personnellement, je n'ai pas eu à redémarrer ou quoi que ce soit, je me suis contenté de passer au Royaume-Uni et à nouveau.

1
Riju Chatterjee

Exemple de travail est donné ci-dessous,

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

Pour plus de détails,

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

J'espère que cela aidera quelqu'un à l'avenir.

0
Sachin Varma