2018年03月25日

Google Home で時報を作って読み上げさせて見た。

前回作ったGoogle-Home-NotifierのServerを更に改造して音声(MP3)を読み上げさせるようにしてみた。

概要
RaspberryPiのcrontabで毎定時にGoogleHomeからランダムなメロディー(時報読み上げMP3)を流す。

サンプル


必要なもの
・自宅サーバー(Raspberry Piなど)
 GoogleHomeNotifierのServerとApacheをPortを分けて起動(1つにしたいな)
・音声ファイル素材(声)
 「あみたろの声素材工房」さんの声素材を使わせていただきました。
・音声ファイル素材(メロティー)
 「ポケットサウンド」さんの効果音素材を使わせて頂きました。

素材フォルダの構成(MP3ファイルの置き場所)
・./ampm
 声(午前、午後 を配置)
・./desu
 声(です。でーす。などをランダムで再生)
・./ji
 声(○時 00.MP3 - 11.MP3を配置)
・./melody
 メロディー(ランダムで再生するのでたくさん置く)

ソースコード
・server.js(前回の記事参照)
・config.js(前回の記事参照)
・commonlib.js(GoogleHomeNotifierのserver.jsにPostするモジュールを作成して汎用化)

// commonlib.js
exports.SendMessage = function(type, speakerNumber, sendText) {

var request = require('request');
var options = {
uri: "http://xxx.xxx.xxx.xxx:xxxx", // RaspberryPiのserver.js
headers: {
"Content-Type" : "application/json",
},
json: {
"type" : type,
"speakerNumber": speakerNumber,
"message": sendText
}
};
request.post(options, function(error, response, body){
console.log(error);
});
}

・timesignal.js

// timesignal.js
"use strict";

const GoogleHomeLib = require('../commonlib'); // 作成したcommonlib.jsを呼び出す
const fs = require('fs');

// フォルダ設定
const melodyDir = './melody';
const ampmDir = './ampm';
const timeVoiceDir = './ji';
const desuDir = './desu';
const talkFile = '/xxx/xxx/xxx/signal.mp3';    // RaspberryPiのApacheでのMP3の場所
const sendUrl = 'http://xxx.xxx.xxx.xxx/xxx/signal.mp3'; // RaspberryPiのApacheでのURL

var melodyFiles = fs.readdirSync(melodyDir);
var melody = GetRandomFile(melodyDir, melodyFiles);
var timeVoice = GetVoiceString();
var desuFiles = fs.readdirSync(desuDir);
var desu = GetRandomFile(desuDir, desuFiles);

// コマンドライン作成
var command = 'cat ' + melody + ' ' + timeVoice + ' ' + desu + ' > ' + talkFile;
console.log(command);

// MP3作成
const execSync = require('child_process').execSync;
const result = execSync(command);

// GoogleHomeへ転送
GoogleHomeLib.SendMessage('sound', 0, sendUrl);

// 時報ファイル取得
function GetVoiceString(){
var todayNow = new Date();
var hours = todayNow.getHours();
// crontabで○時59分に50秒くらいSleepするので次の時刻にする
var signalTime = hours + 1;
var ampmFile;

if (signalTime == 24) {
// 日付変更
ampmFile = ampmDir + '/' + 'gozen.mp3';
signalTime = 0;
} else if (signalTime >= 12) {
// 午後
ampmFile = ampmDir + '/' + 'gogo.mp3';
signalTime -= 12;
} else {
// 午前
ampmFile = ampmDir + '/' + 'gozen.mp3';
}
//
var hourString = ('00' + signalTime).slice(-2);
var timeFile = timeVoiceDir + '/' + hourString + '.mp3';
return ampmFile + ' ' + timeFile;
}

// メロディーファイル取得
function GetRandomFile(Path, fileList){
var min = 0;
var max = fileList.length - 1;
// ランダム選択
var randomIndex = Math.floor( Math.random() * (max + 1 - min) ) + min ;
return Path + '/' + fileList[randomIndex];
}


起動設定
・シェルを作成
timesignal.sh

cd /home/pi/Googlehome/timesignal
node ./timesignal.js

・crontabを設定
毎時59分50秒に開始(7時から23時まで鳴る設定)

59 6-22 * * * sleep 50; /home/pi/Googlehome/timesignal/timesignal.sh >>/tmp/cron.log 2>>/tmp/cronerror.log


最後に
メロディーと声をcatコマンドで繋げられる事を今回初めて知ったけど、サンプリングレート?、それともビットレート?が合っていないと繋いだMP3が正しく再生されないので編集ソフトを使って色々設定を変えるのに苦労した。
posted by Vintage at 14:13| Comment(0) | TrackBack(0) | Google Home

2018年03月17日

複数のGoogleHomeで読み上げさせてみた。

前回までに作った仕組み
RaspberryPiには、GoogleHomeNotifier(ここを参考に)をInstallして受信用Serverを起動している。
スクリーンショット 2018-03-17 11.04.05.png

今回のメイン
複数のGoogleHomeを喋らせるコードを作成。
スクリーンショット 2018-03-17 11.58.21.png
ここのhttpサーバーソースを参考にGoogleHomeNotifierをLine専用ではなく「type(=text),とspeakerNumber、message」のJSONデータをPostされた時に喋るように改造。
speakerNumberが'0'なら全てのSpeakerが喋る。
IFTTTあたりでWebHookを使い自宅サーバーにこのJSONを送ってテスト。

サーバーのコード
server.js (2018/3/25 MP3再生も対応できるように修正)

const googlehome = require('/google-home-notifier');
const config = require('./config.json');
const http = require('http');
const language = 'ja';

// 受信処理
function googlehome_speak(post_data) {
const json = JSON.parse(post_data);
const type = json.type;
const speakerNumber = json.speakerNumber;
const message = json.message;
const speakers = config.speakers;

if (speakerNumber == 0) {
// 0:全てのSpeakerで再生
speakers.forEach(function(speaker, i) {
SendToSpeaker(speaker, type, message);
});
} else {
// 指定のSpeakerで再生
SendToSpeaker(speakers[speakerNumber], type, message);
}
}

// google-home-notifierでコマンド送信
function SendToSpeaker(speaker, type, message) {
googlehome.device(speaker.name, language);
googlehome.ip(speaker.ip);

switch (type) {
case "text":
googlehome.notify(message, function (res) {
//
});
break;
case "sound":
googlehome.play(message, function(res) {
//
});
break;
}
}

// Webサーバー
http.createServer(function (request, response) {
let post_data = '';

request.on('data', function (chunk) {
post_data += chunk;
});
request.on('end', function () {
// 発声/再生
googlehome_speak(post_data);
// 表示ログ
response.writeHead(200, { 'Content-Type': 'text/plain' });
response.end();
});
}).listen(config.server_port);

server.jsの設定ファイル
config.json

{
"server_port": "xxxx",
"speakers":
[
{
"ip": "xxx.xxx.xxx.xxx",
"name": "living"
},
{
"ip": "xxx.xxx.xxx.xxx",
"name": "xxx"
},
{
"ip": "xxx.xxx.xxx.xxx",
"name": "xxx"
}
]
}

汎用にする為、LineのMessagingAPIからの受診処理のコードは、GoogleAppsScript側に持たせた。
Lineの発言をGoogleスプレッドシートに記録させ、GoogleHomeに「再放送」と話しかけると最新の発言を読みあげてくれるようにまで完成。
こちらは次回紹介。

続きを読む
posted by Vintage at 12:37| Comment(0) | TrackBack(0) | Google Home

2018年03月06日

GoogleHomeでLineを読み上げさせる

LineのグループトークをGoogleHomeで読み上げさせたくて調べてみた。

必要なもの、準備するもの、サービスなど
・LineDeveloppersへ登録してBOTを作る
・SSLのサーバー(自宅サーバーにSSL証明書なんてお金かけられないので外部の登録)
・自宅サーバー
・Google home notifier (Google Home を喋らせるためのモジュール)
・httpサーバースクリプト

構成
スクリーンショット 2018-03-17 11.04.05.png
1.Line発言

2.LineDeveloppersのMessagingAPIでBOTが受信

3.SSL(https)のサーバーで受信(ngrokやめてGoogleAppsScriptにした)

4.自宅サーバーPCで受信(わが家ではRaspberryPi)

5.GoogleHomeが受信して発声

最初にできあがったもの
3にngrokというhttpsのサーバーを使ってみた。
Line Developpersからの送信先がhttpsじゃなければ自宅サーバーに直接送信できて簡単なのにね。
問題は、ngrokの無料利用はURLがランダム文字列なので自宅httpサーバーを起動するたびにLineDeveloppersにURLを登録しなければならなかった。

再調査
httpsサーバーにGoogle apps scriptが使える。
スクリプトも書けるし、いいかんじ。
G-Drive使っている人は新規作成ですぐ作れるよ。
ここの記事参考
これでLineDevelopersからGoogleAppsScriptへ投げたデータを自宅へ転送!
とってもシンプル。
自宅サーバーのURL固定用に無料DDNSも申し込むと便利です。

参考:GoogleAppsScriptの転送コード
function doPost(e) {
// 受信
var text = e.postData.contents;

// 転送
var url = "http://xxx.xxx.xxx.xxx:xxxx"; // 自宅のアドレス(DDNS使うのがお勧め)
var headers = {
"Content-Type" : "application/json; charset=UTF-8"
};
var options = {
"method" : "post",
"headers" : headers,
"payload" : text
};
return UrlFetchApp.fetch(url, options);
}


各モジュールについてのインストールや設定は↓の検索でどうぞ。
「Line Developers Google Home Notifier 読み上げ」でググった先の皆様に感謝です。
posted by Vintage at 21:26| Comment(0) | TrackBack(0) | Google Home