FC2ブログ

スマフォのアプリを作りたい(17):音声認識させたい⑤

   プログラミング [2020/03/10]
えーと。
React Native環境で、クロスプラットフォームなアプリを作ろうとしています。
最初、チャットアプリの基本をやってみて、
前回までに、音声認識(音声→テキスト変換)を試作してみました。

作ったアプリはGoogle Cloudを利用するものです。
ただし、音声認識させてはみるものの、
(1)変換がスムーズに続かない。
(2)認識精度がいまいち。

これは、入力している音声データに問題があるのかも。

今回は、テスト環境/音の入力についてのさるの迷走ぶりを書きます。


◆動作確認環境/ヘッドセット(マイク)について
さるの開発(試験)環境は、Windows10タブレットPCで、Androidエミュレータ上でアプリを起動して動作を確認しています。

未だに、実際のスマフォでテストしたことはありません。
それはなぜか

・Androidスマフォ(SIMフリー)の中古版をアプリ開発前に勇んで買いました。
新品 未使用 ARROWS Me F-11D Precious Black docomo スマホ 白ロム 本体 送料無料【当社6ヶ月保証】【中古】
価格:5,980円・・・ただし、ポイント使ったので実際は2000円くらい。

が、このスマフォのAndroidのバージョンが4.0なのに対して、当初想定の開発環境(VisualStudio)が未サポートだった。
React Native(Android Studio)に開発環境を切り替えたが、Androidエミュレータのminimumバージョンが6.0だった。
ってことは、エミュレータで動作確認しても実機で動く可能性が低い。

一方、音声入力についてはもっと迷走した。
・内蔵のマイクは、ハズイ。
電車の中とか外で電話しちゃっている人とか、声が大きくなって、周りに丸聴こえのことが多いですよね。
何か、文章を入力するとか、メッセージをテキストにして伝えたい場合、スマフォ/PCに向かって大き目の声で一人ぶつぶつ言うのはちょっとねぇ。

・ヘッドセット(USB1.0)を既に持っていたのですが・・・
WindowsタプレットPCにUSB-TypeAの口が一個しかなく、その口を増設HDD(SSD)に使っちゃってるので塞がってます。
HUBを使えばいいんですけどね・・・。いずれ、外で手軽に使える感じではないですね。

・ともかく、線で繋がなくてもよくて小さいものを買いました。
無線カケトーク ブラック Bluetooth ヘッドセット 通話 片耳 高音質 耳掛け型 ワイヤレス マイク内蔵 スポーツ KAKETALK-BK
価格:1,080円

が、タブレットにBluetooth接続してみたら、ぶつぶつ話す声はほとんど入りませんでした。サウンドコントロールパネルでレベルメーターみたいなのがあるのですが、ほとんど拾ってないのが分かります。
20200310_1.jpg

買い物に失敗しましたが、まだ諦めが付きません。

続きを読む

スポンサーサイト





スマフォのアプリを作りたい(16):音声認識させたい④

   プログラミング [2020/03/07]
前回、react-native-google-speech-apiパッケージを使って、何やら日本語の音声認識動作ができるところまで確認しました。
ただし、続けて動作させているうちに、ハング状態になる問題があります。
それと、使用言語を日本語にはしてみましたが、パッケージ自体はあまり汎用的な作りになっていない感じです。
上記をもうちょっと改善したいなーなんてちょっと無謀かもしれませんが、やってみようかと・・・。

まずは、Exampleのコードが何をやってそうか予想するところからになります。

◆react-native-google-speech-apiのApp.jsの概要
react-native-google-speech-api\ExampleAppにあったApp.jsについてです。
さるが使っているプロジェクト内では、Speech.jsという名前のファイルにして、処理はSpeechクラスとして定義しています。
実際のコードの内容に関しては、前回の記事に丸っと載せたのでそちらをご参照ください。(根拠のない無責処理が含まれます。)

まずは、初期処理:componentDidMount()メソッドで、
・GoogleSpeechApi.setApiKey()メソッドで、Google Cloud Platformの「APIキー」を設定しています。
・EventEmitter.addListener()で、「onSpeechRecognized」と「onSpeechRecognizedError」と命名されているイベントに対してコールバック処理を定義しています。

実際の操作に関しては、render()メソッドで、
・「Start listening」と表示された(なぜか、キャプションとしてはすべて大文字で表示される。)ボタンをタップした場合、requestAudioPermission()メソッドがコールバックされるように指定しています。
・requestAudioPermission()メソッドでは、「async」※1と入っているため非同期実行なのかと思います。PermissionsAndroid.request()メソッドの実行完了を待って、自startListening()メソッドを呼び出しています。予想ですが、PermissionsAndroid.request()は、マイク入力の使用の許可申請を行うメソッドかと思います。
・startListening()メソッドでは、ボタンのキャプションを「I'm listening」に変更したのち、GoogleSpeechApi.start()メソッドを呼び出しています。予想ですが、この時点でマイク入力音声をGoogleCloud側に送り込み認識(テキスト変換)することを開始指示しているかと思います。

マイクの入力があった場合は、
・componentDidMount()メソッド内のEventEmitter.addListener()で指定した2つのfunctionが「onSpeechRecognized」と「onSpeechRecognizedError」の2種類のイベントに応じて実行されるものと思います。


いくつか分からないことがあります。

・startListening()した後で発生するイベントは、「onSpeechRecognized」と「onSpeechRecognizedError」だけ?
・もし、マイクから音が入ってこない場合は、永遠に待つ?タイムアウトはないのか?
・上記の「待ち」を強制的に終了させることはできないのか?
・同じく「待ち」状態のタイミングで、ボタンを再度タップした場合、requestAudioPermission()を再度実行してしまう。ガードしている節がない。大丈夫なのか?交通整理(待ち)とかキューインとかの能力がPermissionsAndroid.request()、あるいはGoogleSpeechApi.start()メソッド内にあるのか?

上記、辺りがハングする原因とその際のステート不明の原因ではないかと考えます。


-※1:ちょっと寄り道:asyncとawait-
いきなり、そんなこと言われても・・・JavaScriptド素人なので分かりません。
以下を読み始めました。
参考:https://qiita.com/soarflat/items/1a9613e023200bbebcb3
が、いきなり「Promise」を理解していることが前提で書いているみたいなので、(それすら知らないさるは)以下を読んでみました。
参考:https://qiita.com/toshihirock/items/e49b66f8685a8510bd76
※いずれもややこしい話をしていて、誤解があるといけないので、以下のさるな要約は信用しないで、ご自分で理解されることをお勧めします。

上記参考サイトのサンプルのコードの中にsetTimeout()という関数がよく出てきます。そこの理解からです。
「id = setTimeout(処理、実行タイミング);」と書くと、「実行タイミング」後に、「処理」を実行するという処理です。setTimeout()は、コールされた直後にid(タイマーのID)をリターンして次のステートメント(処理)を実行できるようになります。「実行タイミング」はmSec単位で指定します。例えば、「実行タイミング」が十分長く、直後に「clearTimeout(id);」とかやると、「処理」は実行されないでしょう。

new Promise((resolve, reject) => {処理});」とやると、Promise型(どこにも、Promiseがクラスだとか、Function型だとかの説明記述は見られませんでしたが、その方が理解しやすいかと思ってそう書きます。)「処理」=非同期実行される「処理」を定義/生成することを意味します。
function asyncFunc1(param) {return new Promise((resolve, reject) => {処理});}」とやれば、asyncFunc1は非同期で「処理」を実行する関数を定義したことになります。
「resolve」と「reject」はそれぞれ処理完了時のコールバック関数を2種類指定できるようになっていて、「resolve」は正常時、「reject」は異常時という約束になっているみたいです。「resolve」「reject」をどう使うのかは、「処理」の中身:Promise関数の作り手の自由になっています。
実行では、「asyncFunc1(param1).then(resolve関数、reject関数).catch(例外処理関数);」という記述の仕方になります。resolveでもrejectでもない結果の場合には、.catch()で指定された関数が実行されるということになります。reject関数指定は、省略される場合が多いみたい。「asyncFunc1(param1).then(・・・).catch(・・・);」は終わりを待たずに次のステートメントが実行されるものと思われます。「resolve関数」、「reject関数」指定を省略した場合、Promise関数内で使っていないのであれば何もしないと思いますが、使っていてコールバック条件が成立した場合は、例外が発生するかと思います。「catch.(例外処理関数)」が省略された場合は例外が発生しても何もしないということになります。※.finally()もES9でサポートされたそうです。蛇足でした。

さて、「async function asynFunc2() {・・・}」は、「function asyncFunc1(param) {return new Promise((resolve, reject) => {処理});}」と同じ働きのようです。一方、「const result2 = await asyncFunc2();」とやった場合には、asyncFunc2()の完了を待って、結果をresult2に入れるという意味になります。非同期じゃなくなります。ただし、「await」はasync関数の中でしか使えないという制限があります。んー、非同期関数内から非同期関数を呼ぶ場合に使うということですね。※ちなみに「asyncFunc2();」とやった場合、.then()とか.catch()を指定していないので、「非同期の結果如何による処理分けはしない」という場合ですね。



さらに、react-native-google-speech-apiパッケージ内のスクリプトを斜め読みします。

続きを読む



カレンダー
02 | 2020/03 | 04
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
プロフィール

さるもすなる

Author:さるもすなる
さるです。別HPサイト「さるもすなる」から侵食してきました。 山菜/きのこ、それとタイトルにしたPPバンド籠のことをメインに徒然に・・・・暇を持て余したさるの手仕事:男手芸のブログってことで。

最新記事
最新コメント
月別アーカイブ
カテゴリ
天気予報

-天気予報コム- -FC2-
本家のHPのトップ
山菜や茸の話です
PPバンドの籠作品と作り方です
投稿をお待ちしております



PVアクセスランキング にほんブログ村 にほんブログ村 ハンドメイドブログへ



マニュアルのお申し込み



検索フォーム
リンク
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

QRコード
QR