LoginSignup
4
5

More than 5 years have passed since last update.

MESHを使ってゆっくりを喋らせてみた

Last updated at Posted at 2018-10-14

はじめに

プログラミング歴が浅いが、IoTデバイスを触ってみたいと思い切ってMESHの人感センサーを購入しました。
人感センサーなので反応する度何か喋ってほしいなと考えていました。
さらに、喋るならゆっくりに喋ってほしい…と思いでカスタムタグを作成したので、備忘録として載せます。

そもそもMESHってなに?

MESHとは「無線でつながるIoTデバイス」であり、主な特徴としては以下が挙げられます。(MESH公式サイト)

  • ビジュアルプログラミングアプリがあり、プログラミングが分からなくても簡単にMESHの挙動フロー(MESHレシピ)が作成できる
    これはアプリで作成したMESHレシピになるのですが、タグと呼ばれるものを繋げて挙動を決定します。
    image.png

  • SDKがあり、独自のコード(カスタムタグ)を作成できる

  • MESH HubによりRaspberry Piからコードを動かすことができる

MESHに反応があるとゆっくりに喋るようになるまで

MESH Hubを使ってMESHの人感センサーに反応があるたびにRaspberry Piからゆっくりが喋るカスタムタグを作成してみました。

ざっくりとした流れはこちら
1. Raspberry PiからWebAPIサーバを起動する
2. MESHのカスタムタグからWebAPIへHTTPリクエストを発行する
3. WebAPIの中でsubprocessによりAquesTalkコマンドを実行する

主にSony MESH Hubでミクさんにおかえりを言ってもらったを参考にしています。
ゆっくりに喋ってもらいたかったので、OpenJTalkを使う所はAquesTalkに変えています。

ラズパイからゆっくりに喋ってもらう部分はRaspberry pi で音声会話をするを参考にしました。

start.py
#!/usr/bin/perl
# -*- coding:utf-8 -*-

import subprocess

from flask import Flask, request
app = Flask(__name__)

def aquestalk(speech):
  cmd = '/home/pi/aquestalkpi/AquesTalkPi -s 80 ' + speech.decode('utf-8') + '| aplay';

  // コマンドを実行する
  // 実行が成功すると0が返り、失敗するとCalledProcessErrorが生じる 
  // 詳しくは https://docs.python.jp/3/library/subprocess.html
  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
  print(str(output))
  return True

def say(speech):
  aquestalk(speech)
  return speech

// ルーティングをしてURLとPOSTメソッドを紐づける
@app.route('/talk', methods=['POST'])
def handleSay():
  speech = request.form['speech'].encode('utf-8')
  return say(speech)

def main():
  // WebAPIサーバーを起動する
  app.run('127.0.0.1')

if __name__ == '__main__':
  main()

カスタムタグの作り方はSony MESH Hubでミクさんにおかえりを言ってもらったが詳しいため割愛。
Executeメソッドの実装時にrouteデコレーターの引数とPropertyの設定を合わせる必要があります。

カスタムタグのProperty
image.png

カスタムタグのExecuteメソッド

Execute
// AjaxでアクセスするURL
// routeデコレーターの引数と合わせる
var url = "http://localhost:5000/talk";

// URLに送信したいデータオブジェクト
// PropatyのRefarence Nameと合わせる
var speech = {
    "speech" : properties.talk,
};

// Ajaxで非同期通信を行う
// 詳しくは https://meshprj.com/sdk/doc/ja/
ajax({
    url: url,
    type: 'post',
    data: speech,
    timeout: 5000,
    success: function(success) {
        log(success);
        callbackSuccess({
            resultType: 'continue' // 次のメソッドを呼ぶ
        });
    },
    error: function(request, error) {
        log(error);
        callbackSuccess({
            resultType: 'continue' // 次のメソッドを呼ぶ
        });
    }
});

// Ajaxは非同期通信であるためイベントハンドラが実行されるまで待つ
return {
    resultType: 'pause' // 次のメソッドを呼ばない
};

完成したゆっくりが喋るタグがこちら。
image.png

レシピはお試しでシンプルに喋るだけにしました。
Propertyを設定しておくことでレシピのタグから喋る内容が変えられるようになります。

mesh_yukkuri.PNG

以下のコマンドを叩いてMESHの人感センサーを反応させるとゆっくりが喋ります。ヤッター!

$ python start.py

ハマった点

  • MESH HubはRaspbian(Stretch)でしか動かない
    (久々ラズパイを動かしたのでRaspbian Jessieで止まっていていたためsudo apt-get updateを何度も実行しました…)
  • MESH Hubを使う場合、iOS版のMESHアプリでしか対応していない(2018/9/12現在)
  • subprocess.check_outputの引数をリストにした場合、CalledProcessErrorが生じる

# CalledProcessError:Command return non-zero exit status 154が発生
cmd = '/home/pi/aquestalkpi/AquesTalkPi -s 80 ' + speech.decode('utf-8') + '| aplay';
  output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT, shell=True)

subprocess で shell=True でリストを与えたときの挙動によると、shell=Trueを指定した場合、リストではなく文字列を指定しないと適切に引数が渡らないようです。

課題

  • 「python start.py」を打ってWebAPIを起動させるのは面倒くさい問題
  • ゆっくりが最初の4文字分ほどを喋ってくれない問題
    (PropertyのValueに「ゆっくりしていってね」と入れると「していってね」と聞こえてしまい、ラズパイがゆっくりしてくれない)
    よって、PropertyのValueが「ゆっくりゆっくりしていってね」にすると「ゆっくりしていってね」と聞こえる。
    自身の環境の問題かもしれないが解決策が分からない。
4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5