注:筆者は韓国在住のため、本文には韓国特有の文脈が含まれることがあります。

hayakoe シリーズの最初の本編です。導入記事は hayakoe — 使いやすくて速い TTS ライブラリを作る — 序論 からどうぞ。

序論で軽く触れた話の一つが「モデルから選び直した」というところでした。Part 1 ではその過程をもう少し詳しく書こうと思います。

大きく三段階に分けると次のようになります。

  1. 他のライブラリ候補を見て回って、結局 SBV2 に戻ってきた経緯
  2. データセット構築(2年で環境がだいぶ良くなっていました)
  3. 学習設定とチェックポイント評価

1. 他のライブラリも見てみる

2年前に Bert-VITS2 で自分だけの TTS を作る を書いた頃は、日本語 TTS ライブラリの選択肢としては Bert-VITS2 がほぼ唯一の候補でした。あれから2年、音声合成の世界はかなり進んでいたんですね。

どうせ時間をかけていじるなら、他の候補も一度見ておいた方が合理的かなと思って、韓国語サポートが良いと言われている候補を二つ検証しました。

GPT-SoVITS

最初に見たのが GPT-SoVITS でした。韓国語 / 英語 / 日本語をすべてサポートし、事前学習モデルに数秒程度の短い音声サンプルを入れるだけで、その声色で発話を作ってくれるゼロショット推論ができる点が魅力的でした。

まずは学習なしのゼロショットで使ってみたんですが、結果は二点で物足りなかったです。

  • 発話の自然さが足りない。 合成された音声のトーンが平板で、感情 / 抑揚の表現が滑らかにつながらない部分がありました。
  • 韓国語の発話が不自然。 日本語話者の音声サンプルで韓国語を発話させてみると、「できるはできる」程度で、自然とは言いにくい結果でした。日本人が無理やりハングルを発話しているような感じ..? でした。

ゼロショットの時点で気に入らない音質が、学習を一回かけたところで劇的に良くなるとは思えませんでした。元々作りたかったのが韓国語ではなく日本語の発話だったので、他の候補をもう少し見た方がいいと判断して、学習までは行かず次に進みました。

Qwen-TTS / 自己回帰系

序論で軽く触れたとおり、自己回帰系の Qwen-TTS も候補でした。ただこちらは音質検証以前に、計算量自体が多すぎてリアルタイム利用が難しいというのが一次落選の理由でした(詳しくは 序論記事 を参照)。

音質の面でもそれほど満足はできませんでした。ゼロショットだからか、欲しいディテールが出ないんですよね。大体オタクならわかりますよね?

結局 Style-Bert-VITS2 に

候補を見て回った結果、結局音質と速度のバランスが最も良かった Style-Bert-VITS2 (JP-Extra v2.7.0) に戻ってきました。SBV2 は Bert-VITS2 の後継格なので、2年前にすでに似た流れで学習 / 使用の経験があったというのも大きかったです。

2. データセット構築 — 2年で環境がだいぶ良くなっていました

データセットは個人的に集めていた音声データセットがあったので、それをそのまま活用しました。2年前の記事で似た作業を一度やったことがあったので大きな流れは慣れていましたし、資料の精製・品質検証まで進めた結果、約 1,500 サンプル程度集まりました。

ただ2年で音声処理ツールの環境はかなり進化していました。一番印象的だったのは、ボーカル分離(UVR — Ultimate Vocal Remover)のようなツールがもう別の GUI プログラムとして個別にインストールする必要がない点でした。

2年前は、これがちょっと面倒でした。まず UVR が Windows アプリだったのでそれを直接インストールしないといけなくて、アプリの中で「モデルダウンロード」ボタンを押してモデルファイルを別途取得してからやっと、フォルダ単位のバッチ処理が回せたんです。今は audio-separator のようなライブラリを使えば、HuggingFace からモデルを取得して Python コード一行で回せるようになりました。

python
from audio_separator.separator import Separator

separator = Separator()
separator.load_model("model_bs_roformer_ep_317_sdr_12.9755.ckpt")
separator.separate("input.wav")

些細な違いに見えるかもしれませんが、データセット 1,500 個単位で処理する時には、GUI クリック / フォルダ管理 / 進捗確認のような雑務を減らしてくれるのがかなり大きな差を生みます。何より、これをそのまま学習パイプラインの中に統合しておけるので、新しいデータを追加するときも同じコードをもう一度回すだけで済みました。

3. Style-Bert-VITS2 の学習

学習自体は SBV2 が提供する webui をそのまま使いました。

  • サンプリングレート: 44.1 kHz
  • batch_size: 2 (RTX 3080 / 10GB VRAM 基準)
  • learning rate: 1e-4
  • eval_interval: 5,000 step
  • 目標 epoch: 500(実際には約 88 epoch まで進めて中断)
  • 学習データ: 約 1,500 サンプル

500 epoch まで全部回す必要は実は無かったです。一定の step を超えると音質がそれ以上良くならない、あるいはむしろ過学習傾向が見え始めたので、適当なタイミングで止めて評価に移りました。

4. チェックポイント評価 — とにかく全部聴いてみました

チェックポイントごとに音質がどう変わっていくかを最も正確に知る方法は、結局直接聴いてみることでした。SBV2 も学習中に mel reconstruction loss、KL divergence、duration loss、generator / discriminator loss、WavLM adversarial loss といった様々な loss を tensorboard に出してくれます。ただ、これらの数値が下がるからといって音声が自然に聞こえるかというと別物なんですよね。結局、自分の耳に自然に聞こえるかが一番大事でした。

どうせ自分が使うモデルなので、評価はシンプルに行きました。

  • 5,000 step から 50,000 step まで 5,000 step 単位で 10個のチェックポイントを抽出
  • 短い / 中くらい / 長いテキスト 3つを決めて、各チェックポイントで合成
  • 結果 30個のサンプルを HTML matrix 形式に整理して、一ページで聴き比べ
              short    medium    long
ckpt 5k       ▶ wav    ▶ wav     ▶ wav
ckpt 10k      ▶ wav    ▶ wav     ▶ wav
ckpt 15k      ▶ wav    ▶ wav     ▶ wav
ckpt 20k      ▶ wav    ▶ wav     ▶ wav
...
ckpt 50k      ▶ wav    ▶ wav     ▶ wav

各セルに合成された wav ファイルが入っていて、同じテキストを列同士で / 異なる step を音声同士で比較して聴ける構造です。合成にかかる時間はそこそこかかりましたが、評価自体はヘッドホンを着けて順番に聴くだけの単純作業でした。

直接全部聴いてみた結果、15,000 step(epoch 約 34) の音質が一番自然でした。それ以降の step からは音色が微妙に変わったり発話トーンが単調になる傾向があって、この時点が sweet spot だったわけです。

あくまで私の耳基準です。他の方が評価したら別の step の方が良く見えるかもしれませんし、テキストが変わると結果も多少変わるかもしれません。とはいえ、どうせ一人で使うモデルなので、これで十分でした。

Part 1 まとめ

Part 1 では他のモデル候補を見て回った末に、結局 Style-Bert-VITS2 (JP-Extra v2.7.0) に戻ってきた理由、そしてその上でデータセット / 学習 / チェックポイント評価までどう進めたかを整理しました。

要するに — 他の候補(GPT-SoVITS、Qwen-TTS など)はゼロショット音質で欲しいディテールが出なかったり、計算量が多すぎてリアルタイムが難しかったりで、結局 音質・速度・慣れのバランス が最も良かった SBV2 に落ち着いた、というのが大筋でした。

ただ、学習した SBV2 モデルをそのまま使うと、RAM 5GB に CPU 推論 1.09× のような限界がそのまま残っています。次回はその部分をどう削ったかを扱おうと思います。

Part 2 — メモリは半分に、速度は 1.5 倍速くした話 に続きます。