PCでPythonアプリをデバッグしたいので音声強化版PaPeRo i の音声認識アプリをリモートホストで動かすで音声認識やおしゃべり発話(papebot.do_chatbot_operation())をリモートホストから利用できる様にしてみましたが、この方法でplay_song()を呼んでもパペロは歌ってくれません(歌う前に発話、発話完了チェックのシーケンスが入るためと思われます)。そこでPCなどのリモートホストからパペロに歌わせることができないか調べてみました。
パペロの「歌」とは
パペロの歌は/nvm/papebot/data/songsにあるwavファイルの様です。
linaro@tinkerboard:/nvm/papebot/data/songs$ ls
akatonbo.txt donguri.txt kutsuganaru.txt nanatsunoko.txt sakura.txt
akatonbo.wav donguri.wav kutsuganaru.wav nanatsunoko.wav sakura.wav
linaro@tinkerboard:/nvm/papebot/data/songs$ head -100 *.txt
==> akatonbo.txt <==
赤とんぼ
==> donguri.txt <==
どんぐりころころ
==> kutsuganaru.txt <==
くつがなる
==> nanatsunoko.txt <==
ななつの子
==> sakura.txt <==
さくら
xxxx.txtが曲名のテキストファイルでxxxx.wavが歌声の音声データということだと思われます。これは仕様ではなく推測なので、下記の方法はバージョンが変わると使えなくなる可能性があることにご留意ください。
コマンドで歌わせる
実行ホストのwavファイルを音声強化版パペロ本体のスピーカーで再生させることは、sshコマンドで可能です(ノーマルPaPeRo i ではエラーになります)。
linaro@tinkerboard:/nvm/papebot/data/songs$ cat nanatsunoko.wav | ssh cli@aterm.me aplay -
cli@aterm.me's password:
Playing WAVE 'stdin' : Signed 16 bit Little Endian, Rate 44100 Hz, Mono
これはsshコマンドが使えるホストであれば、どこでも実行できます。sshコマンドはパスワード入力が求められるのでPythonプログラム内から標準ライブラリのsubprocessで実行するのは面倒なのですが、paramikoパッケージを使えば簡単に実行できます。
paramikoで歌わせる
Pythonプログラムからparamikoを使って歌わせる例です。
sing.py
def ssh_exec(host, user, passwd, command, indat=None, infile=None, inmode='rb',
encoding=None, out_req=False):
# sshコマンド実行
# host: ホスト
# user: ユーザID
# passwd: パスワード
# indat: 標準入力データの直接指定
# infile: 標準入力データのファイル指定、indatに優先する
# inmode: ファイルのopenモード
# encoding: ファイルのencoding
# out_req: Trueなら標準出力を返す
logger.info('host:{} user:{} passwd:{} command:{} indat:{} infile:{} inmode:{} out_req:{}'.format(
host, user, passwd, command, 'None' if indat is None else 'data({})'.format(len(indat)),
infile, inmode, out_req))
if infile is not None:
with open(infile, inmode, encoding=encoding) as fh:
indat = fh.read()
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host, username=user, password=passwd, port=22)
stdin, stdout, _ = client.exec_command(command)
if indat is not None:
stdin.write(indat)
stdin.flush()
if out_req:
outdat = stdout.readlines()
logger.info('output:{}'.format(outdat))
return outdat
return
def _arg_wav():
import argparse
ap = argparse.ArgumentParser()
ap.add_argument('-f', type=str, help='wav file', default='/nvm/papebot/data/songs/nanatsunoko.wav')
args = ap.parse_args()
wav = args.f
return wav
if __name__ == '__main__':
wav = _arg_wav()
host = 'aterm.me'
user = 'cli'
passwd = 'PASSWORD'
ssh_exec(host, user, passwd, command='aplay -', infile=wav)
コマンドラインから
python3 sing.py -f wavファイルフルパス
で歌わせることができます。これはpython3とparamikoパッケージがインストールされたホストであれば、Windows PCなど、どこでも実行できます。
但しwavファイルを実行ホストに持ってくる必要があります。
Tinker Board S に命令して歌わせる
Tinker Board S にsing.pyを置いておき、リモートホストからsshで
python3 sing.py -f wavファイル名
を実行する方法ならばwavをコピーする必要がなくなります。
singr.py
def ssh_exec(host, user, passwd, command, indat=None, infile=None, inmode='rb',
...省略...
if __name__ == '__main__':
song = 'nanatsunoko.wav'
host = '192.168.5.100'
user = 'linaro'
passwd = 'PASSWORD'
command = '/home/linaro/.pyenv/shims/python3 /nvm/test/sing/sing.py -f /nvm/papebot/data/songs/{}'.format(song))
ssh_exec(host, user, passwd, command=command)
この方法はwavのコピーが不要になる代わりに実行ホスト → Tinker Board S → パペロ本体という通信になる分、実行は遅くなります。