🗂

生成AIをGoogle Colaboratoryで簡単に 【Part1 合成音声Style-Bert-VITS2編】

2024/07/02に公開

はじめに

今回は、初心者向けにGoogle Colaboratoryで、簡単に生成AIを使えるようにする環境を作ります。

Part1の今回は、生成AIの一つ、合成音声AIを使えるようにします。
今回利用する合成音声はStyle-Bert-VITS2になります。

今回の記事シリーズを書く意図としては、音声対話システムを作る上での知識の整理のためです。
音声対話システムとは、ユーザが発話した内容を録音して、それを音声認識AIで文字起こしして、テキスト生成AIでAI側の発話内容を出力して、合成音声AIで発話内容を音声にしてスピーカから出力するという一連の流れを繰り返すシステムです。

そのために必要なAI知識に関して、私と同じ初学者の方が簡単にAIに触れることができるようにGoogle Colabで使えるようにしていきたいと思います。

Style-Bert-VITS2とは

Style-Bert-VITS2(SBV2)とはText to Speech(TTS)と呼ばれる、テキストの文字から音声波形を生成するモデルです。

https://github.com/litagin02/Style-Bert-VITS2
こちらのリポジトリで利用することが可能です。

非常に高性能なモデルで、開発者様がデモも用意してくださっているので、ぜひお試しください。
https://huggingface.co/spaces/litagin/Style-Bert-VITS2-Editor-Demo

また、過去にSBV2に関して、使い方などを詳細にまとめました。
より詳しく知りたい方は、そちらも併せてご覧いただけますと幸いです。
https://zenn.dev/asap/articles/f8c0621cdd74cc

さらに、SBV2を利用した音声対話システムに関しても、下記で記事を書いています。
もし興味があれば一読いただけますと幸いです。
https://zenn.dev/asap/articles/5b1b7553fcaa76

成果物

下記のリポジトリをご覧ください。
https://github.com/personabb/colab_SBV2_sample/tree/main

解説

下記の通り、解説を行います。
まずは上記のリポジトリをcloneしてください。

./
git clone https://github.com/personabb/colab_SBV2_sample.git

その後、cloneしたフォルダ「colab_SBV2_sample」をマイドライブの適当な場所においてください。

ディレクトリ構造

Google Driveのディレクトリ構造は下記を想定します。

MyDrive/
    └ colab_zenn/
          └ colab_SBV2_sample/
                  ├ Agents/
                  |    └ {Agent_name}
                  |          └ SBV2/
                  |             └ {model_name}
                  |                    ├ xxxx.safetensors
                  |                    ├ config.json
                  |                    └ style_vectors.npy
                  ├ configs/
                  |    └ config.ini
                  ├ module/
                  |    └ module_SBV2.py
                  └ Style-Bert-VIT2_sample.ipynb

  • colab_zennフォルダは適当です。なんでも良いです。1階層である必要はなく下記のように複数階層になっていても良いです。
    • MyDrive/hogehoge/spamspam/hogespam/colab_SBV2_sample
  • {Agent_name}は合成音声(SBV2)に話させるキャラクターの名前です。自由に決めてください。
    • のちに、設定ファイルconfig.iniをcolabから上書きする際に、名前を指定します。
  • {model_name}はSBV2を動かすために必要なモデル(の重みなど)が格納されているフォルダ名です。こちらもなんでも良いですが、元のフォルダ名をそのまま利用することをお勧めします。

使い方解説

Style-Bert-VIT2_sample.ipynbをGoogle Colabratoryアプリで開いてください。
ファイルを右クリックすると「アプリで開く」という項目が表示されるため、そこからGoogle Colabratoryアプリを選択してください。

もし、ない場合は、「アプリを追加」からアプリストアに行き、「Google Colabratory」で検索してインストールをしてください。

Google Colabratoryアプリで開いたら、Style-Bert-VIT2_sample.ipynbのメモを参考にして、一番上のセルから順番に実行していけば、問題なく最後まで動作して、合成音声を出力することができると思います。

また、最後まで実行後、パラメータを変更して再度実行する場合は、「ランタイム」→「セッションを再起動して全て実行する」をクリックしてください。

コード解説

主に、重要なStyle-Bert-VIT2_sample.ipynbmodule/module_SBV2.pyについて解説します。

Style-Bert-VIT2_sample.ipynb

該当のコードは下記になります。
https://github.com/personabb/colab_SBV2_sample/blob/main/Style-Bert-VIT2_sample.ipynb

下記に1セルずつ解説します。

1セル目

./colab_zenn/colab_SBV2_sample/Style-Bert-VIT2_sample.ipynb(1セル目)
#SBV2 で必要なモジュールのインストール
!pip install style-bert-vits2
!pip install pyopenjtalk
!pip install sounddevice

ここでは、必要なモジュールをインストールしています。
Google colabではpytorchなどの基本的な深層学習パッケージなどは、すでにインストール済みなため上記だけインストールすれば問題ありません。

2セル目

./colab_zenn/colab_SBV2_sample/Style-Bert-VIT2_sample.ipynb(2セル目)
#Google Driveのフォルダをマウント(認証入る)
from google.colab import drive
drive.mount('/content/drive')

# カレントディレクトリを本ファイルが存在するディレクトリに変更する。
import glob
import os
pwd = os.path.dirname(glob.glob('/content/drive/MyDrive/**/colab_SBV2_sample/Style-Bert-VIT2_sample.ipynb', recursive=True)[0])
print(pwd)

%cd $pwd
!pwd

ここでは、Googleドライブの中身をマウントしています。
マウントすることで、Googleドライブの中に入っているファイルを読み込んだり、書き込んだりすることが可能になります。

マウントをする際は、Colabから、マウントの許可を行う必要があります。
ポップアップが表示されるため、指示に従い、マウントの許可を行なってください。

また、続けて、カレントディレクトリを/から/content/drive/MyDrive/**/colab_SBV2_sampleに変更しています。
**はワイルドカードです。任意のディレクトリ(複数)が入ります)
カレントディレクトリは必ずしも変更する必要はないですが、カレントディレクトリを変更することで、これ以降のフォルダ指定が楽になります

3セル目

./colab_zenn/colab_SBV2_sample/Style-Bert-VIT2_sample.ipynb(3セル目)
#SBV2を切り出したモジュールをimportする
from module.module_SBV2 import SBV2

module/module_SBV2.pySBV2クラスをモジュールとしてインポートします。
この中身の詳細は後の章で解説します。

4セル目

./colab_zenn/colab_SBV2_sample/Style-Bert-VIT2_sample.ipynb(4セル目)
#モデルの設定を行う。

config_text = """
[DEFAULT]
ai_agent = ai
agent_dir = Agents

[SBV2]

device = auto
bert_models_model = ku-nlp/deberta-v2-large-japanese-char-wwm
bert_models_tokenizer = ku-nlp/deberta-v2-large-japanese-char-wwm


"""

with open("configs/config.ini", "w", encoding="utf-8") as f:
  f.write(config_text)

このセルでは、設定ファイルconfigs/config.iniの中身をconfig_textの内容で上書きしています。
SBV2は上記の設定に併せて動作をします。
例えば、下記のような設定になっている。

  • agent_dir=Agentsに格納されているai_agent=aiのフォルダの中にあるSBV2モデルを利用すること。
    • 別のモデルを利用したい場合は、aiフォルダのモデルを入れ替えるか、別の名前の{Agent_name}のフォルダを作成して、その中にaiフォルダと同様にモデルを格納すると良いです。
  • マシンのGPUやCPUのどちらを利用するかどうかはdevice = autoで指定されている
    • autoの場合は、マシンがGPUを利用できるならGPUを利用する。
    • その他ではcudacpuを指定できる。
  • SBV2で利用するBERTモデルを指定する
    • 基本的にここは変更する必要はない。

5セル目

./colab_zenn/colab_SBV2_sample/Style-Bert-VIT2_sample.ipynb(5セル目)
#読み上げるプロンプトを設定する。

prompt = """
こんにちは!
はじめまして。
"""

ここでは、SBV2に読み上げさせたい文章を記載します。
何行になっても問題ないですが、一文ごとに改行する方が発話の質が上がるためお勧めです。

6セル目

./colab_zenn/colab_SBV2_sample/Style-Bert-VIT2_sample.ipynb(6セル目)
from IPython.display import display, Audio
sbv2 = SBV2()
sr, audio = sbv2.call_TTS(prompt)
display(Audio(audio, rate=sr))

ここでは実際にモデルにpromptの内容を読み上げさせています。
モデルにテキスト入力すると、読み上げた音声の音声波形audioとそのサンプリングレートsrを取得できるため、それを元に最後の行で実際にスピーカーから発話させています。

module/module_SBV2.py

続いて、Style-Bert-VIT2_sample.ipynbから読み込まれるモジュールの中身を説明します。

下記にコード全文を示します。

コード全文
./colab_zenn/colab_SBV2_sample/module/module_SBV2.py
import os
import numpy as np
from pathlib import Path
from style_bert_vits2.nlp import bert_models
from style_bert_vits2.constants import Languages
from pathlib import Path
from style_bert_vits2.tts_model import TTSModel
import queue
from style_bert_vits2.logging import logger
from pathlib import Path
import torch

import glob

import configparser
# ファイルの存在チェック用モジュール
import errno

class SBV2config:
    def __init__(self, config_ini_path = './configs/config.ini'):
        # iniファイルの読み込み
        self.config_ini = configparser.ConfigParser()
        
        # 指定したiniファイルが存在しない場合、エラー発生
        if not os.path.exists(config_ini_path):
            raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), config_ini_path)
        
        self.config_ini.read(config_ini_path, encoding='utf-8')
        SBV2_items = self.config_ini.items('SBV2')
        self.SBV2_config_dict = dict(SBV2_items)


class SBV2:
    def __init__(self,device = None,voice = None,config_ini_path = './configs/config.ini'):
        logger.remove()
        sbv2_config = SBV2config(config_ini_path = config_ini_path)
        config_dict = sbv2_config.SBV2_config_dict
        

        if device is not None:
            self.DEVICE = device
        else:
            device = config_dict["device"]

            self.DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
            if device != "auto":
                self.DEVICE = device
    

        bert_models.load_model(Languages.JP, config_dict["bert_models_model"])
        bert_models.load_tokenizer(Languages.JP, config_dict["bert_models_tokenizer"])

        if voice is not None:
            self.voice = voice
        else:
            self.voice = config_dict["ai_agent"]

        assets_root = config_dict["agent_dir"] + "/" + self.voice

        style_file = glob.glob(f'{assets_root}/**/*.npy',recursive=True)[0]
        config_file = glob.glob(f'{assets_root}/**/*.json',recursive=True)[0]
        model_file = glob.glob(f'{assets_root}/**/*.safetensors',recursive=True)[0]

        print(style_file)
        print(config_file)
        print(model_file)

        
        self.model_TTS = TTSModel(
            model_path=model_file,
            config_path=config_file,
            style_vec_path=style_file,
            device=self.DEVICE
        )

    def call_TTS(self,message):
        sr, audio = self.model_TTS.infer(text=message)

        return sr, audio

    

では一つ一つ解説していきます。

SBV2configクラス

./colab_zenn/colab_SBV2_sample/module/module_SBV2.py

class SBV2config:
    def __init__(self, config_ini_path = './configs/config.ini'):
        # iniファイルの読み込み
        self.config_ini = configparser.ConfigParser()
        
        # 指定したiniファイルが存在しない場合、エラー発生
        if not os.path.exists(config_ini_path):
            raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), config_ini_path)
        
        self.config_ini.read(config_ini_path, encoding='utf-8')
        SBV2_items = self.config_ini.items('SBV2')
        self.SBV2_config_dict = dict(SBV2_items)

ここではconfig_ini_path = './configs/config.ini'で指定されている設定ファイルをSBV2_config_dictとして読み込んでいます。
辞書型で読み込んでいるため、設定ファイルの中身をpythonの辞書として読み込むことが可能になります。

SBV2クラスのinitメソッド

./colab_zenn/colab_SBV2_sample/module/module_SBV2.py

class SBV2:
    def __init__(self,device = None,voice = None,config_ini_path = './configs/config.ini'):
        logger.remove()
        sbv2_config = SBV2config(config_ini_path = config_ini_path)
        config_dict = sbv2_config.SBV2_config_dict
        

        if device is not None:
            self.DEVICE = device
        else:
            device = config_dict["device"]

            self.DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
            if device != "auto":
                self.DEVICE = device
    

        bert_models.load_model(Languages.JP, config_dict["bert_models_model"])
        bert_models.load_tokenizer(Languages.JP, config_dict["bert_models_tokenizer"])

        if voice is not None:
            self.voice = voice
        else:
            self.voice = config_dict["ai_agent"]

        assets_root = config_dict["agent_dir"] + "/" + self.voice

        style_file = glob.glob(f'{assets_root}/**/*.npy',recursive=True)[0]
        config_file = glob.glob(f'{assets_root}/**/*.json',recursive=True)[0]
        model_file = glob.glob(f'{assets_root}/**/*.safetensors',recursive=True)[0]

        print(style_file)
        print(config_file)
        print(model_file)

        
        self.model_TTS = TTSModel(
            model_path=model_file,
            config_path=config_file,
            style_vec_path=style_file,
            device=self.DEVICE
        )

まず、設定ファイルの内容をconfig_dictに格納しています。これは辞書型のため、config_dict["ai_agent"]のような形で設定ファイルの内容を文字列として取得することができます。
あくまで、すべての文字を文字列として取得するため、int型やbool型にしたい場合は、適宜型変更をする必要があることに注意してください。

続いて下記の順番で処理を行います。

  • デバイスの設定
    • GPUを利用するか、cpuを利用するかを設定します。
    • autoが設定されている場合は、システムがcudaを利用できるかどうかを調べて、利用できる場合は、cuda(GPU)を利用します。
  • BERTモデルの設定
    • SBV2のテキスト情報に不要するBERT特徴量を抽出するための、BERTモデルを指定します。
  • モデルの定義
    • 設定ファイルから、エージェントの名前を取得して、そのフォルダの中の必要な重みファイルなどを探索し、そのファイルでモデルを定義しています。

SBV2クラスのcall_TTSメソッド

./colab_zenn/colab_SBV2_sample/module/module_SBV2.py

class SBV2:
    ・・・
    def call_TTS(self,message):
        sr, audio = self.model_TTS.infer(text=message)

        return sr, audio

ここでは、大元のSBV2モジュールに定義されているinferメソッドを読み込み、音声波形とサンプリングレートを生成しています。

まとめ

今回は、初心者向けにGoogle Colaboratoryで、簡単に生成AIを使えるようにする環境を作りました。

Part1の今回は、生成AIの一つ、合成音声AIのStyle-Bert-VITS2を使えるようにしました。

また、過去にSBV2に関して、使い方などを詳細にまとめています。
より詳しく知りたい方は、そちらも併せてご覧いただけますと幸いです。
https://zenn.dev/asap/articles/f8c0621cdd74cc

さらに、SBV2を利用した音声対話システムに関しても、下記で記事を書いています。
もし興味があれば一読いただけますと幸いです。
https://zenn.dev/asap/articles/5b1b7553fcaa76

次回Part2では、chatGPT APIを使えるようにしたいと思います。

Discussion