BLOG記事

ブログ記事

では、日本語音声認識の続きです。このような記事を書くのは実は自分のためなんですよね。大体理解が中途半端なのですが、書き留めることでちょっと考えをまとめることにもなります。初心者がつまずいたりわからないなあーとおもうことをわからないなりにも動くプログラムは(アプリとしてAppleStoreで公開することは)できたわけですから、この程度のなんちゃってでもこの程度は可能という例を笑ってくださいませ。

多分、アプリの勉強を初めて学習しだすと簡単なプログラムを組んでもエラーとバグがでて、どうしても自力で解決できないことがあると思います(私はそうでした)。また、例えコードを写経しても何故か動かないこともあると思います(Xcodeのバージョンが違うとコードは動かないことがある)。

そんな時は、解決できなくとも話し相手がいると精神的にいいですね!私は大瀧さんに愚痴っていました。また、手っ取り早くこの挫折経験を解決するのはスクールでしょうかね!(どこがいいのかは私にはわかりません)。

私の解決策はこのブログの第一回で紹介した様に、「Apple Technical Support」の利用でした。すごい初歩的なことでも質問しました。

教科書はSwiftのベストセラーの「絶対に挫折しないiPhoneアプリ開発「超」入門」を使用しました。

私がプログラミングをして何とかAppleの審査を通して有料アプリを公開できる様になったことの一つの理由として思うのは、私が「bFaaaP」というピアノ補助ペダル装置をどうしても開発したかったからという「作りたい物がまずあった」というモーチベーションだと思います。

何でもそうだと思いますが、「勉強しました」「資格を取りました」、では「何をすればいいのでしょう(お金を稼げるのでしょう)」というサイクルになると辛いですね。

歳を取ると雑談(親父ギャグ)が増えますが、コードを見ていきましょう。

このSpeechAnalyzer1では、「SpeechAnalyzer」というclassのオブジェクトのインスタンスをSwiftUIのViewから制御する必要があります。このclassのオブジェクトの中での情報(日本語の会話textや選別したWords)を逐次SwiftUIのviewからアクセスするためにどうしたらよいかを説明します。このやり方は任意のclassオブジェクト(自作のもの等)の制御に応用できますよ。

まず、SwiftUIのviewの定義の部分に「@ObservedObject」として、今回の場合SpeechAnalayzerのインスタンスを作成します。

そして、CombineをimportしてSpeechAnalyzerのClassにObserbableObjectのプロトコルを採用します(これで、SwiftUIViewでObservedObjectとしてインスタンスを作成できる)。そして、SwiftUIViewからアクセスしたい変数(日本語会話のtext,選抜した[selectedWords])を@Publishedでラップします(この言い方で合ってますかね?)。

文言(String)の多言語化する際には、NSLocalizedString(” “, comment: ” “)としますが、最新のものでは必要がないようですね(?)。

では、日本語会話解析のコードの概略を説明します。まずは、音声認識を使える様に許可を出してもらう必要があるので、Viewが表示されて一番初めに実行されるonAppear{}にpermissionを得るコードを書きます。

「タップして話してね」ボタンと録音状態は「self.speechAnalyzer.recordingControl」というclass内に宣言した@Publishedのflagでコントロールしています。そして、録音操作の実行はmicButtonTapped()のメソッドで実行します。

このメソッド中では、audioEngineが動いているならば(録音中)、停止動作をして、recordingControlをfalseにします。

当初は一度は録音できたのですが、2度目ができないバグがありました。これを解決したのは、真ん中の赤枠の部分でaudioをplaysessionにもう一度初期化する必要があることでした。(何とかバグが取れた)

その他の場合に録音を開始開始してrecordingControlをtrueにしてボタンの表示も変えます。

次にrecordingを処理を開始します。localeを”ja-JP”にすると日本語の解析ができます。その後、通常の初期設定で動くはずでしたが、textが””の場合に次のレコーディングでエラーが出るバグがありました。これを解決したのが赤枠の部分の「inputNode.removeTap(onBus: 0)」でした。

次にrecognitionTaskを実行開始します。この際にも当初エラーがでました。赤枠で書いてある様にCode=209エラーがでました。これを解決したのが、recognitionTask?.cancel()とfinish()を両方記載することでした。なぜエラーを回避できたのかはわかりません。

そして、コードは下の方に飛びます(音声認識の結果がある場合の処理の後)。ここでaudioEngine等をスタートさせます。

そして音声認識が終わりisFinalフラグが立った場合に、textを[words]にするためにtagger を動作させます。赤枠の部分でtextが””でない場合にtaggerに導入します。この際にtaggerの最後のoptionsの部分で句読点やスペースを入れないなどの基本設定をします。この部分は宣言の部分に定義しています。

そして、[words]から平仮名1文字と2文字を除外して[selectedWords]を選別します。そのアルゴリズムは赤枠の部分です。そして、実際のヘルパーKアプリでは[selectedWords]を準備したら、下の赤枠のscoringとメニューデータのソーテイング、その後、キーワードの割当処理と進んでいきます。

これで、@Publishedとした変数text(日本語会話のスクリプト)と選別したselectedWordsがclass内で作成されました。この値はSwiftUIのViewで@Stateでラップした変数同様に逐次アップデートされて表示されることになります。

以上がSpeechAnalyzerクラスの概要です。この続きは英語とドイツ語の会話をどうするかという多言語化の部分をみていきたいと思います。

次回はちょっと脱線して、このアプリでSwiftUI Viewで使っているSF Symbolsやアニメーション、それと、リストの背景の設定について少しコーヒーブレークしてみようかなと思います。

関連記事一覧