FastSpeech2をuv + Windowsで動かす

初めに

前回 数年前のTTSの tacotron2を動かしました。今回はtactron2の課題の解決した FastSpeech2を実際に動かしていきます

ayousanz.hatenadiary.jp

FastSpeech2で解決したものとして Variance Adaptorを使うことによって明示的な制御をするようになりました。また非自己回帰になったことで推論速度が上がっています

以下でuvで対応したリポジトリは公開しています

github.com

アーキテクチャと課題

非自己回帰 + Variance Adaptorのアーキテクチャになっています。このため推論速度の改善と音単位での時間が合うようになっています

Adaptorは以下でそれぞれ制御しています

  • Duration Predictor : 長さ予測
  • Pitch Predictor : ピッチ予測
  • Energy Predictor : 音量予測

課題として以下のような問題がありました

  • 前処理の「依存地獄」
  • 音質の「平均化」: Loss_{Total} = Loss_{Mel} + Loss_{Duration} + Loss_{Pitch} + Loss_{Energy} の計算をすると平均値が正になる
  • ボコーダーとの「ミスマッチ」:

開発環境

環境構築

環境を構築します

uv init --no-readme
uv python pin 3.12

uvの環境用に以下の project.toml を作成します

     [project]
     name = "fastspeech2"
     version = "1.0.0"
     description = "FastSpeech 2 - PyTorch Implementation for Text-to-Speech"
     requires-python = ">=3.10,<3.13"
     dependencies = [
         "numpy>=1.24.0,<2.0",
         "scipy>=1.11.0",
         "librosa>=0.10.0",
         "matplotlib>=3.7.0",
         "pyyaml>=6.0",
         "g2p-en>=2.1.0",
         "pypinyin>=0.49.0",
         "inflect>=7.0.0",
         "unidecode>=1.3.0",
         "soundfile>=0.12.0",
         "tgt>=1.4.4",
         "tqdm>=4.65.0",
     ]

     [tool.hatch.build.targets.wheel]
     packages = ["."]

     [[tool.uv.index]]
     name = "pytorch-cu121"
     url = "https://download.pytorch.org/whl/cu121"
     explicit = true

     [tool.uv.sources]
     torch = { index = "pytorch-cu121" }
     torchvision = { index = "pytorch-cu121" }
     torchaudio = { index = "pytorch-cu121" }

依存関係をインストールします

     uv sync --no-install-project
     uv add torch torchvision torchaudio

librosaのAPIの変更に対応するために以下の変更をします

audio/stft.py

     42行目:
     # 変更前
     fft_window = pad_center(fft_window, filter_length)
     # 変更後
     fft_window = pad_center(fft_window, size=filter_length)

     145-147行目:
     # 変更前
     mel_basis = librosa_mel_fn(
         sampling_rate, filter_length, n_mel_channels, mel_fmin, mel_fmax
     )
     # 変更後
     mel_basis = librosa_mel_fn(
         sr=sampling_rate, n_fft=filter_length, n_mels=n_mel_channels, fmin=mel_fmin, fmax=mel_fmax
     )

audio/audio_processing.py

     57行目:
     # 変更前
     win_sq = librosa_util.pad_center(win_sq, n_fft)
     # 変更後
     win_sq = librosa_util.pad_center(win_sq, size=n_fft)

     5.3 utils/model.py(torch.load警告対応)

     20行目、63行目、65行目:
     # 変更前
     ckpt = torch.load(ckpt_path)
     # 変更後
     ckpt = torch.load(ckpt_path, weights_only=False)

モデルのダウンロード

GoogleDriveから任意のモデルをダウンロードします。今回はLJSpeechを使いました。

drive.google.com

HiFi-GANボコーダーもダウンロードをして配置をします

     python -c "import zipfile; zipfile.ZipFile('hifigan/generator_LJSpeech.pth.tar.zip').extractall('hifigan/')"
     python -c "import zipfile; zipfile.ZipFile('hifigan/generator_universal.pth.tar.zip').extractall('hifigan/')"

実行

以下で推論を実行します

uv run python synthesize.py --text "Hello, this is a test." --restore_step 900000 --mode single -p config/LJSpeech/preprocess.yaml -m config/LJSpeech/model.yaml -t config/LJSpeech/train.yaml