スマフォのアプリを作りたい(38):RNをASでデバッグ=カオス
プログラミング [2022/01/29]
ReactNative環境でクロスプラットフォームなアプリを開発しようとして、2年以上が経過してます。しかも、飽きてしまって9か月以上放置しました。
このまま止めちゃおうかとも思ったのですが・・・なんか気持ち悪いので、また再開します。
以下の前半と【念のため】は、昨年の4月頃に書いていたメモの内容です。
あまりに時間を空けすぎたので、自分でも読み返してみました。
色んな試行錯誤をして、エラー出まくりで、さっぱり目的に近づけなかったのですが・・・
※※※【ここから本題】※※※※※※※※※※※※※※※※※※
ReactNativeは、メインの言語としてはJavaScript(その実JSX)を使用します。
でもほしいアプリを作るのに、ReactNative-Andoroid環境では、ネイティブのJavaパッケージを使うのが普通で、かつそのパッケージも何だか思うように出来てはいない印象があります。(バグだったり、制御の仕方がアプリに合わない。)
しかたなく、Javaコードも書き換えちゃったりしてます。
さらにオフライン単語認識機能(Julius)に至ってはC/C++コード。
今になって、「ReactNativeである必要があったのか」とも思えている。
これまで、ReactNativeのJSコードから呼ばれるJava部分に関しては、Chromeのデベロッパーツールでは何ともならなかったのでlogcatメッセージの出力でなんとかデバッグしてました。
でも、今後の事を予想するに、このままではどうにも効率が悪すぎです。
なので、ちゃんとしたデバッグ環境で、ブレーク、ステップ実行、変数参照なんかができないかと・・・
◆デバッグ環境に関する参考サイトの検索
参考:https://developer.android.com/studio/debug/index.html
一般的なAndroidStudio上でのデバッグ実行の仕方の説明のようです。
説明から以下の疑問が残りました。
・「React Nativeパッケージャー」ってなんでしょう。
・それに、AndroidStudioでプロジェクトを開くときのフォルダってどこを起点にするのかしら。
「React Nativeパッケージャー」は、どうも「Metro Bundler」のことのようです。
「react-native run-android」した時も起動されているようです。そんなメッセージが出ます。
でも、それを単独で起動する? そのやり方は?
さらに検索しました。
参考:https://www.javaer101.com/article/1041848.html
今度は、手順ぽく書いてくれてました。
◆Javaコード部分のデバッグ環境
以下は、徒労に終わった試行錯誤(【念のため】)も含めた経過を書きます。
1)「react-native run-android」を実行
AVDエミュレータ上でアプリが起動するのを確認
2)AndroidStudioにインポート
2-1)AndroidStudio(4.0)を起動
※以前、開発していたプロジェクトがオープンされたら、[File]-[Close Project]選択
2-2)Welcomeダイアログが開くので、その右側の[Import Project ・・・]を選択

2-3)ReactNativeのプロジェクトフォルダ下の「android」フォルダを指定して[OK]

しばらくすると、AndroidStudio画面の下に「android: failed at ・・・」と表示されました。
AndroidStudioはプロジェクトオープン時に勝手にSyncをするのは認知してましたが、今回は(Gradle)Buildまでもが走っていました。その際のエラーのようです。メッセージの中身は、以下。
「Error: EPERM: operation not permitted, scandir」を検索ワードにしてぐぐってみたけどシックリくる対応策にヒットしなくて、実際にメッセージされたファイル(signing-config.json)を見てみました。
sakuraで開こうとしたら、Read権限すらないと出ました。
もしやと思って、AndroidStudioを一旦終了し、今度は管理者権限で実行させてみました。

プロジェクトを開いて再度Buildが走り出しました。
途中、「Basedir D:\AppMake\proj\teburarec\android\calljulius does not exist」とか赤いメッセージは出たものの、「android: successful ・・・」「CONFIGURE SUCCESSFUL ・・・」とか表示されたので、たぶんプロジェクトのオープン(ビルド)は成功したようだ。
2-4)次にデバッグ実行(虫マーク)を実行させてみた。
以下のメッセージが出ました。
ただし、ビルドは成功している感じです。
既にアプリを起動済みのエミュレータに「(Refreshing...)」と何回かでている。
※※※※※※※※※※※※※※※※※※※※※
この後にも様々なアラートやエラーが出まくってました。それを解決すべく、別の参考サイトに書いてあったことも試してみました。でも、全然解決しませんでした。それで、嫌になって放り出した。
でも続きます。
このまま止めちゃおうかとも思ったのですが・・・なんか気持ち悪いので、また再開します。
以下の前半と【念のため】は、昨年の4月頃に書いていたメモの内容です。
あまりに時間を空けすぎたので、自分でも読み返してみました。
色んな試行錯誤をして、エラー出まくりで、さっぱり目的に近づけなかったのですが・・・
※※※【ここから本題】※※※※※※※※※※※※※※※※※※
ReactNativeは、メインの言語としてはJavaScript(その実JSX)を使用します。
でもほしいアプリを作るのに、ReactNative-Andoroid環境では、ネイティブのJavaパッケージを使うのが普通で、かつそのパッケージも何だか思うように出来てはいない印象があります。(バグだったり、制御の仕方がアプリに合わない。)
しかたなく、Javaコードも書き換えちゃったりしてます。
さらにオフライン単語認識機能(Julius)に至ってはC/C++コード。
今になって、「ReactNativeである必要があったのか」とも思えている。
これまで、ReactNativeのJSコードから呼ばれるJava部分に関しては、Chromeのデベロッパーツールでは何ともならなかったのでlogcatメッセージの出力でなんとかデバッグしてました。
でも、今後の事を予想するに、このままではどうにも効率が悪すぎです。
なので、ちゃんとしたデバッグ環境で、ブレーク、ステップ実行、変数参照なんかができないかと・・・
◆デバッグ環境に関する参考サイトの検索
参考:https://developer.android.com/studio/debug/index.html
一般的なAndroidStudio上でのデバッグ実行の仕方の説明のようです。
説明から以下の疑問が残りました。
・「React Nativeパッケージャー」ってなんでしょう。
・それに、AndroidStudioでプロジェクトを開くときのフォルダってどこを起点にするのかしら。
「React Nativeパッケージャー」は、どうも「Metro Bundler」のことのようです。
「react-native run-android」した時も起動されているようです。そんなメッセージが出ます。
でも、それを単独で起動する? そのやり方は?
さらに検索しました。
参考:https://www.javaer101.com/article/1041848.html
今度は、手順ぽく書いてくれてました。
◆Javaコード部分のデバッグ環境
以下は、徒労に終わった試行錯誤(【念のため】)も含めた経過を書きます。
1)「react-native run-android」を実行
AVDエミュレータ上でアプリが起動するのを確認
2)AndroidStudioにインポート
2-1)AndroidStudio(4.0)を起動
※以前、開発していたプロジェクトがオープンされたら、[File]-[Close Project]選択
2-2)Welcomeダイアログが開くので、その右側の[Import Project ・・・]を選択

2-3)ReactNativeのプロジェクトフォルダ下の「android」フォルダを指定して[OK]

しばらくすると、AndroidStudio画面の下に「android: failed at ・・・」と表示されました。
AndroidStudioはプロジェクトオープン時に勝手にSyncをするのは認知してましたが、今回は(Gradle)Buildまでもが走っていました。その際のエラーのようです。メッセージの中身は、以下。
----AndroidStudio Build メッセージ----------------
Error: EPERM: operation not permitted, scandir 'D:/AppMake/proj/teburarec/android/app/build/intermediates/signing_config/debug/out/signing-config.json'
---------------------------------------------------
「Error: EPERM: operation not permitted, scandir」を検索ワードにしてぐぐってみたけどシックリくる対応策にヒットしなくて、実際にメッセージされたファイル(signing-config.json)を見てみました。
sakuraで開こうとしたら、Read権限すらないと出ました。
もしやと思って、AndroidStudioを一旦終了し、今度は管理者権限で実行させてみました。

プロジェクトを開いて再度Buildが走り出しました。
途中、「Basedir D:\AppMake\proj\teburarec\android\calljulius does not exist」とか赤いメッセージは出たものの、「android: successful ・・・」「CONFIGURE SUCCESSFUL ・・・」とか表示されたので、たぶんプロジェクトのオープン(ビルド)は成功したようだ。
2-4)次にデバッグ実行(虫マーク)を実行させてみた。
以下のメッセージが出ました。
----AndroidStudio メッセージ------------------------
Project resolve errors
Warning: root project 'teburarec': Unable to resolve additional project configuration.
Details: org.apache.tools.ant.BuildException: Basedir D:\AppMake\proj\teburarec\android\calljulius does not exist
---------------------------------------------------
ただし、ビルドは成功している感じです。
既にアプリを起動済みのエミュレータに「(Refreshing...)」と何回かでている。
※※※※※※※※※※※※※※※※※※※※※
この後にも様々なアラートやエラーが出まくってました。それを解決すべく、別の参考サイトに書いてあったことも試してみました。でも、全然解決しませんでした。それで、嫌になって放り出した。
でも続きます。
スポンサーサイト
スマフォのアプリを作りたい(37):Bluetoothヘッドセットのマイクが使えない
プログラミング [2021/04/24]
まじこのテーマに飽きちゃってるんだけど、意地で続けてます。
今月に入って、ReactNative環境を何とかしようと調べを再開したところで、別の問題に気が付いちゃった。
なので、そっちを先に調べました。
◆Bluetoothヘッドセットのマイク入力問題
Bluetooth接続のヘッドセットを実機(スマフォ)と接続して、作ったアプリで音声認識させてみたら、
ヘッドセットのマイク入力が使えてないことに気が付いた!
音声出力はイヤホン側になってるんだけど、入力は内蔵マイクから拾ってます。
なんで?
参考:http://xawa99.blogspot.com/2013/01/Android-UseBluetoothHeadset.html
Androidでは、Bluetoothヘッドセットが接続されるとデフォルトでA2DPというプロファイルを割り当てるそうだ。このプロファイルはステレオの音声出力用で、マイク入力はサポートされてないんだって。
余計なことをしてくれちゃいますね。
接続されたBluetoothデバイスのプロファイルをHSP/HFPプロファイルに変更してくれるのかは分からないが、なんかアプリ(BTMono)があってそれを使うとヘッドセットのマイクが使えるとある。
やってみた。
ヘッドセットのマイク入力が使えた。
まずは、使えない原因が割り当てられているBluetoothのプロファイルにあるらしいことが分かった。
でも、他人様(別アプリ)の力を借りるのは、ちょっとアプリの独立性(独り立ち度)が低いので、標準的な設定、あるいは処理追加で何とかならないかさらに調べます。
参考:https://xtech.nikkei.com/atcl/nxt/column/18/00095/00005/?P=3
ヘッドセットを接続するときの設定オプションの意味が書いてありました。
「電話の音声」、「メディアの音声」と選択できるようになっているけど、これが「HSP/HFP」、「A2DP/AVRCP」に相当する指定なんだって。(なんと分かりにくい。)
ということは、先の「BTMono」アプリで設定しなくとも「HSP/HFP」:モノラル入出力にして使えるようになるのかと思って、「メディアの音声」を非チェック状態にして、「電話の音声」のみ指定して試してみました。
が、ダメでした。マイクのみならず出力側も内蔵スピーカーだけになってしまいます。
なんで?
使っているスマフォで同様の問題について書いているところはないか探してみました。
「SkypeでBluetoothのイヤホンマイクでマイクが使えない」というようなことを書いているところがありましたが、「ヘッドセットのせい?」で終わってました。
誰も同じ問題にぶち当たったことはないのだろうか・・・
持ってるスマフォ+Bluetoothヘッドセットの機種依存の現象なのか、Androidのバージョン依存なのかすらはっきりしない。
ちょっとげせねぇ。
Android(OS)として、Bluetooth周りの制御がどんな構成で行われているか本家のサイトの説明にありました。
参考:https://source.android.google.cn/devices/bluetooth?hl=ja
なるほど。Andorid7以前とAndroid8以降でがらっと変わってますね。
「android.bluetooth」というフレームワークがあるという点は共通です。
(フレームワーク?:ランタイムであって、OSバージョン毎にビルドが必要ということではないと期待。)
参考:https://android.roof-balcony.com/bluetooth/bluetooth_headset_getstate/
参考:https://www.javaer101.com/ja/article/17472281.html
Android上で、Bluetooth接続を制御するやり方をサンプルコード含めて解説されています。
全文を読んでいないので、はっきりしたことは言えませんが、「電話の音声(HSP/HFP)」Only設定が手持ちのスマフォで機能しない件の対策コードを書くことができるかも。
作成中のアプリに取り込んで試そうかとも思いましたが、
「Android8以降のスマフォでは問題ない」とかだと力を注いだ甲斐がないし、「BTMono」を使えば現状でも何とかなるみたいだし。
この件は、しばらくこのままにしちゃいます。
◆オフラインでも音声認識可能?
前の問題の解決方法を検索している最中に「Andoroid6.0以降だとオフラインでも音声認識可能」とか書いてあるサイトが目に入りました。
参考:https://gourmet-technology-crypto.jp/tech/android-speechrecognizer%E3%81%A7%E5%B8%B8%E6%99%82%E3%82%AA%E3%83%95%E3%83%A9%E3%82%A4%E3%83%B3%E9%9F%B3%E5%A3%B0%E8%AA%8D%E8%AD%98%E3%82%92%E3%81%99%E3%82%8B/
これまで、オフラインで音声認識できないと思ってたから一生懸命Juliusを移植したのに・・・そんな。
手持ちのAndroidスマフォ(arrowsM03)で早速設定を試みました。
でも、サイトの説明通りの設定項目は出てこなかった。
使える/使えないは、機種依存があるみたいですね。
Androidのバージョンが上がった機種だとどうなんですかね。
なので、「ホンマけ?」の答えは出ませんでした。
これも放置します。
新たなスマフォ(Android 8とか)の購入も今のところその気ないし。
いまさらねー。
割り込みでちょと脱線してしまいましたが、
次回からデバッグ環境を何とかしたいを再開します。
では、この話はこの辺で。ごきげんよう。
m(__)m
今月に入って、ReactNative環境を何とかしようと調べを再開したところで、別の問題に気が付いちゃった。
なので、そっちを先に調べました。
◆Bluetoothヘッドセットのマイク入力問題
Bluetooth接続のヘッドセットを実機(スマフォ)と接続して、作ったアプリで音声認識させてみたら、
ヘッドセットのマイク入力が使えてないことに気が付いた!
音声出力はイヤホン側になってるんだけど、入力は内蔵マイクから拾ってます。
なんで?
参考:http://xawa99.blogspot.com/2013/01/Android-UseBluetoothHeadset.html
Androidでは、Bluetoothヘッドセットが接続されるとデフォルトでA2DPというプロファイルを割り当てるそうだ。このプロファイルはステレオの音声出力用で、マイク入力はサポートされてないんだって。
余計なことをしてくれちゃいますね。
接続されたBluetoothデバイスのプロファイルをHSP/HFPプロファイルに変更してくれるのかは分からないが、なんかアプリ(BTMono)があってそれを使うとヘッドセットのマイクが使えるとある。
やってみた。
ヘッドセットのマイク入力が使えた。
まずは、使えない原因が割り当てられているBluetoothのプロファイルにあるらしいことが分かった。
でも、他人様(別アプリ)の力を借りるのは、ちょっとアプリの独立性(独り立ち度)が低いので、標準的な設定、あるいは処理追加で何とかならないかさらに調べます。
参考:https://xtech.nikkei.com/atcl/nxt/column/18/00095/00005/?P=3
ヘッドセットを接続するときの設定オプションの意味が書いてありました。
「電話の音声」、「メディアの音声」と選択できるようになっているけど、これが「HSP/HFP」、「A2DP/AVRCP」に相当する指定なんだって。(なんと分かりにくい。)
ということは、先の「BTMono」アプリで設定しなくとも「HSP/HFP」:モノラル入出力にして使えるようになるのかと思って、「メディアの音声」を非チェック状態にして、「電話の音声」のみ指定して試してみました。
が、ダメでした。マイクのみならず出力側も内蔵スピーカーだけになってしまいます。
なんで?
使っているスマフォで同様の問題について書いているところはないか探してみました。
「SkypeでBluetoothのイヤホンマイクでマイクが使えない」というようなことを書いているところがありましたが、「ヘッドセットのせい?」で終わってました。
誰も同じ問題にぶち当たったことはないのだろうか・・・
持ってるスマフォ+Bluetoothヘッドセットの機種依存の現象なのか、Androidのバージョン依存なのかすらはっきりしない。
ちょっとげせねぇ。
Android(OS)として、Bluetooth周りの制御がどんな構成で行われているか本家のサイトの説明にありました。
参考:https://source.android.google.cn/devices/bluetooth?hl=ja
なるほど。Andorid7以前とAndroid8以降でがらっと変わってますね。
「android.bluetooth」というフレームワークがあるという点は共通です。
(フレームワーク?:ランタイムであって、OSバージョン毎にビルドが必要ということではないと期待。)
参考:https://android.roof-balcony.com/bluetooth/bluetooth_headset_getstate/
参考:https://www.javaer101.com/ja/article/17472281.html
Android上で、Bluetooth接続を制御するやり方をサンプルコード含めて解説されています。
全文を読んでいないので、はっきりしたことは言えませんが、「電話の音声(HSP/HFP)」Only設定が手持ちのスマフォで機能しない件の対策コードを書くことができるかも。
作成中のアプリに取り込んで試そうかとも思いましたが、
「Android8以降のスマフォでは問題ない」とかだと力を注いだ甲斐がないし、「BTMono」を使えば現状でも何とかなるみたいだし。
この件は、しばらくこのままにしちゃいます。
◆オフラインでも音声認識可能?
前の問題の解決方法を検索している最中に「Andoroid6.0以降だとオフラインでも音声認識可能」とか書いてあるサイトが目に入りました。
参考:https://gourmet-technology-crypto.jp/tech/android-speechrecognizer%E3%81%A7%E5%B8%B8%E6%99%82%E3%82%AA%E3%83%95%E3%83%A9%E3%82%A4%E3%83%B3%E9%9F%B3%E5%A3%B0%E8%AA%8D%E8%AD%98%E3%82%92%E3%81%99%E3%82%8B/
これまで、オフラインで音声認識できないと思ってたから一生懸命Juliusを移植したのに・・・そんな。
手持ちのAndroidスマフォ(arrowsM03)で早速設定を試みました。
でも、サイトの説明通りの設定項目は出てこなかった。
使える/使えないは、機種依存があるみたいですね。
Androidのバージョンが上がった機種だとどうなんですかね。
なので、「ホンマけ?」の答えは出ませんでした。
これも放置します。
新たなスマフォ(Android 8とか)の購入も今のところその気ないし。
いまさらねー。
割り込みでちょと脱線してしまいましたが、
次回からデバッグ環境を何とかしたいを再開します。
では、この話はこの辺で。ごきげんよう。
m(__)m
スマフォのアプリを作りたい(36):ReactNative環境でのプロジェクト名の変更
プログラミング [2021/04/23]
だーーーーーーーーーーーいぶ間が空いてしまいました。
現実逃避と言うか・・・PPバンド・アミアミ・マニュアル作りに感(かま)け、さらに韓流ドラマ三昧で、3月は廃人のように過ごしました。
そうこうしているうちにGoogleCloudのサービス(タダ)期間(12か月)が終わってしまった。(ハズです。)
えっ、もう始めてから1年過ぎちゃったの?
我ながら情けない。こんなに進みが悪いなんて。
でも、諦めずにコツコツやります。(死ぬまでには何かできるかも。)
今後、Googleの音声認識サービスを使うと有料になるんだよね。
そんな法外な請求はされないとは思ってるけど、ちょっとドキドキしながら「Google Cloud Platform」(入口:https://cloud.google.com/?hl=ja →「コンソール」)で利用状況を確認してみると・・・今のところ請求額は\0となってます。(あれ?4月に入ってからちょっと使ったはずなんだけどな。)
さて、未だ全部とは言わないまでも、ある程度必要な「コンポーネント」というか「やり方」をそれなりに学習/準備したと思っているので、実際に「使える」レベルのアプリの開発にぼちぼち入りたいと思います。
今回は、ReactNativeの開発プロジェクトのリネームと・・・・
ともかく始めます。
◆開発プロジェクトのリネーム
お試しアプリを作り始めたときに付けたアプリ(プロジェクト)の名前が気に入らなくなったので、変えようと思いました。
プロジェクト名の変更ということになります。
サラからプロジェクトを作り直しした方がよいのかもしれませんが、ReactNativeの場合、プロジェクトの作成は開発環境そのものの作り直しに近い気がします。(単なる印象です。これまで、ともかく大変だったから。)
なので、横着してこれまでのプロジェクトフォルダをコピペして、中身をリネームしてみることにしました。
①旧プロジェクトフォルダをコピペ
②プロジェクトフォルダ名をリネーム
③そのフォルダ下の全ファイルに旧名をGrepし、見つかったファイル(テキスト系)内の記述を新名に変更
④プロジェクトフォルダ配下の旧名フォルダを新名に変更
⑤react-native run-android実行
1)「react-native-google-speech-api」のビルドに失敗
フォルダの中身が空になってました。しかも、普通のフォルダになってます。???
通常のnpmでのインストールとちょっと違うやり方をしたので別のローカルフォルダへの「リンク」になっているのは認知してたのですが、
なぜ「リンク」としてコピーされないんだろう。
コマンドプロンプトを起動して、コピー元の「node_modules」フォルダ内をDIRコマンドで見てみたら、「react-native-google-speech-api」フォルダが<JUNCTION>と表示されます。「.lnk」ファイルでも<DIR>でもない!
JUNCTIONってなんだ?・・・さるは知りませんでした。「.lnk」以外にフォルダアクセスをリダイレクトする機能がファイルシステムにあるんですね。
そのせいで親フォルダまるごとコピーができなかったみたいです。(そういうものなんだ・・・)
再度、「react-native-google-speech-api」のみコピーしてみたら、<JUNCTION>としてのコピーではなく、リンク先の中身が丸ごとコピーされました。
まあ、それはそれでも、ビルドに支障がなければ却ってOK。
2)いつものbuild途中のフォルダアクセスに失敗
ビルド途中に更新されるbuildフォルダ内のファイル/フォルダのcreate/deleteに失敗するエラーが何回か出ました。
その他のエラーもあったようにも見えたのですが、リトライで解消された模様。
今に始まった事ではないですが、どーもビルド環境が不安定です。
おそらく、環境をインストールしているドライブ(SSD USB2.0HUB経由接続)のアクセス性能が悪いせいではないかと。
SSDそのもののスペックは、・・・遅くはないらしい。
HUBをUSB3.0に変えてみましたが、感覚的にはほとんど影響なかった。
3)環境ファイルの修正漏れ
最後に残ったのが、
ちょっと悩みましたが、「android\app\」配下の「build.gradle」に修正漏れがあったためでした。
同フォルダに「BUCK」という名前のファイルもあって、その中にも旧名が存在したので、それも念のため修正した。
これで、ビルドは通るようになったのですが、エミュレータ上でのアプリの起動がなんだかうまく動きません。
(色んな症状が発生する・・・)
これも、アプリをアンインストールしたり、エミュレータの再起動から何度かやり直したら、うまくInstall&Goされるようになりました。
やれやれ、ずっとこんな感じだな。
次に、Javaコード部分のデバッグ環境をなんとかしたいと思って、ReactNativeのビルド環境+AndroidStudioのデバッガとのリンクの仕方を調べてました。
でも、色んな現象が出て、気力も萎えてフリーズ状態になってしまった。
このせいで、2か月は経過しちゃったのかな。
そうこうしている内に別な問題に気が付いたので、そっちを優先で調べることに。
てなわけで、次の話は「環境構築」から離れるので、一旦ここで切ります。
それではまた。ご機嫌よう。
m(__)m
現実逃避と言うか・・・PPバンド・アミアミ・マニュアル作りに感(かま)け、さらに韓流ドラマ三昧で、3月は廃人のように過ごしました。
そうこうしているうちにGoogleCloudのサービス(タダ)期間(12か月)が終わってしまった。(ハズです。)
えっ、もう始めてから1年過ぎちゃったの?
我ながら情けない。こんなに進みが悪いなんて。
でも、諦めずにコツコツやります。(死ぬまでには何かできるかも。)
今後、Googleの音声認識サービスを使うと有料になるんだよね。
そんな法外な請求はされないとは思ってるけど、ちょっとドキドキしながら「Google Cloud Platform」(入口:https://cloud.google.com/?hl=ja →「コンソール」)で利用状況を確認してみると・・・今のところ請求額は\0となってます。(あれ?4月に入ってからちょっと使ったはずなんだけどな。)
さて、未だ全部とは言わないまでも、ある程度必要な「コンポーネント」というか「やり方」をそれなりに学習/準備したと思っているので、実際に「使える」レベルのアプリの開発にぼちぼち入りたいと思います。
今回は、ReactNativeの開発プロジェクトのリネームと・・・・
ともかく始めます。
◆開発プロジェクトのリネーム
お試しアプリを作り始めたときに付けたアプリ(プロジェクト)の名前が気に入らなくなったので、変えようと思いました。
プロジェクト名の変更ということになります。
サラからプロジェクトを作り直しした方がよいのかもしれませんが、ReactNativeの場合、プロジェクトの作成は開発環境そのものの作り直しに近い気がします。(単なる印象です。これまで、ともかく大変だったから。)
なので、横着してこれまでのプロジェクトフォルダをコピペして、中身をリネームしてみることにしました。
①旧プロジェクトフォルダをコピペ
②プロジェクトフォルダ名をリネーム
③そのフォルダ下の全ファイルに旧名をGrepし、見つかったファイル(テキスト系)内の記述を新名に変更
④プロジェクトフォルダ配下の旧名フォルダを新名に変更
⑤react-native run-android実行
1)「react-native-google-speech-api」のビルドに失敗
フォルダの中身が空になってました。しかも、普通のフォルダになってます。???
通常のnpmでのインストールとちょっと違うやり方をしたので別のローカルフォルダへの「リンク」になっているのは認知してたのですが、
なぜ「リンク」としてコピーされないんだろう。
コマンドプロンプトを起動して、コピー元の「node_modules」フォルダ内をDIRコマンドで見てみたら、「react-native-google-speech-api」フォルダが<JUNCTION>と表示されます。「.lnk」ファイルでも<DIR>でもない!
JUNCTIONってなんだ?・・・さるは知りませんでした。「.lnk」以外にフォルダアクセスをリダイレクトする機能がファイルシステムにあるんですね。
そのせいで親フォルダまるごとコピーができなかったみたいです。(そういうものなんだ・・・)
再度、「react-native-google-speech-api」のみコピーしてみたら、<JUNCTION>としてのコピーではなく、リンク先の中身が丸ごとコピーされました。
まあ、それはそれでも、ビルドに支障がなければ却ってOK。
2)いつものbuild途中のフォルダアクセスに失敗
ビルド途中に更新されるbuildフォルダ内のファイル/フォルダのcreate/deleteに失敗するエラーが何回か出ました。
その他のエラーもあったようにも見えたのですが、リトライで解消された模様。
今に始まった事ではないですが、どーもビルド環境が不安定です。
おそらく、環境をインストールしているドライブ(SSD USB2.0HUB経由接続)のアクセス性能が悪いせいではないかと。
SSDそのもののスペックは、・・・遅くはないらしい。
HUBをUSB3.0に変えてみましたが、感覚的にはほとんど影響なかった。
3)環境ファイルの修正漏れ
最後に残ったのが、
----コマンドプロンプト-----------------------------
:
:
Starting: Intent { cmp=com.teburarec/.MainActivity }
Error type 3
Error: Activity class {com.teburarec/com.teburarec.MainActivity} does not exist.
---------------------------------------------------
ちょっと悩みましたが、「android\app\」配下の「build.gradle」に修正漏れがあったためでした。
同フォルダに「BUCK」という名前のファイルもあって、その中にも旧名が存在したので、それも念のため修正した。
これで、ビルドは通るようになったのですが、エミュレータ上でのアプリの起動がなんだかうまく動きません。
(色んな症状が発生する・・・)
これも、アプリをアンインストールしたり、エミュレータの再起動から何度かやり直したら、うまくInstall&Goされるようになりました。
やれやれ、ずっとこんな感じだな。
次に、Javaコード部分のデバッグ環境をなんとかしたいと思って、ReactNativeのビルド環境+AndroidStudioのデバッガとのリンクの仕方を調べてました。
でも、色んな現象が出て、気力も萎えてフリーズ状態になってしまった。
このせいで、2か月は経過しちゃったのかな。
そうこうしている内に別な問題に気が付いたので、そっちを優先で調べることに。
てなわけで、次の話は「環境構築」から離れるので、一旦ここで切ります。
それではまた。ご機嫌よう。
m(__)m
スマフォのアプリを作りたい(35):単語音声認識制御のデバッグ
プログラミング [2021/01/06]
前回まで、JuliusのAndroidスマフォ上へのポーティングの話を延々書いてきて、一旦「完了?」にしたのですが・・・
どーも認識率が悪過ぎるし、何回か試すと動きが固まるし。
なので、もうちょっとデバッグしました。
◆単語認識率0%の件
JuliusをPC上で評価して、さらに.wavファイルを入力として味見したときには見なかった状態:認識率0%。
これは、Juliusのせいではなく、使い方の問題と予想して調べ始めました。
これまで、Windows版、AndroidStudio環境でも確認していなかったのは、
・入力デバイスを標準入力とした場合の動作(-input stdin)
・rawデータを入力とした場合の動作
です。(動作環境を作る手間がめんどうでサボった。)
まずは、サンプリイングレートとかビット深度とかを改めて、VoiceRecorder側とJulius側への指定が一致してるか確認しました。
大丈夫そうです。
Juliusのマニュアル(3.4.3 標準入力)では、以下のように書かれてました。
『標準入力から RAW 形式あるいは WAV 形式の音声入力を受け取ることができる.これには-input stdinを指定する.RAW ファイルの場合、サンプリングレートがチェックされないので注意すること.』
これしか書いてません。
・RAWとWAVは勝手に判断してくれるんだろうか?
・RAW形式って、PCMデータが頭からべた書きされているファイルだよね?
とか不安になります。
なので、まずはWindows環境で、標準入力にリダイレクトでrawファイルを入力して見ます。
まずは、raw形式の音声データを作るところから。
Windows版のJuliusで「-input stdin」を試してみます。
コマンドラインでリダイレクトしたら、rawファイルを入力できるのではないかと・・・
あてずっぽうです。
結果は、ファイルから読み込めてないみたいです。
Juliusには「-input rawfile」という指定も可能なので、そっちも試してみました。
正しく認識しませんでした。
誤認識ぶりもReactNative版のときと同じです。
なので、続けて元のwavファイルを指定してみました。
wavファイルは正常認識されました。
・・・
改めてraw形式の音声ファイルについてぐぐってみました。
16bitデータの場合は、通常ビッグエンディアンになってなければダメらしいことが分かった。
一方、
・wav形式のPCMデータは・・・リトルエンディアンなのか?
・それを、Audacityで単純にraw出力した場合はリトルのまま?
試した方が早いかと思って以下をやってみました。
-Audcityを再度起動して、rawファイルを読み込んでみたら、読み込み時にビッグかリトルを指定するようになってます。
-ビッグを指定してオープンすると波形が化けて、再生してもまともな言葉としては認識不能になりました。
-リトルを指定してオープンすると元の言葉が聞き取れます。
つまり、最初に.wavを.rawとして出力したデータはリトルエンディアンになっているということだと思います。
そこで、
-最初に作成したrawファイルを敢えてビッグということにしてオープンします。
-そのデータを再度、前の<手順1>でセーブし直します。
-新たに作成したrawファイルをAudacityで再生してみると、2倍速再生のようになりました。
-でも、さるの耳でも言葉として聞き取れるので、Juliusに入力してみました。
正常認識されました。
ReactNative版もこれが原因ではないかと思われます。
つまり、VoiceRecorder(com.reactlibrary.voice_recorder)から渡されるPCMデータはリトルエンディアンであって、それをそのまま、Julius(-input atdin)に渡したらダメということ。
・対策方法は、ヘッダデータを付してwavデータとして渡すか
→予めデータ長を把握してからでないとJuliusに渡せない。
・Julius側バッファにコピーする際に、ビッグエンディアンにする。
→性能負荷が増える。
でも、後者ですよね。
続きます。
どーも認識率が悪過ぎるし、何回か試すと動きが固まるし。
なので、もうちょっとデバッグしました。
◆単語認識率0%の件
JuliusをPC上で評価して、さらに.wavファイルを入力として味見したときには見なかった状態:認識率0%。
これは、Juliusのせいではなく、使い方の問題と予想して調べ始めました。
これまで、Windows版、AndroidStudio環境でも確認していなかったのは、
・入力デバイスを標準入力とした場合の動作(-input stdin)
・rawデータを入力とした場合の動作
です。(動作環境を作る手間がめんどうでサボった。)
まずは、サンプリイングレートとかビット深度とかを改めて、VoiceRecorder側とJulius側への指定が一致してるか確認しました。
大丈夫そうです。
Juliusのマニュアル(3.4.3 標準入力)では、以下のように書かれてました。
『標準入力から RAW 形式あるいは WAV 形式の音声入力を受け取ることができる.これには-input stdinを指定する.RAW ファイルの場合、サンプリングレートがチェックされないので注意すること.』
これしか書いてません。
・RAWとWAVは勝手に判断してくれるんだろうか?
・RAW形式って、PCMデータが頭からべた書きされているファイルだよね?
とか不安になります。
なので、まずはWindows環境で、標準入力にリダイレクトでrawファイルを入力して見ます。
まずは、raw形式の音声データを作るところから。
<Audacity手順1>:rawファイルとして出力 -インストール済みのAudacityを起動して、変換元の.wavファイルを開きます。 -メニュー[ファイル]-[音声の書き出し]を選択 -「ファイルの種類」に「その他の非圧縮ファイル」を選択 -ヘッダ:「RAW(header-less)」、 エンコーディング:「Signed 16-bit PCM」を指定 -「ファイル名」欄の名前を確認した後、[保存]ボタンをクリック |
Windows版のJuliusで「-input stdin」を試してみます。
コマンドラインでリダイレクトしたら、rawファイルを入力できるのではないかと・・・
あてずっぽうです。
----コマンドプロンプト-----------------------------
C:\WINDOWS\system32>cd /d d:\appmake\julius_base\for_teburarec
d:\AppMake\julius_base\for_teburarec>chcp 65001
Active code page: 65001
d:\AppMake\julius_base\for_teburarec>..\dictation-kit-4.5\bin\windows\julius.exe -w teburarecword.dict -h ..\dictation-kit-4.5\model\phone_m\jnas-mono-16mix-gid.binhmm -input stdin < w_kiroku.raw
STAT: jconf successfully finalized
STAT: *** loading AM00 _default
:
:
:
------
### read waveform input
Stat: adin_stdin: reading wavedata from stdin...
STAT: 925 samples (0.06 sec.)
STAT: ### speech analysis (waveform -> MFCC)
### Recognition: 1st pass (LR beam)
....WARNING: 00 _default: input processed, but no survived word found
<search failed>
------
### read waveform input
Error: adin_stdin: stdin reached EOF
reached end of input on stdin
d:\AppMake\julius_base\for_teburarec>
---------------------------------------------------
結果は、ファイルから読み込めてないみたいです。
Juliusには「-input rawfile」という指定も可能なので、そっちも試してみました。
----コマンドプロンプト-----------------------------
C:\WINDOWS\system32>cd /d d:\appmake\julius_base\for_teburarec
d:\AppMake\julius_base\for_teburarec>chcp 65001
Active code page: 65001
d:\AppMake\julius_base\for_teburarec>..\dictation-kit-4.5\bin\windows\julius.exe -w teburarecword.dict -h ..\dictation-kit-4.5\model\phone_m\jnas-mono-16mix-gid.binhmm -input rawfile
:
:
:
------
### read waveform input
enter filename->w_kiroku.raw
Stat: adin_file: input speechfile: w_kiroku.raw
STAT: 25078 samples (1.57 sec.)
STAT: ### speech analysis (waveform -> MFCC)
### Recognition: 1st pass (LR beam)
.........................................................................................
pass1_best: チェック
pass1_best_wordseq: チェック
pass1_best_phonemeseq: silB ch e q k u silE
pass1_best_score: -3824.508789
sentence1: チェック
wseq1: チェック
phseq1: silB ch e q k u silE
cmscore1: 0.353
score1: -3824.508789
------
### read waveform input
enter filename->
---------------------------------------------------
正しく認識しませんでした。
誤認識ぶりもReactNative版のときと同じです。
なので、続けて元のwavファイルを指定してみました。
----コマンドプロンプト-----------------------------
enter filename->w_kiroku.wav
Stat: adin_file: input speechfile: w_kiroku.wav
STAT: 25078 samples (1.57 sec.)
STAT: ### speech analysis (waveform -> MFCC)
### Recognition: 1st pass (LR beam)
.........................................................................................
pass1_best: 記録
pass1_best_wordseq: 記録
pass1_best_phonemeseq: silB k i r o k u silE
pass1_best_score: -4061.207031
sentence1: 記録
wseq1: 記録
phseq1: silB k i r o k u silE
cmscore1: 0.972
score1: -4061.207031
------
### read waveform input
enter filename->
---------------------------------------------------
wavファイルは正常認識されました。
・・・
改めてraw形式の音声ファイルについてぐぐってみました。
16bitデータの場合は、通常ビッグエンディアンになってなければダメらしいことが分かった。
一方、
・wav形式のPCMデータは・・・リトルエンディアンなのか?
・それを、Audacityで単純にraw出力した場合はリトルのまま?
試した方が早いかと思って以下をやってみました。
-Audcityを再度起動して、rawファイルを読み込んでみたら、読み込み時にビッグかリトルを指定するようになってます。
<Audacity手順2>:rawファイルの読み込み -メニュー[ファイル]-[取り込み]-[ロー(raw)データの取り込み]を選択 -ファイル選択ダイアログで、rawファイルを指定して[開く] -ダイアログ上のエンコーディング/バイト順序/チャンネル/サンプリング周波数等を指定し[取り込み] |
-ビッグを指定してオープンすると波形が化けて、再生してもまともな言葉としては認識不能になりました。
-リトルを指定してオープンすると元の言葉が聞き取れます。
つまり、最初に.wavを.rawとして出力したデータはリトルエンディアンになっているということだと思います。
そこで、
-最初に作成したrawファイルを敢えてビッグということにしてオープンします。
-そのデータを再度、前の<手順1>でセーブし直します。
-新たに作成したrawファイルをAudacityで再生してみると、2倍速再生のようになりました。
-でも、さるの耳でも言葉として聞き取れるので、Juliusに入力してみました。
----コマンドプロンプト-----------------------------
enter filename->w_kirokuB.raw
Stat: adin_file: input speechfile: w_kirokuB.raw
STAT: 25078 samples (1.57 sec.)
STAT: ### speech analysis (waveform -> MFCC)
### Recognition: 1st pass (LR beam)
.........................................................................................
pass1_best: 記録
pass1_best_wordseq: 記録
pass1_best_phonemeseq: silB k i r o k u silE
pass1_best_score: -3679.109375
sentence1: 記録
wseq1: 記録
phseq1: silB k i r o k u silE
cmscore1: 0.933
score1: -3679.109375
---------------------------------------------------
正常認識されました。
ReactNative版もこれが原因ではないかと思われます。
つまり、VoiceRecorder(com.reactlibrary.voice_recorder)から渡されるPCMデータはリトルエンディアンであって、それをそのまま、Julius(-input atdin)に渡したらダメということ。
・対策方法は、ヘッダデータを付してwavデータとして渡すか
→予めデータ長を把握してからでないとJuliusに渡せない。
・Julius側バッファにコピーする際に、ビッグエンディアンにする。
→性能負荷が増える。
でも、後者ですよね。
続きます。
スマフォのアプリを作りたい(34):スマフォだけで動作する音声認識⑨
プログラミング [2020/12/15]
えーーと、どこまで行ったんでしたっけ?
前の状況を書いてからあまりに間が空いたので、前の記事を自分で読み返してます。
もう何のためにこれをやり始めたのかも忘れそうです。
「スマフォのアプリを作りたい」シリーズのサブテーマ「スマフォだけで動作する音声認識」も9回目になっちゃった。
進み具合が悪くて、かなりダラケ気味になってました。
とりあえずこのサブテーマまでは、何とか完結させます。
前回、AndroidStudio環境で作成したJava+C/C++ライブラリ(calljulius)のビルド環境をReact Nativeの環境に持ち込んでcalljuliusのビルドが走り出すところまでを「見る」ことができました。
残りの課題は、
1)calljuliusで参照する設定ファイル等のapkへの取込み
2)今のフォルダ構成の見直し
3)他Javaコードからcalljuliusの呼出し実装/テスト
になるかと思ってました。
では、ボヤキを再開します。
◆calljuliusライブラリの前提ファイルの追加
AndroidStudioでcalljuliusを作成した段階で、calljulius(JuliusLib(C/C++):音声認識エンジンライブラリ)では、単語辞書/音響モデル?/設定ファイルが必要な作りになっています。
それらのファイルはassetsフォルダで、APK内に組み込まれて動作時にライブラリから参照されます。
VTChat(React Nativeのお試しアプリ)としてのAPK内にcalljuliusの関連ファイルはどういうビルド設定をすれば取り込まれるようになるのかな?
Android/Gradleビルド環境を未だに全く理解できてないので、かなり面倒そうだなーとか思っていました。
まず手始めに、前回calljulius環境込みのビルド結果のAPKの中身を見てみます。
すると、なんということでしょう~!
JuliusLib(C/C++)ライブラリ本体:libjuliusword.so もassetsフォルダに仕込むべきファイルたちも既に入ってるではありませんか!
このシリーズ初の「あれ? ラッキー!」です。
どういう仕組みなのかは、全く分かりませんが、AndroidStudio上で組んだビルドのOutput構成が、そのままReactNative側のOutput構成に取り込まれたみたいです。
なので、この課題はこれで解決・・・です。(たぶん)
React NativeプロジェクトのAPKファイルは以下に収まってました。
「(プロジェクトフォルダ)\android\\app\build\outputs\apk\debug\app-debug.apk」
※リリース版のビルドを意識してビルドさせたことはないので、デバッグ版らしきこのファイルで確認するしかないのかな。
APKの中は以下の感じです。
「\lib\(CPU毎フォルダ)\libjuliusword.so」
「\assets\jdata\*」・・・AndroidStudio環境時に設定したままの内容
◆calljuliusのフォルダ位置変更
前回、AndroidStudioからcalljuliusのビルド環境を React Native(VTChatプロジェクト)環境に持ち込んだ際に、その所在を「(プロジェクトフォルダ)\node_modiles\react-native-google-speech-api\calljulius」としました。
そのフォルダ直下にAnroidStudioで作ったビルド環境をまるっと持ってきてしまってます。※
※Gradle環境で親プロジェクト内に子プロジェクト(ライブラリ)のビルド環境を作成する例がそうなってたから。
でも、React Nativeのパッケージ類で動作デバイス依存のあるものは、パッケージルートの下に、android、ios、windowsなどのデバイス毎のフォルダを作成して、その下にソース等を配置している。
なので、calljuliusもそうします。
「(プロジェクトフォルダ)\node_modiles\react-native-google-speech-api\calljulius」
↓
「(プロジェクトフォルダ)\node_modiles\react-native-google-speech-api\calljulius\android」
それに伴って、ルートプロジェクトのsettings.gladleとreact-native-google-speech-apiのbuild.gradleを修正します。
上記の状態で、「rect-native run-android」を実行して、ビルドできることを確認しました。
さあ、このサブテーマの最終段階です。
JuliusLibを含んだC/C++ライブラリをNeactNative(JS)側から呼出すところの実装です。
続きます。
前の状況を書いてからあまりに間が空いたので、前の記事を自分で読み返してます。
もう何のためにこれをやり始めたのかも忘れそうです。
「スマフォのアプリを作りたい」シリーズのサブテーマ「スマフォだけで動作する音声認識」も9回目になっちゃった。
進み具合が悪くて、かなりダラケ気味になってました。
とりあえずこのサブテーマまでは、何とか完結させます。
前回、AndroidStudio環境で作成したJava+C/C++ライブラリ(calljulius)のビルド環境をReact Nativeの環境に持ち込んでcalljuliusのビルドが走り出すところまでを「見る」ことができました。
残りの課題は、
1)calljuliusで参照する設定ファイル等のapkへの取込み
2)今のフォルダ構成の見直し
3)他Javaコードからcalljuliusの呼出し実装/テスト
になるかと思ってました。
では、ボヤキを再開します。
◆calljuliusライブラリの前提ファイルの追加
AndroidStudioでcalljuliusを作成した段階で、calljulius(JuliusLib(C/C++):音声認識エンジンライブラリ)では、単語辞書/音響モデル?/設定ファイルが必要な作りになっています。
それらのファイルはassetsフォルダで、APK内に組み込まれて動作時にライブラリから参照されます。
VTChat(React Nativeのお試しアプリ)としてのAPK内にcalljuliusの関連ファイルはどういうビルド設定をすれば取り込まれるようになるのかな?
Android/Gradleビルド環境を未だに全く理解できてないので、かなり面倒そうだなーとか思っていました。
まず手始めに、前回calljulius環境込みのビルド結果のAPKの中身を見てみます。
すると、なんということでしょう~!
JuliusLib(C/C++)ライブラリ本体:libjuliusword.so もassetsフォルダに仕込むべきファイルたちも既に入ってるではありませんか!
このシリーズ初の「あれ? ラッキー!」です。
どういう仕組みなのかは、全く分かりませんが、AndroidStudio上で組んだビルドのOutput構成が、そのままReactNative側のOutput構成に取り込まれたみたいです。
なので、この課題はこれで解決・・・です。(たぶん)
React NativeプロジェクトのAPKファイルは以下に収まってました。
「(プロジェクトフォルダ)\android\\app\build\outputs\apk\debug\app-debug.apk」
※リリース版のビルドを意識してビルドさせたことはないので、デバッグ版らしきこのファイルで確認するしかないのかな。
APKの中は以下の感じです。
「\lib\(CPU毎フォルダ)\libjuliusword.so」
「\assets\jdata\*」・・・AndroidStudio環境時に設定したままの内容
-ちょっと余談:APKの中の確認方法- APKファイルってzip形式の圧縮ファイルなんだそうだ。 なので、拡張子を「.zip」にリネームして、「プログラムから開く」でエクスプローラを指定すれば中のフォルダ構成を参照できるかもしれません。 拡張子が「.apk」のままでは通常ダメでした。関連プログラム設定を行えばできるのかも。圧縮ファイルとしての「解凍」はできるかと思います。 ちなみに、さるがずっと以前に作った「ZIPファイル内のファイルリストを出力するツール」※があったので、そのプログラムに食わせてみました。 拡張子が「.apk」のままでも、ファイルリストを出力しました。 ※Vectorサイト(https://www.vector.co.jp/soft/dl/winnt/prog/se488403.html)からダウンロードできるようにしています。 ただし、ダウンロード時に「危ないやつかも知れんぜ!」的な警告はでるし、ダウンロードしたzipファイルからプログラム(saruziplist.exe)を取り出して実行させようとしたときも「こいつ提供元が分かんない怪しいやつですぜ!」的な警告が出ました。しかも起動に物凄く時間が掛りました。 まあ、だいぶ以前にマイナーな開発環境(PHP)で作った怪しいWindowsプログラムなので、致し方ないのかな。 |
◆calljuliusのフォルダ位置変更
前回、AndroidStudioからcalljuliusのビルド環境を React Native(VTChatプロジェクト)環境に持ち込んだ際に、その所在を「(プロジェクトフォルダ)\node_modiles\react-native-google-speech-api\calljulius」としました。
そのフォルダ直下にAnroidStudioで作ったビルド環境をまるっと持ってきてしまってます。※
※Gradle環境で親プロジェクト内に子プロジェクト(ライブラリ)のビルド環境を作成する例がそうなってたから。
でも、React Nativeのパッケージ類で動作デバイス依存のあるものは、パッケージルートの下に、android、ios、windowsなどのデバイス毎のフォルダを作成して、その下にソース等を配置している。
なので、calljuliusもそうします。
「(プロジェクトフォルダ)\node_modiles\react-native-google-speech-api\calljulius」
↓
「(プロジェクトフォルダ)\node_modiles\react-native-google-speech-api\calljulius\android」
それに伴って、ルートプロジェクトのsettings.gladleとreact-native-google-speech-apiのbuild.gradleを修正します。
----settings.gradle--------------------------------
rootProject.name = 'VTChat'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app', ':calljulius:android'
project(':calljulius:android').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-speech-api/calljulius/android')
:
:
---------------------------------------------------
----build.gradle-----------------------------------
:
:
dependencies {
:
:
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
//# calljulius
implementation project(":calljulius:android")
//implementation 'com.teburarec.calljulius:JlibGate:0.0.1'
}
---------------------------------------------------
上記の状態で、「rect-native run-android」を実行して、ビルドできることを確認しました。
さあ、このサブテーマの最終段階です。
JuliusLibを含んだC/C++ライブラリをNeactNative(JS)側から呼出すところの実装です。
続きます。
スマフォのアプリを作りたい(33):スマフォだけで動作する音声認識⑧
プログラミング [2020/10/26]
このボヤキ・シリーズもすでに33回です。
長い。長すぎです。未だに折り返し地点も見えてきてない気がします。
久々に、作業はReactNativeの環境に戻りつつあるのですが、過去の「調べ」についてはすっかり頭から消えて、「これってなんだっけ?」の繰り返しになってます。以前の書き込みを読み返してみても、自分でも「何言ってんのかわかんない」状態。
老いなのか、地頭が悪いからか・・・
さて、このサブタイトル「スマフォだけで動作する音声認識」については、
本当にやれるのか半信半疑で始めたのですが、やっと終盤にさしかかった感じです。
ここまでで予定していた以下の段取り
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
のⅢを始めます。
でも、未だ本当にできるかどうかは自信なしです。
やれたとしても、設計的に無理があって、Juliusさんの十分なパフォーマンスを引き出せるのかが問題。
前回の最後に書いたのですが、Ⅱの「React Nativeで使えるパッケージ化」はスキップしました。
なぜって、面倒そうだし、基本ができていないさるなので、
・ぴったり来る事例/説明が見つかりそうもない。
・お手本の説明の理解に苦労する。
・作ったものを普通に公開したいとか大それたことは思わない。
参考:https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2
だから、パッケージ化はせずに、以前に作っていたReactNativeのプロジェクトへの単語認識用Java&C/C++ライブラリ(calljuliusライブラリ)の取り込みをやってみます。
何はともともあれ、以前VTChatとして試作していたReactNative環境近くにソース類とビルドに必要なファイルを持って行きます。
calljuliusライブラリの呼び出し元は、さるカスタマイズ版react-native-google-speech-api内のJavaコードからとなると思ってます。
◆Gradleでビルドできる環境を作る
ReactNativeも、AndroidStudioもビルドの根っこではGradleを使っています。
予想でしかありませんが、AndroisStudio環境からソースを抜き出して、Gradle(&CMake)で個別にビルドできる環境が必要なんではないだろうかと考えました。
ダウンロードして来た他のReactNative向けのパッケージがそんな感じに見えたので。
そこで最初(失敗手順)、
-「react-native-google-speech-api」の展開先フォルダ(※1)内のフォルダ/ファイル構成を闇雲に真似して作成
-「android」というサブフォルダに「src」というサブフォルダを作成して、AndroidStudioで作成したプロジェクトフォルダ中の「src」フォルダ以下まるっとコピー
-androidフォルダ直下の「build.gradle」他関連するファイルの中をちょこまか弄った
-コマンドプロンプトを開き、カレントをそのandroidフォルダにして、「gradlew compilejava」とかやって見た
まあ、上手く行くはずないですよね。(^^;)
※1:react-native-google-speech-apiパッケージは、「npm init パッケージ名」でインストールができなかったため、ZIP形式をダウンロード-展開し、それをReactNativeアプリのプロジェクト環境に組み込んだので、それに近い感じでOKではと考えてます。
「ReactNative用Javaライブラリの作り方」とかのキーワードで、かなりぐぐっては見たものの、いつも通りピッタリくる感じの解説は見つからない。
というか、少し近そうな説明はあるものの、何を言っているのかさっぱり理解できない。とほほ。
そもそも、Gradleは単なるコンパイラとかではなくビルドツールであって、build.gradleの中身はJavaっぽいGroovyという言語で書かれたスクリプトらしいけど、学習したわけではないから分かるわけない。
そんな中でも、参考にさせてもらったのは以下のサイト。
参考:https://qiita.com/NewGyu/items/c145136c256f801e1402
参考:https://blog1.mammb.com/entry/2015/04/25/020740
(1)Gradleでもプロジェクトを作成可能
「gradle init --type Javal-Library」てやると「build.gradle」のベース他ひな形環境を作ってくれるみたいです。
さっそくやって見ました。
Windows環境なので、gradleコマンドを直接たたくスベが分からなかったので、ReactNativeのプロジェクトのあっちこちにある「gradlew.bat」を使いました。
正しいやり方とは思えませんが・・・
-大元のプロジェクトフォルダ(calljulius)を作成
-さらにその下にandroidフォルダを作成
-ReactNativeのプロジェクト下にあるgradlew.batを使って、Gradleのバージョンを表示
※環境変数(GRADLE_HOME)を設定していないからか?Gradle5.5をダウンロードしてインストールしちゃったみたいです。
-プロジェクトの初期化「gradlew init --type java-library」を実行
-フォルダの中に「build.gradle」他ファイル、フォルダが作成されているのを確認
※「android\src\main\java\calljulius」の下には、「Library.java」というソースも作られていました。
なんだか、この状態でビルドできそうな感じがしたので、やってみました。
-ビルド「gradlew compilejava --info」を実行
※今度は、「gradle-5.5-bin.zip」をダウンロードして組み込んだ模様。???(バージョンを調べたときはgradle-5.5-all.zip)
実際に「C:\Users\(ユーザID)\.gradle\wrapper\dists」下に展開されたフォルダが2つ作成されていました。
ReactNative配下で使用しているものとは別なはずなので、後で消してもいいのかな?
→結局、ビルドはエラーで終了。
続きます。
長い。長すぎです。未だに折り返し地点も見えてきてない気がします。
久々に、作業はReactNativeの環境に戻りつつあるのですが、過去の「調べ」についてはすっかり頭から消えて、「これってなんだっけ?」の繰り返しになってます。以前の書き込みを読み返してみても、自分でも「何言ってんのかわかんない」状態。
老いなのか、地頭が悪いからか・・・
さて、このサブタイトル「スマフォだけで動作する音声認識」については、
本当にやれるのか半信半疑で始めたのですが、やっと終盤にさしかかった感じです。
ここまでで予定していた以下の段取り
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
のⅢを始めます。
でも、未だ本当にできるかどうかは自信なしです。
やれたとしても、設計的に無理があって、Juliusさんの十分なパフォーマンスを引き出せるのかが問題。
前回の最後に書いたのですが、Ⅱの「React Nativeで使えるパッケージ化」はスキップしました。
なぜって、面倒そうだし、基本ができていないさるなので、
・ぴったり来る事例/説明が見つかりそうもない。
・お手本の説明の理解に苦労する。
・作ったものを普通に公開したいとか大それたことは思わない。
参考:https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2
だから、パッケージ化はせずに、以前に作っていたReactNativeのプロジェクトへの単語認識用Java&C/C++ライブラリ(calljuliusライブラリ)の取り込みをやってみます。
何はともともあれ、以前VTChatとして試作していたReactNative環境近くにソース類とビルドに必要なファイルを持って行きます。
calljuliusライブラリの呼び出し元は、さるカスタマイズ版react-native-google-speech-api内のJavaコードからとなると思ってます。
◆Gradleでビルドできる環境を作る
ReactNativeも、AndroidStudioもビルドの根っこではGradleを使っています。
予想でしかありませんが、AndroisStudio環境からソースを抜き出して、Gradle(&CMake)で個別にビルドできる環境が必要なんではないだろうかと考えました。
ダウンロードして来た他のReactNative向けのパッケージがそんな感じに見えたので。
そこで最初(失敗手順)、
-「react-native-google-speech-api」の展開先フォルダ(※1)内のフォルダ/ファイル構成を闇雲に真似して作成
-「android」というサブフォルダに「src」というサブフォルダを作成して、AndroidStudioで作成したプロジェクトフォルダ中の「src」フォルダ以下まるっとコピー
-androidフォルダ直下の「build.gradle」他関連するファイルの中をちょこまか弄った
-コマンドプロンプトを開き、カレントをそのandroidフォルダにして、「gradlew compilejava」とかやって見た
まあ、上手く行くはずないですよね。(^^;)
※1:react-native-google-speech-apiパッケージは、「npm init パッケージ名」でインストールができなかったため、ZIP形式をダウンロード-展開し、それをReactNativeアプリのプロジェクト環境に組み込んだので、それに近い感じでOKではと考えてます。
「ReactNative用Javaライブラリの作り方」とかのキーワードで、かなりぐぐっては見たものの、いつも通りピッタリくる感じの解説は見つからない。
というか、少し近そうな説明はあるものの、何を言っているのかさっぱり理解できない。とほほ。
そもそも、Gradleは単なるコンパイラとかではなくビルドツールであって、build.gradleの中身はJavaっぽいGroovyという言語で書かれたスクリプトらしいけど、学習したわけではないから分かるわけない。
そんな中でも、参考にさせてもらったのは以下のサイト。
参考:https://qiita.com/NewGyu/items/c145136c256f801e1402
参考:https://blog1.mammb.com/entry/2015/04/25/020740
(1)Gradleでもプロジェクトを作成可能
「gradle init --type Javal-Library」てやると「build.gradle」のベース他ひな形環境を作ってくれるみたいです。
さっそくやって見ました。
Windows環境なので、gradleコマンドを直接たたくスベが分からなかったので、ReactNativeのプロジェクトのあっちこちにある「gradlew.bat」を使いました。
正しいやり方とは思えませんが・・・
----コマンドプロンプト-----------------------------
C:\WINDOWS\system32>cd /d d:\appmake\temp
d:\AppMake\temp>mkdir calljulius
d:\AppMake\temp>cd calljulius
d:\AppMake\temp\calljulius>mkdir android
d:\AppMake\temp\calljulius>cd android
d:\AppMake\temp\calljulius\android>\AppMake\proj\VTChat\android\gradlew --version
Downloading https://services.gradle.org/distributions/gradle-5.5-all.zip
.................................................................................................................................
------------------------------------------------------------
Gradle 5.5
------------------------------------------------------------
Build time: 2019-06-28 17:36:05 UTC
Revision: 83820928f3ada1a3a1dbd9a6c0d47eb3f199378f
Kotlin: 1.3.31
Groovy: 2.5.4
Ant: Apache Ant(TM) version 1.9.14 compiled on March 12 2019
JVM: 1.8.0_261 (Oracle Corporation 25.261-b12)
OS: Windows 10 10.0 amd64
d:\AppMake\temp\calljulius\android>
d:\AppMake\temp\calljulius\android>\AppMake\proj\VTChat\android\gradlew init --type java-library
Select build script DSL:
1: Groovy
2: Kotlin
Enter selection (default: Groovy) [1..2]
Select test framework:
1: JUnit 4
2: TestNG
3: Spock
4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4]
Project name (default: android): calljulius
Source package (default: calljulius):
> Task :init
Get more help with your project: https://docs.gradle.org/5.5/userguide/java_library_plugin.html
BUILD SUCCESSFUL in 36s
2 actionable tasks: 2 executed
d:\AppMake\temp\calljulius\android>
d:\AppMake\temp\calljulius\android>dir
ドライブ D のボリューム ラベルは Transcend です
ボリューム シリアル番号は 3E4D-1A2A です
d:\AppMake\temp\calljulius\android のディレクトリ
2020/09/11 17:29 <DIR> .
2020/09/11 17:29 <DIR> ..
2020/09/11 17:29 108 .gitignore
2020/09/11 17:29 <DIR> .gradle
2020/09/11 17:29 982 build.gradle
2020/09/11 17:29 <DIR> gradle
2020/09/11 17:29 5,917 gradlew
2020/09/11 17:29 2,942 gradlew.bat
2020/09/11 17:29 367 settings.gradle
2020/09/11 17:29 <DIR> src
5 個のファイル 10,316 バイト
5 個のディレクトリ 947,452,710,912 バイトの空き領域
d:\AppMake\temp\calljulius\android>
---------------------------------------------------
-大元のプロジェクトフォルダ(calljulius)を作成
-さらにその下にandroidフォルダを作成
-ReactNativeのプロジェクト下にあるgradlew.batを使って、Gradleのバージョンを表示
※環境変数(GRADLE_HOME)を設定していないからか?Gradle5.5をダウンロードしてインストールしちゃったみたいです。
-プロジェクトの初期化「gradlew init --type java-library」を実行
-フォルダの中に「build.gradle」他ファイル、フォルダが作成されているのを確認
※「android\src\main\java\calljulius」の下には、「Library.java」というソースも作られていました。
なんだか、この状態でビルドできそうな感じがしたので、やってみました。
----コマンドプロンプト-----------------------------
d:\AppMake\temp\calljulius\android>gradlew compilejava --info
Downloading https://services.gradle.org/distributions/gradle-5.5-bin.zip
.....................................................................................
Initialized native services in: C:\Users\sarumosunaru\.gradle\native
The client will now receive all logging from the daemon (pid: 10692). The daemon log file: C:\Users\sarumosunaru\.gradle\daemon\5.5\daemon-10692.out.log
Starting 3rd build in daemon [uptime: 7 mins 24.971 secs, performance: 99%, non-heap usage: 14% of 268.4 MB]
:
:
:
Task ':compileJava' is not up-to-date because:
No history is available.
All input files are considered out-of-date for incremental task ':compileJava'.
Full recompilation is required because no incremental change information is available. This is usually caused by clean builds or changing compiler arguments.
Compiling with JDK Java compiler API.
> Task :compileJava FAILED
:compileJava (Thread[Execution worker for ':',5,main]) completed. Took 14.938 secs.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileJava'.
> Could not find tools.jar. Please check that C:\Program Files\Java\jre1.8.0_261 contains a valid JDK installation.
:
:
BUILD FAILED in 1m 11s
1 actionable task: 1 executed
d:\AppMake\temp\calljulius\android>
---------------------------------------------------
-ビルド「gradlew compilejava --info」を実行
※今度は、「gradle-5.5-bin.zip」をダウンロードして組み込んだ模様。???(バージョンを調べたときはgradle-5.5-all.zip)
実際に「C:\Users\(ユーザID)\.gradle\wrapper\dists」下に展開されたフォルダが2つ作成されていました。
ReactNative配下で使用しているものとは別なはずなので、後で消してもいいのかな?
→結局、ビルドはエラーで終了。
続きます。
スマフォのアプリを作りたい(32):スマフォだけで動作する音声認識⑦
プログラミング [2020/09/09]
前回の続きになります。
でも、だいぶ間があいちゃいましたね。
前回割と中途半端なところで話を切ったので、この回から読み始めても「さっぱり何言ってんのかわかんない」と思います。
(それじゃなくても、独り言に近い備忘録なので、他の人が読んでもどうにか理解できるのかはあまり気に掛けてません。)
なので、もし類似の何かを調べしている方は、
「スマフォだけで動作する音声認識⑥」から、あるいは「スマフォだけで動作する音声認識①」からお読みください。
前回までで、JavaからC/C++のライブラリをコールして、さらにライブラリ側からJava側のコールバックを呼び出すところまでを実験的にやってみました。
今回は、今までの内容を整形(コードをそれなりの内容にまで整える)して、さらにReact Native用パッケージに仕立てるところ・・・
行けるかどうか分かりませんが、始めます。
◆単語認識ライブラリのコールバックの実装
ず~~~っと前に作ったGoogle音声認識と同時に録音するJavaコード(さるもすなる版react-native-google-speech-api)では、音声データをバッファで渡すことができます。
データ型はbyte配列(byte[])です。
ただし、そのバッファを握ったまま音声認識の処理が終わるまで離さないということは、どう考えても効率が悪そうだし、そんな制御は却って難しそうです。
なので、認識を開始した後に渡す音声データは、コールバックで渡す段階で認識側専用のバッファ(char *の先)にデータをコピーするのがまあ普通な考え方かと。
じゃあ、そのコピーはJava側で行うのか、C側で行うのか・・・
Java側でやるなら、
Java側にC側で用意したバッファのポインタをそのまま渡せるのか?できない?
前回記事でお試しコードを書いたときは、わざわざJavaのbyte型配列を新しく確保して渡した。
これだと、データコピーが2回発生してしまう。
C側でコピーするとしたら
Java側のコールバック関数のリターン値をデータアドレスとデータ長の2種類を含むものにしないといけなくなる。
①C言語でいうところの参照型の引数を使ってJava側のバッファアドレスを貰って来ることはできるのか?
②バッファを渡した側がデータのコピーの完了を知る術がない(そのバッファの解放判断ができない)んじゃない?
①:そもそも、Javaにポインタという概念はないらしい。
byte[]型のオブジェクトそのものはリターン値として使えて、そこから中身のレングスとポインタはJNIの関数で取り出せるみたいです。
②:でもでも、リターンのタイミングでそれを渡したとすると、コピーの完了を知るすべがないということになります。
Java側のバッファの「用済み」がいつなのか分からないと、バッファを解放できないということになります。
データコピーの完了を知らせるために別の仕掛けを用意しなくちゃいけなくなってしまいます。
認識が完了するまで、Java側バッファも保持しつづける?
それは、後々厄介なことになりそう。
悩んだ末に、こんなことを考えました。
Javaのコールバックを呼ぶんだけど、そのコールバックは再度C関数を呼び出して、そのC関数がデータのコピーをやっちゃうって仕掛けです。
まずは、やってみました。
ここでも結局、Java側のコールバック関数を経由して、C側のバッファのポインタはどう渡すんだ?
と、振り出しに戻るような疑念が出ました。
結局そこはC側にグローバル変数を用意して、自分のバッファとその長さを保持して
コールバックから呼ばれたデータコピー関数は、グローバル変数を参照することで、済ませてしまいました。
かなりベタというか、美しくありません。
これだと、マルチスレッドでこのコールバック処理が非同期に実施されるようなことがあれば、アウトです。
ともあれ、この作りで一旦先に進みます。
続きます。この後も長ーいです。
でも、だいぶ間があいちゃいましたね。
前回割と中途半端なところで話を切ったので、この回から読み始めても「さっぱり何言ってんのかわかんない」と思います。
(それじゃなくても、独り言に近い備忘録なので、他の人が読んでもどうにか理解できるのかはあまり気に掛けてません。)
なので、もし類似の何かを調べしている方は、
「スマフォだけで動作する音声認識⑥」から、あるいは「スマフォだけで動作する音声認識①」からお読みください。
前回までで、JavaからC/C++のライブラリをコールして、さらにライブラリ側からJava側のコールバックを呼び出すところまでを実験的にやってみました。
今回は、今までの内容を整形(コードをそれなりの内容にまで整える)して、さらにReact Native用パッケージに仕立てるところ・・・
行けるかどうか分かりませんが、始めます。
◆単語認識ライブラリのコールバックの実装
ず~~~っと前に作ったGoogle音声認識と同時に録音するJavaコード(さるもすなる版react-native-google-speech-api)では、音声データをバッファで渡すことができます。
データ型はbyte配列(byte[])です。
ただし、そのバッファを握ったまま音声認識の処理が終わるまで離さないということは、どう考えても効率が悪そうだし、そんな制御は却って難しそうです。
なので、認識を開始した後に渡す音声データは、コールバックで渡す段階で認識側専用のバッファ(char *の先)にデータをコピーするのがまあ普通な考え方かと。
じゃあ、そのコピーはJava側で行うのか、C側で行うのか・・・
Java側でやるなら、
Java側にC側で用意したバッファのポインタをそのまま渡せるのか?できない?
前回記事でお試しコードを書いたときは、わざわざJavaのbyte型配列を新しく確保して渡した。
これだと、データコピーが2回発生してしまう。
C側でコピーするとしたら
Java側のコールバック関数のリターン値をデータアドレスとデータ長の2種類を含むものにしないといけなくなる。
①C言語でいうところの参照型の引数を使ってJava側のバッファアドレスを貰って来ることはできるのか?
②バッファを渡した側がデータのコピーの完了を知る術がない(そのバッファの解放判断ができない)んじゃない?
①:そもそも、Javaにポインタという概念はないらしい。
byte[]型のオブジェクトそのものはリターン値として使えて、そこから中身のレングスとポインタはJNIの関数で取り出せるみたいです。
②:でもでも、リターンのタイミングでそれを渡したとすると、コピーの完了を知るすべがないということになります。
Java側のバッファの「用済み」がいつなのか分からないと、バッファを解放できないということになります。
データコピーの完了を知らせるために別の仕掛けを用意しなくちゃいけなくなってしまいます。
認識が完了するまで、Java側バッファも保持しつづける?
それは、後々厄介なことになりそう。
悩んだ末に、こんなことを考えました。
Javaのコールバックを呼ぶんだけど、そのコールバックは再度C関数を呼び出して、そのC関数がデータのコピーをやっちゃうって仕掛けです。
まずは、やってみました。
ここでも結局、Java側のコールバック関数を経由して、C側のバッファのポインタはどう渡すんだ?
と、振り出しに戻るような疑念が出ました。
結局そこはC側にグローバル変数を用意して、自分のバッファとその長さを保持して
コールバックから呼ばれたデータコピー関数は、グローバル変数を参照することで、済ませてしまいました。
かなりベタというか、美しくありません。
これだと、マルチスレッドでこのコールバック処理が非同期に実施されるようなことがあれば、アウトです。
ともあれ、この作りで一旦先に進みます。
続きます。この後も長ーいです。
スマフォのアプリを作りたい(31):スマフォだけで動作する音声認識⑥
プログラミング [2020/08/07]
前回、ちょっと横道に逸れてしまいましたが、元の流れに戻します。
とは言え、ReactNativeからは話が、2か月以上離れてしまってます。
ちょっとこれまでの経緯を説明します。
アプリを作るメインの環境/言語はReactNative(JavaScript:JSX)です。
作りたいアプリでは2種類の音声認識を使いたいと思ってます。
最初の短い単語で、なんらかの機能を選択します。
例えば、「メモ」と言ってから話す内容は音声をテキスト化して残すとか、「チャット」とか言ったらその後の内容をチャットするとか。
短い発話(キーワード)は、スマフォ本体のみで音声認識(Julius)し、長い発話はクラウドサービス(Google Speech)を使います。
そんなことを構想しながらアプリを作り始めて、主題の「スマフォのアプリを作りたい」ももう30回を超えてしまいました。
現在の副題「スマフォだけで動作する音声認識」は、JuliusをAndroidスマフォ上で動作させるところまで来ました。
これまで、以下の段取りで試行錯誤しています。
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
前回までで、Ⅰは終わったかなという感じです。
今回からⅡになります。
パッケージ化の手順もそうですが、その前にReactNativeから利用できるライブラリとしてのI/Fを決めて、JuliusLibを使ってそのI/F・音声認識を実現させないといけない。
つまりⅡとして書いた段取りが、Ⅰ~Ⅲの中で一番重要かつたぶん大変かもしれません。
なぜ大変か。それは、さるがJuliusLibの本当の仕様、I/F、アルゴリズム?・・・何にも理解してないからです。
あちこちの書き込みの背景/前提をろくに理解しないで試すから、無駄、間違いも多いです。
なので、過去記事も含めて、ここの記述事例を「参考に」などと読む方がいらっしゃる場合は、その点を覚悟して読んでください。
またまた、前置きが長いですね。
では、前回からの続きです。
◆JuliusLibに対する機能変更について
だいぶ前に、react-native-google-speech-apiというパッケージをダウンロードしてきて、マイクから入力した音声をGoogle Speechに送り込んで認識させて見ました。(「:音声認識させたい」~「:音声認識させたい④」)
で、さらにそのパッケージに手を加えて、認識と同時に録音するようにもしてみました。(「:音声認識と同時に録音」~「:音声認識と同時に録音③」)
今回、単語認識を取り入れるとしたら、手を加える箇所はマイク入力音声を制御しているreact-native-google-speech-api(さるカスタマイズ版)だと思います。
Google Speechに渡す音声を録音処理に回したように、単語認識のタイミングならGoogle Speechに音声を渡さずにJuliusLibに渡すように作り変えます。
なので、JuliusLibに対して、バッファで音声を受け取れるI/Fを追加します。
まずは、JuliusLibが外部に公開しているI/F関数と、音声入力デバイス制御用の関数の関係をGrep機能(sakuraエディタ)でざっと調べてみました。
だいたい以下の感じ・・・かな。
adin_xxx_...関数は、使用する入力デバイス毎に関数(ソースファイル)が準備されていて、起動パラメタの「-input xxx」で使い分けされるようになっている。
音声データの入力部分(adin_xxx_read)で、バッファ渡しで音声を受け取る仕掛けを作り込めばできそうです。
ただ、「-input」に新しいオプションを追加して、まるっと疑似デバイスの仕掛けを準備するのは、修正がかなり広範囲に及ぶ懸念がある。
関連のパラメタとかも理解するのに骨が折れそう。
なので、既存の「-input stdin」を利用して、かつ対応するコードが含まれているソース(adin_file.c)に手を加えることで済ませたい。
だいたいの修正の内容は以下の感じになるかな。
・JuliusLibへの入り口のソースファイル名は、julius-entry.cppに変更。
・ビルド結果もjuliusword.soに変更。
・インタフェースは、jlibStart、jlibRecognize、jlibStopの3種類。
・jlib_recognize時にJava側コールバック関数を呼び出し、バッファ渡しで音声データを取得する。
・コールバック関数の指定は、jlibStart()コール時に行う。
・パッケージ名は、これまで通りcall_juliusのまま。calljuliusに変更。
・Java側のメソッドにjlib_call_start、jlib_call_recognize、jlib_call_stopの3種類を作ってそれぞれjulius-entry.cppの関数を呼び出す。
まずは、前回までのjulius_callプロジェクトをフォルダ丸ごとバックアップし、ともかくやり始めます。
続きます。長いです。
とは言え、ReactNativeからは話が、2か月以上離れてしまってます。
ちょっとこれまでの経緯を説明します。
アプリを作るメインの環境/言語はReactNative(JavaScript:JSX)です。
作りたいアプリでは2種類の音声認識を使いたいと思ってます。
最初の短い単語で、なんらかの機能を選択します。
例えば、「メモ」と言ってから話す内容は音声をテキスト化して残すとか、「チャット」とか言ったらその後の内容をチャットするとか。
短い発話(キーワード)は、スマフォ本体のみで音声認識(Julius)し、長い発話はクラウドサービス(Google Speech)を使います。
そんなことを構想しながらアプリを作り始めて、主題の「スマフォのアプリを作りたい」ももう30回を超えてしまいました。
現在の副題「スマフォだけで動作する音声認識」は、JuliusをAndroidスマフォ上で動作させるところまで来ました。
これまで、以下の段取りで試行錯誤しています。
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
前回までで、Ⅰは終わったかなという感じです。
今回からⅡになります。
パッケージ化の手順もそうですが、その前にReactNativeから利用できるライブラリとしてのI/Fを決めて、JuliusLibを使ってそのI/F・音声認識を実現させないといけない。
つまりⅡとして書いた段取りが、Ⅰ~Ⅲの中で一番重要かつたぶん大変かもしれません。
なぜ大変か。それは、さるがJuliusLibの本当の仕様、I/F、アルゴリズム?・・・何にも理解してないからです。
あちこちの書き込みの背景/前提をろくに理解しないで試すから、無駄、間違いも多いです。
なので、過去記事も含めて、ここの記述事例を「参考に」などと読む方がいらっしゃる場合は、その点を覚悟して読んでください。
またまた、前置きが長いですね。
では、前回からの続きです。
◆JuliusLibに対する機能変更について
だいぶ前に、react-native-google-speech-apiというパッケージをダウンロードしてきて、マイクから入力した音声をGoogle Speechに送り込んで認識させて見ました。(「:音声認識させたい」~「:音声認識させたい④」)
で、さらにそのパッケージに手を加えて、認識と同時に録音するようにもしてみました。(「:音声認識と同時に録音」~「:音声認識と同時に録音③」)
今回、単語認識を取り入れるとしたら、手を加える箇所はマイク入力音声を制御しているreact-native-google-speech-api(さるカスタマイズ版)だと思います。
Google Speechに渡す音声を録音処理に回したように、単語認識のタイミングならGoogle Speechに音声を渡さずにJuliusLibに渡すように作り変えます。
なので、JuliusLibに対して、バッファで音声を受け取れるI/Fを追加します。
-ちょっと余談:AndroudStudioのTABの間隔変更- JuliusLibに含まれるソースの書き方が、ネストが深くなる毎に2カラムのインデントを追加しているようです。たまーにSPACEコードではなくTABコードが使われているのですが、それがどうも8カラムになっているみたい。それに対して、AndroidStudioのデフォルトは4カラムになっているみたいで、AndoidStudio上でソースを参照するとヒジョーに読みにくい。 なので、AndroisStudioでのTAB間隔の変更方法です。 -[File]-[Settings...]メニューを選択 -「Settings」ダイアログ左側で、「Editor」-「Code Style」-「C/C++」の順で展開/選択 -右側表示の「Scheme」で「Project」を選択し、その下の「Tabs and Indents」タブを選択 -タブ内の上から3番目「Tab size」欄に8をしてして画面右下の[OK]をクリック でも、ソースを追っかける場合は、AndroidStudioじゃなくて、慣れてるテキストエディタを使うけどね。 |
まずは、JuliusLibが外部に公開しているI/F関数と、音声入力デバイス制御用の関数の関係をGrep機能(sakuraエディタ)でざっと調べてみました。
だいたい以下の感じ・・・かな。
外部I/F (julius-simple.c使用関数) | 入力デバイス関数 (ポインタ名) | マイク入力時関数 | 機能概要 |
j_adin_init | a->ad_standby | adin_mic_standby | デバイスの初期化 |
j_open_stream | a->ad_begin | adin_mic_begin | 音の取り込みの開始 |
j_recognize_stream | a->ad_end | adin_mic_end | 音の取り込み終了 |
〃 | a->ad_read | adin_mic_read | 音声入力 |
〃 | j_get_current_filename | a->ad_input_nam | adin_mic_input_name | 入力デバイス名取得 |
〃 | j_request_pause | a->ad_pause | adin_mic_pause | 認識処理の一時停止時に呼出し |
j_request_terminate | a->ad_terminate | adin_mic_terminate | 認識処理の即時停止時に呼出し |
j_request_terminate | a->ad_resume | adin_mic_resume | 一時停止している認識処理の再開時に呼出し |
adin_xxx_...関数は、使用する入力デバイス毎に関数(ソースファイル)が準備されていて、起動パラメタの「-input xxx」で使い分けされるようになっている。
音声データの入力部分(adin_xxx_read)で、バッファ渡しで音声を受け取る仕掛けを作り込めばできそうです。
ただ、「-input」に新しいオプションを追加して、まるっと疑似デバイスの仕掛けを準備するのは、修正がかなり広範囲に及ぶ懸念がある。
関連のパラメタとかも理解するのに骨が折れそう。
なので、既存の「-input stdin」を利用して、かつ対応するコードが含まれているソース(adin_file.c)に手を加えることで済ませたい。
だいたいの修正の内容は以下の感じになるかな。
・JuliusLibへの入り口のソースファイル名は、julius-entry.cppに変更。
・ビルド結果もjuliusword.soに変更。
・インタフェースは、jlibStart、jlibRecognize、jlibStopの3種類。
・jlib_recognize時にJava側コールバック関数を呼び出し、バッファ渡しで音声データを取得する。
・コールバック関数の指定は、jlibStart()コール時に行う。
・パッケージ名は、
・Java側のメソッドにjlib_call_start、jlib_call_recognize、jlib_call_stopの3種類を作ってそれぞれjulius-entry.cppの関数を呼び出す。
まずは、前回までのjulius_callプロジェクトをフォルダ丸ごとバックアップし、ともかくやり始めます。
続きます。長いです。
スマフォのアプリを作りたい(30):番外編(MySQLからPostgreSQLへ)
プログラミング [2020/08/01]
これまでの「スマフォのアプリを作りたい」シリーズの流れから少し脱線します。
ちょっと前に、このアプリのサーバ側DBをメンテナンスするための管理スクリプトを作成したのですが、DBはEclipseに含まれてたMySQLになってました。
わけあってPostgreSQLもサポートすることになりました。
◆Eclipse+PostgreSQL環境の構築
参考:https://www.dbonline.jp/postgresql/install/
<PostgreSQLのダウンロード>
上記のサイトからリンクされているhttps://www.postgresql.org/を表示
-上部の[ダウンロード→]ボタンをクリック
-対象OSのボタンをクリック
-説明文中の「インストーラをダウンロード」をクリック
-OSとバージョンの組み合わせで、「Windows x86-64」の最新(12.3)の[ダウンロード]ボタンをクリック
<PostgreSQLのインストール>
-ダウンロードしたexeを起動します
-いつもの、OS環境に変更を加えますか的なメッセージにOKします
-インストーラ(Setupダイアログ)の初期画面で[Next>]
-インストール先フォルダを指定して[Next>]
※さるの環境の場合、C:ドライブは空きがないので「D:\・・・\PostgreSQL\12」を指定
以降、インストール先「D:\・・・\PostgreSQL」を「PostgreSQLフォルダ」と表記します。
-インストール・コンポーネント選択はデフォルトの全部のまま[Next>]
-データフォルダの指定はデフォルト(PostgreSQLフォルダ\data)のまま[Next>]
-スーパーユーザのパスワードを指定して[Next>]
-ポート番号はデフォルト(5432)のまま[Next>]
-ロケールは「Japanese, Japan」に変更して[Next]
-設定予定の内容がリストされるので、確認して[Next>]
-再度確認メッセージが表示されるので[Next]
※インストールが開始されます。結構な時間が掛かります。
参考:http://cmemo.net/articles/java/eclipse-%E3%81%A7-postgresql-%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B/
<ドライバのインストール>
-PostgreSQLのインストール完了画面の「Stack Builder・・・」をチェックして[Finish]
※あるいはインストール完了後、Windowsのスタートアップメニューから、[PostgreSQL 12]-[Application Stack Builder]を選択
-スタックビルダが起動します。
「PostgreSQL・・・」を選択して[次へ]
-「カテゴリ」-「Database Drivers」-「pgJDBC・・・」をチェックして[次へ]
-ダウンロード先フォルダを指定して[次へ]
※ダウンロード先には、PostgreSQLフォルダを指定した
-[次へ](インストール開始)
-表示された「Setup pgJDBC」ダイアログで[Next>]
-インストール先ディレクトリを指定して[Next>]
※インストール先には「(PostgreSQLフォルダ)\pgJDBC」を指定
-確認メッセージに対して[Next>]
-完了メッセージ画面で[Finish]
-スタックビルダのダイアログで[終了]
※ここからは、
・Eclipseが既にPC内にインストールされていること
・MySQL版のPHPプロジェクトが既に作成されていてベーススクリプトがあること
を前提にしています。
以降、Eclipse(Pleiades)のインストール先フォルダを「Eclipseフォルダ」と表記します。
<新規PHPプロジェクトの作成>
-Eclipseを起動し、ワークスペースはMySQL版のプロジェクトと同じにして続行
-Eclipseのメニューから[ファイル]-[新規]-[PHPプロジェクト]を選択
-ダイアログ上でプロジェクト名を入力して、その他はデフォルトのまま[完了]
-エクスプローラで、ベース(MySQL版)のスクリプトをプロジェクトフォルダにまるっとコピー
-Eclipseに戻って、「プロジェクト・エクスプローラ」タブ上の新規に作成したプロジェクトを選択し、[F5]キーを押す
※これで、新しいプロジェクトの作成は完了。
<Eclipseに対するPostgreSQLドライバの設定>
※この手順はJava用なので不要。かつ動作確認をしていないので無保証です。
-「(PostgreSQLフォルダ)\pgJDBC\」にある postgresql-42.2.12.jre7.jarをコピーして「(Eclipseフィルダ)\eclipce\jre\lib\」に貼り付けます
<php.iniの修正>
「(Eclipseフォルダ)\xampp\php\php.ihi」をエディタで開いて、以下2つの指定のコメントアウトを外します。
extension=php_pdo_pgsql.dll
extension=php_pgsql.dll
1番目の指定は、PDO経由でのアクセスを有効にするためのものだそうです。「PDO」って何?
→PHP Data Objectsの略。「通常、DBの種類毎に異なるI/Fを使用しなければならないが、PDOは共通のI/Fを提供する。」んだそうです。
ちなみにMySQL版のスクリプトで使っているmysqliは、PDOではない。つまり、現状ではPDOを使ってないのでコメントのままでもよいのだが。
<phpPgAdminのダウンロードとインストール>
phpPgAdminは、httpベースでPostgreSQLのデータベースの設定を行えるツールのようです。
MySQLのDB設定のときに使ったxamppに含まれていたphpMyAdminのようなものなのかな?
ともかくダウンロードしてインストールしてみます。
-以下のURLのページ上の
http://phppgadmin.sourceforge.net/doku.php?id=download
「https://github.com/phppgadmin/phppgadmin/archive/REL_5-6-0.zip」をクリック
-ダウンロードした「phppgadmin-REL_5-6-0.zip」をダブルクリックして、解凍先に「(Eclipseフォルダ)\xampp\htdocs」を指定
-「(Eclipseフォルダ)\xampp\htdocs\phppgadmin\conf」に含まれるconfig.inc.php-distを同フォルダにコピーしてconfig.inc.phpにリネームします。
-作成したconfig.inc.phpを編集します。
$conf['servers'][0]['host'] = ''; → 'localhost';
:PosrgreSQLサーバのhost名かIPを指定する。
$conf['servers'][0]['defaultdb'] = 'template1'; → 'postgres';
:ログインユーザがアクセスできるDB名を指定するらしい。
template1はインストール直後は存在しない。
$conf['extra_login_security'] = true; → false;
:trueにしてあると、postgres、root、adminなどのユーザでは
ログインできないらしい。
<PostgreSQL上へのDBの作成>
-Eclipseに含まれるXAMPP Control Panel((Eclipseフォルダ)\xampp\xampp-control.exe)を起動
-「Apache」を[開始]
-「http://localhost/phppgadmin」をブラウズする
-「phpPgAdmin」画面左上側の「サーバ」>「PostgreSQL」を選択
-右側入力欄のIDに「postgres」を指定して、パスワードにはPostgreSQLをインストールしたときに指定したスーパーユーザ用パスワードを入力して[ログイン]
※環境によって「ログインできない」事例が多数あるようです。さるも上記のconfig.inc.phpの処置が分からなくて結構ハマった。
ちなみにこの現象の対策例として、config.inc.php同様編集対象に上げられる頻度が高いpg_hba.confは、Windows版では「(PostgreSQLフォルダ)\12\data」にありました。
-左側の「PostgreSQL」を選択
-右側の最終行「データベースを作成する」をクリック
-名前:データベース名、Templates:(デフォルト)、エンコード:UTF8、他:お好きに指定して[作成]
DBの枠だけ作成されます。
これって、http(apache)&PHPでPostgreSQLにアクセスできたってことですよね。
ちなみに、PostgreSQLをインストールした結果、スタートアップメニュー内の「PostgreSQL 12」フォルダが作成されています。
そのメニューフォルダ内に「pgAdmin 4」というメニューがあるのですが、実行させたら、Fatal Error:エラー「The application server could not be contacted.」になりました。当面放置します。
まだまだ続きます。
ちょっと前に、このアプリのサーバ側DBをメンテナンスするための管理スクリプトを作成したのですが、DBはEclipseに含まれてたMySQLになってました。
わけあってPostgreSQLもサポートすることになりました。
◆Eclipse+PostgreSQL環境の構築
参考:https://www.dbonline.jp/postgresql/install/
<PostgreSQLのダウンロード>
上記のサイトからリンクされているhttps://www.postgresql.org/を表示
-上部の[ダウンロード→]ボタンをクリック
-対象OSのボタンをクリック
-説明文中の「インストーラをダウンロード」をクリック
-OSとバージョンの組み合わせで、「Windows x86-64」の最新(12.3)の[ダウンロード]ボタンをクリック
<PostgreSQLのインストール>
-ダウンロードしたexeを起動します
-いつもの、OS環境に変更を加えますか的なメッセージにOKします
-インストーラ(Setupダイアログ)の初期画面で[Next>]
-インストール先フォルダを指定して[Next>]
※さるの環境の場合、C:ドライブは空きがないので「D:\・・・\PostgreSQL\12」を指定
以降、インストール先「D:\・・・\PostgreSQL」を「PostgreSQLフォルダ」と表記します。
-インストール・コンポーネント選択はデフォルトの全部のまま[Next>]
-データフォルダの指定はデフォルト(PostgreSQLフォルダ\data)のまま[Next>]
-スーパーユーザのパスワードを指定して[Next>]
-ポート番号はデフォルト(5432)のまま[Next>]
-ロケールは「Japanese, Japan」に変更して[Next]
-設定予定の内容がリストされるので、確認して[Next>]
-再度確認メッセージが表示されるので[Next]
※インストールが開始されます。結構な時間が掛かります。
参考:http://cmemo.net/articles/java/eclipse-%E3%81%A7-postgresql-%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B/
<ドライバのインストール>
-PostgreSQLのインストール完了画面の「Stack Builder・・・」をチェックして[Finish]
※あるいはインストール完了後、Windowsのスタートアップメニューから、[PostgreSQL 12]-[Application Stack Builder]を選択
-スタックビルダが起動します。
「PostgreSQL・・・」を選択して[次へ]
-「カテゴリ」-「Database Drivers」-「pgJDBC・・・」をチェックして[次へ]
-ダウンロード先フォルダを指定して[次へ]
※ダウンロード先には、PostgreSQLフォルダを指定した
-[次へ](インストール開始)
-表示された「Setup pgJDBC」ダイアログで[Next>]
-インストール先ディレクトリを指定して[Next>]
※インストール先には「(PostgreSQLフォルダ)\pgJDBC」を指定
-確認メッセージに対して[Next>]
-完了メッセージ画面で[Finish]
-スタックビルダのダイアログで[終了]
※ここからは、
・Eclipseが既にPC内にインストールされていること
・MySQL版のPHPプロジェクトが既に作成されていてベーススクリプトがあること
を前提にしています。
以降、Eclipse(Pleiades)のインストール先フォルダを「Eclipseフォルダ」と表記します。
<新規PHPプロジェクトの作成>
-Eclipseを起動し、ワークスペースはMySQL版のプロジェクトと同じにして続行
-Eclipseのメニューから[ファイル]-[新規]-[PHPプロジェクト]を選択
-ダイアログ上でプロジェクト名を入力して、その他はデフォルトのまま[完了]
-エクスプローラで、ベース(MySQL版)のスクリプトをプロジェクトフォルダにまるっとコピー
-Eclipseに戻って、「プロジェクト・エクスプローラ」タブ上の新規に作成したプロジェクトを選択し、[F5]キーを押す
※これで、新しいプロジェクトの作成は完了。
<Eclipseに対するPostgreSQLドライバの設定>
※この手順はJava用なので不要。かつ動作確認をしていないので無保証です。
-「(PostgreSQLフォルダ)\pgJDBC\」にある postgresql-42.2.12.jre7.jarをコピーして「(Eclipseフィルダ)\eclipce\jre\lib\」に貼り付けます
<php.iniの修正>
「(Eclipseフォルダ)\xampp\php\php.ihi」をエディタで開いて、以下2つの指定のコメントアウトを外します。
extension=php_pdo_pgsql.dll
extension=php_pgsql.dll
1番目の指定は、PDO経由でのアクセスを有効にするためのものだそうです。「PDO」って何?
→PHP Data Objectsの略。「通常、DBの種類毎に異なるI/Fを使用しなければならないが、PDOは共通のI/Fを提供する。」んだそうです。
ちなみにMySQL版のスクリプトで使っているmysqliは、PDOではない。つまり、現状ではPDOを使ってないのでコメントのままでもよいのだが。
<phpPgAdminのダウンロードとインストール>
phpPgAdminは、httpベースでPostgreSQLのデータベースの設定を行えるツールのようです。
MySQLのDB設定のときに使ったxamppに含まれていたphpMyAdminのようなものなのかな?
ともかくダウンロードしてインストールしてみます。
-以下のURLのページ上の
http://phppgadmin.sourceforge.net/doku.php?id=download
「https://github.com/phppgadmin/phppgadmin/archive/REL_5-6-0.zip」をクリック
-ダウンロードした「phppgadmin-REL_5-6-0.zip」をダブルクリックして、解凍先に「(Eclipseフォルダ)\xampp\htdocs」を指定
-「(Eclipseフォルダ)\xampp\htdocs\phppgadmin\conf」に含まれるconfig.inc.php-distを同フォルダにコピーしてconfig.inc.phpにリネームします。
-作成したconfig.inc.phpを編集します。
$conf['servers'][0]['host'] = ''; → 'localhost';
:PosrgreSQLサーバのhost名かIPを指定する。
$conf['servers'][0]['defaultdb'] = 'template1'; → 'postgres';
:ログインユーザがアクセスできるDB名を指定するらしい。
template1はインストール直後は存在しない。
$conf['extra_login_security'] = true; → false;
:trueにしてあると、postgres、root、adminなどのユーザでは
ログインできないらしい。
<PostgreSQL上へのDBの作成>
-Eclipseに含まれるXAMPP Control Panel((Eclipseフォルダ)\xampp\xampp-control.exe)を起動
-「Apache」を[開始]
-「http://localhost/phppgadmin」をブラウズする
-「phpPgAdmin」画面左上側の「サーバ」>「PostgreSQL」を選択
-右側入力欄のIDに「postgres」を指定して、パスワードにはPostgreSQLをインストールしたときに指定したスーパーユーザ用パスワードを入力して[ログイン]
※環境によって「ログインできない」事例が多数あるようです。さるも上記のconfig.inc.phpの処置が分からなくて結構ハマった。
ちなみにこの現象の対策例として、config.inc.php同様編集対象に上げられる頻度が高いpg_hba.confは、Windows版では「(PostgreSQLフォルダ)\12\data」にありました。
-左側の「PostgreSQL」を選択
-右側の最終行「データベースを作成する」をクリック
-名前:データベース名、Templates:(デフォルト)、エンコード:UTF8、他:お好きに指定して[作成]
DBの枠だけ作成されます。
これって、http(apache)&PHPでPostgreSQLにアクセスできたってことですよね。
ちなみに、PostgreSQLをインストールした結果、スタートアップメニュー内の「PostgreSQL 12」フォルダが作成されています。
そのメニューフォルダ内に「pgAdmin 4」というメニューがあるのですが、実行させたら、Fatal Error:エラー「The application server could not be contacted.」になりました。当面放置します。
まだまだ続きます。
スマフォのアプリを作りたい(29):スマフォだけで動作する音声認識⑤
プログラミング [2020/07/19]
JuliusをAndroidスマフォ上で動作させたいと思ってます。
概ね
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
の順番で進めてますが、5回目にもなるのに未だⅠの途中です。
前回、AndroidStudioのデバッグ機能を有効に動作させるための設定に1週間程費やしてしまいました。
今回は、その続き。
なんとかデバッグできる環境にはなりましたが、未だ不足している部分があります。
◆標準出力に出るメッセージが見たい
JuliusLib(libjulius&linsent)内で、メッセージ出力にprintf/fprintfが使われています。
「それってAndroid上ではどうなるの?」と調べたら、「logcatに出力される。」という記述をどこぞのサイトを斜めに読んで見つけた。
でも、実際はそんな簡単ではなくて、「だまっててもlogcatに出力される」ようにはなっていませんでした。
「リダイレクトすれば見える」というような記述もあって、その通りやってみた。
でも、どうも出てるようには見えない。
さらに調べると、なんか色んなことが書いてあって却って面倒そう。
しかたなくJuliusLibのソースに少し付け足しすることに方針転換しました。
プリプロセッサのマクロ定義を使って、printf/fprintfをAndroidのlogcat出力関数に置き換えてみました。
まずは、julius.hの終わりにヘッダファイルの#includeを追加します。
新規追加したヘッダの中身は、こんな感じ。
julius.hと同じフォルダ「(プロジェクト・フォルダ)\app\src\main\cpp\libjulius\include\julius」に追加しました。
ちなみに、マクロ・ヘッダの#includeは「#include <stdio.h>」より前にあるとダメです。
本体の関数定義も置き換えようとしちゃうから。
ちょっと、こんなことしていいのか判断できてないですがいちおう動いてはいるみたいです。
stdout/stderr以外を使って、通常のファイルに出力しようとするfprintf()があった場合に、ちゃんとファイル出力できてるか未確認です。
◆.so側に制御が渡ったときのカレントディレクトリ
JavaのコードからJNI(Java Native Interface)を経由してC/C++の.soを呼び出したとき、元のカレントディレクトリが引き継がれるのかと思いきや。
.so呼び出し直後のカレントディレクトリは、ルート「/」でした。
なので、APKのassetsからアプリ専用フォルダにコピーしたデータファイル※をアクセスするためには、そのパスを.so側に教えてあげる必要があります。
※詳細は、前回記事をご参照願います。
JNIの機構では、Java側の関数呼び出しの際に指定した引数が、C側の第3引数以降になるようです。
また、Javaの変数値をCの変数型の値に変換する関数が用意されているとのこと。
解説サイトを参考にMainActivity.javaとnative-lib.cppを以下のように変更しました。
渡されたパスをカレントディレクトリに設定すれば、後はJuliusLibを動作させるための各種データファイルをファイル名だけでアクセスできる・・・ハズ。
この対策をやって、「-C simple_keyword.jconf」と指定した、.jconfはアクセスされるようになりました。
logcat(printf/fprintf)に出力されるエラーメッセージもさほど詳しいものはないことが、この時点で分かった。
なので・・・
概ね
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
の順番で進めてますが、5回目にもなるのに未だⅠの途中です。
前回、AndroidStudioのデバッグ機能を有効に動作させるための設定に1週間程費やしてしまいました。
今回は、その続き。
なんとかデバッグできる環境にはなりましたが、未だ不足している部分があります。
◆標準出力に出るメッセージが見たい
JuliusLib(libjulius&linsent)内で、メッセージ出力にprintf/fprintfが使われています。
「それってAndroid上ではどうなるの?」と調べたら、「logcatに出力される。」という記述をどこぞのサイトを斜めに読んで見つけた。
でも、実際はそんな簡単ではなくて、「だまっててもlogcatに出力される」ようにはなっていませんでした。
「リダイレクトすれば見える」というような記述もあって、その通りやってみた。
----コマンドプロンプト-----------------------------
C:\WINDOWS\system32>cd /d d:\appmake\android/sdk/platform-tools
d:\AppMake\Android\Sdk\platform-tools>adb shell
root@generic_x86:/ # stop
root@generic_x86:/ # setprop log.redirect-stdio true
root@generic_x86:/ # start
root@generic_x86:/ #
---------------------------------------------------
でも、どうも出てるようには見えない。
さらに調べると、なんか色んなことが書いてあって却って面倒そう。
しかたなくJuliusLibのソースに少し付け足しすることに方針転換しました。
プリプロセッサのマクロ定義を使って、printf/fprintfをAndroidのlogcat出力関数に置き換えてみました。
まずは、julius.hの終わりにヘッダファイルの#includeを追加します。
----julius.h---------------------------------------
:
:
/* read libsent includes */
#include <sent/stddefs.h>
:
:
#include <julius/extern.h>
#if defined(__ANDROID__)
# include <julius/print-android-macro.h>
#endif
#endif /* __J_JULIUS_H__ */
---------------------------------------------------
新規追加したヘッダの中身は、こんな感じ。
----print-android-macro.h--------------------------
#include <jni.h>
#include <android/log.h>
#define printf(...) __android_log_print(ANDROID_LOG_INFO, MYTAG, __VA_ARGS__);
#define fprintf(fptr, ...) { \
if(fptr==_STD_OUT){__android_log_print(ANDROID_LOG_INFO, MYTAG, __VA_ARGS__);} \
else if(fptr==_STD_ERR){__android_log_print(ANDROID_LOG_DEBUG, MYTAG, __VA_ARGS__);} \
else {fprintf(fptr, __VA_ARGS__);} \
};
#define MYTAG "JuliusLib"
#define _STD_OUT stdout
#define _STD_ERR stderr
---------------------------------------------------
julius.hと同じフォルダ「(プロジェクト・フォルダ)\app\src\main\cpp\libjulius\include\julius」に追加しました。
ちなみに、マクロ・ヘッダの#includeは「#include <stdio.h>」より前にあるとダメです。
本体の関数定義も置き換えようとしちゃうから。
ちょっと、こんなことしていいのか判断できてないですがいちおう動いてはいるみたいです。
stdout/stderr以外を使って、通常のファイルに出力しようとするfprintf()があった場合に、ちゃんとファイル出力できてるか未確認です。
◆.so側に制御が渡ったときのカレントディレクトリ
JavaのコードからJNI(Java Native Interface)を経由してC/C++の.soを呼び出したとき、元のカレントディレクトリが引き継がれるのかと思いきや。
.so呼び出し直後のカレントディレクトリは、ルート「/」でした。
なので、APKのassetsからアプリ専用フォルダにコピーしたデータファイル※をアクセスするためには、そのパスを.so側に教えてあげる必要があります。
※詳細は、前回記事をご参照願います。
JNIの機構では、Java側の関数呼び出しの際に指定した引数が、C側の第3引数以降になるようです。
また、Javaの変数値をCの変数型の値に変換する関数が用意されているとのこと。
解説サイトを参考にMainActivity.javaとnative-lib.cppを以下のように変更しました。
----MainActivity.java------------------------------
package com.teburarec.call_julius;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import java.io.IOException;
import android.content.res.AssetManager;
import java.io.File;
import java.io.InputStream;
import java.io.FileOutputStream;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
String myDataPath;
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
File myDirObj = getFilesDir();
this.myDataPath = myDirObj.getPath();
Log.d("to dir path", this.myDataPath);
initDataFiles();
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
String rtmsg = stringFromJNI(this.myDataPath);
tv.setText(rtmsg);
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI(String curpath);
private void initDataFiles() {
AssetManager assetMgr = getResources().getAssets();
try {
byte[] buffer = new byte[4096];
String files[] = assetMgr.list("jdata");
for(int i = 0; i < files.length; i++) {
Log.d("assets file", files[i]);
String assetPath = "jdata/" + files[i];
InputStream infile = assetMgr.open(assetPath);
FileOutputStream outfile = openFileOutput(files[i], MODE_PRIVATE);
int n = 0;
while (-1 != (n = infile.read(buffer))) {
outfile.write(buffer, 0, n);
}
outfile.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
---------------------------------------------------
渡されたパスをカレントディレクトリに設定すれば、後はJuliusLibを動作させるための各種データファイルをファイル名だけでアクセスできる・・・ハズ。
----native-lib.cpp---------------------------------
:
:
extern "C" JNIEXPORT jstring JNICALL
Java_com_teburarec_call_1julius_MainActivity_stringFromJNI(
JNIEnv* env,
jobject jObj /* this */,
jstring curpath) {
const int argc = 3;
const char *argv[] = {"julius-sample", "-C", "simple_keyword.jconf"};
:
:
int ret;
const char *jdataPath = env->GetStringUTFChars(curpath, NULL);
chdir(jdataPath);
env->ReleaseStringUTFChars(curpath, jdataPath);
/* by default, all messages will be output to standard out */
/* to disable output, uncomment below */
//jlog_set_output(NULL);
/* output log to a file */
//FILE *fp; fp = fopen("log.txt", "w"); jlog_set_output(fp);
:
:
---------------------------------------------------
この対策をやって、「-C simple_keyword.jconf」と指定した、.jconfはアクセスされるようになりました。
logcat(printf/fprintf)に出力されるエラーメッセージもさほど詳しいものはないことが、この時点で分かった。
なので・・・
スマフォのアプリを作りたい(28):スマフォだけで動作する音声認識④
プログラミング [2020/07/18]
JuliusをAndroidスマフォ上で動作させたいと思ってます。
概ね
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
の順番かと思ってますが、このサブタイトルで4回目にもなるのですが未だⅠの途中です。
前回、JuliusLib(libjulius&libsent)をAndroidStudioのC++プロジェクト内に持ち込んで、
ビルドして、実行してみるところまでやりました。
とはいっても、肝心な音声認識を確認するところまでは届いてなくて、「起動はした」止まりです。
続きです。
◆JuliusLibの動作のさせかた調査
「ちょっと、移植作業としての順番がおかしくねーか」と言われそうですが、こんな感じです。
提供されているjulius-simple.cをビルドしたバイナリは、dictation-kit-4.5には含まれていないみたい。
実際にPC版とかを動かして確認するのはちょっと面倒そう。
なので、JuliusBookとソース等からJuliusLib&julius-simpleの使い方を調べます。
1)まずはJuliusLibの起動パラメタには何を指定するのか?
julius-simpleのオリジナルコードは起動パラメタをそのままライブラリに渡している。
指定できるパラメタ(オプション)に「-C」があることをライブラリ内のソースから確認しました。
その他は、-AM|-AM_GMM|-LM|-SR|-GLOBAL|-sectioncheck|-nosectioncheck|・・・(※多すぎたので省略)などがありました。
ともかく、-Cで.jconfファイルが指定できれば、上記のその他の動作パラメタは.jconfファイルに記載して指定できるはず。
2)じゃあ、.jconfファイルってどんな?
ディクテーションキット内に00readme-ja.txt(英:00readme.txt)というファイルがあり、その中に仕様が記述されていました。
dictation-kit-4.5\src\julius-4.5\libjulius\00readme-ja.txt
(前記の調べは、このファイルを読めば分かることでした。^^;;)
また、サンプルの.jconfファイルも含まれていた。コメントとしてパラメタの概説も載ってます。
dictation-kit-4.5\main.jconf
これをベースにします。
3)今回Android上で確認したい機能と制約は?
試したいのは個別単語辞書に基づいた単語認識です。
「スマフォのアプリを作りたい(25)」で試した動作をスマフォで確認したい。
「julius.exe -w 個別単語辞書 -h 音響モデル -input mic」と同様のことを試すということです。
ただし、前回のビルド段階で「Juliusが前提としているサウンドシステムは、Android SDK(NDK)標準では含まれていない」ことが分かったので、マイク入力は使えません。
よって、.jconfファイル/個別単語辞書/音響モデル/音声ファイルをAPK含めて、
native-lib.cppでは、argv[]指定を「-C .jconfファイル」※として起動して、単語認識が動作するか確認します。
(※この点は、予想通りなので、native-lib.cppの修正はせずに済みそう・・・?)
4)単語辞書と音声ファイル等を準備する
【単語辞書】
「スマフォのアプリを作りたい(25)」で作った単語辞書は、「読み」の記述の仕方が正しくありませんでした。
例えば、「体操 たいそう」は、「体操 たいそー」にしないといけない。
作り直します。やり方は、「スマフォのアプリを作りたい(25)」に書いてあります。
【音響モデル】
ディクテーションキットに含まれていたjnas-mono-16mix-gid.binhmmを使用させていただきます。
dictation-kit-4.5\model\phone_m\jnas-mono-16mix-gid.binhmm
【音声ファイル】
音声ファイルはwavでいいみたいなので、開発タブレットPCで自分の声を録音して作ります。
と簡単に思って始めたが、結構面倒だった。
まずは、Windowsのサウンドレコーダーでよかろうと思って探したが・・・ない!
Windows10からはボイスレコーダーっていう名前に変わってたのね。
早速、起動してマイク入力して録音してみた。
録音音声はどこに?
ライブラリ>ドキュメント>サウンドレコーディング(C:\Users\(ユーザID)\Documents\サウンド レコーディング)でした。
ファイル拡張子が.m4aです。(.wavでよかったのに。)
サウンドレコーダー自体に.wavで保存する機能は・・・ない!んだよねきっと。
audacityをインストールしてなかったか?・・・ない!
(以前のHDDパンクの折にアンインストールしてしまったようだ。)
再ダウンロード&インストールを実施し、audacity起動して、録音した.m4aを開こうとしたら・・・エラーが出た。
FFmpegというやつが必要なのだそうだ。
FFmpegをダウンロードしてインストール。(最初からaudacityで録音すれば良い話なのだが・・・)
audacityを再起動して、やっと.m4aが開けた。
JuliusBookにあるように、入力音声のタイプとして指定できる属性もあるが、デフォルトでサポートしているのはモノラル/16bit/16000hzのようなので、それに合わせて.wav出力する。
audacityの場合、サンプリングレートの変換はプロジェクトの属性を予め出力するレートに変更しておく必要があるようでした。
【ファイル名リスト】
JuliusBookによると、音声ファイルを入力音源として使用する場合、「-input=rawfile -filelist ファイル名リスト」として指定するみたいです。
なので、ファイル名リストというのも準備します。
単に「音声ファイル名[改行]」の繰り返しのテキストファイルを作成しました。
念のため文字コード指定はUTF-8にしておきました。
【.jconf】
dictation-kit-4.5\main.jconfをコピーして、natibe-lib.cpp内で指定してあった「simple_keyword.jconf」という名前でセーブ。
以下の記述を追加しました。
これで、JuliusLibに必要なデータ(ファイル)類と動作パラメタの指定の仕方がざっくりわかりました。
では、これらをAPKに入れて、プログラムから使わせる方へ話を進めます。
・・・
概ね
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
の順番かと思ってますが、このサブタイトルで4回目にもなるのですが未だⅠの途中です。
前回、JuliusLib(libjulius&libsent)をAndroidStudioのC++プロジェクト内に持ち込んで、
ビルドして、実行してみるところまでやりました。
とはいっても、肝心な音声認識を確認するところまでは届いてなくて、「起動はした」止まりです。
続きです。
◆JuliusLibの動作のさせかた調査
「ちょっと、移植作業としての順番がおかしくねーか」と言われそうですが、こんな感じです。
提供されているjulius-simple.cをビルドしたバイナリは、dictation-kit-4.5には含まれていないみたい。
実際にPC版とかを動かして確認するのはちょっと面倒そう。
なので、JuliusBookとソース等からJuliusLib&julius-simpleの使い方を調べます。
1)まずはJuliusLibの起動パラメタには何を指定するのか?
julius-simpleのオリジナルコードは起動パラメタをそのままライブラリに渡している。
指定できるパラメタ(オプション)に「-C」があることをライブラリ内のソースから確認しました。
その他は、-AM|-AM_GMM|-LM|-SR|-GLOBAL|-sectioncheck|-nosectioncheck|・・・(※多すぎたので省略)などがありました。
ともかく、-Cで.jconfファイルが指定できれば、上記のその他の動作パラメタは.jconfファイルに記載して指定できるはず。
2)じゃあ、.jconfファイルってどんな?
ディクテーションキット内に00readme-ja.txt(英:00readme.txt)というファイルがあり、その中に仕様が記述されていました。
dictation-kit-4.5\src\julius-4.5\libjulius\00readme-ja.txt
(前記の調べは、このファイルを読めば分かることでした。^^;;)
また、サンプルの.jconfファイルも含まれていた。コメントとしてパラメタの概説も載ってます。
dictation-kit-4.5\main.jconf
これをベースにします。
3)今回Android上で確認したい機能と制約は?
試したいのは個別単語辞書に基づいた単語認識です。
「スマフォのアプリを作りたい(25)」で試した動作をスマフォで確認したい。
「julius.exe -w 個別単語辞書 -h 音響モデル -input mic」と同様のことを試すということです。
ただし、前回のビルド段階で「Juliusが前提としているサウンドシステムは、Android SDK(NDK)標準では含まれていない」ことが分かったので、マイク入力は使えません。
よって、.jconfファイル/個別単語辞書/音響モデル/音声ファイルをAPK含めて、
native-lib.cppでは、argv[]指定を「-C .jconfファイル」※として起動して、単語認識が動作するか確認します。
(※この点は、予想通りなので、native-lib.cppの修正はせずに済みそう・・・?)
4)単語辞書と音声ファイル等を準備する
【単語辞書】
「スマフォのアプリを作りたい(25)」で作った単語辞書は、「読み」の記述の仕方が正しくありませんでした。
例えば、「体操 たいそう」は、「体操 たいそー」にしないといけない。
作り直します。やり方は、「スマフォのアプリを作りたい(25)」に書いてあります。
【音響モデル】
ディクテーションキットに含まれていたjnas-mono-16mix-gid.binhmmを使用させていただきます。
dictation-kit-4.5\model\phone_m\jnas-mono-16mix-gid.binhmm
【音声ファイル】
音声ファイルはwavでいいみたいなので、開発タブレットPCで自分の声を録音して作ります。
と簡単に思って始めたが、結構面倒だった。
まずは、Windowsのサウンドレコーダーでよかろうと思って探したが・・・ない!
Windows10からはボイスレコーダーっていう名前に変わってたのね。
早速、起動してマイク入力して録音してみた。
録音音声はどこに?
ライブラリ>ドキュメント>サウンドレコーディング(C:\Users\(ユーザID)\Documents\サウンド レコーディング)でした。
ファイル拡張子が.m4aです。(.wavでよかったのに。)
サウンドレコーダー自体に.wavで保存する機能は・・・ない!んだよねきっと。
audacityをインストールしてなかったか?・・・ない!
(以前のHDDパンクの折にアンインストールしてしまったようだ。)
再ダウンロード&インストールを実施し、audacity起動して、録音した.m4aを開こうとしたら・・・エラーが出た。
FFmpegというやつが必要なのだそうだ。
FFmpegをダウンロードしてインストール。(最初からaudacityで録音すれば良い話なのだが・・・)
audacityを再起動して、やっと.m4aが開けた。
JuliusBookにあるように、入力音声のタイプとして指定できる属性もあるが、デフォルトでサポートしているのはモノラル/16bit/16000hzのようなので、それに合わせて.wav出力する。
audacityの場合、サンプリングレートの変換はプロジェクトの属性を予め出力するレートに変更しておく必要があるようでした。
【ファイル名リスト】
JuliusBookによると、音声ファイルを入力音源として使用する場合、「-input=rawfile -filelist ファイル名リスト」として指定するみたいです。
なので、ファイル名リストというのも準備します。
単に「音声ファイル名[改行]」の繰り返しのテキストファイルを作成しました。
念のため文字コード指定はUTF-8にしておきました。
【.jconf】
dictation-kit-4.5\main.jconfをコピーして、natibe-lib.cpp内で指定してあった「simple_keyword.jconf」という名前でセーブ。
以下の記述を追加しました。
----simple_keyword.jconf---------------------------
:
#!!-C simple_keyword.jconf
:
-input rawfile
:
-filelist invoicename.txt
:
-w teburarecword.dict
:
-h jnas-mono-16mix-gid.binhmm
:
---------------------------------------------------
これで、JuliusLibに必要なデータ(ファイル)類と動作パラメタの指定の仕方がざっくりわかりました。
では、これらをAPKに入れて、プログラムから使わせる方へ話を進めます。
・・・
スマフォのアプリを作りたい(27):スマフォだけで動作する音声認識③
プログラミング [2020/07/09]
JuliusをAndroidスマフォ上で動作させたいと思ってます。
概ね
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
の順番かと思ってますが、現状は未だⅠの途中です。
前回、AndroidStudioでC++のプロジェクトを作成して、テンプレートを動作させました。
それと、Juliusのライブラリ使用のサンプルjulius-simple.cをちょっと俯瞰してみました。
その続きです。
◆続:AndroidStudio環境へのJuliusLib移植
前回julius-simple.cを見ていて気になる点が2つほどありました。
※1:標準出力を使っている。→Androidでは?
※2:音声データの入力方法に「バッファ渡し」的なものはない。
※1の件に関しては調べだしたらすぐ解決しました。
Androidでは標準出力はlogcatになっている(標準エラー出力も含む)そう。
訂正:誤報です。標準出力がだまっててもlogcatに出力されるわけではありませんでした。
詳細は次回に記載いたします。m(__)m
「では、MIC入力は?」とも思いますが、
動き出せたら、Juliusがエラー等のメッセージを出力してるでしょうから、きっと対策の糸口は見えるかと。
AndroidStudioのC++テンプレートでのJavaからC関数のコールのところがまだモヤモヤです。
もうちょっと深追いが必要です。
参考:https://qiita.com/ymmtyuhei/items/7109579210af34ec697c
JNI(Java Native Interface):Javaとネイティブコードとのインタフェース仕様のことだそうです。
呼び出し元のJavaでstringFromJNI()とされている関数名が、呼び出し先で酷く長い関数名になっていたのは、この仕様によるもののようです。
native-lib.cppで定義されていた関数名の形式・意味は、以下だそうです。
Java_[呼び出し元のパス(src後のパス&“_”区切り)とファイル名(拡張子なし)]_呼び出し関数名()
なので、stringFromJNI()が
Java_com_teburarec_call_1julius_MainActivity_stringFromJNI()になるわけです。
途中のcall_juliusと言うフォルダがcall_1juliusと表現されているのは、区切り記号としての「_」とフォルダ名中の「_」を区別するためなんだろうなと思います。
では、移植作業を始めましょう。
上記の参考サイトが参考にしている本家サイトの説明を読んでみます。
参考:https://developer.android.com/studio/projects/add-native-code?hl=ja
まずはソースを作成/追加しろと書かれています。
1)JuliusLibのソースの持ち込み
Juliusサイトからダウンロードしてきたディクテーションキットに含まれるソースからコピーします。
dictation-kit-4.5\src\julius-4.5フォルダ下のlibjulius、libsentをフォルダごとAndroidStudioのプロジェクトフォルダにコピーします。
コピー先:(プロジェクトフォルダ)\app\src\main\cpp ・・・・native-lib.cppのあるフォルダ
2)native-lib.cppへのjulius-simple.c内処理のマージ
2-1)julius-simple.c内の「#include ・・・」から内部関数をnative-lib.cppの「#include ・・・」の下にコピペしました。
2-2)julius-simple.c内のmain()の処理コードをcom_teburarec_call_1julius_MainActivity_stringFromJNI()の処理コードにまるっと置き換えました。
この時点で、AndroidStudio側で、native-lib.cppを開くと、自動的に静的解析(って云うんでしょうか)が行われているようで、辻褄の合わない箇所がエラーとして表示されます。(変な箇所が赤字で表示されて、ポインタを載せるとエラーの内容が表示されます。)
まずは、先頭の「#include」で、「そんなパスは存在しない。」と出ます。
なので、それ以降のライブラリのヘッダに含まれる定義(変数、定数、関数)が全部未定義のものというエラーです。
早い話、JuliusLib用のインクルードパスをどっかで指定しないといけないですね。
先の本家ページの次の手順がCMakeを設定しろなので、設定の仕方を調べました。
CMakeの設定は、CMakeList.txtで行うんですね。
native-lib.ccppと同じフォルダ:(プロジェクトフォルダ)\app\src\main\cppにありました。
3)CMakeList.txtの編集
3-1)CMakeList.txtでインクルードパスを指定します。
以下の朱書きの記述を追加しました。
さらに、-Dコンパイルオプションで振り分けされているインクルードファイルがあるらしく、その中で定義されている定数も未定義となっていました。
3-2)CMakeList.txtでコンパイルオプション(-D)を指定する。
以下の記述を追加しました。
4)native-lib.cppの修正
この時点で残ったエラーは、元のjulius-simple.cのmain()からそのままコピペした部分でした。
・引数(argc,argv)の参照がそのままになっている点
→引数の問題は、参照部分削除/固定値の参照に変更
const int argc = 3;
const char *argv[] = {"julius-simple", "-C", "simple_keyword.jconf"};
・char * を指定するべき引数に、const char *を指定していると警告
「jconf = j_config_load_args_new(argc, argv);」を
→「jconf = j_config_load_args_new(argc, (char **) argv);」に変更
「while (get_line_from_stdin(・・・, "enter MFCC filename->") != NULL) {」を
→「while (get_line_from_stdin(・・・, (char *) "enter MFCC filename->") != NULL) {」
・リターンが数値になっている点・・・元のテンプレートは文字列(ポインタ)
→「return env->NewStringUTF("メッセージ");」に変更
としました。
CMakeList.txtで指定したインクルードパスが有効にならなかった件は放置して、本家サイトに書いてある3番目のGladleを設定しろをやってみます。
・・・
概ね
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
の順番かと思ってますが、現状は未だⅠの途中です。
前回、AndroidStudioでC++のプロジェクトを作成して、テンプレートを動作させました。
それと、Juliusのライブラリ使用のサンプルjulius-simple.cをちょっと俯瞰してみました。
その続きです。
◆続:AndroidStudio環境へのJuliusLib移植
前回julius-simple.cを見ていて気になる点が2つほどありました。
※1:標準出力を使っている。→Androidでは?
※2:音声データの入力方法に「バッファ渡し」的なものはない。
※1の件に関しては調べだしたらすぐ解決しました。
Androidでは標準出力はlogcatになっている(標準エラー出力も含む)そう。
訂正:誤報です。標準出力がだまっててもlogcatに出力されるわけではありませんでした。
詳細は次回に記載いたします。m(__)m
「では、MIC入力は?」とも思いますが、
動き出せたら、Juliusがエラー等のメッセージを出力してるでしょうから、きっと対策の糸口は見えるかと。
AndroidStudioのC++テンプレートでのJavaからC関数のコールのところがまだモヤモヤです。
もうちょっと深追いが必要です。
参考:https://qiita.com/ymmtyuhei/items/7109579210af34ec697c
JNI(Java Native Interface):Javaとネイティブコードとのインタフェース仕様のことだそうです。
呼び出し元のJavaでstringFromJNI()とされている関数名が、呼び出し先で酷く長い関数名になっていたのは、この仕様によるもののようです。
native-lib.cppで定義されていた関数名の形式・意味は、以下だそうです。
Java_[呼び出し元のパス(src後のパス&“_”区切り)とファイル名(拡張子なし)]_呼び出し関数名()
なので、stringFromJNI()が
Java_com_teburarec_call_1julius_MainActivity_stringFromJNI()になるわけです。
途中のcall_juliusと言うフォルダがcall_1juliusと表現されているのは、区切り記号としての「_」とフォルダ名中の「_」を区別するためなんだろうなと思います。
では、移植作業を始めましょう。
上記の参考サイトが参考にしている本家サイトの説明を読んでみます。
参考:https://developer.android.com/studio/projects/add-native-code?hl=ja
まずはソースを作成/追加しろと書かれています。
1)JuliusLibのソースの持ち込み
Juliusサイトからダウンロードしてきたディクテーションキットに含まれるソースからコピーします。
dictation-kit-4.5\src\julius-4.5フォルダ下のlibjulius、libsentをフォルダごとAndroidStudioのプロジェクトフォルダにコピーします。
コピー先:(プロジェクトフォルダ)\app\src\main\cpp ・・・・native-lib.cppのあるフォルダ
2)native-lib.cppへのjulius-simple.c内処理のマージ
2-1)julius-simple.c内の「#include ・・・」から内部関数をnative-lib.cppの「#include ・・・」の下にコピペしました。
2-2)julius-simple.c内のmain()の処理コードをcom_teburarec_call_1julius_MainActivity_stringFromJNI()の処理コードにまるっと置き換えました。
この時点で、AndroidStudio側で、native-lib.cppを開くと、自動的に静的解析(って云うんでしょうか)が行われているようで、辻褄の合わない箇所がエラーとして表示されます。(変な箇所が赤字で表示されて、ポインタを載せるとエラーの内容が表示されます。)
まずは、先頭の「#include
なので、それ以降のライブラリのヘッダに含まれる定義(変数、定数、関数)が全部未定義のものというエラーです。
早い話、JuliusLib用のインクルードパスをどっかで指定しないといけないですね。
先の本家ページの次の手順がCMakeを設定しろなので、設定の仕方を調べました。
CMakeの設定は、CMakeList.txtで行うんですね。
native-lib.ccppと同じフォルダ:(プロジェクトフォルダ)\app\src\main\cppにありました。
3)CMakeList.txtの編集
3-1)CMakeList.txtでインクルードパスを指定します。
以下の朱書きの記述を追加しました。
----CMakeList.txt---------------------------------
:
add_library( # Sets the name of the library.
native-lib
:
:
native-lib.cpp )
# インクルードパス指定
target_include_directories( # ターゲット名
native-lib
# Private指定
PRIVATE
# インクルードパス
${CMAKE_CURRENT_SOURCE_DIR}/libjulius/include
${CMAKE_CURRENT_SOURCE_DIR}/libsent/include
)
:
:
---------------------------------------------------
さらに、-Dコンパイルオプションで振り分けされているインクルードファイルがあるらしく、その中で定義されている定数も未定義となっていました。
3-2)CMakeList.txtでコンパイルオプション(-D)を指定する。
以下の記述を追加しました。
----CMakeList.txt---------------------------------
# コンパイル オプション指定
option(__ANDROID__ "for Android" ON)
if(__ANDROID__)
add_definitions(-D__ANDROID__)
endif()
---------------------------------------------------
4)native-lib.cppの修正
この時点で残ったエラーは、元のjulius-simple.cのmain()からそのままコピペした部分でした。
・引数(argc,argv)の参照がそのままになっている点
→引数の問題は、参照部分削除/固定値の参照に変更
const int argc = 3;
const char *argv[] = {"julius-simple", "-C", "simple_keyword.jconf"};
・char * を指定するべき引数に、const char *を指定していると警告
「jconf = j_config_load_args_new(argc, argv);」を
→「jconf = j_config_load_args_new(argc, (char **) argv);」に変更
「while (get_line_from_stdin(・・・, "enter MFCC filename->") != NULL) {」を
→「while (get_line_from_stdin(・・・, (char *) "enter MFCC filename->") != NULL) {」
・リターンが数値になっている点・・・元のテンプレートは文字列(ポインタ)
→「return env->NewStringUTF("メッセージ");」に変更
としました。
-ちょっとハマった:静的解析機能の混沌- これで、ひとまずjulius-simple.cベースのnative-lib.cppのフラグはとれた。・・・かと思いきや。 何回かCMakeList.txtや、ソースコードをAndroidStudioで書き換えてたのですが、最初のころは書き換えた時点でAndroidStudioが新しい内容で再チェックするような動きをしてました。ですが、その内チェックし直さないようになりました。エラーが消えません。その場合は、エラー個所にカーソルを置いて、[Alt]+[Enter]を押すと赤字表示が赤以外に変化して「問題ない」状態を表してました。 さらに、最初にエラーが消えたと思った、「#include ただしこの段階でビルドした場合は、同様のエラー(インクルード・ヘッダが Not Found)にはならなかった。 つまり、Inspection機能(以降、静的解析と呼んじゃいます。)だけの問題のようです。 最初から出てたのかもしれませんが、AndroidStudioの上部に「Unable to execute Clang-Tidy: Cannot create property=Diagnostics for JavaBean=com.jetbrains.cidr.lang.daemon.clang.tidy.ClangTidyYamlLoader...」というエラーが表示されっぱなしです。ClangTidyはコードチェックツールらしいので、修正結果を自動で更新チェックしなくなった件と関係するんでしょうか。 上記したメッセージは放置しても構わないのか?とも思ったのですが、メッセージの後ろに「設定」が行えるリンクが貼られていたので、クリックしてClang-Tidyの有効?チェックを外したらメッセージは消えた。でも正しい処置とは思えない。注1) それでも、静的解析の#includeに絡む警告は消えません。 「Unable to execute・・・」の件を調べましたが、AndroidStudio3.5とNDK r21では互換性がない?とかの書き込みがあって、AndroidStudio4.0では対策されているとありました。調べたら、その条件に当てはまりました。注2) ちょっと身も蓋もない話で俄に信じがたい感じですが、Clang-Tidyのチェックを外したのは正解かも。 Clang-Tidyと切り離して、さらにググりましたが、なかなか解が見つかりません。 そんなこんなしている間に、AndroidStudioを一旦終了(PCの再起動を含む)し、再起動したら・・・ あれ?エラー表示が消えました。何で? 以下の参考サイトを見つけて、能動的に静的解析を実行することを考えていたのですが、肩透かしに会いました。注3) 参考:https://gihyo.jp/dev/serial/01/android_studio/0040 注1)Clang-Tidyを有効に戻す手順は -[File]-[Settings...]選択 -左側リスト欄の「Editor」を展開し、Inspectionsを選択 -右(中)側のリストから「C/C++」を展開 -「Gerenal」-「Clang-Tidy」をチェックし、右下の[OK]をクリック 注2)AndroidStudioのバージョン確認は、メニュー[Help]-[About] NDKのリビジョンの確認手順は -メニュー[Tools]-[SDK Manager]選択 -右側欄の「SDK Tools」タブを選択 -右下の「Show Package Details」をチェック -「NDK(Side by side)」の下でチェックされているのがそれ 注3)Inspectionの実行は、 -[Analyze]-[Isnpect Code...]選択 -チェックする範囲(プロジェクト全体、単独ファイル等)を選択し実行 -[Inspection Result]タブが画面下に作成される |
CMakeList.txtで指定したインクルードパスが有効にならなかった件は放置して、本家サイトに書いてある3番目のGladleを設定しろをやってみます。
・・・
スマフォのアプリを作りたい(26):スマフォだけで動作する音声認識②
プログラミング [2020/06/27]
前回、Juliusの導入説明をしてくれているチュートリアル文書を読んで、PC上で単語認識をさせてみるところをやって見ました。
使えそうなので、Androidスマフォ上に移植することを試行錯誤してみます。
「経過や失敗事項は要らない。旨くいく手順だけ書け。」と言われそうですが、
さるの自分のための備忘録なので、その辺りはご容赦の程。
今回の場合、React Native(JavaScript)→ Androidネイティブ(Java)→ Juliusライブラリ(C)と呼び出しが掛かりそうなので・・・
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
こんな感じなのかな~
自信ないなー。汗)
以降、図の表示が小さくて見えない場合は、クリックすると文字が見える程度の画像で表示すると思います。
◆Android向けCプログラムのビルド環境
全くの素人です。Javaでプログラムを組んだことすらないし、AndroidStudioをIDEとして使うのも初。
なので、説明してくれているページを探します。そしたら、
参考:https://qiita.com/sanoh/items/ef0b99fc1dd2f1484d7a
タイトルもばっちし。
読みつつマネしていきます。
AndroidStudioは、React Nativeアプリの動作確認をするためのエミュレータ(AVD)の前提だったのでインストール済みです。
SDK(Android6,0/APIレベル23とAndroid4.0.3/APIレベル15)インストール済みです。
(インストール手順は「スマフォのアプリを作りたい(2):・・・」とかに書いてます。)
まずは、AndroidStudioのプロジェクトを作成するところから。
1)AndroidStudioを起動します

2)C++プロジェクトを作成します
2-1)「+ Start a new Android Studio project」をクリック

2-2)タイル風の絵の中から「C++」と書かれたものをクリックして[Next]

2-3)プロジェク名、パッケージ名、プロジェクトフォルダを入力
2-3)言語には「Java」を選択、ミニマムAPIレベルを指定して[Next]
※APIレベルは、エミュレーターの制限の23にしようか、Sound系パッケージの制限16にしようか迷ったのですが、Android6.0(23)にしました。

2-4)[finish]します。以下のような画面でした。

※ここで、OpenJDKが通信を使って何かしだしたようで、以下の警告が出ました。

何をする気なのか分かりませんが、拒否して後で何かが「古いんじゃ!」とか言われると面倒そうなので、許可しちゃいました。
参考サイトの説明だと、このテンプレートの状態でJavaからCを使うようになってるんだそうです。
JavaのコードはMainActivity.javaで、Cはnative-lib.cppのようです。
それっぽいですね。
MainActivity.javaを画面に表示してみました。

さっぱり、よくわかりません。
native-lib.cppの方はこんな内容。
これまた、短い割には何だかわかりません。
併せて見ると、
Java側がonCreateで何やらやろうとして、コード末尾の「public native String stringFromJNI();」がnative-libの中に実装されている処理のようです。
C側では何だか長たらしい名前の関数「Java_com_teburarec_call_1julius_MainActivity_stringFromJNI」として定義されてますが、ここをコールしているんでしょう。
この状態でしばらく放置していたら・・・
使えそうなので、Androidスマフォ上に移植することを試行錯誤してみます。
「経過や失敗事項は要らない。旨くいく手順だけ書け。」と言われそうですが、
さるの自分のための備忘録なので、その辺りはご容赦の程。
今回の場合、React Native(JavaScript)→ Androidネイティブ(Java)→ Juliusライブラリ(C)と呼び出しが掛かりそうなので・・・
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
こんな感じなのかな~
自信ないなー。汗)
以降、図の表示が小さくて見えない場合は、クリックすると文字が見える程度の画像で表示すると思います。
◆Android向けCプログラムのビルド環境
全くの素人です。Javaでプログラムを組んだことすらないし、AndroidStudioをIDEとして使うのも初。
なので、説明してくれているページを探します。そしたら、
参考:https://qiita.com/sanoh/items/ef0b99fc1dd2f1484d7a
タイトルもばっちし。
読みつつマネしていきます。
AndroidStudioは、React Nativeアプリの動作確認をするためのエミュレータ(AVD)の前提だったのでインストール済みです。
SDK(Android6,0/APIレベル23とAndroid4.0.3/APIレベル15)インストール済みです。
(インストール手順は「スマフォのアプリを作りたい(2):・・・」とかに書いてます。)
まずは、AndroidStudioのプロジェクトを作成するところから。
1)AndroidStudioを起動します

2)C++プロジェクトを作成します
2-1)「+ Start a new Android Studio project」をクリック

2-2)タイル風の絵の中から「C++」と書かれたものをクリックして[Next]

2-3)プロジェク名、パッケージ名、プロジェクトフォルダを入力
2-3)言語には「Java」を選択、ミニマムAPIレベルを指定して[Next]
※APIレベルは、エミュレーターの制限の23にしようか、Sound系パッケージの制限16にしようか迷ったのですが、Android6.0(23)にしました。

2-4)[finish]します。以下のような画面でした。

※ここで、OpenJDKが通信を使って何かしだしたようで、以下の警告が出ました。

何をする気なのか分かりませんが、拒否して後で何かが「古いんじゃ!」とか言われると面倒そうなので、許可しちゃいました。
参考サイトの説明だと、このテンプレートの状態でJavaからCを使うようになってるんだそうです。
JavaのコードはMainActivity.javaで、Cはnative-lib.cppのようです。
それっぽいですね。
MainActivity.javaを画面に表示してみました。

さっぱり、よくわかりません。
native-lib.cppの方はこんな内容。
----native-lib.cpp---------------------------------
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_teburarec_call_1julius_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
---------------------------------------------------
これまた、短い割には何だかわかりません。
併せて見ると、
Java側がonCreateで何やらやろうとして、コード末尾の「public native String stringFromJNI();」がnative-libの中に実装されている処理のようです。
C側では何だか長たらしい名前の関数「Java_com_teburarec_call_1julius_MainActivity_stringFromJNI」として定義されてますが、ここをコールしているんでしょう。
この状態でしばらく放置していたら・・・
スマフォのアプリを作りたい(25):スマフォだけで動作する音声認識①
プログラミング [2020/06/22]
音声とその音声をテキストにしてチャットするソフトを考えてます。
相手に送るのは、音声&テキストです。
それと、あるキーワードを話すと記録としてその話した内容をテキスト化して保存できるようにしたいと思ってます。
何に使うかと言えば、
例えば、お百姓仕事中にその時の作業内容とか、作物の状態とかをメモできるようにしたい。
でもたいていの場合、手は土とか燃料とか触るのでバッチイ状態。
なのでスマフォを直接触れるのは・・・。
手袋をしてたとしてもいちいち手袋をはずすのも面倒だし。
だから、入力開始も声で操作できたらきっと嬉しい。
ヘッドセットとスマフォの電池の持ちの問題もあるし、環境音とかの雑音の問題もあるでしょう。
そっちはオイオイ考えるとして、
直近問題なのがキーワードを認識する音声認識、あるいは公衆回線を必要としない音声認識。
残念ながらGoople Speechはクラウドサービスだから電波の届かない場所では使えません。
電池も相当食うでしょう。
長々と話して、それをテキストに変換するのは、音声を録音しておいて後でGoogle Speechを使う手はあります。
でも最初にアプリに何をしたいのかを伝えるときの命令(キーワード)を認識させるのは、「後で」と言うのはちょっと不便な気がする。
何かの拍子で雑音にも反応してたら使い物にはならないし。
前置き説明長いですね。
ともかくスマフォ単独で、短い言葉だけでもいいので、認識させることができないか?
タダで。
◆Juliusを味見
以前からちょいちょい調べてたのです。
Juliusという音声認識エンジンが有名みたいです。
参考:https://julius.osdn.jp/
京都大学とかIPA、奈良先端科学技術大学院、名古屋工業大学の研究チームがよってたかって作ったもので、OSSとして利用できるようにしてくれています。
AndroidやiOSでも動作させることができるとあります。
ピッタリじゃないですか。
さらに、実際にAndroid版として動作を確認した内容をMatsuiさんという方がGitHubにアップしてくれていました。
参考:https://github.com/tech-sketch/JuliusForAndroid
!!でも!!
上記のAndroid版環境は、Macでビルドしたもののようです。
そう書いてあります。
えー・・・
さるのタブレットはWindowsだし、Macは使ったことないので開発用途で使いこなすのにはハードル高過ぎです。
Windowsでやった事例は・・・
それっきりで、なんか見つからない。
同じ様な問い合わせをされた方へのアドバイスで、アップされたのが割と昔なので本家の新しい情報を見るべきとある。
・・・
まあそうですよね、まずは基本から。
本家のhttps://julius.osdn.jp/サイトを斜め読み。
チュートリアル文書と、JuliusBook(おそらく仕様書的なもの)がウンロードできる。
日本語で書かれてる。
なのでまずは、チュートリアル文書(hi200902-julius-チュートリアル.pdf)に従ってみます。
手っ取り早く使ってみることのできる「ディクテーションキット」と言うのがあるそうで、ダウンロードしてきた。
確か、圧縮ファイル(dictation-kit-4.5.zip)を解凍しただけだったように思う。
ソースコードもOS毎のバイナリ形式も含まれているみたいです。(あー神様仏様、感謝します。)
チュートリアルによると、Windows上で試すのなら「run_fast.bat」を実行すればいいとあるが、
展開されたフォルダ内に該当のバッチファイルはなく、代わりにrun_win_xxx.batというのが3つある。
違いは何?・・・
HOWTO.txtにこう書いてありました。
「GMM版はDNN版に比べて精度が下がりますが,その分処理は軽く,処理が高速なバージョンです.DNN版は高精度ですが,比較的処理が重くなります.また,dnnclient版では別途ソフトウェアをインストールする必要があります.」
じゃあ、軽そうなGMM版が単語認識にはよさそうですね。でもGMMって何のこと?
参考:https://www.gavo.t.u-tokyo.ac.jp/~mine/japanese/nlp+slp/HMM2DNN.pd
GMMは、Gaussian Mixture Modelの略で、DNNはDeep Neural Networkの略みたい。
HMMというのはHidden Markov Model(隠れマルコフモデル)のことだそうです。
意味はさっぱり分かりません。(おいおいね。)
run_win_gmm.batを実行してみます。
タブレットPCの内蔵マイクですが、さっぱりダメです。
反応はして、認識テキストの表示はしますが、ほとんど合ってません。
認識精度がいいと言っているDNN版(run_win_dnn.bat)を起動してみました。
認識精度が良くなった印象が全くなく、しかもまったりとしたレスポンスで。
途中、近い認識結果を出すのですが、最終的には全く言ったことと違う結果で完了します。
ディクテーションキット(dictation-kit-4.5.zip)をダウンロードしてきたページには、話ことばモデルキット(ssr-kit-v4.5.zip)というのもダウンロードできるようになっていたので、それもダウンロードしてみました。
解凍先のフォルダには、同じように実行用のバッチファイル(run.bat)があったので起動してみた。
・・・
認識処理中に出力されるメッセージの構成が変わった。
けど、ほとんど誤認識であることや、まーったりな性能は変わらずです。
原因としては、PCの性能不足、マイクの感度不足とかが考えられるのかもしれないが、それでも良くなさ過ぎ。
そもそも、用途に応じて、音響モデルとか言語モデルとかいうデータを用意するものらしい。
お試し版はそこいらも含まれていて動作するわけだが、そのモデルデータが一般的な認識に必要かつ十分なのかは、よくわからない。
つまり、それが合ってないとか、チープだと上手く認識できないということもあるでしょう。
でも、不安になってきました。
しかし、これ以上の環境(日本語ドキュメント、ソース付き)は手に入らない気がするので、チュートリアル他に従って進めてみます。
相手に送るのは、音声&テキストです。
それと、あるキーワードを話すと記録としてその話した内容をテキスト化して保存できるようにしたいと思ってます。
何に使うかと言えば、
例えば、お百姓仕事中にその時の作業内容とか、作物の状態とかをメモできるようにしたい。
でもたいていの場合、手は土とか燃料とか触るのでバッチイ状態。
なのでスマフォを直接触れるのは・・・。
手袋をしてたとしてもいちいち手袋をはずすのも面倒だし。
だから、入力開始も声で操作できたらきっと嬉しい。
ヘッドセットとスマフォの電池の持ちの問題もあるし、環境音とかの雑音の問題もあるでしょう。
そっちはオイオイ考えるとして、
直近問題なのがキーワードを認識する音声認識、あるいは公衆回線を必要としない音声認識。
残念ながらGoople Speechはクラウドサービスだから電波の届かない場所では使えません。
電池も相当食うでしょう。
長々と話して、それをテキストに変換するのは、音声を録音しておいて後でGoogle Speechを使う手はあります。
でも最初にアプリに何をしたいのかを伝えるときの命令(キーワード)を認識させるのは、「後で」と言うのはちょっと不便な気がする。
何かの拍子で雑音にも反応してたら使い物にはならないし。
前置き説明長いですね。
ともかくスマフォ単独で、短い言葉だけでもいいので、認識させることができないか?
タダで。
◆Juliusを味見
以前からちょいちょい調べてたのです。
Juliusという音声認識エンジンが有名みたいです。
参考:https://julius.osdn.jp/
京都大学とかIPA、奈良先端科学技術大学院、名古屋工業大学の研究チームがよってたかって作ったもので、OSSとして利用できるようにしてくれています。
AndroidやiOSでも動作させることができるとあります。
ピッタリじゃないですか。
さらに、実際にAndroid版として動作を確認した内容をMatsuiさんという方がGitHubにアップしてくれていました。
参考:https://github.com/tech-sketch/JuliusForAndroid
!!でも!!
上記のAndroid版環境は、Macでビルドしたもののようです。
そう書いてあります。
えー・・・
さるのタブレットはWindowsだし、Macは使ったことないので開発用途で使いこなすのにはハードル高過ぎです。
Windowsでやった事例は・・・
それっきりで、なんか見つからない。
同じ様な問い合わせをされた方へのアドバイスで、アップされたのが割と昔なので本家の新しい情報を見るべきとある。
・・・
まあそうですよね、まずは基本から。
本家のhttps://julius.osdn.jp/サイトを斜め読み。
チュートリアル文書と、JuliusBook(おそらく仕様書的なもの)がウンロードできる。
日本語で書かれてる。
なのでまずは、チュートリアル文書(hi200902-julius-チュートリアル.pdf)に従ってみます。
手っ取り早く使ってみることのできる「ディクテーションキット」と言うのがあるそうで、ダウンロードしてきた。
確か、圧縮ファイル(dictation-kit-4.5.zip)を解凍しただけだったように思う。
ソースコードもOS毎のバイナリ形式も含まれているみたいです。(あー神様仏様、感謝します。)
チュートリアルによると、Windows上で試すのなら「run_fast.bat」を実行すればいいとあるが、
展開されたフォルダ内に該当のバッチファイルはなく、代わりにrun_win_xxx.batというのが3つある。
違いは何?・・・
HOWTO.txtにこう書いてありました。
「GMM版はDNN版に比べて精度が下がりますが,その分処理は軽く,処理が高速なバージョンです.DNN版は高精度ですが,比較的処理が重くなります.また,dnnclient版では別途ソフトウェアをインストールする必要があります.」
じゃあ、軽そうなGMM版が単語認識にはよさそうですね。でもGMMって何のこと?
参考:https://www.gavo.t.u-tokyo.ac.jp/~mine/japanese/nlp+slp/HMM2DNN.pd
GMMは、Gaussian Mixture Modelの略で、DNNはDeep Neural Networkの略みたい。
HMMというのはHidden Markov Model(隠れマルコフモデル)のことだそうです。
意味はさっぱり分かりません。(おいおいね。)
run_win_gmm.batを実行してみます。
タブレットPCの内蔵マイクですが、さっぱりダメです。
反応はして、認識テキストの表示はしますが、ほとんど合ってません。
認識精度がいいと言っているDNN版(run_win_dnn.bat)を起動してみました。
認識精度が良くなった印象が全くなく、しかもまったりとしたレスポンスで。
途中、近い認識結果を出すのですが、最終的には全く言ったことと違う結果で完了します。
ディクテーションキット(dictation-kit-4.5.zip)をダウンロードしてきたページには、話ことばモデルキット(ssr-kit-v4.5.zip)というのもダウンロードできるようになっていたので、それもダウンロードしてみました。
解凍先のフォルダには、同じように実行用のバッチファイル(run.bat)があったので起動してみた。
・・・
認識処理中に出力されるメッセージの構成が変わった。
けど、ほとんど誤認識であることや、まーったりな性能は変わらずです。
原因としては、PCの性能不足、マイクの感度不足とかが考えられるのかもしれないが、それでも良くなさ過ぎ。
そもそも、用途に応じて、音響モデルとか言語モデルとかいうデータを用意するものらしい。
お試し版はそこいらも含まれていて動作するわけだが、そのモデルデータが一般的な認識に必要かつ十分なのかは、よくわからない。
つまり、それが合ってないとか、チープだと上手く認識できないということもあるでしょう。
しかし、これ以上の環境(日本語ドキュメント、ソース付き)は手に入らない気がするので、チュートリアル他に従って進めてみます。
スマフォのアプリを作りたい(24):サーバ側の仕掛けを作る②
プログラミング [2020/06/18]
メインのタイトルからちょっと逸れた話の2回目です。
前回からだいぶ間が空いてしまいました。
それだけ作るのに手間がかかったと言うことです。
この書き込みのシリーズ「スマフォのアプリを作りたい」の大雑把な目的は、スマフォで動作するチャットプログラムを作ることです。
チャットでやり取りするメッセージは音声認識を使って話した内容をテキスト化し、音声とテキスト両方で伝わるようにするつもり。
スマフォ間で音声&テキストのやり取り/共有するためのサーバ側の仕掛けを作ろうとしています。
サーバ側にそれなりのデータベースを置いて、その中のデータを共有していこうという感じです。
ただし、そう考えた途端、ユーザ登録だの、グループを作りたいだの、色々な下準備が必要になってきます。
DBの構成をツールで作る(前回記事の作業)ところまでは、一度の作業でいいのですが、
使用者次第の環境・前提データなんかはちょいちょい追加/変更したくなるもんです。
そうなると、ツールで都度SQL文流してというわけには行かなくて、
テーブル内に前提データを追加/変更するためのスクリプトが欲しくなる。
今回のDBには、ユーザ・テーブル、グループ・テーブル、音声認識時のキーワード・テーブルなんかをそれぞれ準備。
それに、チャットした内容はある程度期限を決めて履歴として残す方針です。
スマフォから使い始める前に、システムを管理する人用のセットアップの仕掛けを作ります。
言語は、PHPです。
以前に作ったCGI(PHP)を参考に作り始めました。
割と膨大な量のスクリプトになりました。
結構トラブルも多かったので、その内容について書きます。
◆Eclipseのデバッグ実行でやっぱりハマった
はずかしいので、詳細は省きます。
さるなので学習能力が低く、以前やった間違いを懲りずにやらかします。
・ワークスペースをどこに置くと楽か。・・・・「xampp/htdocs」の下
・デバッグ実行時に何を選択するとスムーズか。・・・・「PHP Webアプリケーション」
すっかり忘れてて「テキトー」に進めて、結局失敗。
とは言え、以前の書き込み「Eclipse-PHP環境でちょっとハマった」を見ながら穴から脱出。
(ワークスペースごと削除してやり直した。ここの備忘録が役に立つこともある。)
◆HTMLのタグ仕様が変わってる!
Eclipse内のプロジェクトの環境に、まずは素のサンプルを単にコピーして持ってきたら、
htmlを記述している部分でワンサカとワーニングが出ます。
サンプルにするPHPのスクリプト内で生成するHTMLが、だいぶ前に作ったものなので、HTML5対応にはなってません。
HTML4からHTML5に変わったときに廃止になっているタグ仕様があって、それが随所に出てきます。
廃止とは言え、思った通りにならないとかではないのだが、ワーニングマークが表示されていてウザイ。
それに本当に問題がある記述をしてしまったときに一目で気付かなくなる恐れがあるので、できるだけワーニングは残さない方がよさそうです。
(1)<table>では、width、cellspacing、cellpaddingなんて属性は廃止
border="0"という記述もダメとか言われる。
↓
style="属性名:値; ・・・"の形式で<table>タグ内に指定する。
width="600" → width:600px; (単位は%、px、emとか使い分ける。)
cellspacing="0" → border-collapse:collapse; border-spacing:0;
cellspacing="5" → border-collapse:separate; border-spacing:5px;
cellpadding="2" → padding:2px;
border="0" → border:0;
※border="1" は、ワーニングが出ないのでそのままでいいらしい。
(2)<table></table>の入れ子でもワーニング
・・・これはEclipse側の解釈間違いな気もする。
<table><tr><td><table>・・・</table></td></tr></table>とすると</td>辺りでダメと出る。
↓
<table><tr><td><div><table>・・・</table></div></td></tr></table>とかの<table>関連以外のタグが含まれるとワーニングは消えた。
(3)<frameset>も廃止
・・・これは、iframeに置き換えたという事例があった。
でも、この件は1ファイルで出ただけで、あっちこっちにこのワーニング原因があるわけではないので、そのまま放置。
こんなくらいだったかな。
その次・・・
前回からだいぶ間が空いてしまいました。
それだけ作るのに手間がかかったと言うことです。
この書き込みのシリーズ「スマフォのアプリを作りたい」の大雑把な目的は、スマフォで動作するチャットプログラムを作ることです。
チャットでやり取りするメッセージは音声認識を使って話した内容をテキスト化し、音声とテキスト両方で伝わるようにするつもり。
スマフォ間で音声&テキストのやり取り/共有するためのサーバ側の仕掛けを作ろうとしています。
サーバ側にそれなりのデータベースを置いて、その中のデータを共有していこうという感じです。
ただし、そう考えた途端、ユーザ登録だの、グループを作りたいだの、色々な下準備が必要になってきます。
DBの構成をツールで作る(前回記事の作業)ところまでは、一度の作業でいいのですが、
使用者次第の環境・前提データなんかはちょいちょい追加/変更したくなるもんです。
そうなると、ツールで都度SQL文流してというわけには行かなくて、
テーブル内に前提データを追加/変更するためのスクリプトが欲しくなる。
今回のDBには、ユーザ・テーブル、グループ・テーブル、音声認識時のキーワード・テーブルなんかをそれぞれ準備。
それに、チャットした内容はある程度期限を決めて履歴として残す方針です。
スマフォから使い始める前に、システムを管理する人用のセットアップの仕掛けを作ります。
言語は、PHPです。
以前に作ったCGI(PHP)を参考に作り始めました。
割と膨大な量のスクリプトになりました。
結構トラブルも多かったので、その内容について書きます。
◆Eclipseのデバッグ実行でやっぱりハマった
はずかしいので、詳細は省きます。
さるなので学習能力が低く、以前やった間違いを懲りずにやらかします。
・ワークスペースをどこに置くと楽か。・・・・「xampp/htdocs」の下
・デバッグ実行時に何を選択するとスムーズか。・・・・「PHP Webアプリケーション」
すっかり忘れてて「テキトー」に進めて、結局失敗。
とは言え、以前の書き込み「Eclipse-PHP環境でちょっとハマった」を見ながら穴から脱出。
(ワークスペースごと削除してやり直した。ここの備忘録が役に立つこともある。)
◆HTMLのタグ仕様が変わってる!
Eclipse内のプロジェクトの環境に、まずは素のサンプルを単にコピーして持ってきたら、
htmlを記述している部分でワンサカとワーニングが出ます。
サンプルにするPHPのスクリプト内で生成するHTMLが、だいぶ前に作ったものなので、HTML5対応にはなってません。
HTML4からHTML5に変わったときに廃止になっているタグ仕様があって、それが随所に出てきます。
廃止とは言え、思った通りにならないとかではないのだが、ワーニングマークが表示されていてウザイ。
それに本当に問題がある記述をしてしまったときに一目で気付かなくなる恐れがあるので、できるだけワーニングは残さない方がよさそうです。
(1)<table>では、width、cellspacing、cellpaddingなんて属性は廃止
border="0"という記述もダメとか言われる。
↓
style="属性名:値; ・・・"の形式で<table>タグ内に指定する。
width="600" → width:600px; (単位は%、px、emとか使い分ける。)
cellspacing="0" → border-collapse:collapse; border-spacing:0;
cellspacing="5" → border-collapse:separate; border-spacing:5px;
cellpadding="2" → padding:2px;
border="0" → border:0;
※border="1" は、ワーニングが出ないのでそのままでいいらしい。
(2)<table></table>の入れ子でもワーニング
・・・これはEclipse側の解釈間違いな気もする。
<table><tr><td><table>・・・</table></td></tr></table>とすると</td>辺りでダメと出る。
↓
<table><tr><td><div><table>・・・</table></div></td></tr></table>とかの<table>関連以外のタグが含まれるとワーニングは消えた。
(3)<frameset>も廃止
・・・これは、iframeに置き換えたという事例があった。
でも、この件は1ファイルで出ただけで、あっちこっちにこのワーニング原因があるわけではないので、そのまま放置。
こんなくらいだったかな。
その次・・・
スマフォのアプリを作りたい(24):サーバ側の仕掛けを作る①
プログラミング [2020/05/13]
スマフォだけで全て完結するシステムって言うのはなかなかねー。
一人だけで使うアプリならありそうだけど・・・
複数の人で、データを共有したいとなったら、当然間を取り持つサーバーが必要になります。
今回作っているアプリも基本、チャットの機能だし。
さらに、データが蓄積させたり、利用内容が高度になれば、DBも必要です。
なので、DBを使ったシステムということで、その動作環境とサーバ側アプリ(スクリプト)を作成します。
ちょっとだけやったことがある言語と言えば
・ASP(古い。その実VB)
・PHP(これも古いが最近も使った)
・Perl(もう懲り懲り)
既にEclipseの環境があるので当然PHPを選びました。
DBはMySQLです。
始めます。
◆プロジェクトの作成
この辺の手順は、以前の備忘録Eclipse-PHP環境でちょっとハマった辺りが何かの足しになるかもしれません。そちらを参考にされてください。
ともかくPHPのプロジェクトを新しく作ります。
ソースはまだ何も入ってません。
◆DBの作成
参考:https://blog.goo.ne.jp/xmldtp/e/8cf1d195d8f18661884b7c1c90cca0c4
1)Eclipseのメニューから
-[ウィンドウ]-[パースペクティブを開く]-[その他]を選択
-続けて、「パースペクティブを開く」ウィンドウで、[データベース開発]を選択
-Eclipse画面の左側が、「データ・ソース・エクスプローラー」に変わります。
2)データベース接続
-「データ・ソース・エクスプローラー」の[データベース接続]を右クリックして
-プルダウンから[新規]を選択
-「新規接続プロファイル」上のリストから「MySQL」を選択して[次へ]をクリック
:
:
-ファイル選択ダイアログでJDBCを指定?・・・
あれ?こんなに面倒くさかったかしら。
以前にもDBの作成はやってみたことがあったはずなのに、全くこの手順に馴染みがありません。
・・・
一人だけで使うアプリならありそうだけど・・・
複数の人で、データを共有したいとなったら、当然間を取り持つサーバーが必要になります。
今回作っているアプリも基本、チャットの機能だし。
さらに、データが蓄積させたり、利用内容が高度になれば、DBも必要です。
なので、DBを使ったシステムということで、その動作環境とサーバ側アプリ(スクリプト)を作成します。
ちょっとだけやったことがある言語と言えば
・ASP(古い。その実VB)
・PHP(これも古いが最近も使った)
・Perl(もう懲り懲り)
既にEclipseの環境があるので当然PHPを選びました。
DBはMySQLです。
始めます。
◆プロジェクトの作成
この辺の手順は、以前の備忘録Eclipse-PHP環境でちょっとハマった辺りが何かの足しになるかもしれません。そちらを参考にされてください。
ともかくPHPのプロジェクトを新しく作ります。
ソースはまだ何も入ってません。
◆DBの作成
参考:https://blog.goo.ne.jp/xmldtp/e/8cf1d195d8f18661884b7c1c90cca0c4
1)Eclipseのメニューから
-[ウィンドウ]-[パースペクティブを開く]-[その他]を選択
-続けて、「パースペクティブを開く」ウィンドウで、[データベース開発]を選択
-Eclipse画面の左側が、「データ・ソース・エクスプローラー」に変わります。
2)データベース接続
-「データ・ソース・エクスプローラー」の[データベース接続]を右クリックして
-プルダウンから[新規]を選択
-「新規接続プロファイル」上のリストから「MySQL」を選択して[次へ]をクリック
:
:
-ファイル選択ダイアログでJDBCを指定?・・・
あれ?こんなに面倒くさかったかしら。
以前にもDBの作成はやってみたことがあったはずなのに、全くこの手順に馴染みがありません。
・・・
スマフォのアプリを作りたい(23):実際のスマフォでアプリを試す
プログラミング [2020/04/27]
これまで、ずーーっとエミュレータ(AVD:Android Virtual Device)でしか試作したアプリを動作させてませんでした。
そもそも、エミュレータを使っていたのは、買った中古のSIMフリー・スマフォのAndoridバージョンが古くて対象として使えなかったから。
富士通 ARROWS Me F-11D Android4.0 APIレベル15
APIレベル15だとVisualStudio2017(NDK)ではサポートされてなかった。
たしかAPIレベル19以降だったかと思う。
一方、React Nativeに切り替えたときには、もうエミュレータを使うことしか頭になくて。
エミュレータの最低の前提バージョンが、6.0(APIレベル23)。
ずっと、それで動作確認してきたが、そろそろ実機を使ってみたくなった。
ここで、倅が以前使っていたLUMIXというスマフォが引き出しから出てきた。
確認してみると、Androidバージョンは、4.04となっている。
もしかしたら使えるかも。
ただ、4.0xのコード名がIceCreamSandwichです。それに対して4.1-4.3がJellyBeanという名前。
どっかの機能制限で、「JellyBean以降」というのがあった気がします。
まあ、どうなるかやってみます。
◆SDKの追加インストール
Android SDKとしては、かなり古いバージョンのものまで用意されていたはずなので、SDKの追加インストールから。
-AndroidStudioを起動
-Welcome画面の右下の[Configure]をクリックして、プルダウンから「SDK Manager」を選択
-各SDKの選択画面が表示されます。すでにインストールしてある10.0と6.0にチェックが入ってます。
-「SDK 4.0.3(IceCreamSandwich)」をチェック
-右下の「Show Package Detail」をチェック
-「SDK 4.0.3」の構成が確認できます。
-全部にチェックが入ってるのをそのままにしました。
-一応「SDK Tools」タブを確認しましたが、何か追加要かわからなかったのでここもそのまま
-右下の[OK]ボタンをクリック
-インストールが完了(Done)したようなので、[Finish]をクリック
◆スマフォのPCへの接続
LUMIXの場合
-スマフォ(LUMIX)の画面下のボタンの左側(三本線のマーク下)を押す
-プルアップメニューから「本体設定」を選択
-設定メニューの一番下の方の「開発者向けオプション」を選択
-「注意」メッセージが表示されるのでよく読んでから[OK]をタップ
-「USBデバッグ」項目をチェック状態にします。
(その他の項目はご自由に)
チャント接続可能かどうかは、以下で確認するのだそうです。
参考:https://reactnative.dev/docs/running-on-device
-コマンドプロンプトを起動します。
-カレントドライブをSDKインストール先の「platform-tools」にします。
-「adb devices」コマンドを打ち込んで、表示内容に「xxxxxxxxxxx device」が出るか確認します。
参考(React Native)サイトの説明では、このあと「react-native run-android」をやればいいように書かれています。
それだと、エミュレータが起動されちゃうんじゃ?
「adb -s (デバイス名) reverse tcp:8081 tcp:8081」とやるとありますが、「デバイスがAndroid5.0以降を実行していて」とあります。
じゃ、それより前のバージョンのデバイスはどうするの?
なんで、こういう説明の仕方しかしないのかなー。ちょっとイラつきますよね。
あと、ベースのSDKを変更する部分の設定がまだです。
◆プロジェクトのベースSDKの変更
「どこで、対象Androidのバージョンを決めてたっけ?」と考えて、過去の書き込みを自身で読み返してみました。
(このブログを備忘録として使ってます。)
これかな?
「スマフォのアプリを作りたい(14):音声認識させたい②」
react-native-google-speech-apiを導入しようとしたときに、ビルドが通らなかった原因が、android\build.gradleの中に指定してあった、「minSdkVersion = 16」という記述。
この辺の指定で、四苦八苦したのをジワジワ思い出してきた。
ってことは、
その時ダメだったAPIレベルより低いものを指定して、ビルドが通る分けがない。
でも、試しにやってみた。
見事に、エラーが出まくりました。
前の方のreact-native-audioのエラーは明らかにAPIレベルが合ってないという感じですかね。
後の方は、Javaのバージョンが合ってないから?TypeScript記述?でエラーになってます。
ここで、Android/APIレベル/Javaのバージョンの関係について、ちょっと気になったのでぐぐって見ました。
参考:https://so-zou.jp/software/tech/programming/java/introduction/version/
参考:https://development.relaxes.jp/android%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%80%81api%E3%83%AC%E3%83%99%E3%83%AB%E3%80%81%E3%82%B3%E3%83%BC%E3%83%89%E3%83%8D%E3%83%BC%E3%83%A0%E4%B8%80%E8%A6%A7/
なんか、Javaのバージョンってややこしい。
たぶん、スマフォはAndroid4.0(APIレベル15)-Java1.6 で、
さるの現状の環境はJDK8(Java1.8)だから確かに合ってない。
まあでも、ここを何とか切り抜けたとしても、その先の見通しもない気がします。
なので、この前提不一致の件の対策方法を探るのはやめて、build.gradleは元の記述に戻します。
続いて・・・
そもそも、エミュレータを使っていたのは、買った中古のSIMフリー・スマフォのAndoridバージョンが古くて対象として使えなかったから。
富士通 ARROWS Me F-11D Android4.0 APIレベル15
APIレベル15だとVisualStudio2017(NDK)ではサポートされてなかった。
たしかAPIレベル19以降だったかと思う。
一方、React Nativeに切り替えたときには、もうエミュレータを使うことしか頭になくて。
エミュレータの最低の前提バージョンが、6.0(APIレベル23)。
ずっと、それで動作確認してきたが、そろそろ実機を使ってみたくなった。
ここで、倅が以前使っていたLUMIXというスマフォが引き出しから出てきた。
確認してみると、Androidバージョンは、4.04となっている。
もしかしたら使えるかも。
ただ、4.0xのコード名がIceCreamSandwichです。それに対して4.1-4.3がJellyBeanという名前。
どっかの機能制限で、「JellyBean以降」というのがあった気がします。
まあ、どうなるかやってみます。
◆SDKの追加インストール
Android SDKとしては、かなり古いバージョンのものまで用意されていたはずなので、SDKの追加インストールから。
-AndroidStudioを起動
-Welcome画面の右下の[Configure]をクリックして、プルダウンから「SDK Manager」を選択
-各SDKの選択画面が表示されます。すでにインストールしてある10.0と6.0にチェックが入ってます。
-「SDK 4.0.3(IceCreamSandwich)」をチェック
-右下の「Show Package Detail」をチェック
-「SDK 4.0.3」の構成が確認できます。
-全部にチェックが入ってるのをそのままにしました。
-一応「SDK Tools」タブを確認しましたが、何か追加要かわからなかったのでここもそのまま
-右下の[OK]ボタンをクリック
-インストールが完了(Done)したようなので、[Finish]をクリック
◆スマフォのPCへの接続
LUMIXの場合
-スマフォ(LUMIX)の画面下のボタンの左側(三本線のマーク下)を押す
-プルアップメニューから「本体設定」を選択
-設定メニューの一番下の方の「開発者向けオプション」を選択
-「注意」メッセージが表示されるのでよく読んでから[OK]をタップ
-「USBデバッグ」項目をチェック状態にします。
(その他の項目はご自由に)
チャント接続可能かどうかは、以下で確認するのだそうです。
参考:https://reactnative.dev/docs/running-on-device
-コマンドプロンプトを起動します。
-カレントドライブをSDKインストール先の「platform-tools」にします。
-「adb devices」コマンドを打ち込んで、表示内容に「xxxxxxxxxxx device」が出るか確認します。
----コマンドプロンプト-----------------------------
C:\WINDOWS\system32>cd /d d:\appmake\android\sdk\platform-tools
d:\AppMake\Android\Sdk\platform-tools>adb devices
* daemon not running; starting now at tcp:5037
* daemon started successfully
List of devices attached
5C84000600000001 device
---------------------------------------------------
参考(React Native)サイトの説明では、このあと「react-native run-android」をやればいいように書かれています。
それだと、エミュレータが起動されちゃうんじゃ?
「adb -s (デバイス名) reverse tcp:8081 tcp:8081」とやるとありますが、「デバイスがAndroid5.0以降を実行していて」とあります。
じゃ、それより前のバージョンのデバイスはどうするの?
なんで、こういう説明の仕方しかしないのかなー。ちょっとイラつきますよね。
あと、ベースのSDKを変更する部分の設定がまだです。
◆プロジェクトのベースSDKの変更
「どこで、対象Androidのバージョンを決めてたっけ?」と考えて、過去の書き込みを自身で読み返してみました。
(このブログを備忘録として使ってます。)
これかな?
「スマフォのアプリを作りたい(14):音声認識させたい②」
react-native-google-speech-apiを導入しようとしたときに、ビルドが通らなかった原因が、android\build.gradleの中に指定してあった、「minSdkVersion = 16」という記述。
この辺の指定で、四苦八苦したのをジワジワ思い出してきた。
ってことは、
その時ダメだったAPIレベルより低いものを指定して、ビルドが通る分けがない。
でも、試しにやってみた。
----build.gradle-----------------------------------
:
buildscript {
ext {
buildToolsVersion = "28.0.3"
//*** changed min_version for google-speech-api by sarumosunaru
//minSdkVersion = 16
//minSdkVersion = 21
//compileSdkVersion = 28
//targetSdkVersion = 28
//*** try old api level
minSdkVersion = 15
compileSdkVersion = 15
targetSdkVersion = 15
}
:
:
---------------------------------------------------
見事に、エラーが出まくりました。
----コマンドプロンプト-----------------------------
D:\AppMake\proj\VTChat>react-native run-android
info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag.
Jetifier found 1034 file(s) to forward-jetify. Using 4 workers...
info Starting JS server...
info Installing the app...
> Configure project :react-native-audio
WARNING: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html
WARNING: minSdkVersion (16) is greater than targetSdkVersion (15) for variant "debug". Please change the values such that minSdkVersion is less than or equal to targetSdkVersion.
WARNING: minSdkVersion (16) is greater than targetSdkVersion (15) for variant "release". Please change the values such that minSdkVersion is less than or equal to targetSdkVersion.
> Configure project :react-native-google-speech-api
The com.google.protobuf plugin was already applied to the project: :react-native-google-speech-api and will not be applied again after plugin: android-library
WARNING: API 'variant.getJavaCompile()' is obsolete and has been replaced with 'variant.getJavaCompileProvider()'.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
To determine what is calling variant.getJavaCompile(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.
> Task :react-native-audio:compileDebugJavaWithJavac
> Task :react-native-audio:compileDebugJavaWithJavac FAILED
Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.5/userguide/command_line_interface.html#sec:command_line_warnings
28 actionable tasks: 6 executed, 22 up-to-date
D:\AppMake\proj\VTChat\node_modules\react-native-audio\android\src\main\java\com\rnim\rn\audio\AudioRecorderManager.java:87: error: diamond operator is not supported in -source 1.6
Mapconstants = new HashMap<>();
^
(use -source 7 or higher to enable diamond operator)
D:\AppMake\proj\VTChat\node_modules\react-native-audio\android\src\main\java\com\rnim\rn\audio\AudioRecorderManager.java:277: error: multi-catch statement is not supported in -source 1.6
} catch (InvocationTargetException | RuntimeException | IllegalAccessException e) {
^
(use -source 7 or higher to enable multi-catch statement)
D:\AppMake\proj\VTChat\node_modules\react-native-audio\android\src\main\java\com\rnim\rn\audio\ReactNativeAudioPackage.java:22: error: diamond operator is not supported in -source 1.6
Listmodules = new ArrayList<>();
^
(use -source 7 or higher to enable diamond operator)
3 errors
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':react-native-audio:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
:
:
---------------------------------------------------
前の方のreact-native-audioのエラーは明らかにAPIレベルが合ってないという感じですかね。
後の方は、Javaのバージョンが合ってないから?TypeScript記述?でエラーになってます。
ここで、Android/APIレベル/Javaのバージョンの関係について、ちょっと気になったのでぐぐって見ました。
参考:https://so-zou.jp/software/tech/programming/java/introduction/version/
参考:https://development.relaxes.jp/android%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%80%81api%E3%83%AC%E3%83%99%E3%83%AB%E3%80%81%E3%82%B3%E3%83%BC%E3%83%89%E3%83%8D%E3%83%BC%E3%83%A0%E4%B8%80%E8%A6%A7/
なんか、Javaのバージョンってややこしい。
たぶん、スマフォはAndroid4.0(APIレベル15)-Java1.6 で、
さるの現状の環境はJDK8(Java1.8)だから確かに合ってない。
----コマンドプロンプト-----------------------------
D:\AppMake\proj\VTChat>java -version
Picked up _JAVA_OPTIONS: -Duser.language=en
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
---------------------------------------------------
まあでも、ここを何とか切り抜けたとしても、その先の見通しもない気がします。
なので、この前提不一致の件の対策方法を探るのはやめて、build.gradleは元の記述に戻します。
続いて・・・
スマフォのアプリを作りたい(22):音声ファイル(.m4a)を再生する
プログラミング [2020/04/16]
前々回までに音声認識と同時にその音声を録音する機能を作りました。
録音した音声は、.m4aファイルとして、保存してあります。
その音声ファイルを再生する部分をやってみます。
いつものボヤキに入る前に。
「スマフォのアプリを作りたい」シリーズを最初から読まないとどういう環境でやってることなのか分からないかと思いますので、ここでさらっと説明しておきます。
-React Nativeを開発環境としています。
開発環境のmustな前提/構成については省略します。
スマフォのアプリを作りたい(2)~(4)辺りには書いてあります。
-最初のターゲットとしてはAndroidスマフォとうことにしています。
-動作環境は、AndroidStudioのAVD(エミュレータ)を現状は使用しています。
(未だ実機での動作を一切確認したことがありません。)
-Build、Load&Goは、「react-native run-android」コマンドで行っています。
-デバッガは、Chromeのデベロッパーツールです。
-コードの編集は、sakuraを使っちゃってます。つまり、AndroidStudioは使ってません。
(使い方を現時点で知りません。)
-パッケージ(Javaコード)に手を入れてしまった場合は、デバッガは使ってなくて、
logcatのメッセージログを使ってます。
-これらの開発・動作環境を全てタブレットPC(+SSD増設HDD)に突っ込んでます。
-OSはWindows10です。
-外部との接続は、主にポケットWifiです。
かなり、素朴なやり方ですかね。
そもそも、タブレットPCなので、そんなにパワーはなくて、サクサクというわけには行きません。
「react-native run-android」がかなりか確率で失敗するので、効率は良くありません。
また、Chromeでのデバッグもとっても重い印象です。
でも、「持って歩ける開発環境」です。
では、本題に入りましょう。
◆音声ファイルの再生には何を使う?
ちょっと前に、「録音」に関しては「react-native-audio」を使いかけました。
これで、「再生」もできるのかと思いきや・・・録音だけの機能なんだそうです。
「再生」は、「react-native-sound」を使うのが、どうも定番っぽい?
でも、.m4aは再生できるんでしょうか?
ちょっとぐぐってみました。
参考:http://www.npmjs.com/package/react-native-sound
本家?Ver.1.11.0では、アルファ版だからバグがあるかもしれないよと書いてます。
また、ストリーミング再生はサポートしてないとある。
.m4aが扱えるのかは、上記URLのページ内には書かれていない。
んーー。
一方、以下のサイトには「.m4a」の単語が含まれていました。
参考:https://reactnativeexample.com/play-or-stream-audio-files-in-reactnative-on-ios-android/
タイトルからしてファイル再生とストリーミングもできるっぽい。
パッケージ名はちょっと長くなって」「react-native-sound-player」だそうです。
.m4aがサポートされているかどうかは、Android本家のサイトにリンクがされてあって、
参考:https://developer.android.com/guide/topics/media/media-formats
サポートされてるっぽいぞ。
ちなみに「AVPlayer(iOS)」と書かれている方(リンク先がなぜかstackoverflowのページ)では・・・
iOSのバージョン次第ってことなんでしょうか。10.9.1で問い合わせたときのリストには「public.mpeg-4-audio」がある。
まあ、そっちはまた後で考えるということで。
さるがこの手のページに慣れて来たせいもあって、説明も割と分かりやすいという第一印象。
なので、react-native-sound-playerを使ってみます。
◆追加インストール
参考:https://reactnativeexample.com/play-or-stream-audio-files-in-reactnative-on-ios-android/
に従ってインストールしてみます。
いつもの通りプロジェクトフォルダにカレントを移動して「npm install ・・・」と
いつもと違う「react-native link ・・・」を実行します。(でも、実は実行しなくてよかった。)
何事もなく成功したようです。
ですが、「react-native run-android」したときに以下のエラーが出ました。
もし、さると同じように、サイトの説明を斜めに読んで「react-native link ・・・」を実行してしまった場合は、「react-native unlink ・・・」を実行するとエラーは消えます。
さるにとって「link」というパラメタ指定は鬼門のようです。
あと、本題には関係ないですが、録音音声のファイルリストを表示するために「react-native-fs」をインストールします。
手順としては、「npm install react-native-fs --save」を実行するだけです。
※本家のサイト等に「react-native link react-native-fs」を実行するように書いてありますが、さるの環境では必要ないらしい。また、本家サイトのUsageには、settings.gradle等に何か修正を加えるような記述が書かれているけど、DocumentDirectory以外をアクセスする場合に必要な設定なのかな? 幸いにして今回扱う録音ファイルはDocumentDirectory下なので必要ないはず。
それでは、実装に入ります・・・
録音した音声は、.m4aファイルとして、保存してあります。
その音声ファイルを再生する部分をやってみます。
いつものボヤキに入る前に。
「スマフォのアプリを作りたい」シリーズを最初から読まないとどういう環境でやってることなのか分からないかと思いますので、ここでさらっと説明しておきます。
-React Nativeを開発環境としています。
開発環境のmustな前提/構成については省略します。
スマフォのアプリを作りたい(2)~(4)辺りには書いてあります。
-最初のターゲットとしてはAndroidスマフォとうことにしています。
-動作環境は、AndroidStudioのAVD(エミュレータ)を現状は使用しています。
(未だ実機での動作を一切確認したことがありません。)
-Build、Load&Goは、「react-native run-android」コマンドで行っています。
-デバッガは、Chromeのデベロッパーツールです。
-コードの編集は、sakuraを使っちゃってます。つまり、AndroidStudioは使ってません。
(使い方を現時点で知りません。)
-パッケージ(Javaコード)に手を入れてしまった場合は、デバッガは使ってなくて、
logcatのメッセージログを使ってます。
-これらの開発・動作環境を全てタブレットPC(+SSD増設HDD)に突っ込んでます。
-OSはWindows10です。
-外部との接続は、主にポケットWifiです。
かなり、素朴なやり方ですかね。
そもそも、タブレットPCなので、そんなにパワーはなくて、サクサクというわけには行きません。
「react-native run-android」がかなりか確率で失敗するので、効率は良くありません。
また、Chromeでのデバッグもとっても重い印象です。
でも、「持って歩ける開発環境」です。
では、本題に入りましょう。
◆音声ファイルの再生には何を使う?
ちょっと前に、「録音」に関しては「react-native-audio」を使いかけました。
これで、「再生」もできるのかと思いきや・・・録音だけの機能なんだそうです。
「再生」は、「react-native-sound」を使うのが、どうも定番っぽい?
でも、.m4aは再生できるんでしょうか?
ちょっとぐぐってみました。
参考:http://www.npmjs.com/package/react-native-sound
本家?Ver.1.11.0では、アルファ版だからバグがあるかもしれないよと書いてます。
また、ストリーミング再生はサポートしてないとある。
.m4aが扱えるのかは、上記URLのページ内には書かれていない。
んーー。
一方、以下のサイトには「.m4a」の単語が含まれていました。
参考:https://reactnativeexample.com/play-or-stream-audio-files-in-reactnative-on-ios-android/
タイトルからしてファイル再生とストリーミングもできるっぽい。
パッケージ名はちょっと長くなって」「react-native-sound-player」だそうです。
.m4aがサポートされているかどうかは、Android本家のサイトにリンクがされてあって、
参考:https://developer.android.com/guide/topics/media/media-formats
サポートされてるっぽいぞ。
ちなみに「AVPlayer(iOS)」と書かれている方(リンク先がなぜかstackoverflowのページ)では・・・
iOSのバージョン次第ってことなんでしょうか。10.9.1で問い合わせたときのリストには「public.mpeg-4-audio」がある。
まあ、そっちはまた後で考えるということで。
さるがこの手のページに慣れて来たせいもあって、説明も割と分かりやすいという第一印象。
なので、react-native-sound-playerを使ってみます。
◆追加インストール
参考:https://reactnativeexample.com/play-or-stream-audio-files-in-reactnative-on-ios-android/
に従ってインストールしてみます。
いつもの通りプロジェクトフォルダにカレントを移動して「npm install ・・・」と
いつもと違う「react-native link ・・・」を実行します。(でも、実は実行しなくてよかった。)
----コマンドプロンプト-----------------------------
:
D:\AppMake\proj\VTChat>npm install react-native-sound-player --save
npm WARN @typescript-eslint/eslint-plugin@1.13.0 requires a peer of eslint@^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @typescript-eslint/parser@1.13.0 requires a peer of eslint@^5.0.0 but none is installed. You must install peer dependencies yourself.
:
:
+ react-native-sound-player@0.10.4
added 1 package from 1 contributor and audited 957490 packages in 64.888s
:
:
D:\AppMake\proj\VTChat>react-native link react-native-sound-player
info Linking "react-native-sound-player" iOS dependency
info iOS module "react-native-sound-player" has been successfully linked
info Linking "react-native-sound-player" Android dependency
info Android module "react-native-sound-player" has been successfully linked
---------------------------------------------------
何事もなく成功したようです。
ですが、「react-native run-android」したときに以下のエラーが出ました。
----コマンドプロンプト-----------------------------
D:\AppMake\proj\VTChat>react-native run-android
error React Native CLI uses autolinking for native dependencies, but the following modules are linked manually:
- react-native-fs (to unlink run: "react-native unlink react-native-fs")
- react-native-sound-player (to unlink run: "react-native unlink react-native-sound-player")
This is likely happening when upgrading React Native from below 0.60 to 0.60 or above. Going forward, you can unlink this dependency via "react-native unlink" and it will be included in your app automatically. If a library isn't compatible with autolinking, disregard this message and notify the library maintainers.
---------------------------------------------------
もし、さると同じように、サイトの説明を斜めに読んで「react-native link ・・・」を実行してしまった場合は、「react-native unlink ・・・」を実行するとエラーは消えます。
さるにとって「link」というパラメタ指定は鬼門のようです。
あと、本題には関係ないですが、録音音声のファイルリストを表示するために「react-native-fs」をインストールします。
手順としては、「npm install react-native-fs --save」を実行するだけです。
※本家のサイト等に「react-native link react-native-fs」を実行するように書いてありますが、さるの環境では必要ないらしい。また、本家サイトのUsageには、settings.gradle等に何か修正を加えるような記述が書かれているけど、DocumentDirectory以外をアクセスする場合に必要な設定なのかな? 幸いにして今回扱う録音ファイルはDocumentDirectory下なので必要ないはず。
それでは、実装に入ります・・・
スマフォのアプリを作りたい(21):メニュー作成の一例
プログラミング [2020/04/08]
チャットと音声認識を組み合わせたくて、React Nativeでチャット(react-native-gifted-chat)と音声認識(react-native-google-speech-api)を試しました。
そろそろ組み合わせたものを作ろうかとも思ったのですが、その前に録音した音声を再生するところをやって見ようと思います。
さらにその前に、現状のApp.jsをちょっと変更したくなりました。
というのも、現状のソースは、
App.jsの下にChat.js(チャット制御)とSpeech.js(Google Speech to Text音声認識と録音制御)の2つのコンポーネントがぶら下がっている構成です。
App.js内でreact-native-router-fluxを使って<Router><Scene key=’root><Scene ・・・/><Scene ・・・/></Scene>と2つ並べています。
2つの<Scene ・・・/>の切り替え方を知らないので、今のところ1番目の<Scene ・・・/>が動作を開始した後、切り替えは多分できないようになってます。
せっかくなので、音声認識(&録音)、新規:音声再生、チャットをそれぞれ切り替え可能にしたいと、ちょっと調べました。
◆<Tabs>を使って複数の機能をメニュー化する
「react-native-router-flux 切り替え」でぐぐって見ると、以下のサイトが引っ掛かりました。
参考:https://rara-world.com/react-native-tab-routing/
サンプルが載ってます。
しばらく、React Native JSXのコードから遠ざかっていたので、なんかサンプルコードに違和感が・・・
ともかく、react-native-router-fluxの<Tabs>というコンポーネントがあって、それを使って並べるようです。
結果の絵でもあれば、ちょっとイメージできていいんだろうけど、載ってません。
やってみた方が早いですね。
では、まずはコードです。
こんな風にしました。
どんなiconを使うのかは、「iconName」パラメタで指定しているようです。
「import Icon from 'react-native-vector-icons/MaterialIcons';」というのも初めて見るの書き方。
参考:https://qiita.com/kana-t/items/3cad4fae393b6a5fc8a0
react-native-vendor-iconsをインストールした後で分かったのですが、
react-native-vector-iconsに含まれる、アイコンのセット(.json)をimportしていることになるみたいです。
「(プロジェクトフォルダ)\node-modules\react-native-vector-icons\dist\glyphmaps」の下にMaterialIcons.jsonがあって、
中身を見ると、アイコン名らしき名前と番号がダーっと書かれてました。
その中から、「mic」と「chat」を選びました。
react-native-vendor-iconsのインストールは、いつもの通り、プロジェクトフォルダをカレントにして
npm install react-native-vector-icons --save
を実行しましす。
それで、「react-native run-android」を実行します。
すると、以下のような画面が出ました。

画面下部分に表示されているのがTabバーで、2つのメニューが表示されています。
起動時は、「音声認識&録音」側の機能が有効です。
各メニューをタップするとそれぞれの画面への切り替えが可能です。
ただし、アイコンは□に×のマークで、うまくアイコンが取り込めてないようです。
「rnpm link ・・・」もやれと書いてあるサイトがあった。
(↑注:iOS対応の場合であってrnpmです。npmではない。)
でも、「npm link ・・・」とやって、その後正常だったことは一度もない。
ちょっと躊躇してたのですが、やってみました。
(↓注:やってはいけません。)
npm link react-native-vector-icons
で結果は・・・
そろそろ組み合わせたものを作ろうかとも思ったのですが、その前に録音した音声を再生するところをやって見ようと思います。
さらにその前に、現状のApp.jsをちょっと変更したくなりました。
というのも、現状のソースは、
App.jsの下にChat.js(チャット制御)とSpeech.js(Google Speech to Text音声認識と録音制御)の2つのコンポーネントがぶら下がっている構成です。
----JSX:App.js-------------------------------------
:
import React, { Component } from 'react';
//import { SafeAreaView, View, Text, } from 'react-native';
import { Router, Scene, } from 'react-native-router-flux';
import Chat from './Chat';
import Speech from './Speech';
export default class App extends Component<{}> {
render() {
return (
<Router>
<Scene key='root'>
<Scene key='Text' component={Speech} title="Speech:Google音声認識" />
<Scene key='Chat' component={Chat} title="VTChat:チャットサンプル" />
</Scene>
</Router>
);
}
}
---------------------------------------------------
App.js内でreact-native-router-fluxを使って<Router><Scene key=’root><Scene ・・・/><Scene ・・・/></Scene>と2つ並べています。
2つの<Scene ・・・/>の切り替え方を知らないので、今のところ1番目の<Scene ・・・/>が動作を開始した後、切り替えは多分できないようになってます。
せっかくなので、音声認識(&録音)、新規:音声再生、チャットをそれぞれ切り替え可能にしたいと、ちょっと調べました。
◆<Tabs>を使って複数の機能をメニュー化する
「react-native-router-flux 切り替え」でぐぐって見ると、以下のサイトが引っ掛かりました。
参考:https://rara-world.com/react-native-tab-routing/
サンプルが載ってます。
しばらく、React Native JSXのコードから遠ざかっていたので、なんかサンプルコードに違和感が・・・
ともかく、react-native-router-fluxの<Tabs>というコンポーネントがあって、それを使って並べるようです。
結果の絵でもあれば、ちょっとイメージできていいんだろうけど、載ってません。
やってみた方が早いですね。
では、まずはコードです。
こんな風にしました。
----JSX:App.js-------------------------------------
/**
* Sample React Native App => Chat Sample
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, { Component } from 'react';
import { SafeAreaView, View, Text, StyleSheet } from 'react-native';
import { Router, Scene, Tabs } from 'react-native-router-flux';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Chat from './Chat';
import Speech from './Speech';
const TabBarIcon = (props) => {
return (
<View style={styles.tabIconContainerStyle}>
<Icon
name={props.iconName}
color={props.focused ? 'blue' : 'grey'}
style={styles.tabIconStyle}
/>
</View>
);
}
export default class App extends Component<{}> {
render() {
return (
<Router>
<Tabs key='root' swipeEnabled={true} animationEnabled={true}>
<Scene key='Text'
component={Speech}
title="Speech:音声認識&録音"
iconName='mic'
iconColor='red'
icon={TabBarIcon}
initial
/>
<Scene key='Chat'
component={Chat}
title="Chat:チャット"
iconName='chat'
iconColor='red'
icon={TabBarIcon}
/>
</Tabs>
</Router>
);
}
}
const styles = StyleSheet.create({
tabIconContainerStyle: {
justifyContent: 'center',
alignems: 'center',
},
tabIconStyle: {
width: 24,
height: 24,
fontSize: 24,
},
});
---------------------------------------------------
どんなiconを使うのかは、「iconName」パラメタで指定しているようです。
「import Icon from 'react-native-vector-icons/MaterialIcons';」というのも初めて見るの書き方。
参考:https://qiita.com/kana-t/items/3cad4fae393b6a5fc8a0
react-native-vendor-iconsをインストールした後で分かったのですが、
react-native-vector-iconsに含まれる、アイコンのセット(.json)をimportしていることになるみたいです。
「(プロジェクトフォルダ)\node-modules\react-native-vector-icons\dist\glyphmaps」の下にMaterialIcons.jsonがあって、
中身を見ると、アイコン名らしき名前と番号がダーっと書かれてました。
その中から、「mic」と「chat」を選びました。
react-native-vendor-iconsのインストールは、いつもの通り、プロジェクトフォルダをカレントにして
npm install react-native-vector-icons --save
を実行しましす。
それで、「react-native run-android」を実行します。
すると、以下のような画面が出ました。

画面下部分に表示されているのがTabバーで、2つのメニューが表示されています。
起動時は、「音声認識&録音」側の機能が有効です。
各メニューをタップするとそれぞれの画面への切り替えが可能です。
ただし、アイコンは□に×のマークで、うまくアイコンが取り込めてないようです。
「rnpm link ・・・」もやれと書いてあるサイトがあった。
(↑注:iOS対応の場合であってrnpmです。npmではない。)
でも、「npm link ・・・」とやって、その後正常だったことは一度もない。
ちょっと躊躇してたのですが、やってみました。
(↓注:やってはいけません。)
npm link react-native-vector-icons
で結果は・・・
スマフォのアプリを作りたい(20):音声認識と同時に録音③
プログラミング [2020/04/06]
前回の続きです。
録音込みの音声認識を作りました。
でも、なんだか録音処理を追加する前より認識率が悪くなったような気がします。
もぞもぞ話しても、ほとんど文字にしてくれません。
調子のいいときは、いいんだけど・・・。
録音してみて分かったのですが、PCのマイク入力を経由してAndroidエミュレータに渡ってくる音声の音質なんだかよくない。
ザラザラした感じの音で、プツプツした雑音も混ざってます。
それはそれで仕方ないことかもしれないけど、何とかならんのかな?
試しにサンプルレートを上げてみることにしました。
前回の記事に改造react-natove-google-speech-apiのAndroid向け修正ソースをまるっと乗せたので、コードの全容は前回記事をご参照ください。
◆サンプルレートを変えて見る
ベースの音声入力クラス(VoiceRecoder.java)でどうやってサンプルレートを決めているか見てみました。
以下のような配列が定義されています。
private static final int[] SAMPLE_RATE_CANDIDATES = new int[]{16000, 11025, 22050, 44100};
それで、初期化時に以下のような処理関数を動かしています。
つまり、SAMPLE_RATE_CANDIDATES配列にセットされているサンプルレート毎にAudioRecordクラスをnewしてみて、そのステートが正常であればループを抜けています。
サンプリングレートの値は低目の値から並んでいるので、一番最初の16000でステートがOKならば、その値で確定してしまいます。
なんで、16000が先頭なんだ?
サンプルレートって高い方が「いい音」なのでは?
と思ったので、配列の順番を高い数値順に変えてみました。
private static final int[] SAMPLE_RATE_CANDIDATES = new int[]{44100, 22050, 16000, 11025};
結果から言うと、44100が選択されるけど認識率は変わりませんでした。
サンプルレートは、「音質」というものに直結するわけではない?
Google Cloudの説明に解説がありました。
参考:https://cloud.google.com/speech-to-text/docs/enccoding?hl=ja
高くすると「周波数の高い音を再現できるようになる」ということだそうで。
人間の耳で聞こえる周波数~20,000Hzを再現するのに必要なのが40000Hz以上(44100Hz)なのだそうだ。
さらに、その下の「非圧縮音声」のところを見ると、人の声として拾うなら16000Hzが適していると書いてます。
だからSAMPLE_RATE_CANDIDATES配列の先頭に16000があったのね。
よって、配列の初期化値の変更は不採用です。
◆見つけた不具合
上記の変更を試している最中に不具合を一つ見つけました。
音声入力時のサンプルレートを録音クラス(VoiceEncoder.java)に渡す処理(start()メソッド)のコール位置がよろしくありませんでした。
GoogleSpeechApiModuleクラスのstart()メソッド中にあったのですが、onServiceConnected()コールバックのVoiceRecorderクラスのstart()メソッドのコール後に移動しました。修正版のコード(GoogleSpeechApiModule.java)を全部載せます。
気になる方は、続きをご覧ください。
録音込みの音声認識を作りました。
でも、なんだか録音処理を追加する前より認識率が悪くなったような気がします。
もぞもぞ話しても、ほとんど文字にしてくれません。
調子のいいときは、いいんだけど・・・。
録音してみて分かったのですが、PCのマイク入力を経由してAndroidエミュレータに渡ってくる音声の音質なんだかよくない。
ザラザラした感じの音で、プツプツした雑音も混ざってます。
それはそれで仕方ないことかもしれないけど、何とかならんのかな?
試しにサンプルレートを上げてみることにしました。
前回の記事に改造react-natove-google-speech-apiのAndroid向け修正ソースをまるっと乗せたので、コードの全容は前回記事をご参照ください。
◆サンプルレートを変えて見る
ベースの音声入力クラス(VoiceRecoder.java)でどうやってサンプルレートを決めているか見てみました。
以下のような配列が定義されています。
private static final int[] SAMPLE_RATE_CANDIDATES = new int[]{16000, 11025, 22050, 44100};
それで、初期化時に以下のような処理関数を動かしています。
----VoiceRecoder.java------------------------------
:
private AudioRecord createAudioRecord() {
for (int sampleRate : SAMPLE_RATE_CANDIDATES) {
final int sizeInBytes = AudioRecord.getMinBufferSize(
sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT
);
if (sizeInBytes == AudioRecord.ERROR_BAD_VALUE) {
//Log.d(TAG, "invalid samplrate="+sampleRate);
continue;
}
//Log.d(TAG, "valid samplrate="+sampleRate);
final AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC,
sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
sizeInBytes
);
if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
buffer = new byte[sizeInBytes];
return audioRecord;
} else {
audioRecord.release();
}
}
return null;
}
:
---------------------------------------------------
つまり、SAMPLE_RATE_CANDIDATES配列にセットされているサンプルレート毎にAudioRecordクラスをnewしてみて、そのステートが正常であればループを抜けています。
サンプリングレートの値は低目の値から並んでいるので、一番最初の16000でステートがOKならば、その値で確定してしまいます。
なんで、16000が先頭なんだ?
サンプルレートって高い方が「いい音」なのでは?
と思ったので、配列の順番を高い数値順に変えてみました。
private static final int[] SAMPLE_RATE_CANDIDATES = new int[]{44100, 22050, 16000, 11025};
結果から言うと、44100が選択されるけど認識率は変わりませんでした。
サンプルレートは、「音質」というものに直結するわけではない?
Google Cloudの説明に解説がありました。
参考:https://cloud.google.com/speech-to-text/docs/enccoding?hl=ja
高くすると「周波数の高い音を再現できるようになる」ということだそうで。
人間の耳で聞こえる周波数~20,000Hzを再現するのに必要なのが40000Hz以上(44100Hz)なのだそうだ。
さらに、その下の「非圧縮音声」のところを見ると、人の声として拾うなら16000Hzが適していると書いてます。
だからSAMPLE_RATE_CANDIDATES配列の先頭に16000があったのね。
よって、配列の初期化値の変更は不採用です。
◆見つけた不具合
上記の変更を試している最中に不具合を一つ見つけました。
音声入力時のサンプルレートを録音クラス(VoiceEncoder.java)に渡す処理(start()メソッド)のコール位置がよろしくありませんでした。
GoogleSpeechApiModuleクラスのstart()メソッド中にあったのですが、onServiceConnected()コールバックのVoiceRecorderクラスのstart()メソッドのコール後に移動しました。修正版のコード(GoogleSpeechApiModule.java)を全部載せます。
気になる方は、続きをご覧ください。