ラズパイ3倍美味しいブログ

ラズパイ3を美味しく食べるはずがinto the VR!!!

天気予報喋らせっぞ!!

ラズパイ3で現在時刻を喋ったのであれば、天気予報も喋らせたい。という欲がわいてきた。参考にしたのは下記の2サイト。

raspi.seesaa.net

www.tapun.net

まず1つ目のサイトのやっているとおりに、ことを進める。
jsayコマンドというのを使えるようにするために

raspi.seesaa.net

を参考にjsayで喋ることができるようになるよう頑張る。いままでOpenJTalkで喋らせるようにしてきてたんだけど、一旦おいといて、もう一度イチから真似していれてみる。

jsayを使えるようにする!

今回は、aptではなく、ソースからmake installでインストールをします。

make installでインストールしたアプリケーションを管理する「paco」というソフトウェアをまずインストールしておきます。

 paco・・・当たり前だけどドシロウトのため全く存じません。とりあえず入れるんだね。

$ sudo apt-get install paco

hts_engine API(version 1.09)のインストール
/tmp にダウンロードして解凍
下記を1行ずつ実行していく。
$ cd /tmp
$ sudo wget http://sourceforge.net/projects/hts-engine/files/hts_engine%20API/hts_engine_API-1.09/hts_engine_API-1.09.tar.gz
$ sudo tar zxvf hts_engine_API-1.09.tar.gz

ビルド、コンパイル、インストール。下記を1行ずつ実行していく。
$ cd /tmp/hts_engine_API-1.09
$ sudo ./configure
$ sudo make
$ sudo paco -lD "make install"
あっ最後にpacoというやつ使ってる。

Open JTalk(version 1.08)のインストール
/tmp にダウンロードして解凍

$ cd /tmp
$ sudo wget http://sourceforge.net/projects/open-jtalk/files/Open%20JTalk/open_jtalk-1.08/open_jtalk-1.08.tar.gz
$ sudo tar zxvf open_jtalk-1.08.tar.gz

ビルド、コンパイル、インストール
$ cd /tmp/open_jtalk-1.08
$ sudo ./configure --with-charset=UTF-8
$ sudo make
$ sudo paco -lD "make install"
あっまたpacoってやつ使ってる。

確認
下記のコマンドを実行し「hts_engine_API-1.09」と「open_jtalk-1.08」が表示されればOKです。

$ paco -a

hts_engine_API-1.09 open_jtalk-1.08
ようし、出た。ここまでOK。


辞書ファイルの入手
辞書ファイル(version 1.08) をダウンロードして、/usr/local/share/の下に置きます。
/tmp にダウンロード・解凍して配置
$ cd /tmp
$ sudo wget http://sourceforge.net/projects/open-jtalk/files/Dictionary/open_jtalk_dic-1.08/open_jtalk_dic_utf_8-1.08.tar.gz
$ sudo tar zxvf open_jtalk_dic_utf_8-1.08.tar.gz
$ sudo mkdir /usr/local/share/open_jtalk
$ sudo mv /tmp/open_jtalk_dic_utf_8-1.08 /usr/local/share/open_jtalk/

MMDAgent音声ファイルの入手
MMDAgent(version 1.4 ) をダウンロードして、/usr/local/share/の下に置きます。
/tmp にダウンロード・解凍して配置

$ cd /tmp
$ sudo wget http://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/MMDAgent_Example-1.4/MMDAgent_Example-1.4.zip
$ sudo unzip MMDAgent_Example-1.4.zip
$ sudo mkdir /usr/local/share/hts_voice
$ sudo mv /tmp/MMDAgent_Example-1.4/Voice/mei /usr/local/share/hts_voice/

しゃべらせる
シェルの作成
/usr/local/bin の下にopen_jtalkを使って喋らせるためのシェルを作成します。
$ sudo vim /usr/local/bin/jsay
私はvimを使います。
ところでこのjsayってどういうファイルなんだろう?pyでもないのか。vimで作った後で調べたらシェルスクリプトって書いてあった。

シェルスクリプト - Wikipedia

シェルスクリプトは、オペレーティングシステムのシェルまたはコマンドラインインタプリタ向けに書かれたスクリプトである。シェルスクリプトは他のツールを組み合わせるためのグルー型のドメイン固有言語とみなされることもある[1]。シェルスクリプトで書かれる典型的処理としては、ファイル操作、プログラム実行、テキストの印刷などがある。
うん、わからん。けどそういうものを作ったらしい。
--------------------------------
#!/bin/sh

# 引数チェック
CMDNAME=`basename $0`
if [ $# -lt 1 ]; then
echo "Usage: ${CMDNAME} [ text ]" 1>&2
exit 1
fi


# 定数定義(出力ファイル名、辞書の場所、音声データの場所)
TMPFILE=`mktemp /tmp/tmp.XXXXXXXX.wav`
DIC=/usr/local/share/open_jtalk/open_jtalk_dic_utf_8-1.08/
VOICE=/usr/local/share/hts_voice/mei/mei_normal.htsvoice


# 音声データ生成
echo "$1" | open_jtalk \
-x ${DIC} \
-m ${VOICE} \
-ow ${TMPFILE} && \


# 生成した音声データを再生する
aplay --quiet ${TMPFILE}


# 生成した音声データを削除する
rm -f ${TMPFILE}

# 終了
exit 0
--------------------------------
「jsay」ファイルを保存したら、実行権限を付けます。

$ sudo chmod +x /usr/local/bin/jsay

以下のようにjsayの引数に、喋らせたい文字列を渡すことでしゃべらせることができます。
$ jsay こんにちは
メイさんのノーマルの声で喋った。jsayの中身にもmei_normal.htsvoiceを使うこと書いてあるしね。特にトラブルはなかったけど、黒い背景に白い文字がずっと流れていくのを見つめていた。

これでようやっと下ごしらえ終了だよ。

 

いよいよ天気予報を喋ってもらう

livedoorの天気予報APIWeather Hacks」を使用します。
商用利用は認められておらず、個人利用に限るっぽい

talk_weather.pyファイルを作成する。とりあえずいつもの/home/piに置いておいたらいいだろ。

$ sudo vim talk_weather.py

--------------------------------
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import shlex
import subprocess
from datetime import datetime
import urllib2
import json
CMD_SAY = 'jsay'
def main():
say_datetime()
say_weather()
return
def say_datetime():
d = datetime.now()
text = '%s月%s日、%s時%s分%s秒' % (d.month, d.day, d.hour, d.minute, d.second)
text = CMD_SAY + ' ' + text
print text
proc = subprocess.Popen(shlex.split(text))
proc.communicate()
return
def say_weather():
city = '130010'; # Tokyo 他の地域の方は、番号を変えてください。
json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL
weather_text = u'%sの天気は%sです。'
temperature_text = u'%sの予想最高気温、%s度、予想最低気温、%s度です。'
try:
r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
obj = json.loads( unicode(r.read()) )
title = obj['title']
forecasts = obj['forecasts']
# TODAY
cast = forecasts[0]
temperature = cast['temperature']
today_w_txt = weather_text % (cast['dateLabel'], cast['telop'])
today_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
# TOMMOROW
cast = forecasts[1]
temperature = cast['temperature']
tommorow_w_txt = weather_text % (cast['dateLabel'], cast['telop'])
# SAY
weather_str = title + ' ' + today_w_txt + ' ' + today_t_txt + ' ' + tommorow_w_txt
weather_str = weather_str.encode('utf-8')
text = '''%s '%s' ''' % (CMD_SAY, weather_str)
print text
proc = subprocess.Popen(shlex.split(text))
proc.communicate()
finally:
r.close()
return
### Execute
if __name__ == "__main__":
main()
--------------------------------

さー喋ってもらうぞ。

$ python talk_weather.py

jsay 12月17日、23時51分50秒
Traceback (most recent call last):
File "talk_weather.py", line 52, in <module>
main()
File "talk_weather.py", line 11, in main
say_weather()
File "talk_weather.py", line 35, in say_weather
today_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
TypeError: 'NoneType' object has no attribute '__getitem__'

12月17日、23時51分50秒は言ってくれるけどそれ以降言ってくれない。うーん?

www.tapun.net

参考サイトにも最高気温・最低気温がnullになるとか書いてある。この問題の対処法として下記が紹介されていた。

talk_weather2.pyというものを下記の内容で作っておられる。
--------------------------------
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import shlex
import subprocess
from datetime import datetime
import urllib2
import json
CMD_SAY = 'jsay'
def main():
say_datetime()
say_weather()
say_temperature()
return
def say_datetime():
d = datetime.now()
text = '%s月%s日、%s時%s分%s秒' % (d.month, d.day, d.hour, d.minute, d.second)
text = CMD_SAY + ' ' + text
print text
proc = subprocess.Popen(shlex.split(text))
proc.communicate()
return
def say_weather():
city = '130010'; # Tokyo
json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL
weather_text = u'%sの天気は%sです。'
try:
r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
obj = json.loads( unicode(r.read()) )
title = obj['title']
forecasts = obj['forecasts']
# TODAY
cast = forecasts[0]
temperature = cast['temperature']
today_w_txt = weather_text % (cast['dateLabel'], cast['telop'])
# TOMMOROW
cast = forecasts[1]
temperature = cast['temperature']
tommorow_w_txt = weather_text % (cast['dateLabel'], cast['telop'])
# SAY
weather_str = title + ' ' + today_w_txt + ' ' + tommorow_w_txt
weather_str = weather_str.encode('utf-8')
text = '''%s '%s' ''' % (CMD_SAY, weather_str)
print text
proc = subprocess.Popen(shlex.split(text))
proc.communicate()
finally:
r.close()
return
def say_temperature():
city = '130010'; # Tokyo
json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL
temperature_text = u'%sの予想最高気温、%s度、予想最低気温、%s度です。'
try:
r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
obj = json.loads( unicode(r.read()) )
title = obj['title']
forecasts = obj['forecasts']
# TODAY
cast = forecasts[0]
temperature = cast['temperature']
today_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
# TOMMOROW
cast = forecasts[1]
temperature = cast['temperature']
tommorow_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
# SAY
temperature_str = title + ' ' + today_t_txt + ' ' + tommorow_t_txt
temperature_str = weather_str.encode('utf-8')
text = '''%s '%s' ''' % (CMD_SAY, temperature_str)
print text
proc = subprocess.Popen(shlex.split(text))
proc.communicate()
finally:
r.close()
return
### Execute
if __name__ == "__main__":
main()
--------------------------------

今度こそ喋ってくれよ。
$ python talk_weather2.py
jsay 12月18日、0時5分15秒
jsay '東京都 東京 の天気 今日の天気は晴れです。 明日の天気は晴時々曇です。'
Traceback (most recent call last):
File "talk_weather2.py", line 78, in <module>
main()
File "talk_weather2.py", line 12, in main
say_temperature()
File "talk_weather2.py", line 65, in say_temperature
tommorow_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
TypeError: 'NoneType' object has no attribute '__getitem__'

となる。
12月18日、0時5分15秒
東京都 東京 の天気 今日の天気は晴れです。 明日の天気は晴時々曇です。

とまでは言ってくれるようになった!
予想最高気温、予想最低気温は何故か喋ってくれないのねー。これはどうしたもんかね。
まぁ、天気予報喋ってくれるだけありがたいかねぇ。

他にも天気予報喋らせてる人いないかな。調べてみたい。