Raspberry piで音声認識(julius)を使用して特定の言葉に反応
ストックじゃなくて、いいねくださいw
前提条件
- こちらまでできていることを前提で進んで行きます。
最初に、juliusをmoduleモードで実行し、juliusのプロセスIDを取得するシェルスクリプトを作成します。
#!/bin/sh
julius -C ~/julius-4.4.2/julius-kit/dictation-kit-v4.3.1-linux/word.jconf -module > /dev/null &
echo $! #プロセスIDを出力
sleep 2 #2秒間スリープ
- -module
- juliusをモジュールモードで実行します。
-
/dev/null
- 標準出力は捨てます。
- &> /dev/null
-
/dev/nullの前に&をつけると標準出力と標準エラーを捨てます。今回はエラーが見えた方が良いと思いますのでエラーは捨てません。
-
- echo $!
- プロセスIDを出力.
julius-start.shの実行
./ julius-start.sh
プロセスIDが出力されて数秒後終了すると成功です。
次に、特定の言葉に対してリアクションを返すpythonプログラム
今回は音声ファイルを再生するようにします。
julius-start.shと同ディレクトリにvoice.pyを作成します。
import socket
import xml.etree.ElementTree as ET
import os
import subprocess
import time
host = '127.0.0.1' #localhost
port = 10500 #julisuサーバーモードのポート
def main():
p = subprocess.Popen(["./julius-start.sh"], stdout=subprocess.PIPE, shell=True) # julius起動スクリプトを実行
pid = str(p.stdout.read().decode('utf-8')) # juliusのプロセスIDを取得
time.sleep(3) # 3秒間スリープ
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port)) #サーバーモードで起動したjuliusに接続
try:
data = '' # dataの初期化
killword ='' # 前回認識した言葉を記憶するための変数
while 1:
#print(data) # 認識した言葉を表示して確認
if '</RECOGOUT>\n.' in data:
root = ET.fromstring('<?xml version="1.0"?>\n' + data[data.find('<RECOGOUT>'):].replace('\n.', ''))
for whypo in root.findall('./SHYPO/WHYPO'):
word = whypo.get('WORD')# juliusで認識したWORDをwordに入れる
if word == u'こんにちは':
if killword != ('こんにちは'):
os.system("aplay '/home/pi/Music/konnichiwa.wav'")# 音声ファイルを再生
killword = ('こんにちは')
elif word == u'おはよう':
if killword != ('おはよう'):
os.system("aplay '/home/pi/Music/ohayo.wav'")
killword = ('おはよう')
elif word == u'こんばんは':
if killword != ('こんばんは'):
os.system("aplay '/home/pi/Music/konbanwa.wav'")
killword = ('こんばんは')
elif word == u'ばいばい':
if killword != ('ばいばい'):
os.system("aplay '/home/pi/Music/bye.wav'")
killword = ('ばいばい')
elif word == u'せもぽぬめ':
os.system("aplay '/home/pi/Music/secret.wav'")
killword = ('シークレット')
elif word == u'おやすみ':
os.system("aplay '/home/pi/Music/oyasumi.wav'")
killword = ('おやすみ')
else:
os.system("aplay '/home/pi/Music/name.wav'")
killword = ('name')
print (word) # wordを表示
data = '' # dataの初期化
else:
data += str(client.recv(1024).decode('utf-8')) #dataが空のときjuliusからdataに入れる
print('NotFound')# juliusに認識する言葉がない。認識していない。
except KeyboardInterrupt:
p.kill()
subprocess.call(["kill " + pid], shell=True)# juliusのプロセスを終了する。
client.close()
if __name__ == "__main__":
main()
XMLでエラー出るって話聞いたのでXMLを使わない方法で・・・
# -*- coding: utf-8 -*-
import subprocess
import socket
import string
import os
import random
import numpy as np
from numpy.random import *
import time
host = "localhost"
port = 10500
p = subprocess.Popen(["./julius_start.sh"], stdout=subprocess.PIPE, shell=True)
pid = str(p.stdout.read().decode('utf-8')) # juliusのプロセスIDを取得
time.sleep(5)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
data =""
killword =""
while True:
while (1):
if '</RECOGOUT>\n.' in data:
#data = data + sock.recv(1024)
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)
if strTemp == 'バイバイ':
if killword != 'バイバイ':
print ("Result: " + strTemp)
os.system("aplay '/home/pi/Music/byebye.wav'")
print ("<<<please speak>>>")
killword = "バイバイ"
elif strTemp == 'おはよう':
if killword != 'おはよう':
print ("Result: " + strTemp)
os.system("aplay '/home/pi/Music/ohayo.wav'")
print ("<<<please speak>>>")
killword = "おはよう"
elif strTemp == 'こんにちは':
if killword != "こんにちは":
print ("Result: " + strTemp)
os.system("aplay '/home/pi/Music/konnichiwa.wav'")
print ("<<<please speak>>>")
killword = "こんにちは"
elif strTemp == 'こんばんは':
if killword != "こんばんは":
print ("Result: " + strTemp)
os.system("aplay '/home/pi/Music/konbanwa.wav'")
print ("<<<please speak>>>")
killword = "こんばんは"
elif strTemp == 'こんばんは':
if killword != "こんばんは":
print ("Result: " + strTemp)
os.system("aplay '/home/pi/Music/konbanwa.wav'")
print ("<<<please speak>>>")
killword = "こんばんは"
else:
print("Result:" + strTemp)
i = randint(3)
if i == 0:
os.system("aplay: '/home/pi/Music/aizuchi00.wav'")
elif i == 1:
os.system("aplay: '/home/pi/Music/aizuchi01.wav'")
elif i == 2:
os.system("aplay: '/home/pi/Music/aizuchi02.wav'")
print ("<<<please speak>>>")
data = ""
else:
data += str(sock.recv(1024).decode('utf-8'))
まとめ
今回はwavを再生するようにしましたが、テレビのon,offや部屋の明かりon,offなど声でできるようにすると面白しろそうですね。
また、パターンが少ないので簡単なif文で書きましたが、量が多くなると面倒なのでその場合はDBを使う用にすると良いと思います。
DBを使用するといろいろ応用できます。
また、whypo.get('WORD')はWORDではないものもgetすることができます。
それはjuliusのmoduleモードについてを参照すると良いでしょう。