LoginSignup
37
43

More than 3 years have passed since last update.

Raspberry piで音声認識(julius)を使用して特定の言葉に反応

Last updated at Posted at 2017-11-08

Raspberry piで音声認識(julius)を使用して特定の言葉に反応

ストックじゃなくて、いいねくださいw

前提条件

  • こちらまでできていることを前提で進んで行きます。

最初に、juliusをmoduleモードで実行し、juliusのプロセスIDを取得するシェルスクリプトを作成します。

julius-start.sh
#!/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を作成します。

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を使わない方法で・・・

voice2.py

# -*- 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モードについてを参照すると良いでしょう。

37
43
12

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
43