ラズパイを音声でシャットダウン
車にラズパイを持ち込んで使いたいけど
シャットダウンするときに困りそうなので
音声でシャットダウンできるようにする
bluetooth ボタンも考えたけど
ハズレをひくと買い直しになるし紛失を考えると
音声でシャットダウンし
シガーソケットから給電すればエンジンをかければ電源がはいる
音声認識エンジンJulius をまずはいれる
Raspberry Pi×JuliusとPythonでスマートスピーカー風にカメラを操作
Raspberry PiとJuliusで特定の単語を認識させる
を参考に
mkdir julius
cd julius/
wget https://github.com/julius-speech/julius/archive/v4.4.2.1.tar.gz
tar xvzf v4.4.2.1.tar.gz
cd julius-4.4.2.1/
でGit で取得し展開したファイルに移動
sudo apt-get install libasound2-dev libesd0-dev libsndfile1-dev
で必要なライブラリのインストール
Raspberry pi3B+でjuliusを動かせるようになるまでの覚書き(2019.3.10現在)
にあるように
RaspberryPi3b+の最新カーネルでは
snd-pcm-ossモジュールが含まれていないので
sudo apt-get install osspd-alsa
sudo apt-get install libasound2-dev
でサウンドドライバをインストール
./configure --with-mictype=alsa
make
sudo make install
でコンパイルしてインストール
次に音声認識パッケージの
ディクテーションキットの取得
cd ../
mkdir julius-kit
cd julius-kit/
wget https://osdn.net/dl/julius/dictation-kit-v4.4.zip
unzip dictation-kit-v4.4.zip
で取得
さらに必要なライブラリのインストール
sudo apt-get install alsa-utils sox libsox-fmt-all
次にマイクの設定
arecord -l
の結果が
**** ハードウェアデバイス CAPTURE のリスト ****
カード 2: Device [USB PnP Sound Device], デバイス 0: USB Audio [USB Audio]
サブデバイス: 1/1
サブデバイス #0: subdevice #0
これを元に
ALSADEV設定で使用デバイスを指定
vim ~/.profile
で設定ファイルを開き
export ALSADEV=hw:2
を最終行へ追記
hw;にはカード番号を記述
source ~/.profile
で設定反映
あとは起動して実験
cd ~/julius/julius-kit/dictation-kit-v4.4
julius -C main.jconf -C am-gmm.jconf -demo
起動はするけど精度が低すぎて使い物にならない
このため辞書ファイルを作成する
日本語入力ができるように mozc をインストール
sudo apt-get install fcitx-mozc
次に辞書ファイルの作成
cd ~/julius/
mkdir dict
cd dict/
sudo vim hello.yomi
でファイルを作成
おはよう おはよう
こんにちわ こんにちわ
として保存
左に認識させる言葉
右にはよみかたをひらがなで記述して
.yomi という拡張子で保存
区切りのスペースを半角にしないとバグるので注意
これを元に音素ファイルを作成する
このときに文字コードをUTF8 から EUC-JP に変換するので
iconv -f utf8 -t eucjp hello.yomi | ../julius-4.4.2.1/gramtools/yomi2voca/yomi2voca.pl | iconv -f eucjp -t utf8 > hello.phone
これでファイルが作成される
拡張子は
.phone となる
内容は
おはよう o h a y o u
こんにちわ k o N n i ch i w a
となる
次に構文ファイルの作成
これで
認識する文章の構成を定義している
sudo vim hello.grammar
でファイルを作成
S : NS_B HELLO NS_E
HELLO OHAYOU
HELLO KONNICHIWA
として保存
S : NS_B HELLO NS_E
で
NS_Bが文章の開始
NS_Eが文章の終了
という意味
HELLO OHAYOU
HELLO KONNICHIWA
の部分は
.phone ファイルの読みを大文字にしたもの
あとは語彙ファイルの作成
これはJulius に認識させたい言葉を定義するもので
拡張子は
.voca になる
sudo cp hello.phone hello.voca
でファイルをコピーし編集
% OHAYOU
おはよう o h a y o u
% KONNICHIWA
こんにちは k o N n i ch i w a
% NS_B
[s] silB
% NS_E
[/s] silE
というようにする
次に辞書ファイルへ変換
cd ~/julius/julius-4.4.2.1/gramtools/mkdfa/
mkdfa.pl ~/julius/dict/hello
を実行したがエラー
/home/pi/julius/dict/hello.grammar has 3 rules
/home/pi/julius/dict/hello.voca has 4 categories and 4 words
---
Now parsing grammar file
Error: parse error
Error: cannot open "/home/pi/julius/dict/hello.dfa.tmp"
---
no .dfa or .dict file generated
となる
このため
julius 辞書 自作
で検索
ラズパイ4日目①:Juliusで独自辞書を作成する
をみたところ
grammar ファイルの区切りで
:
で区切っていないので修正
cd julius/dict/
sudo vim hello.grammar
でファイル編集
S : NS_B HELLO NS_E
HELLO : OHAYOU
HELLO : KONNICHIWA
として保存
mkdfa.pl ~/julius/dict/hello
を実行すると
.dfa
.term
.dict
ファイルが生成される
これで独自辞書ができたので
音声認識をするため
julius -C ~/julius/julius-kit/dictation-kit-v4.4/am-gmm.jconf -nostrip -gram ~/julius/dict/hello -input mic
を実行
これで辞書ファイルへ登録した
おはよう
こんにちわ
だけは認識するようになるが
それ以外は表示されない
次に辞書の追加
Raspberry Pi×JuliusとPythonでスマートスピーカー風にカメラを操作
を参考に
.yomi ファイルを編集
おはよう おはよう
こんにちわ こんにちわ
電源オフ でんげんおふ
として保存
iconv -f utf8 -t eucjp hello.yomi | ../julius-4.4.2.1/gramtools/yomi2voca/yomi2voca.pl | iconv -f eucjp -t utf8 > hello.phone
を実行
sudo vim hello.grammar
でファイルを編集
S : NS_B HELLO NS_E
HELLO : OHAYOU
HELLO : KONNICHIWA
HELLO : DENGENNOHU
として保存
sudo vim hello.voca
でファイルを編集
% OHAYOU
おはよう o h a y o u
% KONNICHIWA
こんにちは k o N n i ch i w a
% DENGENNOHU
電源オフ d e N g e N o f u
% NS_B
[s] silB
% NS_E
[/s] silE
として保存
mkdfa.pl ~/julius/dict/hello
で辞書ファイル作成
julius -C ~/julius/julius-kit/dictation-kit-v4.4/am-gmm.jconf -nostrip -gram ~/julius/dict/hello -input mic
で
電源オフ
と認識されるのがわかる
次にモジュールモードでJulius の起動
julius -C ~/julius/julius-kit/dictation-kit-v4.4/am-gmm.jconf -nostrip -gram ~/julius/dict/hello -input mic -module
これで Julius がサーバとなり
python プログラムとの通信待ちになる
次に
sudo vim speech.py
でファイルを区制
ラズパイと音声認識でLチカ
も参考に
いくつかコードも調べてみた
# -*- coding: utf-8 -*-
はpython3 なら記載不要
なおインストールしたままの状態だと
python --version
で調べると
Python 2.7.16
Python で文頭に記載する文字コードの「アレ」の名称(なんちゃら UTF-8 みたいなやつ)
を参考に
ファイルの内容は
# -*- coding: utf-8 -*-
import socket
host = 'localhost' # Raspberry PiのIPアドレス
port = 10500 # juliusの待ち受けポート
# パソコンからTCP/IPで、自分PCのjuliusサーバに接続
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
res = ''
while True:
# 音声認識の区切りである「改行+.」がくるまで待つ
while (res.find('\n.') == -1):
# Juliusから取得した値を格納していく
res += sock.recv(1024)
# 音声XMLデータから、<WORD>を抽出して音声テキスト文に連結する
word =''
for line in res.split('\n'):
# Juliusから取得した値から認識文字列の行を探す
index = line.find('WORD=')
# 認識文字列があったら...
if index != -1:
# 認識文字列部分だけを抜き取る
line = line[index + 6 : line.find('"', index + 6)]
# 文字列の開始記号以外を格納していく
if line != '[s]':
word = word + line
# 「電源オフ」という文字列を認識したら...
if word == '電源オフ':
print("電源オフ")
res =''
この後に
sudo python speech.py
とすると
マイクで
電源オフ
と話しかけると
電源オフ
と表示される
これで音声の認識はできたので
次に
python で linux コマンドの実行
これは subprocess モジュールを使うことでできる
Python: subprocessでOSコマンドを実行する
Pythonでシェルコマンドを実行する
Pythonからシェルコマンドを実行!subprocessでサブプロセスを実行する方法まとめ
を参考に
使い方は
subprocess.run([“実行したいコマンド”,”オプションなど”,…])
でOK
今回はshutdown コマンドを使うので
Raspberry Piの電源をブラウザからOFF
を参考に
# -*- coding: utf-8 -*-
import socket
import subprocess
cmd = "sudo shutdown -h now"
host = 'localhost' # Raspberry PiのIPアドレス
port = 10500 # juliusの待ち受けポート
# パソコンからTCP/IPで、自分PCのjuliusサーバに接続
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
res = ''
while True:
# 音声認識の区切りである「改行+.」がくるまで待つ
while (res.find('\n.') == -1):
# Juliusから取得した値を格納していく
res += sock.recv(1024)
# 音声XMLデータから、<WORD>を抽出して音声テキスト文に連結する
word =''
for line in res.split('\n'):
# Juliusから取得した値から認識文字列の行を探す
index = line.find('WORD=')
# 認識文字列があったら...
if index != -1:
# 認識文字列部分だけを抜き取る
line = line[index + 6 : line.find('"', index + 6)]
# 文字列の開始記号以外を格納していく
if line != '[s]':
word = word + line
# 「電源オフ」という文字列を認識したら...
if word == '電源オフ':
print("電源オフ")
subprocess.call(cmd, shell=True)
res =''
として保存
再度
sudo python speech.py
を実行し
マイクに電源オフと話すと
電源オフと表示された後にラズパイの電源が落ちる