web-dev-qa-db-ja.com

Android(JellyBean)のオフライン音声認識

Googleは、サードパーティアプリ向けにGoogle Nowからオフライン音声認識を利用可能にしたようです。 tterという名前のアプリ で使用されています。

このオフライン音声録音で簡単な音声コマンドを実行する方法の実装を見た人はいますか?通常のSpeechRecognizer APIを使用するだけで、自動的に機能しますか?

78
rmooney

Googleはその検索更新でオフライン認識を静かに有効にしましたが、 SpeechRecognizerクラス 内で利用可能なAPIまたは追加パラメーターはまだありません。 {この投稿の下部にある編集を参照}この機能は追加のコーディングなしで使用できますが、ユーザーのデバイスを正しく構成する必要があります作業を開始すると、ここに問題があります。多くの開発者が「何かを見逃している」と思うのはなぜでしょう。

また、Googleはハードウェアの制約により、特定のJelly Beanデバイスがオフライン認識を使用することを制限しています。これがどのデバイスに適用されるかは文書化されておらず、実際には文書化されていないため、ユーザーの機能を構成することは(彼らにとって)試行錯誤の問題であることが判明しています。すぐに機能するものもあります。そうでない場合は、これが私が提供する「ガイド」です。

  1. デフォルトのAndroid Voice RecogniserがSamsung/VlingoではなくGoogleに設定されていることを確認してください
  2. Google Voice Search設定からインストール済みのオフライン認識ファイルをすべてアンインストールします
  3. Androidアプリケーション設定に移動し、Google検索およびGoogle音声検索アプリケーションの更新をアンインストールできるかどうかを確認します。
  4. 上記を実行できない場合は、Playストアにアクセスして、オプションがあるかどうかを確認してください。
  5. 再起動(2、3、または4を達成した場合)
  6. PlayストアからGoogle検索とGoogle Voice検索を更新します(3または4を達成した場合、または更新が利用可能な場合)。
  7. 再起動(6を達成した場合)
  8. 英語の英国オフライン言語ファイルをインストールする
  9. リブート
  10. 接続で tter! を使用します
  11. 機内モードに切り替えて試してみてください
  12. いったん機能すると、英語(米国)などの他の言語のオフライン認識も機能し始めるはずです。

編集:デバイスのロケールを一時的に英語(英国)に変更することも、一部の人のためにこれをキックスタートするようです。

一部のユーザーは、動作を開始する前に何度も再起動する必要があると報告しましたが、最終的にすべてのユーザーが最終的にそこにたどり着きます。多くの場合、何がトリガーであるか、キーは Google Search APK 、パブリックドメインまたは AOSP の一部ではありません。

私が確立できることから、Googleはオフライン認識を使用するかオンライン認識を使用するかを決定する前に、接続の可用性をテストします。最初に接続が利用可能であるが、応答前に失われた場合、Googleは接続エラーを提供し、オフラインにフォールバックしません。副次的な注意事項として、ネットワーク合成音声の要求が行われた場合、失敗してもエラーは提供されません。沈黙が得られます。

Google検索の更新により、Google Nowの追加機能は有効にならず、実際、インターネットに接続せずに使用しようとするとエラーになります。能力が出現するのと同じくらい静かに撤回され、したがって生産に頼るべきではないかと思ったので、私はこれに言及します。

SpeechRecognizerクラスの使用を開始する場合、警告があります。かなり関連する 主要なバグ があり、これを処理するには独自の実装が必要です。

特にoffline = trueを要求できないため、データ接続を操作しないとこの機能を制御できません。ゴミ。簡単な機能を有効にしない理由を尋ねる何百ものユーザーメールが届きます。

EDIT:APIレベル23以降、新しいパラメーターが追加されました EXTRA_PREFER_OFFLINE これはGoogle認識サービスに準拠しているようです。

上記がお役に立てば幸いです。

71
brandall

答え https://stackoverflow.com/a/17674655/2987828 がユーザーに画像とともに送信するガイドを改善したいと思います。 「そうでない人のために、これは私が彼らに提供する「ガイド」です」という文です。私が改善したいこと。

ユーザーは、これらの画像で青で強調表示されている4つのボタンをクリックする必要があります。

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.

その後、ユーザーは任意の言語を選択できます。ダウンロードが完了したら、彼はネットワークから切断し、キーボードの「マイク」ボタンをクリックする必要があります。

それは私のために働きました(Android 4.1.2)、そして言語認識は再起動することなく、箱から出して働いた。ターミナルエミュレーターのシェルに指示を指示できるようになりました!また、ASUSのpadfone 2では、オフラインよりもオンラインの2倍高速です。

これらの画像は、cc by-sa 3.0の下でライセンスが付与され、stackoverflow.com/a/21329845/2987828に帰属が必要です。したがって、これらの画像をこの属性とともにどこにでも追加できます。

(これは、stackoverflow.comのすべての画像とテキストの標準ポリシーです)

20
user2987828

Androidのシンプルで柔軟なオフライン認識は、オープンソースの音声認識ツールキットであるCMUSphinxによって実装されています。純粋にオフラインで、高速で設定可能です。たとえば、キーワードを継続的にリッスンできます。

最新のコードと チュートリアルはこちら を見つけることができます。

16
Nikolay Shmyrev

要するに、実装はありませんが、説明があります。

Googleは、サードパーティのアプリでオフライン音声認識を利用できるようにしませんでした。オフライン認識は、キーボードからのみアクセスできます。 Ben Randall(まったくの開発者!)は、Android Policeの記事で回避策について説明しています。

私は自分のキーボードを実装し、Google Voice Typingとユーザーのデフォルトのキーボードを切り替えて、非表示の編集テキストフィールドと透明なアクティビティで入力を取得しました。汚いハック!

これはそれを行う唯一の方法でした。オフラインの音声入力はIMEまたはシステムアプリケーション(それが私のルートハック)によってのみトリガーされたためです。他のタイプの認識API…はトリガーされず、サーバーエラーで失敗しました。 …回避策のために多くの作業が無駄になりました!しかし、少なくとも実装の準備はできていました...

から tter!Jelly Beanでオフライン音声認識を利用する最初の非IMEアプリであると主張

7
Leon Joosse

オフラインの場合はonPartialResults、オンラインの場合はonResultsを使用して、オフライン機能を備えたSpeech-Serviceを正常に実装しました。

3
P. Stresow

私はこれを扱っていましたが、あなたはあなたの言語のオフラインパッケージをインストールする必要があることに気付きました。私の言語設定は「Español(Estados Unidos)」でしたが、その言語のオフラインパッケージはないため、すべてのネットワーク接続をオフにすると、RecognizerIntentからGoogleに到達できないという警告が表示され、言語を「英語(米国)」(オフラインパッケージを既に持っているため)およびRecognizerIntentを起動しました。

キー:言語設定== Offline Voice Recognizer Package

2
Akino

ファイルを直接ダウンロードし、適切な場所に手動でインストールすることにより、オフライン音声認識を手動でインストールすることは明らかに可能です。これは、Googleのハードウェア要件を回避するための単なる方法だと思います。しかし、個人的には、再起動する必要はありませんでした。単に英国に変更し、再び元に戻しました。

1
Riju Chatterjee

以下に作業例を示します。

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

詳細については、

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

これが将来誰かを助けることを願っています。

0
Sachin Varma