ラズベリーアラーム制作第2回目は、時間を読み上げてくれる機能の実装です!
前回作った目覚まし時計は、アラームをボタンで止めるだけのシンプルなもの。これだけでは物足りない!もっと便利な目覚まし時計になるように、今までの知識を応用してどんどん機能を追加してきましょう。
今回は「Open JTalk」という音声合成システムを使用します。Debian用のパッケージが用意されているので、ラズベリーパイにも簡単にインストールできます!
Open JTalkとは?
Open JTalk公式サイト
open-jtalkパッケージ
デモンストレーションページ
「Open JTalk」は、入力された日本語テキストに基づいて自由な音声を生成するHMMテキスト音声合成システム
デモンストレーションページでは、音声の合成結果をブラウザ上で確認できます。声の種類は6種類用意されており、最大200文字まで試せるのがすごい!パラメータの微調整にとても便利ですね!
パッケージインストール&準備&テスト
Open JTalkのパッケージをインストールしましょう!ここでは依存パッケージを含め、全部で4種類のパッケージをインストールする必要があります。
apt-get install open_jtalk
インストールコマンドを実行すると、図1のように、必要なパッケージを一緒に教えてくれます。
「特別パッケージ」の「libhtsengine1」は、自動で一緒にインストールされますが、「提案パッケージ」として挙げられている2つは、別途インストールする必要があります。「open-jtalk-mecab-naist-jdic」は辞書ファイル、「hts-voice-nitech-jp-atr503-m001」は音声ファイルです。「提案」とされていますが、日本語を喋らせるためにはどちらも必須となります。
apt-get install open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001
インストールが完了したら、ヘルプを表示してみましょう!
open_jtalk -h
パラメータがたくさん表示されます!このパラメータ、未指定にすればデフォルトのものが適用されるというわけではなく、音声ファイルなどをひとつひとつ指定する必要があるようです。全部というわけではありませんが、この数を毎回指定するのはちょっと大変……ということで、パラメータ設定を行うスクリプトをこちらからお借りしました。
/root/jsay.sh
#!/bin/sh TMP=/tmp/jsay.wav cd /usr/share/hts-voice/nitech-jp-atr503-m001 echo "$1" | open_jtalk \ -td tree-dur.inf \ -tf tree-lf0.inf \ -tm tree-mgc.inf \ -md dur.pdf \ -mf lf0.pdf \ -mm mgc.pdf \ -dm mgc.win1 \ -dm mgc.win2 \ -dm mgc.win3 \ -df lf0.win1 \ -df lf0.win2 \ -df lf0.win3 \ -dl lpf.win1 \ -ef tree-gv-lf0.inf \ -em tree-gv-mgc.inf \ -cf gv-lf0.pdf \ -cm gv-mgc.pdf \ -k gv-switch.inf \ -s 16000 \ -a 0.05 \ -u 0.0 \ -jm 1.0 \ -jf 1.0 \ -jl 1.0 \ -x /var/lib/mecab/dic/open-jtalk/naist-jdic \ -ow $TMP && \ aplay --quiet $TMP rm -f $TMP
プログラムの内容を簡単にまとめると、「/tmp/jsay.wav」に音声ファイルを作成し、「aplay」コマンドで再生、再生が終わるとファイルを削除、という流れになります。
3行目の「 /usr/share/hts-voice/nitech-jp-atr503-m001 」は、音声ファイルの場所を指定しています。後述しますが、声の種類を変更する場合はこのパスを変更します。
ラズベリーパイで日本語入力
さぁ日本語を喋らせてみよう!と思ったら日本語入力ができなかった!
表示はされるのに入力ができないというのも不思議だなぁと思いつつ調べてみると、日本語入力に対応するには「IBus」というパッケージが別途必要とのこと。
apt-get install ibus-anthy
まずはいつものようにインストールコマンドを実行。そして、インストール後にもう1つ設定があります。
メニューの「システムツール」の中から「IBusの設定」を選択します。
ウインドウの中には3つのタブがあります。今回は入力に関する設定ですので、中央の「インプットメソッド」タブをクリックします。「インプットメソッドの選択」というメニューがあるので、その中から「日本語」を選択しましょう。
設定はこれで完了!キーボードの[半角/全角]キー、または、[Ctrl]+[Shift]キーで入力切り替えができます。
Open JTalk実行!
日本語入力ができるようになったので、Open JTalkを実行してみましょう!LX Terminalからコマンドを実行します。
/root/jsay.sh "おはようございます"
男性の声で「おはようございます」と読み上げられれば成功です!
先程作成した「jsay.sh」に実行コマンドまで記述してあるので、上記のように日本語の文字列を添えるだけで実行できます。わたしの環境では、話す速度などもちょうど良く、パラメータの調整も必要ありませんでした。
このままプログラムに組み込んでいっても良いのですが、朝は女性アナウンサーのようなさわやかでかわいい声で起こしてほしい!そんなわけで女性に変更してみることにしました。
デモンストレーションページで使用されている女性話者の声「Mei」のファイルを使用します。
ダウンロードページからver.1.3.1のファイルをダウンロードします。ver.1.4以降はファイル形式が違うのでご注意ください。ファイルを解凍すると、「Voice」フォルダの中に、下記の5種類の音声データが格納されています。
・mei_angry
・mei_bashful
・mei_happy
・mei_normal
・mei_sad
デモンストレーションページで使用されている5種類と同じですね!
このファイルをラズベリーパイの適当な場所に置いて、「jsay.sh」のスクリプト3行目のパスを置き換えましょう。
/root/jsay.sh(3行目部分)
cd /usr/share/hts-voice/mei_normal
たとえば、男性話者の音声ファイルと同じ場所に格納した場合は上記のようになります。女性の声の方が少し早口に聞こえますが、さわやかで目覚まし時計らしくなりました!
PHPプログラム作成
/var/www/morning_call_test.php
<?php $weekday = array('日','月','火','水','木','金','土'); $date = date('n月j日'); $dow = $weekday[ date('w') ].'曜日'; $time = date('G時i分'); $txt = 'おはようございます。'.$date.'、'.$dow.'、'.$time.'です。'; echo $txt.PHP_EOL; exec('/root/jsay.sh '.$txt);
上記は、現在の日付、曜日、時刻を読み上げてくれるプログラムです。PHP側で文字列を作成し、「jsay.sh」のパラメータとして渡しています。
実行コマンド
php /var/www/morning_all_test.php
「おはようございます。○月○日○曜日、○時○分です。」
このように、現在の日時を教えてくれます。適当な位置に句読点を打って調整すると聞きやすいです。
日時がずれてしまう場合は、ラズベリーパイ側のタイムゾーン設定に問題がある可能性があります。「raspi-config」から、設定を再度確認してみましょう。
目覚まし時計プログラムと連携
前回cronに登録した目覚まし時計プログラムに、新たに作成した機能を組み込んでいきます。せっかくなので、第18回記事で作った温度取得プログラムも組み込んで、現在の室温も読み上げてくれるように仕上げてみました!
部品を追加したので、まずは配線を微調整。
線が増えて複雑になったように見えますが、19回と18回を合体させただけ。3.3V電源とGNDは温度センサとスイッチで共通で使うので、ひとつにまとめました。
次に、プログラムに組み込みます。こちらも少々リニューアル!各機能を関数化し、1つのファイルにまとめました。
/var/www/morning_call.php
<?php start(); wait(); /* アラーム */ function start(){ exec('mpg321 -l 0 -q /var/www/alerm1.mp3 > /dev/null &'); } /* ストップボタン待機 */ function wait(){ $interval_sec = 0.25; //スイッチのチェック間隔(秒) $wait_sec = 60; //最大待機時間(秒) exec('echo 2 > /sys/class/gpio/export'); exec('echo in > /sys/class/gpio/gpio2/direction'); for($i=0; $i<($wait_sec / $interval_sec); $i++){ if(exec('cat /sys/class/gpio/gpio2/value')==1){ break; } usleep($interval_sec * 1000000); echo $i.PHP_EOL; } exec('killall mpg321'); exec('echo 2 > /sys/class/gpio/unexport'); morning_call(); } /* モーニングコール */ function morning_call(){ $weekday = array('日','月','火','水','木','金','土'); $date = date('n月j日'); $dow = $weekday[ date('w') ].'曜日'; $time = date('G時i分'); $txt = 'おはようございます。'.$date.'、'.$dow.'、'.$time.'です。'; $temp = get_temperature(); if($temp!=null){ $txt .= '現在の室温は、'.$temp.'度です。'; } echo $txt.PHP_EOL; exec('/root/bin/jsay.sh '.$txt); return; } /* 温度を取得 */ function get_temperature(){ $deviceId = '28-000006470bec'; $sensor_path = '/sys/bus/w1/devices/'.$deviceId.'/w1_slave'; $t = null; exec("cat ".$sensor_path, $w1_slave); if(isset($w1_slave[1])){ $arr = explode('t=', $w1_slave[1]); if(isset($arr[1])) $t = $arr[1] / 1000; } return $t; }
実行コマンド
php /var/www/morning_call.php
「おはようございます。○月○日○曜日、○時○分です。現在の室温は○○度です。」
スイッチでアラームを止めると、このように情報を読み上げてくれます。文章によっては、イントネーションに違和感があることもありますが……なまりがあるようでかわいく聞こえますね!
最後の仕上げに、cronの内容を修正します。呼び出しのタイミングには変更がないので、前回cronに登録したシェルスクリプトを書き換えます。
/root/morning.sh
php /var/www/morning_call.php
ワンクッション置いてシェルスクリプトをcronに登録したので、プログラムの差し替えも手軽になりました!プログラムを1つのファイルにまとめたので、呼び出しも1行でOKです。
まとめ
機能が増えて、だんだん手作りらしさが出てきました!
時間を教えてくれるようにしたので、曜日ごとに起きる時間が違う方にもおすすめです。鳴る時間をランダムに少しずらしてみるというのもスリリングでおもしろそう!
室温も教えてくれるので、朝の室温を基準にエアコンの設定温度を決める、というような判断基準として役立ちそうです。
次に付けたい機能は……天気予報!
朝一で知りたい情報といえば今日のお天気。目覚まし時計が教えてくれたら、テレビをつける間もない忙しい朝も安心ですね!
時刻、温度と一緒に、天気予報も読み上げてくれるようにカスタマイズしたいと思います!