乗車日記

自転車ときのこ

音声認識と合成音声実装

ボタンを押すとニュースが流れる装置に音声認識と合成音声機能を入れました。マイクに向かって「ぶんちゃん、NHKニュースを聞かせて」のように話すとニュースが流れ、「ぶんちゃん、タイマースタート」のように話すとタイマー(実際はストップウォッチ)が起動するようにしました。ストップウォッチは1分ごとに「今何分経過」と喋り、また「今何分?」と聞くと、現在の経過時間を喋ってくれるようにしました。タイマーの仕様は全て自分が紅茶やコーヒーを入れる時に必要な要件に合わせてあります。Siriのタイマーにいろいろ不満があったもので。。。。

使用した音声認識ソフトjuliusは河原先生のところで開発されたものですが、導入についてはこちらのページを参考にしました。制御プログラム自体はこちらのページを参考にしました。また、合成音声生成ソフトOpenJtalkの導入にあたってはこちらのページを参考にしました。

ちなみに、ラズベリーパイ は最新のmodel 3Bを買いました。4300円です。スピーカーやマイクは死蔵されていたものです。


# -*- coding: utf-8 -*-
import subprocess
import socket
from time import sleep
import time

host = "localhost"
port = 10500
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
data =""
timer_pid=-1
while True:
  if '</RECOGOUT>\n.' in data:
    strTemp = ""
    for line in data.split('\n'):
      index = line.find('WORD="')
      if index != -1:
        line = line[index+6:line.find('"',index+6)]
      strTemp += str(line)+" "
      print(strTemp)

    if ('文ちゃん' in strTemp) and ('NHKニュース' in strTemp):
      ret=subprocess.Popen(['pgrep','mplayer'],stdout=subprocess.PIPE).stdout.readlines()
      if len(ret)==0:
        mplayer_pid=-1
      else:
        mplayer_pid=int(ret[0])
      if('聞かせて' in strTemp) and (mplayer_pid==-1):
        subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','NHKニュースを流します'])
        sleep(3)
        subprocess.Popen(['sh','/home/pi/.podracer/pod.sh'])
      elif (('ストップ' in strTemp) or ('止めて' in strTemp)) and (mplayer_pid > 0):
        subprocess.Popen(['sh','/home/pi/.podracer/stop.sh'])
        subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','NHKニュースを止めました'])
      elif (('ストップ' in strTemp) or ('止めて' in strTemp)) and (mplayer_pid < 0):
        subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','NHKニュースは流してません'])
      elif mplayer_pid==-1:
        subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','NHKニュースを流します'])
        sleep(3)
        subprocess.Popen(['sh','/home/pi/.podracer/pod.sh'])
    if ('文ちゃん' in strTemp) and ('タイマー' in strTemp):
      if ('スタート'  in strTemp) and (timer_pid==-1):
        timer_pid=subprocess.Popen(['sh','/home/pi/scripts/timer.sh']).pid
        start_time=time.time()
      elif (('ストップ' in strTemp) or ('止めて' in strTemp)) and (timer_pid > 0):
        subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','タイマーを停止します'])
        subprocess.Popen(['kill',str(timer_pid)])
        timer_pid=-1
      elif (('ストップ' in strTemp) or ('止めて' in strTemp)) and (timer_pid ==-1):
        subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','タイマーは動かしてません'])
      elif ('何分' in strTemp) or ('今' in strTemp) or ('何秒' in strTemp):
        elapse=time.time()-start_time
        minutes=int(elapse/60)
        seconds=int(elapse-60*minutes)
        if minutes==0:
          subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','タイマーは今'+str(seconds)+'秒です'])
        else:
          subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','タイマーは今'+str(minutes)+'分'+str(seconds)+'秒です'])
      elif timer_pid==-1:
        timer_pid=subprocess.Popen(['sh','/home/pi/scripts/timer.sh']).pid
        start_time=time.time()
    if ('何分' in strTemp) or ('今' in strTemp) or ('何秒' in strTemp):
      elapse=time.time()-start_time
      minutes=int(elapse/60)
      seconds=int(elapse-60*minutes)
      if minutes==0:
        subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','タイマーは今'+str(seconds)+'秒です'])
      else:
        subprocess.Popen(['bash','/home/pi/scripts/jsay.sh','タイマーは今'+str(minutes)+'分'+str(seconds)+'秒です'])
    data=""
  else:
    data+=str(sock.recv(1024))