初めに
TTSのモデルの中にjetsがあります。2年ほど前のモデルなので環境構築がかなり大変だったのでDockerを使って動かせる環境を作ります
今回の記事に関する内容は以下のリポジトリにまとめています。
開発環境
- Windows11
必要なリポジトリをclone
jetsを動かすためには、以下のライブラリが必要になります。 * espnet * kaldi
そのため以下のような構造になるようにリポジトリをcloneしていきます。 それぞれのリポジトリは、今回のために整理したリポジトリを作成しました。
project/
├── espnet/
├── tools
├── kaldi
Docker環境を作る
jetsの当時の環境が安定していたた、以下の条件でdocker環境を構築します
- cuda 11.x
- python 3.8
- torch 1.10
以下が実際に作成したDockerfileです
FROM nvidia/cuda:11.3.1-cudnn8-runtime-ubuntu20.04 # 非対話モードとタイムゾーンの設定 ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Asia/Tokyo # tzdata を先にインストールしてタイムゾーンの設定、その後必要なパッケージをインストール RUN apt-get update && \ apt-get install -y tzdata && \ ln -fs /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ dpkg-reconfigure --frontend noninteractive tzdata && \ apt-get install -y software-properties-common && \ add-apt-repository universe && \ apt-get update && \ apt-get install -y git \ python3.8 python3.8-dev python3.8-venv python3-pip wget \ libfreetype6-dev libpng-dev pkg-config && \ python3.8 -m pip install --upgrade pip # PyTorch 1.10.1 (CUDA 11.3 対応版) のインストール RUN python3.8 -m pip install torch==1.10.1+cu113 torchvision==0.11.2+cu113 torchaudio==0.10.1+cu113 \ -f https://download.pytorch.org/whl/torch_stable.html # python コマンドで python3.8 を利用できるようにシンボリックリンクを作成 RUN ln -sf /usr/bin/python3.8 /usr/bin/python WORKDIR /work/espnet ENV PYTHONPATH=/work/espnet:$PYTHONPATH # ここで ESPnet の依存ライブラリをインストール RUN python -m pip install \ kaldiio==2.18.0 \ humanfriendly==10.0 \ numpy==1.24.4 \ resampy==0.4.3 \ soundfile==0.13.1 \ nltk==3.9.1 \ tqdm==4.67.1 \ matplotlib==3.7.5 \ typeguard==2.7.1 \ inflect==5.0.3 \ espnet_model_zoo==0.1.7 # 必要な NLTK リソースのダウンロード(同じ Python 環境内で実行) RUN python -c "import nltk; nltk.download('averaged_perceptron_tagger_eng')" CMD ["/bin/bash"]
この時点でのフォルダ構造は以下になります
project/ ├── espnet/ │ ├── tools │ ├── kaldi ├──Dockerfile
このDockerfileを以下でビルドして、コンテナ内に入ります。このときにボリュームはマウントして実行します
docker build -t espnet-jets . docker run -it --rm -v "${PWD}:/work" espnet-jets bash
前処理
コンテナ内に入った後にespnetが正しくインストールされるように以下を実行してインストールを行います
pip install -e .
音声合成の実行
まずは実行するためのフォルダを移動します
cd egs2/ljspeech/tts1
次に音声合成を行うために以下を実行します。 データの前処理、モデルのダウンロードを一括で行います (少し時間がかかるので放置してください)
./run.sh --skip_data_prep false --skip_train true --download_model imdanboy/jets
音声合成の結果
以下のパスに処理が終わった後にwavファイルが保存されています。
exp/imdanboy/jets/decode_train.loss.ave/dev/wav/
root@a895d360c83b:/work/espnet/egs2/ljspeech/tts1# ls -l exp/imdanboy/jets/decode_train.loss.ave/dev/wav/ total 69404 -rw-r--r-- 1 root root 235052 Feb 17 15:21 LJ049-0008.wav -rw-r--r-- 1 root root 421420 Feb 17 15:22 LJ049-0009.wav -rw-r--r-- 1 root root 138284 Feb 17 15:22 LJ049-0010.wav -rw-r--r-- 1 root root 394284 Feb 17 15:22 LJ049-0011.wav
以下は推論実行時のログです
root@a895d360c83b:/work/espnet/egs2/ljspeech/tts1# ./run.sh --skip_data_prep false --skip_train true --download_model imdanboy/jets 2025-02-17T15:11:01 (tts.sh:211:main) ./tts.sh --lang en --feats_type raw --fs 22050 --n_fft 1024 --n_shift 256 --token_type phn --cleaner tacotron --g2p g2p_en_no_space --train_config conf/train.yaml --inference_config conf/decode.yaml --train_set tr_no_dev --valid_set dev --test_sets dev eval1 --srctexts data/tr_no_dev/text --audio_format wav --skip_data_prep false --skip_train true --download_model imdanboy/jets 2025-02-17T15:11:02 (tts.sh:307:main) Stage 1: Data preparation for data/tr_no_dev, data/dev, etc. 2025-02-17T15:11:02 (data.sh:16:main) local/data.sh 2025-02-17T15:11:02 (data.sh:39:main) stage -1: Data Download already exists. skipped. 2025-02-17T15:11:03 (data.sh:44:main) stage 0: Data Preparation utils/validate_data_dir.sh: WARNING: you have only one speaker. This probably a bad idea. Search for the word 'bold' in http://kaldi-asr.org/doc/data_prep.html for more information. utils/validate_data_dir.sh: Successfully validated data-directory data/train 2025-02-17T15:20:07 (data.sh:77:main) stage 2: utils/subset_data_dir.sg utils/subset_data_dir.sh: reducing #utt from 13100 to 500 utils/subset_data_dir.sh: reducing #utt from 500 to 250 utils/subset_data_dir.sh: reducing #utt from 500 to 250 utils/subset_data_dir.sh: reducing #utt from 13100 to 12600 2025-02-17T15:20:10 (data.sh:86:main) Successfully finished. [elapsed=548s] 2025-02-17T15:20:10 (tts.sh:323:main) Stage 2: Format wav.scp: data/ -> dump/raw/ utils/copy_data_dir.sh: copied data from data/tr_no_dev to dump/raw/org/tr_no_dev utils/validate_data_dir.sh: WARNING: you have only one speaker. This probably a bad idea. Search for the word 'bold' in http://kaldi-asr.org/doc/data_prep.html for more information. utils/validate_data_dir.sh: Successfully validated data-directory dump/raw/org/tr_no_dev 2025-02-17T15:20:12 (format_wav_scp.sh:42:main) scripts/audio/format_wav_scp.sh --nj 8 --cmd run.pl --audio-format wav --fs 22050 data/tr_no_dev/wav.scp dump/raw/org/tr_no_dev 2025-02-17T15:20:13 (format_wav_scp.sh:110:main) [info]: without segments 2025-02-17T15:20:34 (format_wav_scp.sh:142:main) Successfully finished. [elapsed=22s] utils/copy_data_dir.sh: copied data from data/dev to dump/raw/org/dev utils/validate_data_dir.sh: WARNING: you have only one speaker. This probably a bad idea. Search for the word 'bold' in http://kaldi-asr.org/doc/data_prep.html for more information. utils/validate_data_dir.sh: Successfully validated data-directory dump/raw/org/dev 2025-02-17T15:20:35 (format_wav_scp.sh:42:main) scripts/audio/format_wav_scp.sh --nj 8 --cmd run.pl --audio-format wav --fs 22050 data/dev/wav.scp dump/raw/org/dev 2025-02-17T15:20:36 (format_wav_scp.sh:110:main) [info]: without segments 2025-02-17T15:20:39 (format_wav_scp.sh:142:main) Successfully finished. [elapsed=4s] utils/copy_data_dir.sh: copied data from data/dev to dump/raw/org/dev utils/validate_data_dir.sh: WARNING: you have only one speaker. This probably a bad idea. Search for the word 'bold' in http://kaldi-asr.org/doc/data_prep.html for more information. utils/validate_data_dir.sh: Successfully validated data-directory dump/raw/org/dev 2025-02-17T15:20:40 (format_wav_scp.sh:42:main) scripts/audio/format_wav_scp.sh --nj 8 --cmd run.pl --audio-format wav --fs 22050 data/dev/wav.scp dump/raw/org/dev 2025-02-17T15:20:41 (format_wav_scp.sh:110:main) [info]: without segments 2025-02-17T15:20:44 (format_wav_scp.sh:142:main) Successfully finished. [elapsed=4s] utils/copy_data_dir.sh: copied data from data/eval1 to dump/raw/eval1 utils/validate_data_dir.sh: WARNING: you have only one speaker. This probably a bad idea. Search for the word 'bold' in http://kaldi-asr.org/doc/data_prep.html for more information. utils/validate_data_dir.sh: Successfully validated data-directory dump/raw/eval1 2025-02-17T15:20:45 (format_wav_scp.sh:42:main) scripts/audio/format_wav_scp.sh --nj 8 --cmd run.pl --audio-format wav --fs 22050 data/eval1/wav.scp dump/raw/eval1 2025-02-17T15:20:45 (format_wav_scp.sh:110:main) [info]: without segments 2025-02-17T15:20:49 (format_wav_scp.sh:142:main) Successfully finished. [elapsed=4s] 2025-02-17T15:20:49 (tts.sh:468:main) Stage 3: Remove long/short data: dump/raw/org -> dump/raw utils/copy_data_dir.sh: copied data from dump/raw/org/tr_no_dev to dump/raw/tr_no_dev utils/validate_data_dir.sh: WARNING: you have only one speaker. This probably a bad idea. Search for the word 'bold' in http://kaldi-asr.org/doc/data_prep.html for more information. utils/validate_data_dir.sh: Successfully validated data-directory dump/raw/tr_no_dev fix_data_dir.sh: kept all 12600 utterances. fix_data_dir.sh: old files are kept in dump/raw/tr_no_dev/.backup utils/copy_data_dir.sh: copied data from dump/raw/org/dev to dump/raw/dev utils/validate_data_dir.sh: WARNING: you have only one speaker. This probably a bad idea. Search for the word 'bold' in http://kaldi-asr.org/doc/data_prep.html for more information. utils/validate_data_dir.sh: Successfully validated data-directory dump/raw/dev fix_data_dir.sh: kept all 250 utterances. fix_data_dir.sh: old files are kept in dump/raw/dev/.backup 2025-02-17T15:20:55 (tts.sh:523:main) Stage 4: Generate token_list from data/tr_no_dev/text [nltk_data] Downloading package averaged_perceptron_tagger to [nltk_data] /root/nltk_data... [nltk_data] Unzipping taggers/averaged_perceptron_tagger.zip. [nltk_data] Downloading package cmudict to /root/nltk_data... [nltk_data] Unzipping corpora/cmudict.zip. /usr/bin/python3 /work/espnet/espnet2/bin/tokenize_text.py --token_type phn -f 2- --input dump/raw/srctexts --output dump/token_list/phn_tacotron_g2p_en_no_space/tokens.txt --non_linguistic_symbols none --cleaner tacotron --g2p g2p_en_no_space --write_vocabulary true --add_symbol '<blank>:0' --add_symbol '<unk>:1' --add_symbol '<sos/eos>:-1' 2025-02-17 15:21:10,513 (tokenize_text:174) INFO: OOV rate = 0.0 % 2025-02-17T15:21:10 (tts.sh:907:main) Skip training stages 2025-02-17T15:21:10 (tts.sh:912:main) Use imdanboy/jets for decoding and evaluation (…)2p_en_no_space%2Ftrain%2Fpitch_stats.npz: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 770/770 [00:00<00:00, 266kB/s] (…)e%2Fimages%2Fdiscriminator_fake_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 75.2k/75.2k [00:00<00:00, 4.79MB/s] (…)p_en_no_space%2Ftrain%2Fenergy_stats.npz: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 770/770 [00:00<00:00, 238kB/s] (…)images%2Fdiscriminator_backward_time.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 73.7k/73.7k [00:00<00:00, 5.66MB/s] README.md: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 11.6k/11.6k [00:00<00:00, 4.72MB/s] (…)n_tacotron_g2p_en_no_space%2Fconfig.yaml: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 9.54k/9.54k [00:00<00:00, 3.15MB/s] (…)2p_en_no_space%2Ftrain%2Ffeats_stats.npz: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.40k/1.40k [00:00<00:00, 481kB/s] .gitattributes: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.17k/1.17k [00:00<00:00, 426kB/s] (…)ages%2Fdiscriminator_optim_step_time.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 36.0k/36.0k [00:00<00:00, 11.1MB/s] (…)_space%2Fimages%2Fdiscriminator_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 75.1k/75.1k [00:00<00:00, 16.8MB/s] (…)%2Fimages%2Fdiscriminator_train_time.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 74.1k/74.1k [00:00<00:00, 19.7MB/s] (…)es%2Fgenerator_align_forwardsum_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 32.7k/32.7k [00:00<00:00, 26.1MB/s] (…)%2Fimages%2Fgenerator_align_bin_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 32.8k/32.8k [00:00<00:00, 23.1MB/s] (…)pace%2Fimages%2Fgenerator_align_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 31.7k/31.7k [00:00<00:00, 23.5MB/s] (…)e%2Fimages%2Fgenerator_backward_time.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 76.1k/76.1k [00:00<00:00, 29.8MB/s] (…)ce%2Fimages%2Fgenerator_forward_time.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 27.8k/27.8k [00:00<00:00, 25.9MB/s] (…)Fimages%2Fdiscriminator_forward_time.png: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 76.3k/76.3k [00:00<00:00, 533kB/s] (…)e%2Fimages%2Fdiscriminator_real_loss.png: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 75.7k/75.7k [00:00<00:00, 505kB/s] (…)pace%2Fimages%2Fgenerator_g_adv_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 65.5k/65.5k [00:00<00:00, 45.3MB/s] (…)no_space%2Fimages%2Fgenerator_g_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 36.8k/36.8k [00:00<00:00, 40.3MB/s] (…)pace%2Fimages%2Fgenerator_g_mel_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 33.9k/33.9k [00:00<00:00, 28.1MB/s] (…)images%2Fgenerator_g_feat_match_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 44.5k/44.5k [00:00<00:00, 21.5MB/s] (…)n_no_space%2Fimages%2Fgenerator_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 33.2k/33.2k [00:00<00:00, 28.5MB/s] (…)2Fimages%2Fgenerator_optim_step_time.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 39.0k/39.0k [00:00<00:00, 35.3MB/s] (…)2Fimages%2Fgenerator_var_energy_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 31.1k/31.1k [00:00<00:00, 27.1MB/s] (…)ce%2Fimages%2Fgenerator_var_dur_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 39.5k/39.5k [00:00<00:00, 30.8MB/s] (…)ace%2Fimages%2Fgpu_max_cached_mem_GB.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 32.8k/32.8k [00:00<00:00, 22.4MB/s] (…)_space%2Fimages%2Fgenerator_var_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 30.9k/30.9k [00:00<00:00, 10.4MB/s] (…)%2Fimages%2Fgenerator_var_pitch_loss.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 35.4k/35.4k [00:00<00:00, 14.0MB/s] (…)pace%2Fimages%2Fgenerator_train_time.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 30.3k/30.3k [00:00<00:00, 33.5MB/s] (…)2p_en_no_space%2Fimages%2Foptim0_lr0.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 25.2k/25.2k [00:00<00:00, 22.6MB/s] (…)2p_en_no_space%2Fimages%2Foptim1_lr0.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 25.0k/25.0k [00:00<00:00, 19.9MB/s] (…)2p_en_no_space%2Fimages%2Ftrain_time.png: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 36.2k/36.2k [00:00<00:00, 27.2MB/s] (…)g2p_en_no_space%2Fimages%2Fiter_time.png: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 85.4k/85.4k [00:00<00:00, 592kB/s] meta.yaml: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 326/326 [00:00<00:00, 319kB/s] train.total_count.ave_5best.pth: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 334M/334M [00:09<00:00, 33.6MB/s] Fetching 36 files: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 36/36 [00:12<00:00, 2.90it/s] 2025-02-17T15:21:24 (tts.sh:933:main) Stage 7: Decoding: training_dir=exp/imdanboy/jets 2025-02-17T15:21:24 (tts.sh:956:main) Generate 'exp/imdanboy/jets/decode_train.loss.ave/run.sh'. You can resume the process from stage 7 using this script 2025-02-17T15:21:25 (tts.sh:1010:main) Decoding started... log: 'exp/imdanboy/jets/decode_train.loss.ave/dev/log/tts_inference.*.log' 2025-02-17T15:30:33 (tts.sh:1010:main) Decoding started... log: 'exp/imdanboy/jets/decode_train.loss.ave/eval1/log/tts_inference.*.log' 2025-02-17T15:40:02 (tts.sh:1180:main) Skip the uploading stage 2025-02-17T15:40:02 (tts.sh:1232:main) Skip the uploading to HuggingFace stage 2025-02-17T15:40:02 (tts.sh:1235:main) Successfully finished. [elapsed=1741s]
JETSの学習
学習をする場合は、以下のコマンドにて一から学習を開始できます
./run.sh --train_config conf/tuning/train_jets.yaml --tts_task gan_tts --stage 1 --stop_stage 7 --ngpu 1
トレーニングのパラメータを引数から変更したい場合は、以下を付けます
--train_args "--max_epoch 1 --num_iters_per_epoch 30"