私はTTS(Text to Speech)を学ぶのは今回が初めて。
昔、Speech-To-Textで、Juliusでラズパイにつけた音声マイクを拾ってGoで書いたWebアプリケーションに表示させる、というのを少しやった経験はある。が、それとは逆で、TTSは自然言語のテキストから音声に変える技術。
そのTTSの中でも、オープンソースでありながら、日本語TTSでは最も品質が高いとの呼び名が強いStyle-Bert-VITS2。他のTTSに比べて発話が滑らか、と言われているようです。
Style-Bert-VITS2を理解するには、まずは動かして触ってみるのが大事、ということで、ローカルのVagrant/ubuntu22.04 にインストールして、簡単なスクリプトでwavファイル(音声ファイル)を作成しました。
ubuntu22.04にStyle-Bert-VITS2をインストール
リポジトリのクローンと初期セットアップ
$ mkdir tts
$ cd tts
$ git clone https://github.com/litagin02/Style-Bert-VITS2.git
$ cd Style-Bert-VITS2
$ python3 -m venv venv
$ ls
$ source venv/bin/activate
$ pip3 install "torch<2.4" "torchaudio<2.4" --index-url https://download.pytorch.org/whl/cu118
自分のVirtualBox環境はGPUなしの仮想マシンなので、CPU版に置き換えます。
※ onnxruntime-gpuをコメントアウトします。
$ vi requirements.txt
# onnxruntime-gpu; sys_platform != 'darwin'
$ pip3 install onnxruntime
$ pip3 install -r requirements.txt
$ pip3 initialize.py
※Style-Bert-VITS2 のモデルやトークナイザー、リソースを Hugging Face などからダウンロードしてキャッシュする処理を行うので、凄く時間がかかります。通信環境の良い場所で作業するのがおすすめです。
simpleaudio の ビルドに必要な C コンパイラやヘッダファイルを入れます。
$ pip install style-bert-vits2 soundfile simpleaudio
$ sudo apt install libasound2-dev
$ pip3 install simpleaudio
$ pip3 install style-bert-vits2 soundfile
Running setup.py install for simpleaudio ... done Successfully installed simpleaudio-1.0.4 style-bert-vits2-2.5.0
ここまででStyle-Bert-VITS2を動かす準備が完了しました。私の場合、予想以上にpython3 initialize.pyに時間がかかってしまい、数時間かかりました。initialize.pyの実行中は、別の作業をやった方がいいですね。
PythonでStyle-Bert-VITS2を動かす
from style_bert_vits2.tts_model import TTSModel
from pathlib import Path
import soundfile as sf # soundfile は requirements.txt に含まれています
# モデルパス
model_path = Path("model_assets/jvnv-F1-jp/jvnv-F1-jp_e160_s14000.safetensors")
config_path = Path("model_assets/jvnv-F1-jp/config.json")
style_vec_path = Path("model_assets/jvnv-F1-jp/style_vectors.npy")
model = TTSModel(
model_path=model_path,
config_path=config_path,
style_vec_path=style_vec_path,
device="cpu"
)
text = "こんにちは!仮想環境でも音声ファイルに保存できます。"
# 音声生成
sr, audio = model.infer(text=text)
# WAV に保存
sf.write("output.wav", audio, sr)
print("output.wav に保存完了")
▼作成したoutput.wav
https://hpscript.s3.ap-northeast-1.amazonaws.com/style-bert.wav
▼ "東京タワー前のバス停で待ち合わせした"
東京タワー 前のバス停、東京タワー前 のバス停 などイントネーションによってニュアンスが異なるケースがある。
https://hpscript.s3.ap-northeast-1.amazonaws.com/style-bert-sample.wav
上記のpythonのコードで、jvnv-F1-jp/jvnv-F1-jp_e160_s14000.safetensors は Style-Bert-VITS2 が使う日本語向け音声合成モデル本体 のことです。
Bert ベースのテキスト埋め込み + VITS2(音声生成部分)の構造になっています。
日本語テキストを入力すると音声波形を出力できます。
style_vectors.npy は、中身:NumPy 配列で、各行が異なる声質(話者)の特徴ベクトル
VITS2 モデルに入力すると、指定したスタイルの声で音声を生成できる
たとえば「女性」「男性」「少年」「落ち着いた声」などに対応
以下のように音声パラメータを設定することで、音声を調整できる。
sr, audio = model.infer(
text="こんにちは",
style=selected_style,
length_scale=1.0, # 1.0が標準、<1で早口、>1でゆっくり
noise_scale=0.5, # 音声の自然さ
noise_scale_w=0.5, # ピッチ揺れの調整
)
形態素解析(日本語の前処理)
Style-Bert-VITS2 の日本語処理部分では、別ライブラリを使っている。
例えば:
pyopenjtalk(日本語テキスト → 音素列変換)
MeCab / SudachiPy / fugashi(文章を分かち書きにして読みを決定)
Style-Bert-VITS2の仕組み
少し仕組みについても触れておきたい。
音声合成時の流れ:
テキストが入力される→
それがTextEncoderを通る→
その結果をもとに(Stochastic)DurationPredictorで各音素の長さが決まる→
それらの結果がflowを通る→
それがdecoderに流される
- TextEncoder (テキストを受け取り、色々な情報を返す)
- DurationPredictor (音素間隔(発音の長さ)を返す)
- StochasticDurationPredictor (DurationPredictorにランダム性をつけたもの)
- Flow (声音、声の高さ)
- Decoder (色々な情報から最終的に合成して声を出力、声音情報を持つ)
学習の仕組み
GAN: GAN(Generative Adversarial Networks: 敵対的生成ネットワーク)は、2つのAI(ニューラルネットワーク)がお互いに競い合いながら学習することで、本物と見分けがつかないような新しいデータを生成する機械学習モデル
学習時にはGenerator(音声の生成)とDiscriminator(生成音声が本物か偽物か見分けるやつ)が訓練される
Generator: 上の構造をしていて、実際にテキストから音声を生成するもの。G_1000.pthファイルに保存されるやつ。推論にはこれのみ必要。
MultiPeriodDiscriminator: D_1000.pthファイルに保存されるやつ。メインのdiscriminatorで、HiFi-GANとやらとかで使われているらしいです。
DurationDiscriminator: 音素間隔(上のDurationPredictor等の出力)に対するdiscriminatorらしい。DUR_1000.pthファイルに保存されていたやつ。
WavLMDiscriminator: WD_1000.pthファイルに保存されるもので、WavLMという音声のSSLモデルを使ったdiscriminatorのようです。
まとめ
ということで、今回は少し触っただけでしたが、モデルアセットのjvnv-F1-jp_e160_s14000.safetensorsが重要だということがわかる。前後関係を考えた発音ルールは モデルの中に学習された形で入っている。
記事読むだけより、絶対動かしてみた方が良いですね。huggingfaceなどありますが、pythonで動かした方が勉強になる。