AI連携FW『シンプルエーアイ』を使ってみた(2)：AIっぽい事をさせてみたい(その2)

#はじめに

**2018/05/11**
**指定した命令をAIに実行して貰う事ができるようになる「スマートエージェント」機能への音声キー追加に関して、説明を修正・追記しました。**

AI連携フレームワーク『シンプルエーアイ』を使って遊ぶ、第2回目(その2)です。
・[(1)準備編](https://qiita.com/denaripam/items/0c128c50788d9553f88e)
・[(2)：AIっぽい事をさせてみたい(その1)](https://qiita.com/denaripam/items/1aede5526136729ea0c5)

**公式サイトはこちら：[https://smartaifw.com/simpleai-trial/](https://smartaifw.com/simpleai-trial/)**


#AIとお喋りしたい
前回の『[(2)：AIっぽい事をさせてみたい(その1)](https://qiita.com/denaripam/items/1aede5526136729ea0c5)』では、カメラを起動して画像分析を行いました。
サンプルプログラムのコードは、HTML含めて約50行です。短い！書いてみてびっくりしました。

それでは、次のステップへ進みましょう。
画像の次は音声という事で、今回はAIとお喋りできるようにしたいと思います。


#やりたい事

* 音声認識を行い、AIとお喋りできるようにする。
* 「人物判断」ボタンの動作を、音声で行えるようにする。


#音声認識を行い、AIとお喋りできるようにする。

それでは、本記事で想定しているサンプルプログラムの動作を説明します。
前回の『[(2)：AIっぽい事をさせてみたい(その1)](https://qiita.com/denaripam/items/1aede5526136729ea0c5)』では、画面を開くとカメラが起動し、画面に表示されるようにしました。
この起動時処理の部分にマイクの初期化処理を追加し、カメラとマイクを同時に利用可能にします。

追加部分のソースは以下の通りです。

```js
			initMicrophone:true,
			VoiceRecognition:{listen:true},
```

追加部分を含めた初期化処理は、以下のようになります。

```js
//起動時処理
window.onload = function () {
	var SimpleAI = new denaripamSimpleAI(
		this,
		{},
		{
			initCamera:true,
			initMicrophone:true,
			VoiceRecognition:{listen:true},
		},
	);
```

初期化だけならJavaScriptの追加だけでOKですが、マイクが正しく動作しているかが分かり辛いので、HTMLでサウンドビジュアライザー（音声を波形で表示する部品）を表示するよう、追加します。

```html
<canvas id="denaripamControlSensor_soundvisualizer" width="800px" height="60px"></canvas><br>
```


#『シンプルエーアイ』の機能：スマートエージェントについて

これで音声認識が出来るようになりました。
しかしこの時点では、マイクに話しかけても、AIは反応してくれません。

ここで必要になるのが、『シンプルエーアイ』の機能である「スマートエージェント」。
特定の言葉にAIが反応し、命令を実行してくれる機能です。
この機能を使えば、昨今あちこちで見かけるスマートスピーカーのような事を、自分のパソコンで出来てしまいます。

それでは、サンプルプログラムにスマートエージェントの機能を追加していきましょう。
追加する場所は、マイク初期化と同じく起動時処理のところです。
先程マイクの初期化を行った、その後に入れましょう。（サンプルプログラムでは、ＡＰＩキー設定の後に行っています。）

追加部分のソースは以下の通りです。

```js
	if(SimpleAI) {
		//スマートエージェント開始
		SimpleAI.SmartAgent();
	}
```
　


**//-----2018/05/11修正・追記ここから-----//**
# 「人物判断」ボタンの動作を、音声で行えるようにする。

スマートエージェントを有効にした事により、AIが反応してくれるようになりました。
続けて、AIに人物判断をお願いできるようにします。
AIに言葉でお願いするために「音声キー」を追加しましょう。（ソースでは「スマートエージェントコマンド」と記しています。）
スマートエージェントの開始後に、処理を行って下さい。

追加部分のソースは以下の通りです。

```js
		//人物判断（スマートエージェントコマンド追加サンプル）
		var cmd;
		cmd=SimpleAI.getSmartAgentCommand();
		cmd.MainCommand.push(
			{
				//人物判断
				label: "PersonalJudgment",
				labelname: "人物判断",			//ラベル名称、現在のモード読み上げ等に使用
				word:[/人物/,/判断/],
				message:"人物判断を行います",
				messageafter:function(sender,event,param) {
					SimpleAI.Personinformation();
				},
			},
		);
```


###命令文の追加は、まずこれを書こう

『シンプルエーアイ』独自の機能に関する部分ですので、少しずつ見ていきますね。
何か音声キーを追加したいと思ったら、以下の部分が必ず必要です。

```js
		var cmd;
		cmd=SimpleAI.getSmartAgentCommand();
		cmd.MainCommand.push(
			{
```

###命令文の追加用の構文　その1

次に、実際に追加したい音声キーに沿って考えます。

```js
label: "PersonalJudgment",
labelname: "人物判断",
```

上記二行分が、AIに対するキーの見出しです。一目で分かり易いようにして下さい。

続けて、実際にAIが認識する言葉を設定します。
"/"で囲まれた単語で一つのセンテンスとなっています。
","で区切る事で、複数の単語を一かたまりの命令文として設定しています。

```js
word:[/人物/,/判断/],
```

###複数単語に対応させたい時は

『シンプルエーアイ』は単語のゆらぎに対応しています。
例えば以下のように"|"で区切った単語を記述すると、「人物判断してください」という言葉でも「人物判定してください」という言葉でも、AIが同じ機能を実行してくれるようになります。

```js
word:[/人物/,/判断|判定/],
```

なお、AIはある程度の長さの文章の方が正しく判定してくれます。
ですので、単純に「人物判断」という呼びかけよりは、「人物判断してください」と伝えた方が、きちんと意味を読み取ってくれます。

###命令文の追加用の構文　その2

続いて、音声キーを告げられた時にAIが返答する内容（メッセージ）を設定します。
お喋りさせたくない場合は記述不要です。

```js
message:"人物判断を行います",
```

メッセージの後に処理を行う場合は、以下の一文となります。
メッセージの前に処理を行いたい場合は"messagebefore:"です。

```js
messageafter:function(sender,event,param) {
```

この後に、実際に動作させたい内容をJavaScriptで記入します。
先のソースで言うなら、画像分析処理である以下の部分です。

```js
SimpleAI.Personinformation();
```

これで、音声キーが追加されます。

　
###結果をAIに教えてもらおう

これだけでは少々物足りないので、結果を音声で教えて貰うようにしましょう。
AIに言葉を喋らせる為には、「SimpleAI.SpeechSynthesis」に文字列を渡す必要があります。

「SimpleAI.Personinformation」の部分が画像分析の処理なので、この後に音声で結果を返すようにします。
追加ソースは以下の通りです。

```js
					//判断結果をAIが音声で返す
					SimpleAI.Personinformation(
						{
							done:function(data) {
								var output=document.getElementById("denaripamSimpleAI_responseTextArea");
								if(output) {
									var responsedata = JSON.parse(output.value);
									//responsedata.Processingtext=Processingtext;
									if(responsedata[0]) SimpleAI.SpeechSynthesis(responsedata[0].Processingtext);
								}
							},
							fail:function(errstring) {alert("NG!!" + errstring);
							},
						},
					);
```


**//-----2018/05/11修正・追記ここまで-----//**

　

追加部分を含めた処理は、以下のようになります。

```js
	if(SimpleAI) {
		//スマートエージェント開始
		SimpleAI.SmartAgent();

		//人物判断（スマートエージェントコマンド追加サンプル）
		var cmd;
		cmd=SimpleAI.getSmartAgentCommand();
		cmd.MainCommand.push(
			{
				//人物判断
				label: "PersonalJudgment",
				labelname: "人物判断",			//ラベル名称、現在のモード読み上げ等に使用
				word:[/人物/,/判断/],
				message:"人物判断を行います",
				messageafter:function(sender,event,param) {
//取得結果を音声で返す
					SimpleAI.Personinformation(
						{
							done:function(data) {
								var output=document.getElementById("denaripamSimpleAI_responseTextArea");
								if(output) {
									var responsedata = JSON.parse(output.value);
									//responsedata.Processingtext=Processingtext;
									if(responsedata[0]) SimpleAI.SpeechSynthesis(responsedata[0].Processingtext);
								}
							},
							fail:function(errstring) {alert("NG!!" + errstring);
							},
						},
					);
				},
			},
		);
	}
```


#サンプルコード全文

最後に、今回作成したサンプルプログラムの全文を記載しておきます。

<details><summary>サンプルコード</summary><div>

```js
<!DOCTYPE html>
<html>
<head>
    <title>シンプルエーアイ　デモ</title>
    <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
    <script src="simpleai-0.1.0.min.enc.js"></script>
<script>
//------------------------------------------------------------------------------------------------------------------------
//起動時処理
window.onload = function () {
	var SimpleAI = new denaripamSimpleAI(
		this,
		{},
		{
			initCamera:true,
			initMicrophone:true,
			VoiceRecognition:{listen:true},

//-----uriBase、APIキーを設定してください START-----
			MicrosoftAzureFaceAPI:true,
			MicrosoftAzureFaceAPIuriBase:"",					//FaceAPIのエンドポイントを入力
			MicrosoftAzureFaceAPIsubscriptionKey:"",									//FaceAPIのキー②を入力

			MicrosoftBingSpeechAPIREST:true,
			MicrosoftBingSpeechAPIRESTuriBase:"https://speech.platform.bing.com/speech/recognition/<RECOGNITION_MODE>/cognitiveservices/v1?language=<LANGUAGE_TAG>&format=<OUTPUT_FORMAT>",		//※※※※変更不要※※※※
			MicrosoftBingSpeechAPIsubscriptionKey:"",									//BingSpeechAPIのキー②を入力

			MicrosoftAzureComputerVisionAPI:true,
			MicrosoftAzureComputerVisionAPIuriBase:"",		//ComputerVisionAPIのエンドポイントを入力

			MicrosoftAzureComputerVisionAPIsubscriptionKey:"",							//ComputerVisionAPIのキー①を入力

//-----uriBase、APIキーを設定してください END-----
		},
	);
//-----------------------------------------------
	if(SimpleAI) {
		//スマートエージェント開始
		SimpleAI.SmartAgent();

		//人物判断（スマートエージェントコマンド追加サンプル）
		var cmd;
		cmd=SimpleAI.getSmartAgentCommand();
		cmd.MainCommand.push(
			{
				//人物判断の音声キーを追加する
				label: "PersonalJudgment",
				labelname: "人物判断",			//ラベル名称、現在のモード読み上げ等に使用
				word:[/人物/,/判断/],
				message:"人物判断を行います",
				messageafter:function(sender,event,param) {
					//判断結果をAIが音声で返す
					SimpleAI.Personinformation(
						{
							done:function(data) {
								var output=document.getElementById("denaripamSimpleAI_responseTextArea");
								if(output) {
									var responsedata = JSON.parse(output.value);
									//responsedata.Processingtext=Processingtext;
									if(responsedata[0]) SimpleAI.SpeechSynthesis(responsedata[0].Processingtext);
								}
							},
							fail:function(errstring) {alert("NG!!" + errstring);
							},
						},
					);
				},
			},
		);
	}
//-----------------------------------------------
//人物判断ボタン
var captureButton = document.getElementById('capture');
	captureButton.addEventListener('click', function() {
	SimpleAI.Personinformation();
  });
//--------------------------------------------
};
//------------------------------------------------------------------------------------------------------------------------
</script>
</head>
<body>
<button id="capture">人物判断</button><br>
<video id="denaripamControlSensor_video" width="800px" height="600px" controls autoplay></video>
<div id="denaripamSimpleAI_responseRect"></div><br>
<canvas id="denaripamControlSensor_soundvisualizer" width="800px" height="60px"></canvas><br>
<textarea id="denaripamSimpleAI_responseTextArea" class="UIInput" style="width:580px; height:400px;"></textarea><br>
</body>
</html>
```

</div></details>


#余談1：謎のエラーが出ると思ったら、Chromeのオーディオ自動再生の設定の仕様が変わっていた

サンプルプログラムを作っている途中、気づいた事が一つありました。
マイクが正しく音声を拾っている事を確認する為に表示させたサウンドビジュアライザーが、1回目の起動では必ずエラーになります。
![2-10.png](https://qiita-image-store.s3.amazonaws.com/0/255412/583eff33-93d6-9bd5-015e-d93e3c956f82.png)












ソースは正しいのに、何故？

調べたところ、Chromeのオーディオ自動再生設定が原因でした。
詳細の原文ページはこちら：
[https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio](https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio)
2018年4月の仕様変更により、Chromeの設定を自ら変更していない場合、動画や音源は「自動再生しない」になります。
※試してみたところ、実際には「ページ読込時から7秒以上経つと自動再生を開始する」という動作のようです。
　原文を元に中の人が動作確認しただけなので、取り違い等があるやもしれません。詳細は原文をご確認下さい。

エラーを解消するには「ユーザーにクリックして貰う等、ワンクッション挟む」か、或いは「Chromeの設定を変更する」必要があります。

###Chromeの設定変更の仕方
1.Google ChromeのURLバーに「chrome://flags」をコピーして貼り付けます。
2.「AutoPlay policy」の項目を「Default」ではなく、「No user gesture is required」に設定して「LELUNCH　NOW」を押下する。
3.Chromeを再起動する。

ただし「Chromeの設定を変更する」は環境依存なので、実際に使用するには「ワンクッション挟む」が現実的な対応になるでしょう。
解決策や他の対処方法に詳しい方がいらっしゃいましたら、コメントいただければ幸いです。


#最後に

今回のプログラムについては、使用しているAPIサービスの仕様により、SSL接続が可能なサーバにアップする必要があります。
以下のように、無料で借りられるサーバもあります。
[https://www.bitballoon.com/](https://www.bitballoon.com/)


今回はここまでです。お疲れ様でした。
次回の記事では、更に機能を追加していきます。