Ubuntu Weekly Recipe

第887回AIボイスチェンジャーであるSeed-VC用に⁠任意の音声ファイルをトレーニングしてみよう

前回はAIを利用した音声合成ツールであるSeed-VCの使い方を紹介しました。今回はさらにSeed-VCのトレーニング機能を利用して、より自然な音声を生成してみましょう。

Seed-VCでトレーニングする

改めて紹介しておくとSeed-VCとは、音声合成を目的としたAIツールです。ある入力された音声(Source Audio)に対して、参考となる音声(Reference Audio)をベースに変換し、別の人の声として音声データを生成します。単純に言うとボイスチェンジャーです。特にSeed-VCは次の特徴を持っています。

  • 事前の学習をせずとも音声変換できること
  • GPUを使えばリアルタイムに近い速度で変換できること
  • 音声データから直接変換できること
  • ローカルで動かせること
  • CLIのツールが充実していること
  • オープンソースライセンスで提供されていること

Seed-VCの特徴のひとつは事前の学習が不要な、⁠ゼロショットの変換」をできることです。すでに学習済みのデータが存在し、あとは30秒以内の参照元の音声データを用意すれば、それに近い声を出してくれるのです。

図1 前回も紹介したように、Seed-VCはWeb UIからかんたんに任意の音声ファイル・マイクの入力データを、参照用の音声ファイルに似た声へと変換してくれる

しかしながらゼロショット変換はそれなりに近い声を出してはくれるものの、より参照音声に近づけたければトレーニング(fine-tuning)することになります。たとえば通常の変換だと参照音源として30秒以内のデータをひとつだけしか使えません。それに対してトレーニングなら任意の数の音声ファイルを指定できるため、より精度があがるのです[1]

なお音声ファイルは.wav.flac.mp3.m4a.opus.oggを利用できます。ファイルの数の下限はなく、数が増えれば精度はあがります。また音声ファイル以外の情報も不要です。各ファイルの30秒以上のデータは無視されます。

音声ファイルはその人のみの声が入っていることと、可能な限りノイズやBGMなどがないデータでなくてはいけません。

前回は参照音声(Reference Audio)として、つくよみちゃんコーパス(CV.夢前黎)に含まれる単一の音声ファイルのみを使用しました。しかしながらこの「つくよみちゃんコーパス」には、おおよそ2秒から13秒までの、100種類の音声データも含まれています。今回はこの100種類すべてのファイルを、そのままトレーニングに使ってみましょう。

Seed-VCにはトレーニング用のスクリプトが用意されています。実行環境として、前回と同じ構成をあらかじめ用意しておいてください。基本的に8GiB以上のVRAMを搭載したGPUが必要です。

トレーニングもV1のリアルタイム変換用・オフライン変換用・歌声変換用に加えて、V2用のスクリプトが用意されています。今回はまずV2のWeb UIで使いたいため、V2で変換してみましょう。

V1のリアルタイム変換用の設定スクリプト:
configs/presets/config_dit_mel_seed_uvit_xlsr_tiny.yml
V1のオフライン変換用の設定スクリプト:
configs/presets/config_dit_mel_seed_uvit_whisper_small_wavenet.yml
V1の歌声変換用の設定スクリプト:
configs/presets/config_dit_mel_seed_uvit_whisper_base_f0_44k.yml
V2のオフライン変換用の設定スクリプト:
configs/v2/vc_wrapper.yaml

最初につくよみちゃんコーパスのWAVファイルを任意のディレクトリに展開します。Seed-VCのトレーニングでは、特定のディレクトリ以下にあるすべてのサポートフォーマットのファイルをすべてトレーニング対象とします。よってトレーニング対象としたい音声ファイル一式は、異なるディレクトリに保存しておくと良いでしょう。

$ mkdir -p tsukuyomi/01 tsukuyomi/03
$ unzip ~/tyc-corpus1.zip -d tsukuyomi/
$ mv 'tsukuyomi/つくよみちゃんコーパス Vol.1 声優統計コーパス(JVSコーパス準拠)/01 WAV(収録時の音量のまま)/'*.wav tsukuyomi/01/
$ mv 'tsukuyomi/つくよみちゃんコーパス Vol.1 声優統計コーパス(JVSコーパス準拠)/おまけ:WAV(+12dB増幅&高音域削減)/WAV(+12dB増幅&高音域削減)/'*.wav tsukuyomi/03/

tsukuyomi/01/に通常のコーパスを、tsukuyomi/03/「おまけ:WAV(+12dB増幅&高音域削減⁠⁠」のコーパスを展開しています。使うのはどちらか片方だけでかまいませんが、体感的に「おまけ:WAV(+12dB増幅&高音域削減⁠⁠」のほうが低めの自然な声になるようです。

$ uv run accelerate launch train_v2.py --dataset-dir tsukuyomi/03 --run-name tsukuyomi03 \
  --batch-size 2 --max-steps 1000 --max-epochs 1000 --save-every 500 \
  --num-workers 0 --train-cfm --train-ar
(snip)
Saving checkpoint...
Saved AR checkpoint to runs/tsukuyomi03/AR_epoch_00019_step_01000.pth
Saved CFM checkpoint to runs/tsukuyomi03/CFM_epoch_00019_step_01000.pth

トレーニングは上記を実行するだけです。--dataset-dirに音声ファイルが保存されているディレクトリを指定します。--run-nameはあとで使用するラベル名を指定してください。トレーニング結果はruns/ラベル名?以下に保存されます。その他の設定項目は次のとおりです。

  • --batch-size:GPUメモリに応じて調整するバッチサイズ
  • --max-steps:データセットのサイズやトレーニング時間に合わせて変更する最大ステップ数
  • --max-epochs:上と同じように変更する最大エポック数
  • --save-every:どのステップごとにモデルチェックポイント保存かの間隔
  • --num-workers:データ読み込み用ワーカー数
  • --train-cfm:音声変換用のCFMモデルを作成
  • --train-ar:アクセントや感情のスタイルを変換するARモデルを作成

これらはとりあえず上記と同じ値で実行してみましょう。メモリが足りないようならバッチサイズを減らしてみてください。ちなみに設定ファイルは何も指定しなければconfigs/v2/vc_wrapper.yamlが使われます。手元の環境だとおおよそ10分で完了しました。

トレーニング結果は次のように保存されます。

$ ls -1sh runs/tsukuyomi03/
total 655M
319M AR_epoch_00019_step_01000.pth
336M CFM_epoch_00019_step_01000.pth
4.0K vc_wrapper.yaml

トレーニング結果を使用するにはWeb UIにオプションを渡す必要があります。前回はapp.pyを使用しましたが、こちらはトレーニング結果を渡すオプションに対応していません。これはV1/V2でモデルが異なるためです。そこで今回はV2専用のWeb UIスクリプトであるapp_vc_v2.pyを起動しましょう。

$ uv run python app_vc_v2.py \
  --cfm-checkpoint-path runs/tsukuyomi03/CFM_epoch_00019_step_01000.pth \
  --ar-checkpoint-path runs/tsukuyomi03/AR_epoch_00019_step_01000.pth
Loading weights from nvidia/bigvgan_v2_22khz_80band_256x
Loading CFM checkpoint from runs/tsukuyomi03/CFM_epoch_00019_step_01000.pth...
Loading AR checkpoint from runs/tsukuyomi03/AR_epoch_00019_step_01000.pth...
* Running on local URL:  http://127.0.0.1:7860

To create a public link, set `share=True` in `launch()`.

音声変換に使われるCFMモデルと、アクセントや可能のスタイルを変換するのに使われるARモデルをそれぞれ異なるオプションで渡しています。ちなみ--ar-checkpoint-pathのほうは、省略すればデフォルトのモデルが使われます。

training_01_normal.mp3:「01 WAV(収録時の音量のまま)」でトレーニングしてそのまま変換した結果
training_01_df50_sim1.mp3:上記と同じトレーニング結果に対して、Diffusion Stepsを50に、Similarity CFG Rateを1にした例
training_03_normal.mp3:「おまけ:WAV(+12dB増幅&高音域削減)」でトレーニングした結果をそのまま変換した例
training_03_df50_sim1.mp3:上記と同じトレーニング結果に対して、Diffusion Stepsを50に、Similarity CFG Rateを1にした例

1番上でも前回に比べるとだいぶ良くなっていますが、2番目は単語感のつながりがより自然になったように感じます。また、⁠おまけ」のほうは高音域が削除されているせいか全体的に落ち着いた声になりました。どちらが良いかは好みが分かれるところです。

最初に「つっ」とか発音している部分がありますが、これは入力音声の無音の部分(もしくは小さな雑音が入っている部分)も変換しているためです。リアルタイム変換にこだわらなければ、入力音声ファイルも前処理しておくと良いでしょう。

ただしスタイル変換についてはうまくいきませんでした。特に「おまけ:WAV(+12dB増幅&高音域削減⁠⁠」のトレーニング結果の場合、何か中国語っぽいようにも聞こえる、意味のない音声になってしまいます。

training_03_convert.mp3:「おまけ:WAV(+12dB増幅&高音域削減)」のトレーニング結果を元にして、convert styleにチェックを入れた例
何かよくわからない言葉で喋りだした。こわい

これはARモデルがうまく作れていないことが原因かもしれません。

リアルタイム変換用のトレーニング

前回はリアルタイム変換に対応したGUIアプリケーションも起動しました。これもトレーニング結果を指定して実行してみましょう。このリアルタイム変換のアプリケーションはV1のモデルが必要であるため、V1のリアルタイム変換用のスクリプトを実行します。

$ uv run python train.py --config configs/presets/config_dit_mel_seed_uvit_xlsr_tiny.yml \
  --dataset-dir tsukuyomi/03 --run-name tsukuyomi03a --batch-size 2 --max-steps 1000 \
  --max-epochs 1000 --save-every 500 --num-workers 0

V2用のトレーニング結果は使えないので注意してください。

トレーニングが成功したら、次のように実行します。

$ uv run real-time-gui.py \
  --checkpoint-path runs/tsukuyomi03a/DiT_epoch_00009_step_00500.pth \
  --config-path runs/tsukuyomi03a/config_dit_mel_seed_uvit_xlsr_tiny.yml

なお、リアルタイム変換ではARモデルは使いません。また、引き続き参照音声の指定は必要になります。

こちらもより自然な発音になっていることがわかります。

CLIのみで音声変換する

リアルタイムではないオフライン変換は、基本的に変換元と参照用の音声ファイルをアップロードし、それをトレーニング結果を使って変換することになります。これはマイクを使って変換元を録音した場合も同様で、録音した結果は一時的に/tmp/gradio/以下の一時ディレクトリにaudio.wavなどの名前で保存されます。

言い方を変えると、元となる音声ファイルがあれば、Web UIを使わなくても直接CLIから変換が可能です。

$ uv run python inference_v2.py --source ~/source.wav --target ~/tsukuyomi01.wav --output ~/output \
  --diffusion-steps 50 --length-adjust 1.0 --intelligibility-cfg-rate 0.7 --similarity-cfg-rate 1.0 \
  --convert-style false --anonymization-only false --top-p 0.9 --temperature 1.0 \
  --repetition-penalty 1.0 --cfm-checkpoint-path runs/tsukuyomi03/CFM_epoch_00019_step_01000.pth \
  --ar-checkpoint-path runs/tsukuyomi03/AR_epoch_00019_step_01000.pth

Loading weights from nvidia/bigvgan_v2_22khz_80band_256x
Loading CFM checkpoint from runs/tsukuyomi03/CFM_epoch_00019_step_01000.pth...
Loading AR checkpoint from runs/tsukuyomi03/AR_epoch_00019_step_01000.pth...
(snip)
Voice conversion completed in 88.49 seconds
Output saved to: /home/ubuntu/output/vc_v2_source_tsukuyomi01_1.0_50_1.0.wav

--outputで指定したディレクトリを作成し、パラメーターに合わせたファイル名で音声ファイルを保存してくれます。複数の音声データを同じパラメーターで変換したい場合に便利でしょう。

ちなみにinference_v2.py--source--targetはファイル名となる文字列を渡す実装になっています。ただしその実体はlibrosalibrosa.load()を利用するため、soundfile.SoundFileaudioreadのオブジェクトも指定可能です。inference_v2.py自身がファイル名前提で作り込まれているためそのままではファイル名以外を渡せませんが、これをベースにたとえばマイクのデータを取得して変換するCLIも作ることが可能でしょう。


音声合成と言うとどうしても悪用するイメージがつきものではありますが、まっとうな使い方もたくさんあります。世にある他の道具と同じく、きちんとライセンスを含む様々なルールや一般常識を守って運用することに注意すれば良いのです。Seed-VCを使って、自分や世の中にとって便利な(そして周りに迷惑をかけない)ツールを作ってみてください。

おすすめ記事

記事・ニュース一覧