声を作ってみた・Style-Bert-VITS2編

Mod作成

はじめに

公式サイトはおそらくここです。

インストールは書いてある通りにするだけです。とても簡単です。

GeForce RTX 5080/5090の場合は後述する追加の作業が必要になります。

とりあえずしゃべらせる

音声合成と言うようです。書いてある通りにすれば簡単です。

学習させる

事前に音声データを用意しました。

wav形式で用意します。Audacityで雑音やノイズを簡単に除去しました。

App.batを実行してブラウザの画面を開いておきます。

データセット作成

データセット作成タブを開きます。

モデル名を入力します。

用意したwav形式のファイルをinputsフォルダの中に入れます。

スライスを実行ボタンをクリックします。

次に音声の文字起こしボタンをクリックします。

私の環境では「HuggingFaceのWhisperを使う(速度が速いがVRAMを多く使う)」のチェックを外さないとutf-8がどうとかいうエラーが出て失敗しました。

メモリ不足でエラー終了した場合はWhisperモデルを小さくするといいようです。

学習

モデル名を入力します。

自動前処理を実行ボタンをクリックします。

学習を開始するボタンをクリックします。

GPUのメモリを使い切っている場合はバッチサイズを小さくするといいようです。

途中でコマンドプロンプトを閉じることで中断できます。続きから再開することもできるようです。また、それまでの成果で音声合成が可能です。

試してみる

音声合成タブに戻ります。

更新ボタンを押さないとモデル一覧に学習させたモデルが出てきません。

概ね良い結果が得られるのですが、一部は調整が必要でした。

余計な間は・を除いたり、逆に間が欲しいところに読点を足します。

読みがおかしい部分は仮名になおします。

イントネーションがおかしい部分はひらがなやカタカナにすると良くなる場合があります。

音声合成を一括して行う

WebUIは簡易的なものみたいで、VOICEVOXやRVCのように大量のファイルを一括で処理する手段がどうやら用意されていないようです。

そのかわりにCLIとAPIがあります。スキルがあることが前提となってしまいますが、APIを叩けるのであれば自由度はこちらの方が格段に上です。

そこで、DBVOの辞書から一括してwavファイルを生成するPHPスクリプトを書いてみました。

サーバーの設定

config.ymlを編集して文字数上限を解除しておいたほうがいいでしょう。

Server:
limit: -1

Server.batを実行してAPIサーバを立ち上げます。

ブラウザで http://127.0.0.1:5000/docs を開くと、APIを叩くときのパラメータを確認できます。

  • /voiceをクリックして広げてます。
  • Try it outをクリックします。
  • セリフに何でもいいので入力します。
  • Executeをクリックします。
  • 成功すれば下にURLが表示されますので、そこからパラメータを読み取ります。生成された音声もその場で再生して確認できます。

DBVOの辞書から

create_DBVO_wav.php (php)

<?php
$context_opts = [];
$http_opts = [];

try {
    if ($argc < 2) {
        throw new Exception('Usage: create_DBVO_wav.php [-n] <DBVO local pack json>');
    }

    $test_mode = ($argv[$argc - 2] == '-n');
    $json_filename = $argv[$argc - 1];

    if ( !is_readable($json_filename) ) {
        throw new Exception($json_filename . ' is not readable.');
    }

    $json_data = json_decode( file_get_contents($json_filename) );

    if ( !$json_data ) {
        throw new Exception('json decode failed.');
    }

    $context_opts = [
        'http' => [
            'method' => 'GET',
        ]
    ];

    $http_opts = [
        'model_name' => '',
        'model_id' => 0,
        'speaker_id' => 0,
        'sdp_ratio' => 0.2,
        'noise' => 0.6,
        'noisew' => 0.8,
        'length' => 1,
        'language' => 'JP',
        'auto_split' => 'true',
        'split_interval' => 0.5,
        'assist_text_weight' => 1,
        'style' => 'Neutral',
        'style_weight' => 1,
    ];

    foreach ($json_data as $key => $value) {
        $key = preg_replace('/\(.+?\)/', '', $key);
        $key = preg_replace('/__[0-9a-zA-Z=\.]+?__/', '', $key);
        $key = preg_replace('/?_/', '?', $key);
        $key = preg_replace('/!_/', '!', $key);
        $key = str_replace('_', '、', $key);

        $key = trim($key);

        //$key = preg_replace('/…$/', '', $key);
        $key = preg_replace('/。$/', '', $key);

        $key = trim($key);

        if ( strlen($key) == 0 ) {
            continue;
        }

        $filename = $value . '.wav';

        if ( $test_mode ) {
            echo $key . PHP_EOL;
        } else {
            if ( !file_exists($filename) ) {
                echo $key . PHP_EOL;

                create_wav($key, $filename);
            }
        }
    }
} catch (Exception $e) {
    echo $e->GetMessage() . PHP_EOL;
}

function create_wav($text, $filename)
{
    global $context_opts, $http_opts;

    $http_opts['text'] = $text;

    $url = 'http://127.0.0.1:5000/voice?' . http_build_query($http_opts);

    $context = stream_context_create($context_opts);

    $data = file_get_contents($url, false, $context);

    file_put_contents($filename, $data);
}

コマンドプロンプトを開き、以下のコマンドで実行できます。

php create_DBVO_wav.php <DBVOの辞書のjsonファイル名>

APIを叩く時のパラメータが埋め込まれていますので、調整しておきます。

以下は最低限変更しないと希望のモデルになりません。

$http_opts = [
'model_id' => 0,
'style' => '04',
]

自分で学習させたモデルを指定する場合は以下になります。

$http_opts = [
'model_name' => 'hogehoge',
'model_id' => 0,
'style' => 'Neutral',
]

LazyVoiceFinderのcsvファイルから

create_dialogue_wav.php (php)

<?php
$context_opts = [];
$http_opts = [];

try {
    if ($argc < 2) {
        throw new Exception('Usage: create_dialogue_wav.php [-n] <LazyVoiceFinder_export.csv>');
    }

    $test_mode = ($argv[$argc - 2] == '-n');
    $csv_filename = $argv[$argc - 1];

    if ( !is_readable($csv_filename) ) {
        throw new Exception($csv_filename . ' is not readable.');
    }

    $csv_data = parse_csv($csv_filename);

    $context_opts = [
        'http' => [
            'method' => 'GET',
        ]
    ];

    $http_opts = [
        'model_name' => 'Skyrim-MaleKhajiit',
        'model_id' => 0,
        'speaker_id' => 0,
        'sdp_ratio' => 0.2,
        'noise' => 0.6,
        'noisew' => 0.8,
        'length' => 1,
        'language' => 'JP',
        'auto_split' => 'true',
        'split_interval' => 0.5,
        'assist_text_weight' => 1,
        'style' => 'Neutral',
        'style_weight' => 1,
    ];

    foreach ($csv_data as $filename => $dialogue) {
        $dialogue = proofread($dialogue);

        if ( strlen($dialogue) == 0 ) {
            continue;
        }

        if ( $test_mode ) {
            echo $filename . ' => ' . $dialogue . PHP_EOL;
        } else {
            if ( !file_exists($filename) ) {
                echo $dialogue . PHP_EOL;

                create_wav($dialogue, $filename);
            }
        }
    }
} catch (Exception $e) {
    echo $e->GetMessage() . PHP_EOL;
}

function proofread($text)
{
    $text = preg_replace('/\(.+?\)/', '', $text);
    $text = preg_replace('/__[0-9a-zA-Z=\.]+?__/', '', $text);
    $text = preg_replace('/?_/', '?', $text);
    $text = preg_replace('/!_/', '!', $text);
    $text = str_replace('_', '、', $text);

    $text = trim($text);

    //$text = preg_replace('/…$/', '', $text);
    $text = preg_replace('/。$/', '', $text);

    $text = trim($text);

    return $text;
}

function create_wav($text, $filename)
{
    global $context_opts, $http_opts;

    $http_opts['text'] = $text;

    $url = 'http://127.0.0.1:5000/voice?' . http_build_query($http_opts);

    $context = stream_context_create($context_opts);

    $data = file_get_contents($url, false, $context);

    file_put_contents($filename, $data);
}

function parse_csv($csv_filename)
{
    $csv_data = [];

    $fp = fopen($csv_filename, 'r');

    if ( !$fp ) {
        throw new Exception('could not open csv file - ' . $csv_filename);
    }

    // ヘッダ行を読み捨てる
    fgets($fp);

    while ( !feof($fp) ) {
        $ary = fgetcsv($fp);

        // CSVですらない不正な行(ファイルの末尾など)
        if ( !is_array($ary) ) {
            continue;
        }

        // カラムの数が合わない不正な行
        if ( count($ary) != 8 ) {
            continue;
        }

        // セリフが存在しない行
        $dialogue = trim($ary[6]);

        if ( strlen($dialogue) == 0 ) {
            continue;
        }

        // filename
        $filename = $ary[4];

        if ( strlen($filename) == 0 ) {
            continue;
        }

        $filename = str_replace('.fuz', '.wav', $filename);

        $csv_data[$filename] = $dialogue;
    }

    fclose($fp);

    return $csv_data;
}

コマンドプロンプトを開き、以下のコマンドで実行できます。

php create_dialogue_wav.php <LazyVoiceFinderのcsvファイル名>

感想

処理が速いです。速すぎてエラー終了しているのかと思いました。

適当に用意した素材でもそっくりに話します。

何より話し方が自然です。VOICEVOXにあるような違和感がだいぶ減ります。

とある有名キャラクターの場合

素材が8分しか用意できませんでした。

設定は「HuggingFaceのWhisperを使う(速度が速いがVRAMを多く使う)」のチェックを外したのみで、他はすべてデフォルトのまま、全部入れて数時間で終わりました。

素材が少なすぎるため期待はしていませんでしたが、結果は予想以上の出来で、十分に実用的と言える品質になりました。

Skyrimの男カジートの場合

素材はSkyrim.esmのセリフからすべて、十分すぎるほどあります。

設定は「HuggingFaceのWhisperを使う(速度が速いがVRAMを多く使う)」のチェックを外しただけではダメで、WhisperモデルをMediumに、バッチサイズを1に下げました。

半日経過しても学習の進捗が50%だったので中断し、音声合成してみましたが、十分に実用的と言えました。素材が十分にあったからだと思います。

GeForce RTX 5080/5090の場合

GPUのアーキテクチャが新しいせいで、デフォルトのインストールでは対応していないようです。音声合成はできるのですが、学習ができません。

試行錯誤してうまくできた手順を書いておきます。

Style-Bert-VITS2を普通にインストールします。

ターミナルを起動してffmpegをインストールします。

winget install ffmpeg

NVIDIA CUDA Toolkitをインストールします。(本当に必要なのかは不明です)

Style-Bert-VITS2をインストールしたフォルダのvenvの中で右クリックしてターミナルを起動します。

私の環境では以下のパスでした。

C:\GAMES\sbv2\Style-Bert-VITS2\venv

次のコマンドでpytorchを更新します。

.\Scripts\pip3 install --pre torch==2.7.0.dev20250311 torchaudio==2.6.0.dev20250312 torchvision==0.22.0.dev20250312 --index-url https://download.pytorch.org/whl/nightly/cu128

これで学習から音声合成まで一連の流れが成功しました。

また、この環境だと「HuggingFaceのWhisperを使う(速度が速いがVRAMを多く使う)」のチェックを入れたままでも大丈夫でした。

ちなみに、この記事を書いている時点では次のようになっているようです。

  • PyTorchの安定版がCUDA 12.6まで対応
  • RTX 5080/5090はCUDA 12.8が必要なので動作しない
  • Style-Bert-VITS2に同梱されているPyTorchはもっと古い
  • PyTorchの開発版なら対応している
  • 開発版の最新版は20250408だったがエラーが出て動作せず
  • あれこれ試して20250312まで遡ると動作した
タイトルとURLをコピーしました