iOS10のSpeech frameworkを使って画面タップしないWEBブラウジング

iOS10のSpeech frameworkを使って画面タップしないWEBブラウジング

前回の記事にてiOS10新機能の一つである『Speech framework』を少しだけ紹介させていただきました。
<参考>『iOS10新搭載のStickerPackでiMessage専用のスタンプを作ってみた

ただし、別の新機能である『Message Application』をメインにご紹介させていただいたので、今回は『Speech framework』に舵を切ってご紹介させていただきます。

『Speech framework』を使ってみた

早速ですが、『Speech framework』を使用した完成イメージをご紹介させていただきます。GIF画像にしているため分かりづらいとは思いますが、実際には音声のみで操作しているんです。

image05

『Speech framework』の実装ポイント

『Speech framework』を使ったサンプルについては、すでに色々なところで説明もされておりますし、Appleの公式サンプルコードがとても参考になるのでそちらをご参照ください。

なお、今回の重要なポイントは2つあります。

<ポイントその①>
音声内容とjsのコードを紐付けて、UIWebViewにてjsイベントを実行させる

<ポイントその②>
ボタンによる録音のON/OFFの切り替えではなく、jsイベント発火後に一度クリアし、再度録音を開始できるようにする

ポイントその①について

これはとても簡単な話です。

「しゃべった内容を受け取ったら、どんなjsをWebページに実行させるか?」を当てはめればいいだけですね。
今回は「下にスクロール」、「上にスクロール」、そして「止めて(スクロールをやめる)」の3つに限定しました。試しに列挙型(enum)にしてみました。

「case ○○ = “××”」の「××」部分がjavascriptで実装させたいコードになります。

「clear();」という関数を呼び出しておりますが、これはsetIntervalをキャンセルさせないと、上に下にスクロールしまくるので、事前にclear関数をwebViewDidFinishLoadでセットしております。

特にページのDOM構造に依存する関数ではありませんし、webViewDidStartLoadでセットしてもいいかもしれませんが、流れとしては以下のような感じになります。

マイクと音声認識の録音開始
⬇︎
WEB画面の読み込み開始(webViewDidStartLoad)
⬇︎
WEB画面の読み込み終了(webViewDidFinishLoad)
 ➡︎clear関数をページにセット
⬇︎
音声入力を元に文字が取得される
 ➡︎文字の内容に応じてWebでjsを実行する

さて、最後に肝心な「文字内容に応じてjsを実行する部分」ですが、以下のような関数を作ってみました。

今回の『Speech framework』はiOS10の新機能を謳っているだけに、非常に精度は高いとは思いますが、あえて苦言を呈するならば、少し助詞が判定しづらい印象を受けます。

例えば、「下へスクロール」➡︎「したいスクロール」という感じです。

そういったこともあり、今回は助詞の判定を考慮せず、「下」か「上」と「スクロール」という組み合わせだけで動かせるようにしました。
あくまでもブログ原稿用として簡単なif分にはしてしまいましたが、ちゃんと作るのであればDBなどで検索かけた方が良いかもしれませんね。

ポイントその②について

これは少しハマってしまいました。

公式リファレンスでは、音声の開始と停止をボタンのタップで行われています。
それは以下のような関数になります。

オーディオエンジン(AVAudioEngine)が動いていたらストップする。逆に動いていなかったらレコードを開始する。
このように一回停止をかけてあげないと、どんどん文字が増えていってしまうわけです。

 ○録音開始
  「下」
  ⬇︎
  「下に」
  ⬇︎
  「下にスクロール」
  ⬇︎
  「下にスクロール止めて」
  ⬇︎
  「下にスクロール止めて上に・・・(移行延々と続く)」

こちらはログ出力した画像です。

image01

機械側はどこで区切ればいいのかは分からないわけですから、任意のタイミングで止めなければいけません。

公式リファレンスの場合、ボタンによるON/OFF切り替えでクリアしているわけです。
でも、私は一切画面に触りたくない。手を動かしたくない(笑)。

ということで、私の場合はしゃべった内容のEvalTypeがNone以外の場合、jsを実行した後にクリア処理を走らせることにしました。

マイクと音声認識の録音開始
⬇︎
WEB画面の読み込み開始(webViewDidStartLoad)
⬇︎
WEB画面の読み込み終了(webViewDidFinishLoad)
 ➡︎clear関数をページにセット
⬇︎
音声入力を元に文字が取得される
 ➡︎文字の内容に応じてWebでjsを実行する
  ➡︎一旦リセットしてすぐに再録音開始

最初は以下のような感じで書いてみました。

しかし、このやり方ではうまくいかないようです。。。

beta版だからなのか分かりませんが、stackoverflowにも類似した悩みが掲載されていました。

今回は試行錯誤の結果、伝家の宝刀『遅延実行』で対応!
さすがは伝家の宝刀、カンペキに解決いたしました。

これを上記の「try! self.startRecording()」の箇所を「restartRecording()」に置き換えて再度実行して解決いたしました。
(この実装でも時折落ちることがあります。作り込む際にはご注意ください!)

どんな声でも操作できるのか?

この『Speech framework』ですが、前記のとおり助詞がたまに狂うとは言ったものの、その他は大変精度が良いです!

私の感覚値にはなりますが、ほぼ80%以上は正しく音声を聞き取っているような気がします。
気になるのは「私の声以外でも正しく認識されるのか?」ということ。

では、さっそく検証してみたいと思います。
今回はショーケース・ティービーで7色の声を持つと言われる男 a.k.a. しみっちにやってもらいます。

カルシ◯ァー編

「下にスクロール」と「止めて」は反応しました

グー◯ィー編

何も反応しませんでした。。。

どんな応用ができるのか!?

いい機能ですね~。

「こんな機能、一体誰が使うの?」と思われるかもしれませんが、自炊派の私は料理サイトなどを閲覧しながら調理する際に役立つのではと思いました。
手を汚さずに操作できるようになるのは、大変嬉しい限りです。

しかし、アプリを開いたら音声のみで操作できるようになるかもしれませんが、そもそもにしてアプリ起動はアイコンをタップしなければいけない……。
でも諦めるのはまだ早いです!

もう1つ、iOS10に実装された便利な新機能があるじゃないですか!

ニーズがあれば、いずれ「Hey Siri!から始めるWebブラウジングアプリ」にもチャレンジしてみたいと思います!

コメント