Nano Pi Neo2にOpen JTalkでしゃべらせたのでメモ。

Open Jtalkは「入力された日本語テキストに基づいて自由な音声を生成するHMMテキスト音声合成システム」とのこと。
http://open-jtalk.sp.nitech.ac.jp/

open-jtalk、辞書をインストールする。
open-jtalkをインストールすれば辞書もついてくる。

$ apt search open-jtalk  
ソート中... 完了  
全文検索... 完了  
open-jtalk/artful 1.10-1 amd64  
日本語音声合成システム

open-jtalk-mecab-naist-jdic/artful,artful,now 1.10-1 all  
NAIST Japanese Dictionary for Open JTalk

$ sudo apt-get install open-jtalk  
パッケージリストを読み込んでいます... 完了  
依存関係ツリーを作成しています  
状態情報を読み取っています... 完了  
提案パッケージ:  
hts-voice-nitech-jp-atr503-m001  
以下のパッケージが新たにインストールされます:  
open-jtalk open-jtalk-mecab-naist-jdic  
(略)

提案パッケージであるhts-voice-nitech-jp-atr503-m001も。
これは音声データ。男性の声。

hts-voice-nitech-jp-atr503-m001 - Japanese male voice data for Open JTalk

open-jtalkのコマンドはopen_jtalk(間はアンダースコア)として、open_jtalkの辞書は/var/lib/mecab/dic/open-jtalk/naist-jdicに、音声データは/usr/share/hts-voice/にインストールされる。
「こんにちは」と書いたvoice.txtを作り、open_jtalkに食わす。

$ cat ./voice.txt  
こんにちは

$ open_jtalk -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow test.wav ./voice.txt

喋ってくれるはず。
やはり女性の声のほうが良いので、名工大のMMDAgentを使う。
http://share.udialogue.org/meissen/login.htm
2018/3/21時点で1.7が最新
ダウンロードして展開し、/usr/share/hts-voice/に格納する。
使うのは中身の「mei」ディレクトリ配下のみ。
Meiさんは名工大キャラクターだそうな。

$ wget https://sourceforge.net/projects/mmdagent/files/MMDAgent\_Example/MMDAgent\_Example-1.7/MMDAgent_Example-1.7.zip
$
$ unzip ./MMDAgent_Example-1.7.zip  
$ sudo cp -R ./MMDAgent_Example-1.7/Voice/mei /usr/share/hts-voice/

声には以下の5種類がある。実際に発声させる際に選ぶ。
mei_angry.htsvoice mei_happy.htsvoice mei_sad.htsvoice
mei_bashful.htsvoice mei_normal.htsvoice

以下のスクリプトを用意する。
どこかのサイトから持ってきたんですが、どのサイトからだったか忘れてしもうた…。
これをjtalk.pyとして保存する。1行目は環境に応じて変えること。
htsvoiceは上記の通り喜怒哀通常から選べる。
speedも選べる。
このあたりは試行錯誤。

あとはこれをimportして使う。

#!/usr/bin/python
#coding: utf-8
import subprocess
from datetime import datetime

def jtalk(t):
    open_jtalk=['/usr/bin/open_jtalk']
    mech=['-x','/var/lib/mecab/dic/open-jtalk/naist-jdic']
    htsvoice=['-m','/usr/share/hts-voice/mei/mei_normal.htsvoice']
    speed=['-r','1.0']
    outwav=['-ow','/tmp/open_jtalk.wav']
    cmd=open_jtalk+mech+htsvoice+speed+outwav
    c = subprocess.Popen(cmd,stdin=subprocess.PIPE)
    c.stdin.write(t.encode('utf-8'))
    c.stdin.close()
    c.wait()
    aplay = ['aplay','-q','/tmp/open_jtalk.wav']
    wr = subprocess.Popen(aplay)

def say_datetime():
    d = datetime.now()
    text = '%s%s日、%s%s%s秒' % (d.month, d.day, d.hour, d.minute, d.second)
    jtalk(text)

if __name__ == '__main__':
    say_datetime()

先ほどのファイルをimportして、jtalk.jtalk(string)で、発話させたい文章を渡せばOK。

#!/usr/bin/python
#coding: utf-8
import jtalk

jtalk.jtalk('何か話してください')

さあテストである。
青空文庫「注文の多い料理店」を朗読させてみる。
「新字新仮名」版をダウンロード。
http://www.aozora.gr.jp/cards/000081/card43754.html

そのままではOpen Jtalkに渡せないので、以下の変更を加える。

  • 文字コードをShift-JISからUTF-8へ
  • ルビを削除(正規表現パターンは"《.*?》"
  • ルビの個所を示す区切り記号を削除("|"
  • 構成を示す注釈を削る(正規表現パターンは"\[.*?\]"
  • 改行コードをCR+LFをLFのみに。(\rを削る)

できれば以下も。

  • 行頭字下げ、要するに行頭の全角スペースを削除(正規表現パターンは"^ "
  • セリフのカギかっこを削る。行頭のものだけでよい。(正規表現パターンは"^「"

以下までできれば完璧

  • 改行をいったん全て削り、句点のあとに改行コード(\n)を挿入

neko.txtとでも保存し、以下のPythonスクリプトを実行。

#!/usr/bin/python

import jtalk

for line in open('neko.txt','r'):
    print(line)
    jtalk.jtalk(line)

こんな感じ。

試してみるとわかるが、漢字の読み方が変だったり(山猫軒を「やまねこのき」と読んだり)、読めない漢字があったりする。
そりゃまあ仕方ないよね。

それはさておき。
十分なスペックがあるときに複数行の文章を読ませると、発話が終わっていないのに次の行の処理を始めてしまって困ることがある。
そういうときは発話の終了を待つよう、wait()を入れればよい。
関数jtalk()の最後に一行追加。

def jtalk(t):
    open_jtalk=['/usr/bin/open_jtalk']
    mech=['-x','/var/lib/mecab/dic/open-jtalk/naist-jdic']
    htsvoice=['-m','/usr/share/hts-voice/mei/mei_normal.htsvoice']
    speed=['-r','1.0']
    outwav=['-ow','/tmp/open_jtalk.wav']
    cmd=open_jtalk+mech+htsvoice+speed+outwav
    c = subprocess.Popen(cmd,stdin=subprocess.PIPE)
    c.stdin.write(t.encode('utf-8'))
    c.stdin.close()
    c.wait()
    aplay = ['aplay','-q','/tmp/open_jtalk.wav']
    wr = subprocess.Popen(aplay)
    wr.wait()

参考サイト

Raspberry piで日本語音声合成(Open JTalk)を試してみる。 https://qiita.com/lutecia16v/items/8d220885082e40ace252#%E5%A5%B3%E6%80%A7%E3%81%AE%E5%A3%B0%E3%81%AB%E5%A4%89%E3%81%88%E3%81%A6%E3%81%BF%E3%82%8B