Raspberry Pi をNode.jsを使ってブラウザから喋らせる。

色んな方が試されているRaspberry Piのおしゃべりですが、Node.jsを使ってブラウザから喋らせてみました。

## 環境

- Raspberry Pi2 ModelB （raspbian-wheezy・Node.js v4.2.4）
- PLANEX 無線LAN子機 (USBアダプター型) GW-USNANO2A (FFP)
- サンワサプライ USBスピーカー(ブラック) MM-SPU8BK

Raspberry Pi本体のセットアップやNode.jsのインストールは済んでいるという環境です。Node.jsを利用するのは初めてなので、出来る限り既存のパッケージを利用しようと考えました。

## インストール

ディレクトリは以下の位置に作りました。

```bash:ssh
pi@raspberrypi ~/work $ mkdir talk

```

必要なパッケージ類をインストールします。

```bash:ssh
$  npm init

$  npm install express --save

$  npm install ejs --save

$  npm install voicetext --save

$  npm install node-aplay --save

```

ファイルは二つだけ作成しました。

```bash:ssh
 ~/work/talk/app.js

 ~/work/talk/views/talk.ejs

```

ファイル構成はこんな感じです。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/47128/17b46fcc-2994-bac8-6a43-c03d3e130e6e.png)

## Raspberry Piで合成音声を喋らせる。

[voice-text - npm](https://www.npmjs.com/package/voice-text)

こちらを利用してHOYA社の[VoiceTextWebAPI](https://cloud.voicetext.jp/webapi)から合成音声を取得します。wavファイルのRaspberry Piでの再生は

[node-aplay -npm](https://www.npmjs.com/package/node-aplay)

こちらを利用します。

```js:app.js

//パッケージの読み込み許可
var express = require('express');
var ejs = require("ejs");
var VoiceText = require('voicetext');
var Sound = require('node-aplay');

//ファイル読み込み許可
var fs = require('fs');

//ブラウザ操作用のejsファイルのレダリング
var app = express();
app.engine('ejs',ejs.renderFile);

app.get('/', function(req, res){
    res.render('talk.ejs',
        {title: 'Raspberry Pi Talk'});
})

//合成音声の読み込みとwavファイル作成・再生
var voice = new VoiceText('xxxxxxxxxxxxxxxxx');

app.get('/control', function (req, res) {
  console.log(req.query);
  var text = req.query.text ? req.query.text : "";

  var name = "ポンダッド"
　if(text == "はじめまして"){
    text = "はじめまして、わたしはラズベリーパイって言います。"
  }else if(text =="わたしは" + name + "です"){
    text = name + "さん、よろしくね"
  }else if(text == "がんばれよ"){
    text = name + "お前も、がんばれよ。"
  }

  var speaker       = req.query.speaker ? req.query.speaker : voice.SPEAKER.HARUKA;
  var emotion       = req.query.emotion ? req.query.emotion : voice.EMOTION.HAPPINESS;
  var emotion_level = req.query.emotion_level ? req.query.emotion_level : voice.EMOTION_LEVEL.LOW;
  var pitch         = req.query.pitch ? req.query.pitch : 100;
  var speed         = req.query.speed ? req.query.speed : 100;
  var volume        = req.query.volume ? req.query.volume : 100;
  voice.speaker(speaker)
       .emotion(emotion)
       .emotion_level(emotion_level)
       .pitch(pitch)
       .speed(speed)
       .volume(volume)
       .speak(text, function(e, buf){
         return fs.writeFile('./talk.wav', buf, 'binary', function(e){
          if(e){
            return console.error(e);
          }
          new Sound('talk.wav').play();
         })
       });
  res.send(text);
});

//ローカルサーバーの起動
var server = app.listen(3000, function () {
  var host = server.address().address
  var port = server.address().port
  console.log('This app listening at http://192.168.x.xx:',port)
});


```

19行めより合成音声の作成になります。`app.get`のパスを`/control`としています。

これによりここでは`192.168.x.xx:8000/control?text=〇〇〇〇`という形で送られてきたGETリクエストの変数名`text`と引数`〇〇〇〇`を受け取ることが出来ます。

基本はこの引数を喋らせるのですが、今回は2,3のキーワードに対して返答をするようにしました。

あとはパッケージのドキュメントに沿って記述しました。wavファイルを保存して、再生させます。

## ブラウザで操作する

```html:views/talk.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta http-equiv="content-type"
        content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no">
    <title><%=title %></title>
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" type="text/css" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
    <style>
     article{
       margin: 20px;
     }
    </style>
    </head>
<body>
    <header>
        <h1 class="text-center h2"><%=title %></h1>
    </header>
    <article>
    <form>
    <div class="form-group">
    <input class="form-control" type="text" id="query">
    </div>
    <input  class="btn btn-default" type="reset" value="しゃべるよ" onclick="send()" />
  </form>
    </article>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

    <script>
        var send = function() {
                var msg = document.getElementById('query').value;
                $.get("http://192.168.x.xx:3000/control", { text: msg } );
            };

    </script>
</body>
</html>

```

`app.js` の９行めよりこの`talk.ejs`のレダリング指示を出しています。`css`や`js`のファイルを設置する際はもう少しレダリングの記述が増える為１ファイルにまとめました。
（BootstrapとJQueryはCDNで読み込んでいます）

JQueryのAJAXリクエストを利用して、フォームの`input`より登録された`text`をGETリクエストとして送信します。

```
 $.get("http://192.168.x.xx:3000/control", { text: msg } );
```

この部分が

```
http://192.168.x.xx:3000/control?text=msg
```

と送信されるので変数`msg`を引数としてvoicetextに引き渡すことが出来ます。

## こんな感じ

アプリはsshより起動させます。

```bash:ssh
pi@raspberrypi ~/work/talk $ node app.js
This app listening at http://192.168.x.xx: 3000
```

ブラウザ側は`http://192.168.x.xx:3000`で開けます。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/47128/d9d27216-9d33-7cc4-ef3c-0f9c6cfd7e34.png)



![5.png](https://qiita-image-store.s3.amazonaws.com/0/47128/7c327f02-6d06-04e4-e643-69ac6c0e0940.png)

入力した言葉を返します。

名前を変数`name`で登録したのでこんな返事もします。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/47128/16853611-d14c-5295-1336-db4eee3d955a.png)

![６.png](https://qiita-image-store.s3.amazonaws.com/0/47128/e8b59276-226a-83d1-24c4-8d7a7c8e54df.png)

こんな言葉を投げかけると。

![4.png](https://qiita-image-store.s3.amazonaws.com/0/47128/e06fd121-fee1-d26b-a3b2-7e2d94d54b61.png)

![７.png](https://qiita-image-store.s3.amazonaws.com/0/47128/b6c7b089-137f-29f2-0843-4a899f7a92cb.png)

・・・。

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

[RAPIRO（ラピロ）に音声合成で喋らせる - MUDAなことをしよう。](http://make-muda.weblike.jp/2014/11/1859/)

[Rapiro に音声合成で喋ってもらう - Linux & Android Dialy](http://wp.developapp.net/?p=3879)