Web Speech API + 雑談APIで楽しく会話

# 自己紹介

じゅんじゅんというニックネームで、関西を拠点に活動しているフロントエンドエンジニアです。

HAL大阪の2回生です👍 (2016.10.24現在)

よくstart up系イベントに行くので、大阪らへんの方は会いましょう！

# 音声認識と音声合成

今回は、[Web Speech API](https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API)と[DOCOMO雑談API](https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_name=dialogue&p_name=api_reference)を使って音声だけで雑談をしたいと思います。

まずWeb Speech APIですが

> 音声認識は SpeechRecognitionインターフェース経由で使用出来ます。これは入力された音声（通常はデバイスのデフォルト音声認識サービス経由）から文脈を認識し、適切に対応する機能を提供します。通常は、SpeechRecognition オブジェクトを生成するためにインターフェースコンストラクタを使用します？これはデバイスのマイクから入力された音声を検知するための複数のイベントハンドラを持ちます。 SpeechGrammarインターフェースはSpeechGrammar インターフェースは、あなたのアプリが認識するGrammer（語群）の集合のコンテナを提供します。

>音声合成は SpeechSynthesis インターフェース経由で使用出来ます。

と書いています。

まぁHTML5で使える音声認識と合成のAPIです（？）

DOCOMOの雑談APIの使い方はQiitaにたくさん記事があるので一覧にしておきます。

- [【LINE Bot】Heroku+PHP+雑談対話APIで会話Bot作ってみた](http://qiita.com/shanonim/items/f90ee13180ee70a1903d)
- [LINE Bot で Docomo雑談APIとトークする](http://qiita.com/Arashi/items/a1a6663d3fba0947815d)
- [DocomoruでBOTと雑に会話する](http://qiita.com/r7kamura/items/55f398624dbce1c6dc14)

# まずは音声認識をしてみましょう
`index.html`を作ってコードを書いていきます。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>会話テスト</title>
	<style>
		li{
			list-style: none;
			margin: 10px 0;
		}
	</style>
</head>
<body>

	<h1>会話テスト</h1>
	<ul id="result"></ul>
	<button class="start-btn">開始！</button>

	<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
	<script type="text/javascript">
		(function($){

			// initialize
			var recognition,isRecognition = false;
			const LANG_JAPAN = "ja-JP";

			$(".start-btn").on("click",start);

			/*
			*		認識 start
			*/
			function start(){
				recognition = new webkitSpeechRecognition(); // 音声認識
				recognition.lang = LANG_JAPAN; // 日本語
				recognition.start(); // 認識開始
				isRecognition = !isRecognition; // 認識しているかどうかのフラグを反転
				recognition.onend = function(){
					stop(); // 認識が終わったら終了する
				}
				recognition.onresult = function(e){ // 結果を得たら
					if(e.results.length > 0){
						var value = e.results[0][0].transcript; // ここに日本語
						$("#result").append("<li>"+value+"</li>");
					}
				}
				alert("喋って！")
			}

			/*
			*		認識 stop
			*/
			function stop(){
				if(isRecognition){
					recognition.stop();
					isRecognition = !isRecognition;
				}
			}
		})(jQuery);
	</script>
</body>
</html>
```

これでブラズザを開くと

![スクリーンショット 2016-10-25 16.06.53.png](https://qiita-image-store.s3.amazonaws.com/0/90347/56c3ed79-b160-97ed-6c66-13fe280454e4.png)

こんな画面ができていると思います。

**開始ボタン**を押すと音声認識が始まるので喋ってください！


# 雑談しましょう
では、雑談していきましょう。

サーバーはNodeで書いたサンプルがあるので載せていきます。

```js
var express = require("express");
var request = require('request');
var PORT = 4000 || process.env.PORT;
var app = express();

var status = { // ここで自分の設定をしておきましょう
	nickname: "じゅんじゅん",
	nickname_y: "ジュンジュン",
	sex: "男",
	bloodtype: "O",
	age: 19,
	constellations: "魚座",
	place: "大阪"
};

app.get("/",function(req,res){
	res.sendfile("index.html");
})
app.get("/api",function(req,res){
	var value = req.query.text, // 会話APIに送るテキストデータ
			url = "https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=",
			token = process.env.DOCOMO_API_KEY; // 環境変数を使っています。

	status.utt = value;
	
	var param = {
		body: JSON.stringify(status),
		"Content-Type": "application/json"
	}

	request.post(url+token,param,function(err,response,data){
		if (err) throw err;
		var body = JSON.parse(data);
		status.context = body.context;
		body.utt = value == "バイバイ" ? "またねー！" : body.utt // バイバイというと終わるようにする
		res.json({
			res: body.utt
		})
	});

})

app.listen(PORT,function(){
	console.log("app is http://localhost:"+PORT)
})
```

`npm i`としてから`node app.js`としてサーバーを起動します。

少しフロント部分も書き換えていきましょう！

まず`start`関数の中に会話データを呼べるように`talkData`関数を作って呼びましょう

```js
function start(){
  recognition = new webkitSpeechRecognition();
  recognition.lang = LANG_JAPAN;
  recognition.start();
  isRecognition = !isRecognition;
  recognition.onend = function(){
    stop();
  }
  recognition.onresult = function(e){
    if(e.results.length > 0){
      var value = e.results[0][0].transcript;
      talkData(value); //　ここ
      $("#result").append("<li>"+value+"</li>");
    }
  }
  alert("喋って！");
}
```

では、`talkData`関数を作っていきます。

```js
function talkData(value){
  $.ajax({
    url: "/api",
    type: "get",
    data: {
      text: value
    },
    success: function(data){
      $("#result").append("<li>"+data.res+"</li>");
      speech(data.res);
    }
  });
}
```

`speech`関数が出てきましたね。

音声合成APIでテキストをもとにブラウザが喋るようにしていきます。

```js
function speech(value){
  var msg = new SpeechSynthesisUtterance(); // インスタンス化
  var voices = window.speechSynthesis.getVoices(); // 声を選べます
  msg.volume = 1;
  msg.voice = voices[7];
  msg.rate = 10;
  msg.pitch = 2;
  msg.text = value; // ここへ読み上げるテキストのデータを代入します
  msg.lang = LANG_JAPAN;
  speechSynthesis.speak(msg); // .speakを使って話始めます
  msg.onend = function(){
    setTimeout(function(){
      start(); // 読み終えてから2秒でまたスタート
    },2000);
  }
}
```

これで完成です！

[localhost:4000](http://localhost:4000)へ行って確認してみましょう！

コードの全貌はgithubへアップしておきます。

[konojunya/speech api](https://github.com/konojunya/speech_api/)


# あとがき
今回は全て無料で作成できました！

UIいい感じにして楽しく雑談しましょう！

Twitter [@konojunya](https://twitter.com/konojunya) ぜひフォローください！