ブラウザで音声操作をする。（Speech Recognition API）

AppleのSiriやGoogleのOK Googleの様に音声コマンドで様々な機能を操作する事が可能になっています。「ブラウザでも似たようなこと出来ないかな」と以前より思っておりました。

そこでHTML5の音声認識API - [Speech Recognition API](https://developers.google.com/web/updates/2013/01/Voice-Driven-Web-Apps-Introduction-to-the-Web-Speech-API) を利用して、ブラウザの要素を音声で操作してみました。

APIのサポート状況は現在のところChromeとAndroid Chromeのみです。[caniuse.com - Speech Recognition API](http://caniuse.com/#feat=speech-recognition) 

## 音声認識の基本操作

W3Cのドキュメント - [Web Speech API Specification - W3C](https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#speechreco-section)にこの様なサンプルが書かれています。

```html:example.html

  <textarea id="textarea" rows=10 cols=80></textarea>
  <button id="button" onclick="toggleStartStop()"></button>

  <script type="text/javascript">
    var recognizing;
    var recognition = new SpeechRecognition();
    recognition.continuous = true;
    reset();
    recognition.onend = reset;

    recognition.onresult = function (event) {
      for (var i = resultIndex; i < event.results.length; ++i) {
        if (event.results.final) {
          textarea.value += event.results[i][0].transcript;
        }
      }
    }

    function reset() {
      recognizing = false;
      button.innerHTML = "Click to Speak";
    }

    function toggleStartStop() {
      if (recognizing) {
        recognition.stop();
        reset();
      } else {
        recognition.start();
        recognizing = true;
        button.innerHTML = "Click to Stop";
      }
    }
  </script>

```
`var rec = new SpeechRecognition();`によってマイクを通じた音声を自動的に認識してくれます。

ここでは書かれていませんが`rec.lang = "ja"`の指定をすることで日本語の音声認識も可能です。

音声は自動的に解析してくれるので `rec.onresult`　を発火点としてイベントを実行することが出来ます。

ここでは音声解析の一番正しいと思われる言葉を抽出してテキストエリアに表示させています。

## 音声認識を継続する

ボタンクリックをせずに音声操作を継続して行うのに悩んだのですが、これは上記のサンプルにあるように`rec.continuous = true;` の指定をすることで可能になります。

一旦`rec.start();`で音声認識を開始させると音声の録音を継続して行うので、音声入力を発火点として実行処理を継続して行うことが出来ます。

「...これ、キーワードを登録しておいて、条件分岐で一致したら実行。で良いんじゃないか？」

## 試してみました

```html:index.html
<!DOCTYPE html>
<head lang="ja-JP">
	<meta charset="utf-8">
	<title>HTML5 ボイスコントロール テスト</title>
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" type="text/css" />
    <link href="style.css" rel="stylesheet">
</head>
<body>
<h1 class="text-center h3"> Speech Recognition API 6</h1>
     <p  class="text-center">ボイスコントロールテスト</p>
<div id="content">
      <div id="box">
      </div>
</div>
<div class="text-center">
	<button id="startRecBtn" class="btn btn-default">マイク 開始</button>
	<button id="stopRecBtn" class="btn btn-default">マイク 停止</button>
</div>
<div id="text" class="text-center">
    「赤」「青」「黄色」「緑」<br>
    って話しかけてみてね。
</div>      
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
	<script src="main.js"></script>
</body>
</html>
```

```js:main.js
$(document).ready(function() {
    var rec = new webkitSpeechRecognition();
		rec.continuous = true;
		rec.interimResults = false;
		rec.lang = 'ja-JP';

		var userSaid = function(str, s) {
			return str.indexOf(s) > -1;
		}

		rec.onresult = function(e) {
			for (var i = e.resultIndex; i < e.results.length; ++i) {
	       		if (e.results[i].isFinal) {
		       			var str = e.results[i][0].transcript;
		       			console.log('Recognised: ' + str);
		       			if (userSaid(str, '赤')) {
		       				$('#box').css("background-color","red");
                }
		       				else if (userSaid(str, '青')) {
		       				$('#box').css("background-color","blue");
                }
		       				else if (userSaid(str, '黄色')) {
		       					$('#box').css("background-color","yellow");
		       				}
		       				else if (userSaid(str, '緑')) {
		       					$('#box').css("background-color","green");
											}

										}
									}
		       				}

    $("#startRecBtn").click(function() {
      rec.start();
    });
    $("#stopRecBtn").click(function() {
      rec.stop();
    });
});
```

```css:style.css
@import url(//fonts.googleapis.com/earlyaccess/notosansjapanese.css);

body {
  font-family: 'Noto Sans Japanese', serif;
	max-width:640px;
	margin: 0 auto;
}


#content{
   margin: 0 auto;
  width:300px;
  height: 200px;
  padding:20px;
  position: relative;
}

#box{
  position: absolute;
  top: 75px;
   right:125px;
  width:50px;
  height:50px;
  background-color:#ddd;
}

#text{
    margin-top:40px;
}
```

デモ：  [Speech Recognition API 6 ボイスコントロールテスト](http://jsdo.it/PonDad/cHbN)

音声入力による表示切替が上手くいきました。`console.log`をいれてあるので開発者ツールから自分の音声がどのように認識されたか確認することが出来ます。

## ついでに動画プレーヤーを操作する

JavaScriptで操作できるものであれば何でも音声操作できるだろうと思い、動画プレーヤーの音声操作を試してみたら上手くいきました。

デモ：  [Speech Recognition API 7 Voice Control Video](http://jsdo.it/PonDad/8k9X)

## まとめ

音声認識自体はAPIが自動的に行なってくれるので、実行処理をドキュメントに沿って記述すれば簡単に利用することが出来ます。

工夫次第であんなものも、こんなものも音声で操作出来るのではないかなと想像が膨らみます。ぜひお試し下さい。

## 参考にさせていただきました

[Using the Web Speech API to control a HTML5 video -  Ian Devlin](http://www.iandevlin.com/blog/2014/01/javascript/using-the-web-speech-api-to-control-a-html5-video)