スマフォのアプリを作りたい(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下なので必要ないはず。
それでは、実装に入ります・・・
嬉し恥ずかしお百姓Season2(3):ふくたち祭り
園芸 [2020/04/15]
昨年の夏~秋口にかけて、新たに畑に戻したスペースに植えたハクサイ。
昨年中は、ハクサイの玉にならず、雪のシーズンに突入。
収穫はあきらめて、春の董立ち(花が咲くときに茎がニョキっと伸びる現象)に期待を掛けたヤツです。
雪が消えかかった辺りから見張ってました。
3月の下旬、雪が日陰にまだ残っているころ、見に行ったら、こんな感じでした。

冬の間に、全て朽ち果ててるかと思いきや、それなりに元気そうでした。

なにしろ、シシガミ様やうさちゃんたちの楽園なので、雪解けと同時に「食われちまうだろう」と思ってたのですが、それ程の被害もなく。(食った跡はありましたよ。)
そこからさらに1週間。

花芽が出始めました。
と言うか、もう採っても大丈夫なくらいでした。
さるの棲む地域では、これをふくたちと言って、春野菜として食します。

実家界隈の特産品として、絶賛売り出し中です。
馴染みはないかと思いますが、本当です。
この時は、スーパーの袋に満杯になるくらい収穫しました。
さらに、先週末。
昨年中は、ハクサイの玉にならず、雪のシーズンに突入。
収穫はあきらめて、春の董立ち(花が咲くときに茎がニョキっと伸びる現象)に期待を掛けたヤツです。
雪が消えかかった辺りから見張ってました。
3月の下旬、雪が日陰にまだ残っているころ、見に行ったら、こんな感じでした。

冬の間に、全て朽ち果ててるかと思いきや、それなりに元気そうでした。

なにしろ、シシガミ様やうさちゃんたちの楽園なので、雪解けと同時に「食われちまうだろう」と思ってたのですが、それ程の被害もなく。(食った跡はありましたよ。)
そこからさらに1週間。

花芽が出始めました。
と言うか、もう採っても大丈夫なくらいでした。
さるの棲む地域では、これをふくたちと言って、春野菜として食します。

実家界隈の特産品として、絶賛売り出し中です。
馴染みはないかと思いますが、本当です。
この時は、スーパーの袋に満杯になるくらい収穫しました。
さらに、先週末。
嬉し恥ずかしお百姓Season2(2):水汲み場を整備
園芸 [2020/04/14]
例年、雪が消えると、栗林や畑の柿の木の周辺の片付けをします。
冬の間に雪の重みで折れて散乱した木の枝、倒木などをできるだけ集めて置きます。
ほぼ、荒らしてあるのに何故やっているかと言うと、夏の間の草刈りのときに、
草刈り機が木の枝を食っちゃったり、刺さったりして、危ない&邪魔になるからです。
栗林は、こんな感じ。

カタクリの花が咲き始める前に済まそうと思ってたのですが、
ブルーベリーの地植えを優先させたので、結局咲き始めちゃってました。
上の写真の場所に結構な数でカタクリが咲きます。
写真はだいぶ前のものですが、こんな感じです。

柿畑の方もあらかた終わって、残り
この冬に倒れた大きなタラの木の解体をしているときに、
割としっかりした木だった(脆くない)ので・・・いいことを思いつきました。
冬の間に雪の重みで折れて散乱した木の枝、倒木などをできるだけ集めて置きます。
ほぼ、荒らしてあるのに何故やっているかと言うと、夏の間の草刈りのときに、
草刈り機が木の枝を食っちゃったり、刺さったりして、危ない&邪魔になるからです。
栗林は、こんな感じ。

カタクリの花が咲き始める前に済まそうと思ってたのですが、
ブルーベリーの地植えを優先させたので、結局咲き始めちゃってました。
上の写真の場所に結構な数でカタクリが咲きます。
写真はだいぶ前のものですが、こんな感じです。

柿畑の方もあらかた終わって、残り
この冬に倒れた大きなタラの木の解体をしているときに、
割としっかりした木だった(脆くない)ので・・・いいことを思いつきました。
嬉し恥ずかしお百姓Season2(1):ブルーベリーを地植え
園芸 [2020/04/13]
冬のあいだ、例年には考えられない程、雪が降らなかった。
実家内陸部の積雪は、ホンの一時期1mくらいはあったかと思うが、普段の半分。
お陰で、例年だと3回~4回の雪下ろしするのが、今回は1回しかしないで済んだ。
ともかく、いつもより雪解けが1か月くらい早い。
畑の雪も早めに無くなったので・・・
自宅裏に鉢植え/ポットで育ててたブルーベリーの苗を畑に移すことにした。
YouTube先生が、春先に地植えするのだと言ってたから。
でも、先生が地植えした苗よりだいぶ小さい。
挿し木して、2年近く経ってるけど、まだ早いのかな。
それでも、ポットのままだと、始終水やりを気にしないといけないので、とっとと巣立ってもらおうと。
1日目
ピートモスという土をホームセンターで買いました。
20L入りをとりあえず10個。行ったホームセンターでは数量が足らず、このときはこれだけ。
約5000円。
実家畑の荒らしたままの部分に、φ50cm×d60cm穴を34個掘りました。

これでこの日は終了。
実家内陸部の積雪は、ホンの一時期1mくらいはあったかと思うが、普段の半分。
お陰で、例年だと3回~4回の雪下ろしするのが、今回は1回しかしないで済んだ。
ともかく、いつもより雪解けが1か月くらい早い。
畑の雪も早めに無くなったので・・・
自宅裏に鉢植え/ポットで育ててたブルーベリーの苗を畑に移すことにした。
YouTube先生が、春先に地植えするのだと言ってたから。
でも、先生が地植えした苗よりだいぶ小さい。
挿し木して、2年近く経ってるけど、まだ早いのかな。
それでも、ポットのままだと、始終水やりを気にしないといけないので、とっとと巣立ってもらおうと。
1日目
ピートモスという土をホームセンターで買いました。
20L入りをとりあえず10個。行ったホームセンターでは数量が足らず、このときはこれだけ。
約5000円。
実家畑の荒らしたままの部分に、φ50cm×d60cm穴を34個掘りました。

これでこの日は終了。
育てたら食べよー(5):備蓄食料の消費
園芸 [2020/04/12]
雪が消えたので、農作業の話を書こうと思ったら、
ちょいちょい、撮り貯めてた写真が出てきたのでそっちを先に。
昨年秋にセコセコ保存加工したものを冬の間、食べてました。
その写真が何枚かあるので、載せます。
◆栗の甘露煮
あまり、美味しくないと評判の栗の甘露煮です。
瓶詰めにして冷蔵庫に入ってます。

お酒(ブランデーの水割り)のおつまみにしました。

確かに、美味そうに見えないね。
3個に1個くらいホクホクな感じのがあるけど・・・
残り2瓶あります。
1瓶は、冷凍してます。
もう1瓶は、「育てた白カボチャと一緒に煮てやろう」と思ってたのですが・・・
春になっちゃいました。
去年のカボチャはまだ家に転がってます。
いつ、やろうかなー。
◆唐辛子味噌
赤くならなかった鷹の爪を唐辛子味噌にしました。

「辛すぎる!」とこれまたと不評。
したがって、これもさるのみ消費。
でも、割と美味いのよ。
殆ど、朝に自分の朝ご飯のおかず。
A)そのまま、ご飯に載せる。
B)多めに載せて、お茶漬けにする。
C)納豆に入れて混ぜて。

たいていの場合、眠気が覚めます。
辛いのはそんなに得意ではないので、朝から汗ばみます。
あと、焼き鳥(塩)を買ってきたときに、付けて食べてみました。

グーです。
◆干し柿
去年より、取り入れるまでの期間が長くなりました。
単に、さぼってただけです。

今年も、親戚筋に、60個くらいは送ったかな。

お世辞でも、「甘かったよ。買うとけっこうするのよねー。」と言っていただけると嬉しいです。
これまた、家人は一切食べません。
残り、90個くらいありますが、全て冷凍庫行きになったようです。
さるたまーに、小腹がすいたときに2~3個食べるくらい。
去年の干し柿もアイスと一緒にあったりして。
最後に、またもや鷹の爪なのですが、昨日やっと処理しました・・・
ちょいちょい、撮り貯めてた写真が出てきたのでそっちを先に。
昨年秋にセコセコ保存加工したものを冬の間、食べてました。
その写真が何枚かあるので、載せます。
◆栗の甘露煮
あまり、美味しくないと評判の栗の甘露煮です。
瓶詰めにして冷蔵庫に入ってます。

お酒(ブランデーの水割り)のおつまみにしました。

確かに、美味そうに見えないね。
3個に1個くらいホクホクな感じのがあるけど・・・
残り2瓶あります。
1瓶は、冷凍してます。
もう1瓶は、「育てた白カボチャと一緒に煮てやろう」と思ってたのですが・・・
春になっちゃいました。
去年のカボチャはまだ家に転がってます。
いつ、やろうかなー。
◆唐辛子味噌
赤くならなかった鷹の爪を唐辛子味噌にしました。

「辛すぎる!」とこれまたと不評。
したがって、これもさるのみ消費。
でも、割と美味いのよ。
殆ど、朝に自分の朝ご飯のおかず。
A)そのまま、ご飯に載せる。
B)多めに載せて、お茶漬けにする。
C)納豆に入れて混ぜて。

たいていの場合、眠気が覚めます。
辛いのはそんなに得意ではないので、朝から汗ばみます。
あと、焼き鳥(塩)を買ってきたときに、付けて食べてみました。

グーです。
◆干し柿
去年より、取り入れるまでの期間が長くなりました。
単に、さぼってただけです。

今年も、親戚筋に、60個くらいは送ったかな。

お世辞でも、「甘かったよ。買うとけっこうするのよねー。」と言っていただけると嬉しいです。
これまた、家人は一切食べません。
残り、90個くらいありますが、全て冷凍庫行きになったようです。
さるたまーに、小腹がすいたときに2~3個食べるくらい。
去年の干し柿もアイスと一緒にあったりして。
最後に、またもや鷹の爪なのですが、昨日やっと処理しました・・・
スマフォのアプリを作りたい(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)を全部載せます。
気になる方は、続きをご覧ください。
スマフォのアプリを作りたい(19):音声認識と同時に録音②
プログラミング [2020/04/04]
前回の続きです。
「音声認識(react-google-speech-api)と同時にその音を録音させるには、ひとさまの作ったフレームワークを弄るしかない。」という結論に達しました。
しかし、ちょっとした修正ならまだしも、結構な作り込みになるのは予想つくので些か躊躇・・・というか、面倒臭くなってちょっとの間、現実逃避してました。
その後、シブシブ再開したが、Androidのことも、Javaについても全く無知なさるなので、やっぱりエライ時間が掛かりました。
録音処理の実装でトラブった話を纏まりなく以下に書きます。
初心者の方の・・・何かになるんでしょうか。
◆ああ、Javaだったのね
react-native-google-speech-api内にエンコード用の処理(ソースファイル/クラス)を追加する方針です。
ここで、上記のパッケージ内のコードが「.java」であることがジワジワ響いてきました。
JavaScriptすらド素人なのに、Javaは全く未経験です。
予備知識 0なのに弄っちゃってるなんて無謀でしたよね。
JSとJAVAの違いも知らないのに、「違う言語だ」という認識も薄いため、コードをどう書けばいいのか行き詰ることもしばしばでした。
元々のコードも理解できてないのに、それらの書き方を適当に真似してみるというやり方です。
まずは初期のころ、
・追加したエンコード・クラス内のメソッドに、意識せずに「static」指定してしまったり
・呼び出し元でクラスのインスタンス生成(new)の要/不要やタイミングとか分かってなかったり
イミフなビルドエラーが出まくりました。
ちょっと分かった気分になれたのは以下の解説のおかげ。
参考:https://java.keicode.com/lang/initialize-initialization-block.php
(他サイトは細かい説明も含まれていて耳からミソが垂れてきそうでした。)
※さる並みの方は上記のサイトを頭から読んでお勉強されることをお勧めします。
さる自身は・・・まあイズレね。
ちょっと知恵がついたことと言えば、
◆Context(ApplicationContext)の参照の仕方が分かりません
Androidの本家の説明では、「Context」とか「Application」とかのクラスが準備されていて、これらを使うと、アプリケーション毎に固有に割り当てられたリソースに関する情報を参照できるように書かれてありました。
アプリ毎にワークのディレクトリ(ストレージ上のフォルダ)も準備されているらしい。
それをエンコードしたファイルの出力先にしようとして、追加したエンコード処理クラスの中で「Application myapp = new Application();」とかやったのですが、どうも上手くいきません。
「myapp.getFilesDir()」でExceptionになります。「Contextがnull」だとメッセージが出ます。Applicationクラスの基底クラスがContextなのは分かるけど、myappはnullではないのは確認しました。
正体が掴めず、この件は挫折。
(呼び出しの元(JavaScript側)でファイル名パスを指定する方向に変更しました。
まだ、序の口です。ぼやきは続きます・・・
「音声認識(react-google-speech-api)と同時にその音を録音させるには、ひとさまの作ったフレームワークを弄るしかない。」という結論に達しました。
しかし、ちょっとした修正ならまだしも、結構な作り込みになるのは予想つくので些か躊躇・・・というか、面倒臭くなってちょっとの間、現実逃避してました。
その後、シブシブ再開したが、Androidのことも、Javaについても全く無知なさるなので、やっぱりエライ時間が掛かりました。
録音処理の実装でトラブった話を纏まりなく以下に書きます。
初心者の方の・・・何かになるんでしょうか。
◆ああ、Javaだったのね
react-native-google-speech-api内にエンコード用の処理(ソースファイル/クラス)を追加する方針です。
ここで、上記のパッケージ内のコードが「.java」であることがジワジワ響いてきました。
JavaScriptすらド素人なのに、Javaは全く未経験です。
予備知識 0なのに弄っちゃってるなんて無謀でしたよね。
JSとJAVAの違いも知らないのに、「違う言語だ」という認識も薄いため、コードをどう書けばいいのか行き詰ることもしばしばでした。
元々のコードも理解できてないのに、それらの書き方を適当に真似してみるというやり方です。
まずは初期のころ、
・追加したエンコード・クラス内のメソッドに、意識せずに「static」指定してしまったり
・呼び出し元でクラスのインスタンス生成(new)の要/不要やタイミングとか分かってなかったり
イミフなビルドエラーが出まくりました。
ちょっと分かった気分になれたのは以下の解説のおかげ。
参考:https://java.keicode.com/lang/initialize-initialization-block.php
(他サイトは細かい説明も含まれていて耳からミソが垂れてきそうでした。)
※さる並みの方は上記のサイトを頭から読んでお勉強されることをお勧めします。
さる自身は・・・まあイズレね。
ちょっと知恵がついたことと言えば、
- メンバ変数の初期化は、コンストラクタ(クラス名のメソッド)を書かなくてもできるらしい。
- 単にクラス内に変数を定義して、「・・・= xxx;」とかやっとけば、そのクラスのオブジェクト(インスタンス)が生成(new)されたときに初期化されるらしい。
- 固定値で初期化するのであれば、「static」と付ける。これを「クラス変数」とか呼ぶ。これに対して先の「new」時に初期化されるのを「インスタンス変数」と呼ぶ。
- 「static」を付けたメソッド/メンバは、「new」しなくても呼び出し/参照できる。クラス名.メソッド名()/クラス名.変数名 と記述して使う。
- 以上から察するに、コンストラクタ(クラス名と同じ名前のメソッド)を明示的に定義する意義は、
-基底クラスの初期化を引き継げる(super()する)ことや、
-メンバ変数をコンストラクタ「new クラス名(引数)」時に初期化内容を引数で制御できること
かと思う。 - でもイミフな現象がありました:
-例えば、「AruClass」という名前でクラスを定義して、
-参照側クラスのメンバ変数を「AruClass aruClass = new AruClass();」とやって、
-参照側クラス内のメソッドから「aruClass.xxxxx();」とやったら、
-エミュレータで実行しかけた時に「xxxxx()はstaticじゃねーよ!」的なエラーになった。
→クラス名とは頭1文字違う「aruClass」としてるんだけど・・・
「AruClass aruCla = new AruClass();・・・aruCla.xxxxx();」的な修正をしたら治まった。
◆Context(ApplicationContext)の参照の仕方が分かりません
Androidの本家の説明では、「Context」とか「Application」とかのクラスが準備されていて、これらを使うと、アプリケーション毎に固有に割り当てられたリソースに関する情報を参照できるように書かれてありました。
アプリ毎にワークのディレクトリ(ストレージ上のフォルダ)も準備されているらしい。
それをエンコードしたファイルの出力先にしようとして、追加したエンコード処理クラスの中で「Application myapp = new Application();」とかやったのですが、どうも上手くいきません。
「myapp.getFilesDir()」でExceptionになります。「Contextがnull」だとメッセージが出ます。Applicationクラスの基底クラスがContextなのは分かるけど、myappはnullではないのは確認しました。
正体が掴めず、この件は挫折。
(呼び出しの元(JavaScript側)でファイル名パスを指定する方向に変更しました。
まだ、序の口です。ぼやきは続きます・・・
スマフォのアプリを作りたい(18):音声認識と同時に録音
プログラミング [2020/04/02]
だいぶ間が空いちゃいましたが、ハマりまくってたためです。
ここ数か月掛けてもなお、思ってたような成果が出せてません。
さるだから、仕方ない。
春っぽくなって、野外の活動を始めたので、こっちに割ける時間が減ったのもある。
巷は新型コロナで大変な状況のようですが、そろそろ圏内でも染った話が頻繁になってきた。
ヤバイかな。さるもリスクの高い年齢だし、タバコ吸いまくってるし、染りたくないなぁ。
ともかく、「スマフォのアプリを作りたい」続けます。
音声認識させてみたんだけど、結局、100%の音声認識(テキスト化)は不可能なのは、凡そ見当がついてました。
どうも、話す内容がちゃんとした「文章」になってないとあまり正確な認識はしないらしい。
頭の中で「文章」を組み立ててから話始める人なんかそうそういない。
それに、話す側の発音(訛り)の問題とか、周囲の雑音が思いのほか影響するみたいです。
一度、空調送風音の大き目の場所でタブレットの内蔵マイクで試してみたら、ほとんどまともに変換してくれませんでした。
そんな場合、認識させた音声そのものを録音しておいたら、相手、あるいは本人が聴いたときは、判別できるんではないだろうか。
この分野は、未だ人間様の言語認識能力の方が高いはず。
というわけで、
音声認識はさせておくんだけど、同時に録音(ファイル化)がしたいってことです。
◆フレームワークに何を使うか
ちょっと、React Nativeの事例をみると、録音(ファイル化)してみたという記事はたくさん見つかる。
素直に、そのパッケージを使ってやればいいのかな。
でも、react-native-google-speech-apiのコードを見てた時、音声データが定期的に送られてくる箇所があった。
そのデータをGoogle Cloudに送り込んでるんだけど、それと同時にファイルに突っ込めないのだろうか。
効率よさそう。
とは、思ったものの・・・・
そういうレベルで制御しているサンプルは見つけられず、
react-native-google-speech-apiパッケージ内で使っていた「MediaRecorder」というAndroidのマルチメディアフレームワークの使い方を検索してみました。
参考:https://developer.android.com/guide/topics/media/mediarecorder?hl=ja
録音にも使えそうです。
でも、
・バッファによる入力部とファイル保存部のデータ受け渡しの処理は見られません。
・Android固有の処理ということになります。iOSのときには、同等の別の処理が必要ということになります。
(なので、置き場所や「切り替え方」も意識しないといけなくなります。)
※そういえば。導入してみたreact-native-google-speech-apiの仕様が気に入らなくて修正しちゃいました(前々回の記事)が、iOS側もいずれ何とかしないといけないんですね。
ちょっと悩んだけど、面倒だなと思って、結局react-native-audioを使うサンプルをマネしてみることに。
参考:https://blog.leko.jp/post/rn-audio-record/
◆react-native-audioのインストール
1)「npm install react-native-audio --save」
react-native-google-speech-apiで四苦八苦したことが記憶に新しいので、少し不安もありましたが、やってみました。
余計なnpmの宣伝も出たけど、成功した模様。
2)「react-native link react-native-audio」(不要かも)
参考サイトではやるとあるのですが、
さるの環境ではやらなくてよかったコマンドのようです。
とりあえず、「react-native link・・・」すると以下のメッセージ。
これも何事もなく終わってくれるんですが、「react-native run-android」したら、
てなエラーになります。
なので、結局「react-native unlink・・・」しました。
3)「android/app/src/main/AndroidManifest.xml」修正
これもまた、さる環境ではreact-native-google-speeck-apiのときにやってたので済み。
◆録音処理の味見
先に挙げたサイトの説明を参考に実装してみました。
ところが、以下の実装(一部抜粋)だとthis.record()=>AudioRecorder.startRecording()でExceptionが発生しました。
そこで、録音関連の処理とstartListening()と順番を変えてみたところ、Exceptionは発生しなくなった。
録音はされたようだけど、音声認識はされません。
録音された音声ファイルは、以下のコマンドで取り出せました。
参考:https://qiita.com/t2low/items/cb37cec5f864c4748e14
※ソース上で、「AudioUtils.DocumentDirectoryPath」とされているのが「/data/user/0/com.vtchat/files」になっているのをデバッガで確認。
取り出したファイルを再生しても見ました。音質は良くありませんでしたが、確かにしゃべったことが録音されてました。
GoogleSpeechApiのlogcat(Log.i())メッセージによると、どうも音声データがGoogleSpeechApi側に渡ってこなくなっているみたいです。
さもありなんな現象です。
単にマイク入力をファイル化するだけなら、最初の方で上げた参考サイト(https://blog.leko.jp/post/rn-audio-record/)のやり方でOKということです。
でも今回、そうではないので、もう一回調べ直し・・・・
ここ数か月掛けてもなお、思ってたような成果が出せてません。
さるだから、仕方ない。
春っぽくなって、野外の活動を始めたので、こっちに割ける時間が減ったのもある。
巷は新型コロナで大変な状況のようですが、そろそろ圏内でも染った話が頻繁になってきた。
ヤバイかな。さるもリスクの高い年齢だし、タバコ吸いまくってるし、染りたくないなぁ。
ともかく、「スマフォのアプリを作りたい」続けます。
音声認識させてみたんだけど、結局、100%の音声認識(テキスト化)は不可能なのは、凡そ見当がついてました。
どうも、話す内容がちゃんとした「文章」になってないとあまり正確な認識はしないらしい。
頭の中で「文章」を組み立ててから話始める人なんかそうそういない。
それに、話す側の発音(訛り)の問題とか、周囲の雑音が思いのほか影響するみたいです。
一度、空調送風音の大き目の場所でタブレットの内蔵マイクで試してみたら、ほとんどまともに変換してくれませんでした。
そんな場合、認識させた音声そのものを録音しておいたら、相手、あるいは本人が聴いたときは、判別できるんではないだろうか。
この分野は、未だ人間様の言語認識能力の方が高いはず。
というわけで、
音声認識はさせておくんだけど、同時に録音(ファイル化)がしたいってことです。
◆フレームワークに何を使うか
ちょっと、React Nativeの事例をみると、録音(ファイル化)してみたという記事はたくさん見つかる。
素直に、そのパッケージを使ってやればいいのかな。
でも、react-native-google-speech-apiのコードを見てた時、音声データが定期的に送られてくる箇所があった。
そのデータをGoogle Cloudに送り込んでるんだけど、それと同時にファイルに突っ込めないのだろうか。
効率よさそう。
とは、思ったものの・・・・
そういうレベルで制御しているサンプルは見つけられず、
react-native-google-speech-apiパッケージ内で使っていた「MediaRecorder」というAndroidのマルチメディアフレームワークの使い方を検索してみました。
参考:https://developer.android.com/guide/topics/media/mediarecorder?hl=ja
録音にも使えそうです。
でも、
・バッファによる入力部とファイル保存部のデータ受け渡しの処理は見られません。
・Android固有の処理ということになります。iOSのときには、同等の別の処理が必要ということになります。
(なので、置き場所や「切り替え方」も意識しないといけなくなります。)
※そういえば。導入してみたreact-native-google-speech-apiの仕様が気に入らなくて修正しちゃいました(前々回の記事)が、iOS側もいずれ何とかしないといけないんですね。
ちょっと悩んだけど、面倒だなと思って、結局react-native-audioを使うサンプルをマネしてみることに。
参考:https://blog.leko.jp/post/rn-audio-record/
◆react-native-audioのインストール
1)「npm install react-native-audio --save」
react-native-google-speech-apiで四苦八苦したことが記憶に新しいので、少し不安もありましたが、やってみました。
----コマンドプロンプト-----------------------------
C:\WINDOWS\system32>cd /d d:\appmake\proj\vtchat
d:\AppMake\proj\VTChat>npm install react-native-audio --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-audio@4.3.0
added 1 package from 1 contributor and audited 957442 packages in 67.884s
21 packages are looking for funding
run `npm fund` for details
found 19 vulnerabilities (4 low, 15 moderate)
run `npm audit fix` to fix them, or `npm audit` for details
・────────────────────────────────・
│ │
│ New minor version of npm available! 6.12.1 -> 6.14.2 │
│ Changelog: https://github.com/npm/cli/releases/tag/v6.14.2 │
│ Run npm install -g npm to update! │
│ │
・────────────────────────────────・
---------------------------------------------------
余計なnpmの宣伝も出たけど、成功した模様。
2)「react-native link react-native-audio」(不要かも)
参考サイトではやるとあるのですが、
さるの環境ではやらなくてよかったコマンドのようです。
とりあえず、「react-native link・・・」すると以下のメッセージ。
----コマンドプロンプト-----------------------------
d:\AppMake\proj\VTChat>react-native link react-native-audio
info Linking "react-native-audio" iOS dependency
info iOS module "react-native-audio" has been successfully linked
info Linking "react-native-audio" Android dependency
info Android module "react-native-audio" has been successfully linked
---------------------------------------------------
これも何事もなく終わってくれるんですが、「react-native run-android」したら、
----コマンドプロンプト-----------------------------
:
error React Native CLI uses autolinking for native dependencies, but the following modules are linked manually:
- react-native-audio (to unlink run: "react-native unlink react-native-audio")
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.
Read more about autolinking: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md
:
---------------------------------------------------
てなエラーになります。
なので、結局「react-native unlink・・・」しました。
----コマンドプロンプト-----------------------------
d:\AppMake\proj\VTChat>react-native unlink react-native-audio
info Unlinking "react-native-audio" iOS dependency
info iOS module "react-native-audio" has been successfully unlinked
info Unlinking "react-native-audio" Android dependency
info Android module "react-native-audio" has been successfully unlinked
---------------------------------------------------
3)「android/app/src/main/AndroidManifest.xml」修正
これもまた、さる環境ではreact-native-google-speeck-apiのときにやってたので済み。
◆録音処理の味見
先に挙げたサイトの説明を参考に実装してみました。
ところが、以下の実装(一部抜粋)だとthis.record()=>AudioRecorder.startRecording()でExceptionが発生しました。
----Speech.js--------------------------------------
:
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
{
title: 'Record Audio Permission',
message:
'App needs access to your microphone ' +
'so you can convert speech to text.',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('permission granted');
this.startListening();
await this.setUp();
await this.record();
} else {
console.log('permission denied');
}
:
---------------------------------------------------
そこで、録音関連の処理とstartListening()と順番を変えてみたところ、Exceptionは発生しなくなった。
----Speech.js--------------------------------------
:
:
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('permission granted');
await this.setUp();
await this.record();
this.startListening();
} else {
console.log('permission denied');
}
:
---------------------------------------------------
録音はされたようだけど、音声認識はされません。
録音された音声ファイルは、以下のコマンドで取り出せました。
----コマンドプロンプト-----------------------------
d:\AppMake\Android\Sdk\platform-tools>adb pull /data/user/0/com.vtchat/filesvoice.aac C:\temp\
/data/user/0/com.vtchat/filesvoice.aac: 1 file pulled. 3.1 MB/s (187558 bytes in 0.057s)
---------------------------------------------------
参考:https://qiita.com/t2low/items/cb37cec5f864c4748e14
※ソース上で、「AudioUtils.DocumentDirectoryPath」とされているのが「/data/user/0/com.vtchat/files」になっているのをデバッガで確認。
取り出したファイルを再生しても見ました。音質は良くありませんでしたが、確かにしゃべったことが録音されてました。
GoogleSpeechApiのlogcat(Log.i())メッセージによると、どうも音声データがGoogleSpeechApi側に渡ってこなくなっているみたいです。
さもありなんな現象です。
単にマイク入力をファイル化するだけなら、最初の方で上げた参考サイト(https://blog.leko.jp/post/rn-audio-record/)のやり方でOKということです。
でも今回、そうではないので、もう一回調べ直し・・・・