Last active
September 2, 2021 16:37
-
-
Save tam17aki/aaa273e868a10ffc7857befc14d52a65 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: UTF-8 | |
import subprocess | |
import numpy as np | |
import pyopenjtalk | |
import speech_recognition as sr | |
import urllib3 | |
from bs4 import BeautifulSoup | |
from scipy.io import wavfile | |
# 合成した音声ファイルの一時格納場所 | |
OUT_WAV = "/tmp/tts.wav" | |
# 地域名と地域コードをまとめた辞書テーブル | |
# | |
# 例 | |
# YAHOO_DICT["愛知"]ならば | |
# ("名古屋市", 5110, "https://weather.yahoo.co.jp/weather/jp/23/") | |
# という「タプル」が得られる | |
YAHOO_DICT = { | |
"愛知": ("名古屋市", 5110, "https://weather.yahoo.co.jp/weather/jp/23/"), | |
"岐阜": ("岐阜市", 5210, "https://weather.yahoo.co.jp/weather/jp/21/"), | |
"三重": ("津市", 5210, "https://weather.yahoo.co.jp/weather/jp/24/"), | |
} | |
def speak_text(text): | |
"""音声合成をする関数""" | |
# 音声合成(テキストデータ→音声データ) | |
wav, sr = pyopenjtalk.tts(text) | |
# wavファイルに保存 | |
wavfile.write(OUT_WAV, sr, wav.astype(np.int16)) | |
# 保存したwavファイルを再生 | |
subprocess.run("afplay " + OUT_WAV, shell=True) | |
def speak_weather(query, day=None): | |
"""Yahoo天気予報をスクレイピングして音声合成により喋らせる関数 | |
取得したHTMLをパースするコードは以下を参考にした | |
https://www.ishilog.com/python-scraping-yahoo-weather/ | |
""" | |
http = urllib3.PoolManager() | |
place = YAHOO_DICT[query][0] # 地域名 | |
areacode = YAHOO_DICT[query][1] # 地域コード | |
url = YAHOO_DICT[query][2] + str(areacode) + ".html" | |
# HTMLをパースして解析 | |
instance = http.request("GET", url) | |
soup = BeautifulSoup(instance.data, "html.parser") | |
# 地域の予報部分を抽出 | |
rs = soup.find(class_="forecastCity") | |
rs = [i.strip() for i in rs.text.splitlines()] | |
rs = [i for i in rs if i != ""] | |
# テキスト決定 | |
if day == "今日": | |
text = "今日の" + place + "の天気は" + rs[1] + "です。" | |
elif day == "明日": | |
text = "明日の" + place + "の天気は" + rs[19] + "です。" | |
else: | |
text = ( | |
rs[0] + "の" + place + "の天気は" + rs[1] + "、" | |
"明日の" + place + "の天気は" + rs[19] + "です。" | |
) | |
# テキスト表示 | |
print(text) | |
# 音声合成 | |
speak_text(text) | |
if __name__ == "__main__": | |
while True: | |
# マイクからの音声入力 | |
r = sr.Recognizer() | |
with sr.Microphone() as source: | |
print("話しかけてください!(Ok Google)") | |
audio = r.listen(source) # 音声取得 | |
try: | |
# 日本語でGoogle音声認識 | |
# textには音声認識結果が文字列として入っている | |
text = r.recognize_google(audio, language="ja-JP") | |
except sr.UnknownValueError: | |
print("Google音声認識は音声を理解できませんでした。") | |
except sr.RequestError as e: | |
print("Google音声認識からの結果を" "要求できませんでした;" " {0}".format(e)) | |
else: | |
# 音声認識結果を表示 | |
print("音声認識結果:{0}".format(text)) | |
day = None | |
if "Ok" in text and "Google" in text: # wake word "Ok Google" | |
if "天気予報" in text or "天気" in text: | |
if "今日" in text: | |
day = "今日" | |
elif "明日" in text: | |
day = "明日" | |
if "名古屋" in text or "愛知" in text: | |
speak_weather("愛知", day) | |
elif "岐阜" in text: | |
speak_weather("岐阜", day) | |
elif "三重" in text: | |
speak_weather("三重", day) | |
else: | |
speak_text("東海三県を指定してください。") | |
elif "ありがとう" in text: | |
print("こちらこそ、ありがとうございます。") | |
speak_text("こちらこそ、ありがとうございます。") | |
break # while 脱出 -> プログラム終了 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment