イントネーション調整ができる音声合成の作り方【ESPNet】【VITS】

# はじめに

Windows10,WSL2上でESPNetの環境構築が終わっていることを前提としています。
環境構築していない方は[windows10,WSL2でESPNetの環境構築【音声合成】](https://qiita.com/seichi25/items/fc6c22042f926baa08e6)で解説しているのでこちらをご参照ください．

この記事ではESPNetのVITSレシピをイントネーション調整ができるように改造した自作レシピの使い方を説明します．現状はjsutデータセットのみ対応の形ですが、今後任意のデータセットで学習可能なレシピを公開する予定です。

このレシピで学習したモデルの音声はこんな感じになります．
<iframe width="560" height="315" src="https://www.youtube.com/embed/ES3WyMotA6E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 1. 環境変数の確認
公式ドキュメントなど，上記の私が書いた記事以外を参考に環境構築されている場合は，今回のレシピ作成スクリプトで使用する環境変数がない状態のはずです．なので先にそちらを用意します．

espnetの一番最初のフォルダ(例：~/espnet/)に移動して，こちらのコマンドを実行してください．

```shell
esp_root=`pwd`
echo "export ESPNET_ROOT=$esp_root" >> ~/.bashrc
mkdir data_root
echo "export TTS_DATA_ROOT=${esp_root}/data_root" >> ~/.bashrc
source ~/.bashrc
```
## 1.1 必要なファイルをダウンロード，展開する
必要なファイルをダウンロード，展開するコマンドです．コピペで実行してください．
```shell
cd ~/
wget "https://drive.google.com/uc?export=download&id=1r0fxorTWgqwQWal1A61j4oycJwmfZzyZ" -O full_context_extractor.zip
wget "https://drive.google.com/uc?export=download&id=14GMn9WxQMUd2HbEDS0QEssenkNZzudfv" -O vits_custom.zip
unzip full_context_extractor.zip
unzip vits_custom.zip
rm full_context_extractor.zip
rm vits_custom.zip
mv full_context_extractor-master $ESPNET_ROOT/full_context_extractor
mv vits $ESPNET_ROOT/vits_custom
```

## 1.2 Juliusのコンパイル
学習には音素アライメントが必要なので，Juliusをコンパイルします．インストール場所がホームディレクトリになっているので気に食わない方がいらっしゃるかもしれませんが，今回自作したレシピではこのフォルダ構造が前提なのでご了承ください．

```shell
sudo echo スムーズにsudo実行するためのダミーです
cd ~/
sudo apt-get install build-essential zlib1g-dev libsdl2-dev libasound2-dev
git clone https://github.com/julius-speech/julius.git
cd julius
./configure --enable-words-int
make -j4
ls -l julius/julius
```

## 1.3 レシピ作成スクリプトのダウンロード
レシピ作成スクリプトをダウンロードするコマンドです．コピペで実行してください．
```shell
wget "https://drive.google.com/uc?export=download&id=11x35f_bJ6c9TBpdS9LfVkihUnVRWDKd3" -O create_recipe_for_vits_custom.sh
chmod +x create_recipe_for_vits_custom.sh
```

# 2. レシピの実行
## 2.1 レシピフォルダ作成
まず，create_recipe_for_vits_custom.shで任意の名前のレシピフォルダ？(なんといえばいいかわからないがこれで伝わってほしい)
を作成します．
コマンドの `JSUT_vits_custom` の部分が任意です．

```shell
./create_recipe_for_vits_custom.sh JSUT_vits_custom
cd $ESPNET_ROOT/egs2/JSUT_vits_custom
```

このような出力になれば正常に終了しています．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1604294/ad43ea48-d803-db81-01b9-c86059188833.png)

## 2.2 学習の実行
レシピフォルダ内に`all_run.sh`というスクリプトがあるのでこれを実行します．
```shell
./all_run.sh
```
データをダウンロードしたりアライメントをとったりといろいろな処理が詰め込まれていますので，それなりに時間がかかります．
最終的にこのような文字列が表示されていれば正常に学習が実行されています．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1604294/694c873e-5e34-2670-5fe6-8fd3a12bf062.png)

ぱっと見では，この画面でフリーズしているように見えますがこの状態でちゃんと動作しています(タスクマネージャをのぞいてみるとGPUメモリの使用率がかなり上がっているはずです)
`exp/tts_full_band_vits_custom/train.log`というフォルダにlogが出力されているので学習の進捗はそちらを確認します．
こちらのコマンドでlogを逐次確認できます．(JSUT_vits_customの部分を任意の名前に変更した方は同様に以下のコマンドのJSUT_vits_custom部分を書き換えてください)
```shell
tail -f $ESPNET_ROOT/egs2/JSUT_vits_custom/tts1/exp/tts_full_band_vits_custom/train.log | grep -oP "2.*INFO:([^=]*=[^=]|[^=]*seconds|[^=]*minutes)"
```

## 2.3 よくあるエラーについて
```shell
RuntimeError: CUDA out of memory. #何たら~
```
というエラーが出たときは，GPUのメモリ不足です．
バッチサイズが私の環境に合わせて指定されているので，このエラーが出た際には都度バッチサイズを調整してください．
バッチサイズの調整は`tts/conf/tuning/train_full_band_vits_custom.yaml`内の`batch_bins: 800000`という箇所の数字をいじれば変えられます．
私の使っているGPUは RTX 3080 Ti VRAM 12GB　なのでGPUのメモリが12Gより小さい方は調整が必要かと思います．

# おわりに
これでエラーが出なければjsutのイントネーション調整可能な音声合成モデルが作れます。十分学習が進むまでにかかる時間はおそらく2,3日程度です。
その間は放置でいいので何か別のことをして気長に待ちましょう。
十分学習が進んでも自動で終了しませんので，手動でctrl+Cで実行停止してください．
ただし、PCのスペックが低いと、メモリやGPUの専用メモリをほとんど占有してしまうので、負荷の高い作業をするのはおすすめしません...

ゲームなどは相当軽いものでない限り重すぎてできないでしょう。ブラウジングやyoutubeなどの動画視聴は問題なくできるかと思います。(あくまで私の環境では)


# 参考
https://github.com/espnet/espnet/tree/master/egs2/tsukuyomi/tts1

https://qiita.com/RRR_troisR/items/6288b9bdc6e725aa8440

https://tech.fusic.co.jp/posts/2021-08-03-espnet/

https://kan-bayashi.github.io/asj-espnet2-tutorial/

https://github.com/espnet/espnet