こんにちは、eQOL(イーキュオル)の山下です。
今回はOpenJTalkへのユーザー辞書登録、特にPythonのラッパーであるpyopenjtalkへのユーザー辞書登録について紹介します。OpenJTalkはMecabを利用していますので基本的にはMecabへのユーザー辞書登録なのですが、OpenJTalkがTextToSpeech(TTS)のライブラリなので、若干Mecab辞書と異なる点があります。その点を中心に解説していきたいと思います。
OpenJTalkとは
名工大や情報通信研究機構(NICT)が中心となって作ったオープンソースのTTSシステムで、簡単なコマンドやプログラミングインタフェースを通じて利用できます。テキストから音声合成を行う際、使いやすいAPIやコマンドラインツールを提供し、幅広い環境で利用可能です。また、カスタマイズ性が高く、ユーザーが音声の特性や発音を調整できる柔軟性も持ち合わせています。
ESPnetとOpenJTalk
ESPnetは、End-to-Endの音声処理のためのオープンソース・ツールキットです。言語翻訳、音声認識、音声合成など、多岐にわたる音声処理のタスクに対応している革新的なツールキットです。ニューラルネットワークをベースにしたモデルとデータ処理の高度な技術を組み合わせ、幅広い音声処理タスクに適用されています。音声合成のためのAIモデル訓練ツールを持っているため、独自音声でのTTSシステムを構築する際に利用されます。この中でOpenJTalkはESPnetの音声合成エンジンとして使用され、非常に重要な役割を担います。ESPnetで独自音声TTSを実行する際にはOpenJTalkが持つ日本語辞書が使われるので、TTSの読みに問題がある場合にはOpenJTalkのMecab辞書を更新する必要があります。ESPnetはPythonで記述されていますので、OpenJTalkのラッパーpyopenjtalkが使用されます。つまりESPnetのTTS辞書をカスタマイズするには、pyopenjtalkで使用するMecab辞書をカスタマイズする必要があるということです。
OpenJTalkのユーザー辞書
OpenJTalkにはMecabの辞書が使われます。ただし、TTS用の辞書となるため通常のMecab辞書に加えて2つの項目(赤字)が追加されています。OpenJTalk の解析資料
[一般のMeCabの辞書]
歌う,817,817,7077,動詞,自立,*,*,五段・ワ行促音便,基本形,歌う,ウタウ,ウタウ
[OpenJTalkのMeCabの辞書]
歌う,854,854,6898,動詞,自立,*,*,五段・ワ行促音便,基本形,歌う,ウタウ,ウタウ,0/3,C4
最後から2つ目の数字は、分母が語句の音素数、分子がアクセント位置を表します。最後の記号は語句の品詞を表しています。この記号は読みにどういう影響があるのはわかりませんが、*としておけばTTSは問題なく実行されます。
- C1: 一般的な名詞(サ変接続、ナイ形容詞語幹など)
- C2: 固有名詞(地名、人名、組織名など)
- C3: 形容詞(イ形容詞、ナ形容詞など)
- C4: 動詞(自立、接尾など)
- C5: 助動詞
- C6: 助詞(格助詞、接続助詞など)
- C7: 副詞(一般、助詞類接続など)
- C8: 連体詞
- C9: 感動詞
- CA: 接頭詞
pyopenjtalkでの利用
pyopenjtalkは以下でインストールして使用することができます。
pip install pyopenjtalk
しかし、この標準ライブラリにはユーザー辞書を追加する機能が準備されていません。ユーザー辞書を追加するためには、githubから直接インストールすることが必要です。
pip install git+https://github.com/katsuhiro-eqol/pyopenjtalk.git
ライブラリは通常通り、import で利用できます。ちなみに、「鬼滅の刃」を読ませるとデフォルトでは次のようになります。
import pyopenjtalk
pyopenjtalk.g2p("鬼滅の刃")
>>>o n i m e ts u n o h a
「おにめつのは」になってしまいます。ここにユーザー辞書を追加します。OpenJTalkの辞書に必要な2項目を追加したCSVファイルを準備します。costの計算は不要です。
user.csv
鬼滅の刃,,,1,名詞,一般,*,*,*,*,鬼滅の刃,キメツノヤイバ,キメツノヤイバ,5/7,*
その上で、以下を実施します。
import pyopenjtalk
pyopenjtalk.mecab_dict_index("user.csv", "user.dic")
pyopenjtalk.update_global_jtalk_with_user_dict("user.dic")
pyopenjtalk.g2p("鬼滅の刃")
>>>k i m e ts u n o y a i b a
ユーザ辞書が反映されています。これで音声合成を行います。
import numpy as np
from scipy.io import wavfile
x, sr = pyopenjtalk.tts("鬼滅の刃")
wavfile.write("kimetu.wav", sr, x.astype(np.int16))
無事、ユーザー登録辞書でTTSが実施できました。pyopenjtalkをカスタマイズしておくと、ESPnetのTTSでもその辞書を反映したTTSとなります。ちなみに、ESPnetで独自音声を学習したエンジンを用いるとこんなイケメンの声にも囁いてもらえます。
これはESPnetをTTSシステムとして用いる場合に大変役立つ手法でありますが、極めて手間のかかる作業でもあります。eQOLではESPnet用のOpenJTalkユーザー辞書作成の受託を行っています。関心のある方はぜひこちらからアクセスお願いします。


