Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
litagin02 committed Feb 7, 2024
2 parents 6adfab9 + 865b75f commit 023592e
Show file tree
Hide file tree
Showing 20 changed files with 196 additions and 192 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ venv/
*.csv
*.bak
/mos_results/

safetensors.ipynb
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ https://github.com/litagin02/Style-Bert-VITS2/assets/139731664/e853f9a2-db4a-420
- [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](http://colab.research.google.com/github/litagin02/Style-Bert-VITS2/blob/master/colab.ipynb)
- [🤗 オンラインデモはこちらから](https://huggingface.co/spaces/litagin/Style-Bert-VITS2-JVNV)

- [**リリースページ**](https://github.com/litagin02/Style-Bert-VITS2/releases/tag/2.0)[更新履歴](docs/CHANGELOG.md)
- [**リリースページ**](https://github.com/litagin02/Style-Bert-VITS2/releases/)[更新履歴](docs/CHANGELOG.md)

- 2024-02-05: ver 2.0.1
- 2024-02-07: ver 2.1
- 2024-02-03: ver 2.0
- 2024-01-09: ver 1.3
- 2023-12-31: ver 1.2
Expand All @@ -25,7 +25,7 @@ This repository is based on [Bert-VITS2](https://github.com/fishaudio/Bert-VITS2
- GitやPythonがない人でも(Windowsユーザーなら)簡単にインストールでき、学習もできます (多くを[EasyBertVits2](https://github.com/Zuntan03/EasyBertVits2/)からお借りしました)。またGoogle Colabでの学習もサポートしています: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](http://colab.research.google.com/github/litagin02/Style-Bert-VITS2/blob/master/colab.ipynb)
- 音声合成のみに使う場合は、グラボがなくてもCPUで動作します。
- 他との連携に使えるAPIサーバーも同梱しています ([@darai0512](https://github.com/darai0512) 様によるPRです、ありがとうございます)。
- 元々が「楽しそうな文章は楽しそうに、悲しそうな文章は悲しそうに」読むのがBert-VITS2の強みですので、このフォークで付加されたスタイル指定を無理に使わずとも感情豊かな音声を生成することができます
- 元々「楽しそうな文章は楽しそうに、悲しそうな文章は悲しそうに」読むのがBert-VITS2の強みですので、スタイル指定がデフォルトでも感情豊かな音声を生成することができます


## 使い方
Expand Down Expand Up @@ -141,23 +141,20 @@ python speech_mos.py -m <model_name>

- [EasyBertVits2](https://github.com/Zuntan03/EasyBertVits2)のように、PythonやGitを知らない人でも簡単に使える。
- 感情埋め込みのモデルを変更(256次元の[wespeaker-voxceleb-resnet34-LM](https://huggingface.co/pyannote/wespeaker-voxceleb-resnet34-LM)へ、感情埋め込みというよりは話者識別のための埋め込み)
- 埋め込みもベクトル量子化を取り払い、単なる全結合層に。
- 感情埋め込みもベクトル量子化を取り払い、単なる全結合層に。
- スタイルベクトルファイル`style_vectors.npy`を作ることで、そのスタイルを使って効果の強さも連続的に指定しつつ音声を生成することができる。
- 各種WebUIを作成
- bf16での学習のサポート
- safetensors形式のサポート、デフォルトでsafetensorsを使用するように
- その他軽微なbugfixやリファクタリング

## TODO
- [ ] デフォルトのJVNVモデルにJP-Extra版のものを追加
- [x] デフォルトのJVNVモデルにJP-Extra版のものを追加
- [x] LinuxやWSL等、Windowsの通常環境以外でのサポート ← おそらく問題ないとの報告あり
- [x] 複数話者学習での音声合成対応(学習は現在でも可能)
- [ ] 本家のver 2.1, 2.2, 2.3モデルの推論対応?(ver 2.1以外は明らかにめんどいのでたぶんやらない)
- [x] `server_fastapi.py`の対応、とくにAPIで使えるようになると嬉しい人が増えるのかもしれない
- [x] モデルのマージで声音と感情表現を混ぜる機能の実装
- [ ] 英語等多言語対応?
- [ ] ONNX対応


## References
In addition to the original reference (written below), I used the following repositories:
Expand Down
11 changes: 8 additions & 3 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
DEFAULT_SPLIT_INTERVAL,
DEFAULT_STYLE,
DEFAULT_STYLE_WEIGHT,
LATEST_VERSION,
Languages,
)
from common.log import logger
Expand All @@ -36,6 +37,8 @@


def tts_fn(
model_name,
model_path,
text,
language,
reference_audio_path,
Expand All @@ -54,7 +57,7 @@ def tts_fn(
use_tone,
speaker,
):
assert model_holder.current_model is not None
model_holder.load_model_gr(model_name, model_path)

wrong_tone_message = ""
kata_tone: Optional[list[tuple[str, int]]] = None
Expand Down Expand Up @@ -190,8 +193,8 @@ def tts_fn(
],
]

initial_md = """
# Style-Bert-VITS2 ver 2.0 音声合成
initial_md = f"""
# Style-Bert-VITS2 ver {LATEST_VERSION} 音声合成
注意: 初期からある[jvnvのモデル](https://huggingface.co/litagin/style_bert_vits2_jvnv)は、[JVNVコーパス(言語音声と非言語音声を持つ日本語感情音声コーパス)](https://sites.google.com/site/shinnosuketakamichi/research-topics/jvnv_corpus)で学習されたモデルです。ライセンスは[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/deed.ja)です。
"""
Expand Down Expand Up @@ -418,6 +421,8 @@ def gr_util(item):
tts_button.click(
tts_fn,
inputs=[
model_name,
model_path,
text_input,
language,
ref_audio_path,
Expand Down
29 changes: 12 additions & 17 deletions clustering.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"もっといろいろ足したりいろんなスタイルベクトルを作って遊べると思います。\n",
"ある程度慣れている人向けです。\n",
"\n",
"JVNVコーパスのように**スタイルが既にファイル名等で分かれている場合は、最後の方のセルを使えばそれを利用してスタイルを作ることができます。**\n",
"\n",
"例では[JVNVコーパス](https://sites.google.com/site/shinnosuketakamichi/research-topics/jvnv_corpus)のjvnv-M1を使います。\n",
"\n",
"## そもそもスタイルベクトルとは\n",
Expand Down Expand Up @@ -204,31 +206,24 @@
"np.save(\"model_assets/jvnv-M1/style_vectors.npy\", save_vectors)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 正解ラベルがファイル名から分かる場合の作り方\n",
"JVNVコーパス等でファイル名によってスタイルラベルが分かる場合、以下のようにしてスタイルベクトルを作ることができます(デフォルトのJVNVモデルのスタイルはこれで作成しています)。"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# JVNVコーパスの場合は正解はファイル名の最初の方から分かる。それを使って正解ラベルを作成\n",
"y_true = [name[3:6] for name in names]\n",
"label_dict = {\"ang\": 0, \"dis\": 1, \"fea\": 2, \"hap\": 3, \"sad\": 4, \"sur\": 5}\n",
"\n",
"for i, y in enumerate(y_true):\n",
" if y == \"ang\":\n",
" y_true[i] = 0\n",
" elif y == \"dis\":\n",
" y_true[i] = 1\n",
" elif y == \"fea\":\n",
" y_true[i] = 2\n",
" elif y == \"hap\":\n",
" y_true[i] = 3\n",
" elif y == \"sad\":\n",
" y_true[i] = 4\n",
" elif y == \"sur\":\n",
" y_true[i] = 5\n",
" else:\n",
" print(y)\n",
" raise ValueError"
"y_true = [label_dict[name[3:6]] for name in names]"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion colab.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Style-Bert-VITS2 (ver 2.0) のGoogle Colabでの学習\n",
"# Style-Bert-VITS2 (ver 2.1) のGoogle Colabでの学習\n",
"\n",
"Google Colab上でStyle-Bert-VITS2の学習を行うことができます。\n",
"\n",
Expand Down
1 change: 1 addition & 0 deletions common/constants.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import enum

LATEST_VERSION: str = "2.1"
DEFAULT_STYLE: str = "Neutral"
DEFAULT_STYLE_WEIGHT: float = 5.0

Expand Down
12 changes: 12 additions & 0 deletions common/tts_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,18 @@ def load_model_gr(
raise ValueError(f"Model `{model_name}` is not found")
if model_path not in self.model_files_dict[model_name]:
raise ValueError(f"Model file `{model_path}` is not found")
if (
self.current_model is not None
and self.current_model.model_path == model_path
):
# Already loaded
speakers = list(self.current_model.spk2id.keys())
styles = list(self.current_model.style2id.keys())
return (
gr.Dropdown(choices=styles, value=styles[0]),
gr.Button(interactive=True, value="音声合成"),
gr.Dropdown(choices=speakers, value=speakers[0]),
)
self.current_model = Model(
model_path=model_path,
config_path=os.path.join(self.root_dir, model_name, "config.json"),
Expand Down
36 changes: 29 additions & 7 deletions config.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
"""
@Desc: 全局配置文件读取
"""
import argparse

import os
import shutil
from typing import Dict, List

import torch
import yaml

from common.log import logger

# If not cuda available, set possible devices to cpu
cuda_available = torch.cuda.is_available()


class Resample_config:
"""重采样配置"""
Expand Down Expand Up @@ -44,13 +48,23 @@ def __init__(
max_val_total: int = 10000,
clean: bool = True,
):
self.transcription_path: str = transcription_path # 原始文本文件路径,文本格式应为{wav_path}|{speaker_name}|{language}|{text}。
self.cleaned_path: str = cleaned_path # 数据清洗后文本路径,可以不填。不填则将在原始文本目录生成
self.train_path: str = train_path # 训练集路径,可以不填。不填则将在原始文本目录生成
self.val_path: str = val_path # 验证集路径,可以不填。不填则将在原始文本目录生成
self.transcription_path: str = (
transcription_path # 原始文本文件路径,文本格式应为{wav_path}|{speaker_name}|{language}|{text}。
)
self.cleaned_path: str = (
cleaned_path # 数据清洗后文本路径,可以不填。不填则将在原始文本目录生成
)
self.train_path: str = (
train_path # 训练集路径,可以不填。不填则将在原始文本目录生成
)
self.val_path: str = (
val_path # 验证集路径,可以不填。不填则将在原始文本目录生成
)
self.config_path: str = config_path # 配置文件路径
self.val_per_lang: int = val_per_lang # 每个speaker的验证集条数
self.max_val_total: int = max_val_total # 验证集最大条数,多于的会被截断并放到训练集中
self.max_val_total: int = (
max_val_total # 验证集最大条数,多于的会被截断并放到训练集中
)
self.clean: bool = clean # 是否进行数据清洗

@classmethod
Expand Down Expand Up @@ -83,6 +97,8 @@ def __init__(
):
self.config_path = config_path
self.num_processes = num_processes
if not cuda_available:
device = "cpu"
self.device = device
self.use_multi_device = use_multi_device

Expand All @@ -104,6 +120,8 @@ def __init__(
):
self.config_path = config_path
self.num_processes = num_processes
if not cuda_available:
device = "cpu"
self.device = device

@classmethod
Expand Down Expand Up @@ -143,7 +161,7 @@ def from_dict(cls, dataset_path: str, data: Dict[str, any]):


class Webui_config:
"""webui 配置"""
"""webui 配置 (for webui.py, not supported now)"""

def __init__(
self,
Expand All @@ -155,6 +173,8 @@ def __init__(
share: bool = False,
debug: bool = False,
):
if not cuda_available:
device = "cpu"
self.device: str = device
self.model: str = model # 端口号
self.config_path: str = config_path # 是否公开部署,对外网开放
Expand Down Expand Up @@ -182,6 +202,8 @@ def __init__(
origins: List[str] = None,
):
self.port: int = port
if not cuda_available:
device = "cpu"
self.device: str = device
self.language: str = language
self.limit: int = limit
Expand Down
2 changes: 1 addition & 1 deletion configs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,5 @@
"use_spectral_norm": false,
"gin_channels": 256
},
"version": "2.0.1"
"version": "2.1"
}
2 changes: 1 addition & 1 deletion configs/configs_jp_extra.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,5 @@
"initial_channel": 64
}
},
"version": "2.0.1-JP-Extra"
"version": "2.1-JP-Extra"
}
11 changes: 11 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## v2.1 (2024-02-07)

### 変更
- 学習の際、デフォルトではbfloat16オプションを使わないよう変更(学習が発散したり質が下がることがある模様)
- 学習の際のメモリ使用量を削減しようと頑張った

### バグ修正や改善
- 音声合成(やそのAPI)において、同時に別の話者が選択され音声合成がリクエストされた場合に発生するエラーを修正
- モデルマージ時に、そのレシピを`recipe.json`ファイルへ保存するように変更
- 「改行で分けて生成」がより感情が乗る旨の明記等、軽微な説明文の改善

## v2.0.1 (2024-02-05)

軽微なバグ修正や改善
Expand Down
19 changes: 10 additions & 9 deletions initialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,18 @@ def download_jvnv_models():
)


parser = argparse.ArgumentParser()
parser.add_argument("--skip_jvnv", action="store_true")
args = parser.parse_args()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--skip_jvnv", action="store_true")
args = parser.parse_args()

download_bert_models()
download_bert_models()

download_slm_model()
download_slm_model()

download_pretrained_models()
download_pretrained_models()

download_jp_extra_pretrained_models()
download_jp_extra_pretrained_models()

if not args.skip_jvnv:
download_jvnv_models()
if not args.skip_jvnv:
download_jvnv_models()
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ gradio
jaconv
jieba
langid
librosa
librosa==0.9.2
loguru
matplotlib
mecab-python3
Expand Down
Loading

0 comments on commit 023592e

Please sign in to comment.