2018-01-06 14:33 | カテゴリ:コンピュータ

RasPiの勉強を続けています。
インターネットから天気予報を読み出すことができる様で、以前に購入したRasPiの本を見ていたらやり方などが詳しく紹介されていました。

(RP0401)
RP0401.jpg


(RP0402)
RP0402.jpg

これによりますと、LivedoorのサイトにWEBで接続して、特定のコマンドを送信すると、コードで指定した地域の天気予報の概況、向こう三日間の天気と気温をえることができるのです。
ここを利用して、RasPiのプログラムでコマンドデータを送信し、天気データを受信、そのごその受信データを解析して、必要な情報を抜き出して利用できるようです。

今回は、この高度なプログラミングにちょっと挑戦してみようと思います。





続きは、、、、


参考書のプログラムを見ていて、思ったのですが、天気や気温を読み込めたとして、それをどの様に表示させるか?です。

気温などなら先日製作した「ドットマトリクスLED」にスクロール表示させればいいのですが、天気は文字なので、その文字を受信データから判読して、ASCII文字に変換して表示させなければなりません。
(WEBから取得した天気データは、漢字かな交じりの日本語です)

なにか良い手は無いかとWEBを探していたら、「RasPiで日本語を発声」させるサイトが見つかりました。


「Raspberry Pi 3で日本語音声を合成して喋らせる方法(OpenJTalk編)」

http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_open_jtalk/

Copyright (c)1996-2017 FREE WING, Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator
http://www.neko.ne.jp/~freewing/


表示が難しいのなら、しゃべらせればよさそうです。

こちらでは、個人使用でFREEのOpenJTalkを使用して簡単なコマンドを与えると、日本語文章をしゃべる機能を実現できるようです。

早速、こちらの手順に従って、「しゃべらせる」準備を進めました。

(1)RasPiの音の出力設定

もともとRasPiには、音を出力する機能があります。
設定からONにしておきます。

(2)音の再生の確認

音声出力の動作の確認をします。

音量の設定は、このコマンドを実行して、RasPiのコンソール画面から行えます。
$ alsamixer


スピーカーから、ちゃんと音が出るかの確認は、
$ speaker-test -t sine -f 800

で行えます。
RasPiのスピーカー出力ジャックにスピーカーかヘッドフォンを繋いで音が出るか確認してください。


$ aplay /usr/share/sounds/alsa/Front_Center.wav


(3)実際に日本語をしゃべらせる!

RasPiにOpenJTalkのパッケージをインストールして、日本語発声の準備をします。


$ sudo apt-get -y install open-jtalk libhtsengine1 open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001

このコマンドをRasPiのコマンドコンソールから入力します。

$ open_jtalk -h

さらにこれも入力します。

これで準備が出来ました。
コマンドラインから以下のコマンドを入力すると発声します。

$ echo "私の名前はビビッドです。どうぞよろしく。" | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -ow ~/ojtalk.wav
$ aplay ~/ojtalk.wav

 男の声で「私の名前はビビッドです。どうぞよろしく。」と喋ります。

結構ちゃんとした日本語に聞こえます。
この方法は、音声をwavファイルに一旦変換したうえで、それを再生して、発声する仕組みです。

これだと使いにくいので、直接発声する様にしたのがこれです。


$ echo "おはようございます、お元気ですか?" | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -ow /dev/stdout | aplay --quiet

ここまでくるとプログラム中で文字変数を与えて発声させたいですよね?
その前に、この男性の声による発声ソフトでは、連続18文字を超えて発声させると、それ以降の発声が、極端に遅い発声になるバグがあるようです。

ちなみに、少し長い文章を発声させてみてください。
途中からずいぶん間の抜けた声になりませんでしたか??(笑)

それを避けるためには、バグの解消のパッチを導入するか、別の女声のソフトに変更するかです。
私は、パチソフトを当てる実力がなかったので、女声の発声に切り替えました。

この辺りの詳細も先ほどの「猫屋敷工房」さんのサイトに詳細に書かれていますので、是非ご参照ください。

女声の場合のセットアップ「猫屋敷工房」さんのサイトより抜粋

$ wget http://tenet.dl.sourceforge.net/project/mmdagent/MMDAgent_Example/MMDAgent_Example-1.6/MMDAgent_Example-1.6.zip
 MMDAgent_Example-1.6.zip 11MBをダウンロードする

$ unzip MMDAgent_Example-1.6.zip
$ mv -f ./MMDAgent_Example-1.6/Voice/mei/ ./Voice_mei/
$ rm -r -f ./MMDAgent_Example-1.6

その後

$ echo "私の名前は、ビビッドです。どうぞよろしく。" | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m ~/Voice_mei/mei_normal.htsvoice -ow /dev/stdout | aplay --quiet


で、発声します。

これらを踏まえて、WEBの天気データにアクセスして、データを取得し、天気概況と天気、気温をしゃべるプログラムを作成しました。

ほとんどは、「猫屋敷工房」さんのサイトの受け売りと、購入した参考書「実例で学ぶRaspberryPi電子工作」の例題をつなげて作りました。

まずは、男声の例です。



今回の例では上手くしゃべっていますが、句読点の間隔が長く、長文を発生させるとものすごくゆっくりしゃべることがあります。



途中で発声が超スローになって、笑ってしまいます。


次は女声です。




今度はちゃんとスムースに話しています。

時々変な発声もあります。
「寒気」を、「カンキ」と言うべきところで、「サムケ」と発声したりします。
辞書の問題でしょうが、無償ソフトなので、良しとしました。(笑)



RasPiの再トライは、一応ここまでで置いておきます。

次は、模型にしようかと思いますが、何にチャレンジするか、決めていません。

(注意)

最後に今回のプログラムを載せておきます。(Python3です)
事前に「猫屋敷工房」さんのサイトを参考にして、女声の発生ができるように設定しておく必要があります。
http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_open_jtalk/

---
ご注意
---

今気づいたのですが、下記のPythonのプログラムは、タブが欠落しています。
本来なら、Pythonはインデントで段落を付けて、区切りをつけていますが、タブが無いと、正常動作出来ません。
参考と言う事で、ご覧いただければ幸いです。


#=====================================================================
# WEBサイトから天気データを受信し概況を日本語で発声する
#
#=====================================================================


#---------------------------------------
# 初期設定
#---------------------------------------

#---------------------------
# 音声処理初期設定
#---------------------------
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# urllib パッケージを使ってインターネット上のリソースを取得するには
# https://docs.python.org/ja/3.6/howto/urllib2.html
#import urllib
#import urllib2

import urllib.request, urllib.parse, urllib.error

# 19.2. json — JSON エンコーダおよびデコーダ
# https://docs.python.org/ja/3.6/library/json.html#module-json
import json
import subprocess


#--------------------------
# LEDとSPIの初期設定
#--------------------------

import RPi.GPIO as GPIO
import spidev
from time import sleep
GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.OUT) #Monitor用LED
GPIO.setup(24, GPIO.OUT) #LEDのCS用

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 10000000# 10 MHz
spi.mode = 0x00





#-----------------------------------------------------------------------------
# 発声の関数設定(男声)
#
#------------------------------------------------------------------------------
def voice(message):
command = "echo \"%s\"" % message
#以下は男性の声
command += " | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -ow /dev/stdout"
#以下は女性の声
#command += " | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m ~/Voice_mei/mei_normal.htsvoice -ow /dev/stdout"
command += " | aplay --quiet"
proc = subprocess.Popen(
command,
shell = True,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
# 終了を待つ場合(同期する)は下記のコメントを取る
proc.communicate()



#-----------------------------------------------------------------------
# 発声の関数設定(女声)
#
#-----------------------------------------------------------------------
def voice_ldy(message):
command = "echo \"%s\"" % message
command += " | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m ~/Voice_mei/mei_normal.htsvoice -ow /dev/stdout | aplay --quiet"
command += " | aplay --quiet"
proc = subprocess.Popen(
command,
shell = True,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)

# 終了を待つ場合(同期する)はコメントを取る
proc.communicate()








#=======================================================================
# メイン処理
#=======================================================================

try:

# お天気Webサービス(Livedoor Weather Web Service / LWWS)
# http://weather.livedoor.com/weather_hacks/webservice
url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=280010'
req = urllib.request.Request(url)
response = urllib.request.urlopen(req)
print('----')
print(response.getcode())
print(response.geturl())
print(response.info())

the_page = response.read().decode("utf-8")
jsonObject = json.loads(the_page, 'utf-8')
#the_page = response.read()
#jsonObject = json.loads(the_page)
print('----')
# print(jsonObject['description']['text'])
# print(jsonObject['description']['publicTime'])


speechString = jsonObject['description']['text']
# 改行が有ると切れてしまうので改行を文字列置換で取り除く
speechString = speechString.replace("\n", "")
#print(speechString)

print(jsonObject['description']['publicTime'])


num = len(speechString.split("。"))

for i in range(num -1):
print(str(speechString.split("。")[i]))
voice_ldy(str(speechString.split("。")[i]))





# 終了を待つ場合(同期する)はコメントを取る
#proc.communicate()

#------------------------------------
# 天気、気温等を読み出す
#------------------------------------

for forecast in jsonObject['forecasts']:

if forecast['temperature']['min'] != None:
min = "最低気温は、" + forecast['temperature']['min']['celsius'] + "度、"
else:
min = '--'

if forecast['temperature']['max'] != None:
max = "最高気温は、" + forecast['temperature']['max']['celsius'] + "度"
else:
max = '--'

s = forecast['dateLabel'] + ', ' + forecast['telop'] + '' + min + '' + max + "です。"

print(str(s))
voice_ldy(str(s))



#----------------------------
# キーボード割り込み発生処理
#----------------------------

except KeyboardInterrupt:
pass

GPIO.cleanup()
spi.close() #SPI終了処理

関連記事

管理者のみに表示する