Google Cloud Speech APIでストリーミング音声認識してみる
あすかです。
今日はJavaのおはなしです。
クラウドで音声認識というと、最近はいろいろなものがあります。
Bing、Watson、それからGoogle。
今回は、Google Cloud Speechを使って、ストリーミング音声認識に挑戦してみます!
今回は、その導入にあたって不満はまったことがたくさんありましたので、
その愚痴解決法とかを書いてみます。
※4/10追記:実行時のコマンドラインパラメータを書き忘れてたので追記しました
用語解説
音声認識とは
音声認識は、みなさん御存知の通り、音声をテキストに変換する技術です。
例えば、「おはよう」とマイクとかに話しかけて録音したやつを音声認識すると、「おはよう」という文字が出てくるわけです。
プログラムは、音声を文字として変換できます。
うひょおハイテク!と、言葉だけ聞くとだれもがそう思うのでしょうが、音声認識慣れが必要です。
音声認識に慣れていない人が話した音声を認識しようとしても、うまく変換できません。
意味不明な日本語になります。
私は耳が聴こえないので、音声認識で話す時のコツはよくわかりませんが、
大学の教授が言うには、アナウンサーみたいな話し方をすれば認識精度が向上するらしいです。
なぜGoogle Speech API?
精度がいいと評判だったので、何が何でも試してみたくてもってきました。
他にBingとかもありますが、私が調べた限り、精度に関してはお察しです。
Watsonも、Google Cloud Speechより微妙に精度が低いという比較の記事がありましたので、今回はGoogle Cloud Speechを使ってみます。
ストリーミング音声認識
音声認識には、2つのタイプがあります。
今回は、後者をやってみます。
Google Speech APIは、ストリーミング音声認識をサポートしています。
しかし、ストリーミングは、Java、Pythonなど一部の言語でしかサンプルが提供されていません。
C#ではサンプルは提供されていませんが、gRPCがnugetで提供されており、Google SpeechのgRPCの仕様と組み合わせれば、時間はかかるでしょうが理論上は可能です。
追記:C#でStreamingするソースができあがりました
めんどいので今回はJavaを使います。
今回やること
Googleが公開しているJavaサンプルをビルドしてみます。
まず、ここからリポジトリを落とします。
speech / grpc フォルダにあるのが、今回実行したいプログラムになります。
grpcフォルダをプロジェクトフォルダとして開きます。java-docs-samplesのルートをプロジェクトとして開くわけではありませんので注意してください。
これはmavenになっていますので、githubの説明を参照の上、適切な方法でビルドする必要があります。私はNetBeansでやりました。
Google Cloudプロジェクトを作成
Google Cloudコンソールを開き、画面上のバーから現在開いているプロジェクト名をクリックします。
するとプロジェクト選択画面が出てきますので、右上の「+」を押します。
プロジェクト名を入力し、画面の指示に従って進めます。
デフォルトではダッシュボードの中央に「APIの概要」が出てきますので、これをクリックして、
画面右側から「ライブラリ」をクリックし、検索ボックスに「speech」と入れます。
「Google Cloud Speech API」を選択します。
紛らわしいですが、下の「Speech API」はクローズドベータテスト中のものです。
一部に「Google Speech APIは商用利用不可」という記述を見かけますが、それはこのクローズドβテスト中のもののことで、今回利用するものは大丈夫です。多分。(ここの記事の「すでに公開済のアルファ版は~」の段落参照)
APIをプロジェクトに追加したら、「認証情報」より、認証情報を作成します。
「サービスアカウントキー」を選択します。
サービスマンではありません。
サービスアカウントを適当に選ぶなり作るなりしてからJSONを選択して、作成します。
作成すると、JSONファイルがダウンロードされますので、それをどこかに保存します。
認証キーをプログラムから読み込む
UNIX(mac含む)の場合は別の方法がありますが、Windowsでの設定方法がわからなかったので、今回は代替として以下のようにします。
StreamingRecognizeClient.javaのcreateChannel
メソッドからこういう行を見つけます。
GoogleCredentials creds = GoogleCredentials.getApplicationDefault();
これをこうします。
GoogleCredentials creds = GoogleCredentials.fromStream(new FileInputStream("C:\\credential.json"));
パスのところは、さっき保存したjsonファイルを指定しておきます。
利用言語を日本語に設定する
デフォルトではen-US
、つまり音声認識結果が英語で出力されます。
なので、言語を日本語に変える必要があります。
recognize
メソッド内で、
RecognitionConfig config = RecognitionConfig.newBuilder() .setEncoding(RecognitionConfig.AudioEncoding.LINEAR16) .setSampleRate(recorder.getSamplingRate()) .build();
こういう行を見つけて、
RecognitionConfig config = RecognitionConfig.newBuilder() .setEncoding(RecognitionConfig.AudioEncoding.LINEAR16) .setSampleRate(recorder.getSamplingRate()) .setLanguageCode("ja-JP") .build();
といった感じで、「ja-JP」の設定をはさみます。
pom.xmlを編集する
ここでサンプルを修正することで、利用するクラスが増減しました。
このままビルドするとmavenのcheckerでエラーが出ます。
そこで、ちょっと荒業ですが、
C:\Users\(ユーザ名)\.m2\repository\com\google\cloud\samples\shared-configuration\1.0.2\shared-configuration-1.0.2.pom
このファイルをテキストエディタで開きます。
こういう記述がありますので、そっくりそのまま消してしまいます。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-checkstyle-plugin</artifactId> <version>${maven-checkstyle-plugin-version}</version> <configuration> <configLocation>google-checks.xml</configLocation> <consoleOutput>true</consoleOutput> <failOnViolation>true</failOnViolation> <failsOnError>true</failsOnError> <includeTestSourceDirectory>true</includeTestSourceDirectory> <suppressionsLocation>suppressions.xml</suppressionsLocation> </configuration> <dependencies> <!-- Add a dependency to use bundled resources. See: http://stackoverflow.com/a/19690484/101923 --> <dependency> <groupId>com.google.cloud.samples</groupId> <artifactId>checkstyle-configuration</artifactId> <version>1.0.0</version> </dependency> </dependencies> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin>
これでリビルドしてください。
実行!
※画面は、このサンプルとプロセス間通信を利用して連携させたWPFアプリのものです。実際にサンプルをビルドすると、結果はコマンドラインやIDEの出力欄に表示されます。
※実行時にALPNなんとかのエラーが出る場合は、この記事を下へ読み進めてください。
サンプルアプリを起動するには、プロジェクトフォルダを開いて、コマンドプロンプトに、以下のように入力します。
java -cp target\grpc-sample-1.0-jar-with-dependencies.jar com.examples.cloud.speech.StreamingRecognizeClient --sampling 16000
音声認識がちゃんと出ます!わーいわーい
誤変換もところどころにありますが、日本語として理解できなくはないレベルです。
音声認識精度を、他のサービスと比べてみましょう。
Bing Speech APIのサンプルを走らせて、同じ動画を読ませたところ、こういう結果が返ってきます。
理解できなくはないですが、ところどころ難しい表現が入っています。
今回は、音声認識エンジンの弱点である「違う人が同時に話す」音声データを読み込ませたため、
ところどころセリフがとんでいたりしていますが、
それを引きにすると、精度の面ではGoogle Speechのほうがわかりやすいと思います。
いつか、Google Speechくらいの精度が普通になればいいですね。
実行時に「Jetty ALPN/NPN has not been properly configured.」が出る場合は
ALPNライブラリのページで「あまりおすすめできない」と書かれてはいるのですが、現状この解決法しか見つかりません。
まず、以下の2つのページから、最新verをクリックして、「******.jar」をダウンロードします。
- https://repo.maven.apache.org/maven2/org/mortbay/jetty/alpn/alpn-boot/
- https://repo.maven.apache.org/maven2/org/mortbay/jetty/alpn/jetty-alpn-agent/
次に、プログラムを起動する時のコマンドラインオプションに、
-Xbootclasspath/p:jars\alpn-boot-8.1.9.v20160720.jar -javaagent:jars\jetty-alpn-agent-2.0.6.jar
を加えます。今回の場合は2つのファイルをjars
フォルダに入れましたが、みなさんの環境に合わせて適切な名前に置き換えてください。
なお、プログラム起動時のオプション設定ですが、NetBeansの場合はプロジェクトのプロパティから設定できます。
参考:Googleドキュメントの誤りについて
Google Speech APIに関するGoogleドキュメントに、少なくとも2つの誤りがあります。
サンプルアプリケーションにおける「Java 非ストリーミングおよびストリーミング音声認識サンプル」ですが、このリンクからとぶのはNatual Language APIという別のAPIのサンプルです。
正しくはこっちです。
また、クライアントライブラリのページで、Javaのmavenコードが示されていますが、0.11.0-beta
というバージョンは存在しません。(17/4/8時点)
0.11.0-alpha
に置き換える必要があります。
公式がんばれ・・・!
まとめ
争え・・・!もっと争え・・・!