Japan Accessibility Conference digital information vol.2行ったことをきっかけにUDトークの存在を認識して、そういえば、AMP Conf 2019 - amp.dev でも UDトークみたいなのを使っていた気がします。
UD トークからブラウザ上での音声認識ついて調べ、TalAter/annyang: Speech recognition for your siteいうJavaScript ライブラリの存在を知って、試しにサンプル HTML を実装してみましたので、実施したことを記載します。


1. 目次

目次を記載します。



2. この記事で主に記載すること

Browser JavaScript 以外での 音声認識もありますが、調べ始めは、Browser JavaScript のスコープでの音声認識でした。
調べている途中で、Browser から<wbr>離れる<wbr>こと考え初めて、OS、デバイスもさらっと見てみたら底は広く深い気がしました。
汎用性を考えると、Webサイト上でのみ使える音声認識よりもOS機能や、スマートスピーカーのようなデバイスで、音声認識機能を実装していないサイト上でも使用できるのがメインストリームなのかなと思いますが、現状、あるタスクをこなすWebサイトがあるとすると、そのタスクをこなすVoice command を作るのは以下、2つの選択肢のどちらかな気がしました。

  1. Voice command ではなく、API first な実装に力を入れる。OS機能や、デバイスから Voice command をトリガーにAPIを使ってタスクを実行する。
  2. OS、デバイスの機能のサポートを受けつつもサイト上での込み入った動作は、Browser JavaScript を駆使した Voice command を実装する。

この記事では、1.ついては調べる過程で見つけた文書へのリンクを薄く記載しています。
また、Voice command が実現できるということは、音声認識はできているので、文字起こしについてのサンプルも作成してみたので、その説明を記載しています。


3. 音声認識APIで実現できていること、Webサービスについて

薄く調べてことについて記載します。


3.1. Webサイトでの音声認識のアーキテクチャについて

音声認識自体の技術、実装方法ではなく、以下にその技術が実装されているデバイス、PC上のアプリケーションを使って、Webサイトでの音声認識を実現するかという観点で考えると、以下のようなアーキテクチャがあると思う、もしくは既に実現されていると思いました。

3.1.1. Browser 拡張としての音声認識

Hands Free for Chromeいう Chrome plugin です。
小窓が立ち上がるのが、気持ち悪いですが英語による操作で、表示しているWebページのコントロールができます。
* ブラウザを音声操作しよう!(Chrome拡張「Hands Free for Chrome」を使った方法)
* Hands Free for Chrome - Chrome ウェブストア

3.1.2. スマートスピーカーによるブラウザ操作

Google Home や、 Amazon Alexa で、ブラウザ操作というか、ブラウザ操作をした結果のタスクをこなせるのかもしれません。
調べ他ところ以下のような記事が見つかりました。
* アレクサ居酒屋 * 話題沸騰のスマートスピーカーは店舗運営にも使えるのか? | POSレジの比較・購入なら「レジチョイス」 レジ選びで迷っている人に
* Alexaを利用して音声注文ができる居酒屋が登場。まずは実証実験からで体験したい人は予約が必要 - Engadget 日本版

記事を見ていると、ブラウザ操作というか、Web API を駆使してブラウザ操作した結果のタスクを、音声で実施できるようにした気がします。

3.1.3. PC、Mac の音声識別機能を使う

3.1.4. Web Speech API を使う

ブラウザ上で音声認識するには、Web Speech API - Web API | MDN使用できます。
SpeechRecognition (Asynchronous Speech Recognition; 非同期音声認識) が実装されているのは、PC の Chorome と、 Androidの Chrome のみで、 SpeechSynthesis (Text-to-Speech; 音声合成) が実装されているのは、IE以外のブラウザです。

音声認識については、Chrome のみが使える状況ですが、昔から使えるからかJavaScript のラッパーライブラリがそこそこありました。
以下、見つけたものを記載します。


3.2. Webサービス

音声認識をするWebサービスは、音声の認識APIを提供する側 (要素技術)と、音声認識した結果、ユーザーのタスクを解決するWebサービスを作っている側 (応用技術) に分かれると思いました。それぞれ記載します。

3.2.1. 音声認識API

音声認識APIの紹介記事がたくさんありましたので、それらのリンクを記載します。
* アプリケーションの音声操作を可能にする音声認識APIまとめ | NTT Communications Developer Portal
音声認識APIのまとめ記事でそれぞれリンクが記載されています。

3.2.2. ツール、アプリケーション


4. Voiceコマンドのサンプル、作成した文字起こしツール

4.1. Voiceコマンドのサンプル

文字起こしツールの作成で力尽きてしまったので、annyang のVoiceコマンドのサンプルページへのリンクを記載します。
ページ上で、登録された言葉をブラウザに向かって話すと、対応するJavaScript関数が実行されます。
annyang! Easily add speech recognition to your site

4.2. 文字起こしツール

annyang を使って、文字起こしを作成するツールを作ってみました。
少ししようしてみところ、Web Speech API の精度的に以下の条件の元であれば現状良い感じに使えるかと思います。
* 文字起こしツールの使用条件
* 1人の人間が話す状態。
* はっきりした言葉で少しゆっくり話す。

個人的に読書のログを残しているのですが、読みながら Markdown テキストに起こすのが割と面倒だったので、読書中にツールを起動して話かけてメモを取ろうかと思います。

  • PCのみ対応
    ツールのCSS調整すれば、モバイルでもうまく表示できそうですが、一旦PCのみでいいかなと表示の調整はしておりません。
    Chrome の開発者ツールでモバイル表示させてみたところ崩れていたので、実機でもうまく表示されないかなと思います。

  • Webアプリ
    Google Apps Script の Webアプリケーションとしてデプロイしました。
    EXPORT GOOGLE DOCUMENT で文字を起こした結果を、Google Document にエクスポートできます。
    Gooogle Document へのエクスポートには、Google アカウントでのログインが必要です。
    speech to text

  • Github repository
    作成したプログラムは、以下のrepository に あります。
    kemsakurai/gas-speechToText

  • 作成したプログラムの説明
    以下、作成したプログラムについて説明を記載します。

    • annyang デバッグログ出力について
      annyang.debug() デバッグログの出力が可能です。各コールバック、状態変更時にログを出力してくれるようになります。

          annyang.debug(true);
      

    • annyang 言語の変更
      以下で言語の変更が可能です。デフォルトは、en-US です。

          annyang.setLanguage('ja-JP');
      

    • annyang Callback
      annyang.addCallback で、イベント発生時の Callback 関数を登録できます。
      annyang/README.md at master · TalAter/annyang Callback イベントの一覧が記載されています。
      文字起こしには、result イベントを使用します。ここで、登録した Callback 関数に認識した文字列が設定されるので、その文字列をハンドリングします。

          annyang.addCallback('result', function(phrases) {
              if (isPhrasesReading(phrases)) {
                  noteContent += "、";   
              } else if (isPhrasesPunctuation(phrases)) {
                  noteContent += "。";           
              } else if (isLineBreak(phrases)) {
                  noteContent += "\r\n";           
              } else {
                  noteContent += phrases[0];
              }
              noteTextarea.val(noteContent);
              noteTextarea.focus();
              noteTextarea.setSelectionRange(noteTextarea.value.length, noteTextarea.value.length);
          });
          annyang.addCallback('start', function() {
              // Do Nothing...
          });
          annyang.addCallback('end', function() {
              // Do Nothing...    
          });                
          annyang.addCallback('error', function(event) {
              if(event.error == 'no-speech') {
              // Do Nothing...    
              };
          }); 
      

    • SpeechKITT について
      annyang作っている方が、TalAter/SpeechKITT: 🗣 A flexible GUI for Speech Recognitionいうライブラリも作っています。このライブラリは、Web Speech API と、annyang操作するUIを提供するライブラリです。
      作ったサンプルの左下に表示されるのが、このUIで、以下の実装で UIが使用できるようになります。

          // Tell KITT to use annyang
          SpeechKITT.annyang();
          // SpeechKITT.setToggleLabelText('録音する'); flat-concrete.css を使用する場合は、使われない。    
          SpeechKITT.setInstructionsText('録音中しています...'); // 録音時に表示するテキストを設定する。   
          // Define a stylesheet for KITT to use
          SpeechKITT.setStylesheet('//cdnjs.cloudflare.com/ajax/libs/SpeechKITT/1.0.0/themes/flat-concrete.css'); // テーマの設定    
          // Render KITT's interface
          SpeechKITT.vroom();    
      
      テーマはいくつかあり、以下がcdn配信されているテーマの一覧になります。
      SpeechKITT - cdnjs.com - The best FOSS CDN for web related libraries to speed up your websites!

    • 認識された言葉の調整
      <wbr>「まる」<wbr>「てん」<wbr>「改行」話した際に、「。」「、<wbr>」「\r\n」` に変換されるようにしたかったので、以下のような実装を Callback 処理に追加しました。

      function isLineBreak(phrases) {
          for (var i = 0; i < phrases.length; i++) {
          if("改行" == phrases[i]) {
              return true;
          }
          if("開業" == phrases[i]) {
              return true;
          }
          if("戒名" == phrases[i]) {
              return true;
          }
          if("MARU" == phrases[i]) {
              return true;
          }       
          }
          return false;
      }
      function isPhrasesPunctuation(phrases) {
          for (var i = 0; i < phrases.length; i++) {
          if("まる" == phrases[i]) {
              return true;
          }
          if("丸" == phrases[i]) {
              return true;
          }
          if("マル" == phrases[i]) {
              return true;
          }
          if("MARU" == phrases[i]) {
              return true;
          }       
          }
          return false;
      }
      function isPhrasesReading(phrases) {
          for (var i = 0; i < phrases.length; i++) {
          if("10" == phrases[i]) {
              return true;
          }
          if("天" == phrases[i]) {
              return true;
          }
          if("てん" == phrases[i]) {
              return true;
          }
          if("店" == phrases[i]) {
              return true;
          }       
          if("テン" == phrases[i]) {
              return true;
          }       
          }
          return false;
      }
      annyang.addCallback('result', function(phrases) {
          if (isPhrasesReading(phrases)) {
              noteContent += "、";   
          } else if (isPhrasesPunctuation(phrases)) {
              noteContent += "。";           
          } else if (isLineBreak(phrases)) {
              noteContent += "\r\n";           
          } else {
              noteContent += phrases[0];
          }
          noteTextarea.val(noteContent);
          noteTextarea.focus();
          noteTextarea.setSelectionRange(noteTextarea.value.length, noteTextarea.value.length);
      });    
      
      phrases には、5要素認識した文字列の候補が設定されます。何回か認識された結果の文字列を事前に記録しておき、候補の中にそれらが含まれれば、みなしで変換するようにしました。実装してから気がつきましたが、annyang を使用する場合はこのようなユースケースはタスクで登録してもいいかと思います。

4.3. サンプルを作ったり、調べたりして思ったこと

サンプルプログラムの作成、調べた結果思ったことを記載します。

  • Web Speech API の精度はPCのマイクを使う前提だとそれほど良くない。
    1人のみ、はっきると話す必要があります。外付けのマイクを使うなどするともっと良い感じになるのかもしれません。

  • Voiceコマンド使用時の注意点
    1つのことを上手くやるようなイメージで実装するのが上手く行きそうに思いました。
    画面の使用するコンテキストを絞り込んでおくとコマンドの名寄せがある程度できて認識率も高められるかと思います。


5. 参考

以下、調べている最中に読んだ記事になります。
* UDトークって? | UDトーク

以上です。
Voice command のサンプルも作ってみようと思ったのですが、力尽きてしまったのでそのうちチャレンジしてみようかと思います。

コメント