OpenJTalk on Windows10 (環境構築からPythonで日本語をしゃべらせる)

# はじめに
Windows10でOpenJTalkを試してみようとしたのですが，必要な環境を一から整えたためどなたかのためになるようにメモしておきます．
タイトルにもある通り，環境構築からPythonで日本語をしゃべらせるところまで説明します．

# 環境
 - windows 10
 - Visual Studio 2019 Community
 - OpenJTalk 1.09
 - Python 3.7

# ビルド環境の準備
WindowsではOpenJTalkを実行するには自分でビルドする必要があるので環境を整えます．

## Visual Studio 2019 Communityのインストール
これは本題ではないのでしまっておきます．

<details>
<summary>Visual Studio 2019 Communityのインストール</summary>
[ここ] (https://docs.microsoft.com/ja-jp/visualstudio/install/install-visual-studio?view=vs-2019) のサイトからVisualStudio 2019をインストールします．
インストーラーが起動したらC++によるデスクトップ開発にチェックを入れ、インストールを押してください．
インストール完了後に一度起動してください．
↓こちらのサイトを参考にさせていただきました．ありがとうございます．
https://qiita.com/Gaccho/items/f748f59784ff68d7a474
</details>

## ビルドの設定
コマンドプロンプトを起動して，以下の2つのコマンドを実行します．

```shell
$ cd C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build

$ vcvarsall.bat x64
```

## nmakeの設定
コマンドプロンプトで`nmake`コマンドを実行しようとした際に実行できない(コマンドが認識されていないみたいなエラー)が出た場合は環境変数に`nmake.exe`のパスを通しておく必要があります．(自分は通さないとだめでした)
自分は以下のパスでいけました．
`C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\bin\Hostx64\x64`

# OpenJTalkのインストール
ここからは[こちら](https://qiita.com/kkoba84/items/b828229c374a249965a9)のサイトを参考にさせていただきました．ありがとうございます．

## ソースコードの入手 OpenJTalk，hts_engineAPI
まず，OpenJTalk 1.09を入手します．[ここ](http://open-jtalk.sourceforge.net/)から選びますが，以下のリンクですぐにダウンロードされます．

http://downloads.sourceforge.net/open-jtalk/open_jtalk-1.09.tar.gz

コンパイルに必要な音声合成用のライブラリhts_engineAPIを[ここ](http://hts-engine.sourceforge.net/)から選びますが，OpenJTalkと同様以下のリンクですぐにダウンロードされます．

http://downloads.sourceforge.net/hts-engine/hts_engine_API-1.10.tar.gz

ダウンロードした`open_jtalk-1.09.tar.gz`を展開して 
`c:\temp\open_jtalk-1.09`としてください．また，hts_engineAPIは、`c:\temp\open_jtalk-1.09\hts_engine_API-1.10` に展開しておくとコンパイルの際に問題が少なくすみます．

## nmakeでのコンパイル
先ほどコマンドプロンプトで`nmake`が使えるようになったので，コンパイルを行います．

### hts_engine_API-1.10のコンパイル
まずはhts_engine_API-1.10から行うので，以下の3つのコマンドを実行してください．
完了するとc:\hts_engine_API にファイルが作成されます．

```shell
$ cd c:\temp\open_jtalk-1.09\hts_engine_API-1.10
$ nmake /f Makefile.mak
$ nmake /f Makefile.mak install
```

### open_jtalk-1.09のコンパイル
次にopen_jtalk-1.09のコンパイルを行います．以下の3つのコマンドを実行してください．完了するとc:\open_jtalk にファイルが作成されます．

```shell
$ cd c:\temp\open_jtalk-1.09
$ nmake /f Makefile.mak
$ nmake /f Makefile.mak install
```

最後の方で文字化けした文字列が表示されますがとりあえずは気にしなくていいそうです．詳細は[こちら](https://qiita.com/kkoba84/items/b828229c374a249965a9)

これにより、c:\open_jtalk\bin\open_jtalk.exe が生成されます．

# Voiceデータの入手
MMDAgent から
https://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/MMDAgent_Example-1.6/
から、MMDAgent_Example-1.6.zip をダウンロードして、Voice/mei/*.htvoice を c:\open_jtalk\bin\ にコピーしておきます．
meiという女の子?の4つの感情のデータです．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426354/cec16408-4fd2-faaa-5fd4-c6ce3dcf9ab9.png)

これで準備は完了です．

# Open JTalk実行テスト
日本語を入力したファイルを input.txt　として c:\open_jtalk\bin に作成したとして
，以下のコマンドを実行してください．

```shell
$ cd c:\open\jtalk\bin
$ open_jtalk -m mei_normal.htsvoice -x ../dic -ow output.wav input.txt
```
同じディレクトリにoutput.wavが作成されていれば成功です．それをダブルクリックで再生されるかどうか確認してみてください．この時点ではエンコードの影響で日本語だとうまくいかないかもしれません．実際に自分はうまくいかなかったです．

# PythonからOpenJTalkを実行
WindowsでPythonからOpenJTalkを実行する際にはwinsound モジュールを利用します．また，今回のWindowsでのコンパイルでの辞書生成ではshift-jisとなっていましたので，python の内部エンコードからstdin に渡す際に encoding を変換する必要があります．


```Python:jtalk.py

#coding: utf-8
import subprocess
from datetime import datetime
import winsound

def jtalk(t):
    # depend on your install folder
    OPENJTALK_BINPATH = 'c:/open_jtalk/bin'
    OPENJTALK_DICPATH = 'c:/open_jtalk/dic'
    # VOICEPATH -> can change mei voice
    OPENJTALK_VOICEPATH = 'c:/open_jtalk/bin/mei_normal.htsvoice'
    open_jtalk=[OPENJTALK_BINPATH + '/open_jtalk.exe']
    mech=['-x',OPENJTALK_DICPATH]
    htsvoice=['-m',OPENJTALK_VOICEPATH]
    speed=['-r','1.0']
    outwav=['-ow','open_jtalk.wav']
    cmd=open_jtalk+mech+htsvoice+speed+outwav
    c = subprocess.Popen(cmd,stdin=subprocess.PIPE)

    # convert text encoding from utf-8 to shitf-jis
    c.stdin.write(t.encode('shift-jis'))
    c.stdin.close()
    c.wait()

    # play wav audio file with winsound module
    winsound.PlaySound('open_jtalk.wav', winsound.SND_FILENAME)


def say_datetime():
    # get datetime and call jtalk
    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()
```

これを任意のディレクトリに配置して`Python jtalk.py`で起動します．起動方法はもちろん自由です．日付と時間をパソコンが喋ってくれたら成功です．

# Pythonモジュールとして利用する
同じディレクトリ(ここももちろん自由)から上記ファイル(jtalk.pyのjtalk)を呼び出します．また引数は喋らせたい文字なのでそれを指定します．`u''`は，エンコードも指定です．

```Python:test.py
import jtalk
jtalk.jtalk(u'これでおしまい')
```

以上です．
長くなってしまいましたがありがとうございました！

# 参考にさせていただいたサイト
https://qiita.com/Gaccho/items/f748f59784ff68d7a474
https://qiita.com/kkoba84/items/b828229c374a249965a9