Todayee シリーズ第8弾「Todayee Voice」をリリースしました。音声認識を使ってエバーノートへテキストを投稿できるアプリです。
まずは動画デモをどうぞ。
上記動画の音量が小さめですが実際に話しかけた内容が変換されていって最後に音声コマンドで送信されている様子がわかると思います。
アプリの起動直後からすぐに音声認識が開始されます。
中央の円は1分間のカウントダウンタイマーになっています
(音声認識の上限が1分なため)。
話しかけると音声が次々にテキストに変換されて行きます。
(青い文字が認識途中で、黒文字は確定済)
テキストへの変換が終わったら送信ボタンを押すだけです。
後述する音声コマンドを使うとボタンを押さずに送信することもできます。
音声認識
iOS10 から提供された音声認識の API を使用していて、これは Siri でも使われている技術です。この音声認識は次のような特徴があります。
・オンラインのみ利用可能
・最長1分で終了
・一定時間無音だと終了
・認識途中に文脈に合わせて変化
・Appleがサービス提供中のみ利用可能
・利用可能な言語は60以上
言語設定は現在のものが使われますが、設定画面で他の言語に設定することも可能です。
音声コマンド
Todayee Voice では独自に音声コマンドというものを用意しています。音声認識の最後に特定のフレーズを言うことで、何らかのアクションを起こすことができます。このフレーズと仕組みを音声コマンドと呼んでいます。現在は「送信」「終了」「停止」がサポートされています。
「送信(そうしん)」... 音声認識を確定させ、テキストを送信します。
「終了(しゅうりょう)」「停止(ていし)」... 音声認識を確定して、テキスト編集状態になります。
※コマンドの文字列自体はテキストには含まれません。
音声コマンドとして認識されるとコマンドの文字列が緑色に光、ピピッと音がします。時々うまく認識されないことがあります。多くの場合はネットワークの一時的遅延(もしくはAppleの音声認識サービスの遅延)が原因だと思われます。外での移動中などネットワークが安定しない場合に多く発生する可能性があります。※この点はまだ改良の余地があります。
特殊文字入力
句読点なども変換することができます。
「かいぎょう」... ※改行が入る
「まる」... 句点(。)
「てん」... 読点(、)
「はてな」... ?
「かっこ」... (
「かっことじ」... )
「かぎかっこ」... 「
「かぎかっことじ」... 」
Todayee 共通機能
Todayee Voice は、Todayee(トゥデー) という名前の付く複数のアプリシリーズの1つです。一番の特徴は Todayeeシリーズからの投稿がすべて 毎日1つのノートへまとまる点です。Voiceから投稿したノートに、写真や音声を追記していくといったことができます。さらに複数のデバイスからの投稿も同様にまとめることができます(同一のエバーノートアカウントを使用した場合)。
下の図は Place と Pics からの投稿が1つのノートにまとまっている例です。
投稿は時刻で自動的にソートされます。
他の Todayeeアプリの記事
【アプリ】Todayee Text / Photo 1.0 をリリースしました
【アプリ】Todayee Silent 1.0 をリリースしました
【アプリ】Todayee Extension 1.0 をリリースしました(無料)
【アプリ】Todayee Place 1.0 をリリースしました(無料)
【アプリ】Todayee Pisc 1.0 をリリースしました
【アプリ】Todayee Rec 1.0 をリリースしました
開発メモ
音声認識 API がやってきた
iOS 10 から音声認識の API(SFSpeechRecognizer)が開発者に提供されるようになった。音声認識の機能自体は古くから存在したが、これまで開発者には公開されてこなかった。今年の WWDC の iOS10 発表で Siri の一部機能解放と共に音声認識 APIの発表があって、ついに一般のアプリに組み込めるチャンスがやってきた。このニュースを聞いた時から何かのアプリで音声入力インターフェイスを搭載したいと考えていた。
iOS 9 以前の Appleの音声認識技術はお世辞にも高いとは言えなかった。Siriに話しかけても誤変換が多くイライラした人も多かったと思う。その点ライバルの Googleの音声認識の方が数段優れていた印象があって、小さな声で不明瞭に話しかけてもかなりの精度で変換してくれてた。それでも iOS10 になってからようやく Appleでも音声認識技術に進歩が見られてきて、以前と比べると明らかに認識精度が良くなった。まだ誤変換は多いけれど前ほどではなくなっている。少なくとも適切な音量ではっきりと話しかければまずまずの高い精度でテキストに変換してくれるようになった(なんだこりゃ、ってのも未だにあるが...)。まだ物足りない点はあるものの今回のアプリのような私的なメモ用途では徐々に実用的なレベルになってきたと感じる。そんなこともあって Todayeeシリーズの一つとして今回開発することにしてみた。
SFSpeechRecognizer
サンプルコード(多くは元ネタがAppleのやつ)が出回っているので実装自体は難しくない。API自体もシンプル。音声入力のために AVAudioEngine を入れるところが慣れないとわかりづらいくらいか。コールバックの処理はクロージャは使わずデリゲート(SFSpeechRecognitionTaskDelegate)を使った。そのほうが細かい制御ができるため。
この API は現状だとデフォルトで認識途中の文字列を返してくれるが(shouldReportPartialResults=true)、この時点ではまだ確定してなくて、話しかけていくうちに文脈に合わせて刻々と結果の文字列が変わっていく。この間は SFTranscription.segments: [SFTranscriptionSegment] には十分な情報は入らない。ここに SFTranscriptionSegmentに substringや confidence などが入ってくるのは最後に確定した後(デリゲートだと speechRecognitionTask(task: didFinishSuccessfully:) 、クロージャでも同様の動き)。認識途中は話しかけた全内容が暫定的な文字列として渡ってくるだけ。
イメージ)こんな感じ
人間:「今日は」
暫定結果:「強は」
人間:「とても」
暫定結果:「今日はとても」
人間:「よい天気だった」
暫定結果:「今日はとてもよい」
暫定結果:「今日はとてもよい天気」
暫定結果:「今日はとてもよい天気だった」
確定:「今日はとてもよい天気だった」
確定:「今日はとてもよい天気だった」
開発者的には文節あるいは単語・句単位の情報が途中経過でも得られれば良いのだがそれはもらえない。毎回その時点での暫定の全文が渡される。
イメージ
人間:「今日は」
暫定結果:「京は」
人間:間違ってるじゃん。リテイク(仮)ボタンをポチして、再発音
人間:「今日は」
暫定結果:「京は今日は」
アプリ文字列:「今日は」(とりあえず開始のインデックスを +2としよう)
人間:「良い天気だ」暫定結果:「京は今日は良い天気だ」
アプリ文字列:「今日は良い天気だ」
確定:「今日は今日はとてもよい天気だった」 ← 認識結果を最後に変えてしまった
アプリ文字列:「は今日はとてもよい天気だった」 あれ?
というわけで、iOS11ではこのあたりの改良を希望。
音声コマンド
これも音声認識APIを応用する上でやってみたかったことの一つ。実装してみると意外に楽しくてついついこの為に使ってしまったことも。単純なんだけどプチ未来感が感じられる機能。
この音声コマンドの実装は、大げさな仕組みは無くて実現方法はいたって簡単。コマンド(単語:例えば「送信」)の前後の空白時間を測ることで認識している。
(前回の認識)<-- t1 --> 「送信」 <-- t2--->
前回認識から t1秒すぎて、「送信」が認識され、さらにその後に t2秒の空白があったら「送信」をコマンドとして認識する。今後 APIの利用が進むともっと良い方法が出てくると思う(期待)。
あとがき
Voiceを作ってからというもののエバーノートへの投稿が格段に増えた。何かあれば起動して音声でつぶやく。手入力から音声入力への転換は思った以上に投稿のスタイルを変えるかもしれない。
アプリの入手は下記からどうぞ。