Unify webui to single webui
This commit is contained in:
@@ -8,12 +8,6 @@ from common.constants import GRADIO_THEME
|
||||
from common.log import logger
|
||||
from common.subprocess_utils import run_script_with_log
|
||||
|
||||
# Get path settings
|
||||
with open(os.path.join("configs", "paths.yml"), "r", encoding="utf-8") as f:
|
||||
path_config: dict[str, str] = yaml.safe_load(f.read())
|
||||
dataset_root = path_config["dataset_root"]
|
||||
# assets_root = path_config["assets_root"]
|
||||
|
||||
|
||||
def do_slice(
|
||||
model_name: str,
|
||||
@@ -69,13 +63,11 @@ def do_transcribe(
|
||||
]
|
||||
)
|
||||
if not success:
|
||||
return f"Error: {message}"
|
||||
return f"Error: {message}. しかし何故かエラーが起きても正常に終了している場合がほとんどなので、書き起こし結果を確認して問題なければ学習に使えます。"
|
||||
return "音声の文字起こしが完了しました。"
|
||||
|
||||
|
||||
initial_md = """
|
||||
# 簡易学習用データセット作成ツール
|
||||
|
||||
how_to_md = """
|
||||
Style-Bert-VITS2の学習用データセットを作成するためのツールです。以下の2つからなります。
|
||||
|
||||
- 与えられた音声からちょうどいい長さの発話区間を切り取りスライス
|
||||
@@ -107,10 +99,10 @@ Style-Bert-VITS2の学習用データセットを作成するためのツール
|
||||
"""
|
||||
|
||||
|
||||
def create_dataset_app():
|
||||
|
||||
with gr.Blocks(theme=GRADIO_THEME) as app:
|
||||
gr.Markdown(initial_md)
|
||||
def create_dataset_app() -> gr.Blocks:
|
||||
with gr.Blocks() as app:
|
||||
with gr.Accordion("使い方", open=False):
|
||||
gr.Markdown(how_to_md)
|
||||
model_name = gr.Textbox(
|
||||
label="モデル名を入力してください(話者名としても使われます)。"
|
||||
)
|
||||
@@ -118,8 +110,8 @@ def create_dataset_app():
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
input_dir = gr.Textbox(
|
||||
label="入力フォルダ名(デフォルトはinputs)",
|
||||
placeholder="inputs",
|
||||
label="元音声の入っているフォルダパス",
|
||||
value="inputs",
|
||||
info="下記フォルダにwavファイルを入れておいてください",
|
||||
)
|
||||
min_sec = gr.Slider(
|
||||
@@ -201,20 +193,4 @@ def create_dataset_app():
|
||||
outputs=[result2],
|
||||
)
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--server-name",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Server name for Gradio app",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-autolaunch",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Do not launch app automatically",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# app.launch(inbrowser=not args.no_autolaunch, server_name=args.server_name)
|
||||
return app
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
import argparse
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import gradio as gr
|
||||
import torch
|
||||
import yaml
|
||||
|
||||
from common.constants import (
|
||||
DEFAULT_ASSIST_TEXT_WEIGHT,
|
||||
@@ -21,7 +16,6 @@ from common.constants import (
|
||||
DEFAULT_STYLE,
|
||||
DEFAULT_STYLE_WEIGHT,
|
||||
GRADIO_THEME,
|
||||
LATEST_VERSION,
|
||||
Languages,
|
||||
)
|
||||
from common.log import logger
|
||||
@@ -29,119 +23,9 @@ from common.tts_model import ModelHolder
|
||||
from infer import InvalidToneError
|
||||
from text.japanese import g2kata_tone, kata_tone2phone_tone, text_normalize
|
||||
|
||||
# Get path settings
|
||||
with open(os.path.join("configs", "paths.yml"), "r", encoding="utf-8") as f:
|
||||
path_config: dict[str, str] = yaml.safe_load(f.read())
|
||||
# dataset_root = path_config["dataset_root"]
|
||||
assets_root = path_config["assets_root"]
|
||||
|
||||
languages = [l.value for l in Languages]
|
||||
|
||||
|
||||
def tts_fn(
|
||||
model_name,
|
||||
model_path,
|
||||
text,
|
||||
language,
|
||||
reference_audio_path,
|
||||
sdp_ratio,
|
||||
noise_scale,
|
||||
noise_scale_w,
|
||||
length_scale,
|
||||
line_split,
|
||||
split_interval,
|
||||
assist_text,
|
||||
assist_text_weight,
|
||||
use_assist_text,
|
||||
style,
|
||||
style_weight,
|
||||
kata_tone_json_str,
|
||||
use_tone,
|
||||
speaker,
|
||||
pitch_scale,
|
||||
intonation_scale,
|
||||
):
|
||||
model_holder.load_model_gr(model_name, model_path)
|
||||
|
||||
wrong_tone_message = ""
|
||||
kata_tone: Optional[list[tuple[str, int]]] = None
|
||||
if use_tone and kata_tone_json_str != "":
|
||||
if language != "JP":
|
||||
logger.warning("Only Japanese is supported for tone generation.")
|
||||
wrong_tone_message = "アクセント指定は現在日本語のみ対応しています。"
|
||||
if line_split:
|
||||
logger.warning("Tone generation is not supported for line split.")
|
||||
wrong_tone_message = (
|
||||
"アクセント指定は改行で分けて生成を使わない場合のみ対応しています。"
|
||||
)
|
||||
try:
|
||||
kata_tone = []
|
||||
json_data = json.loads(kata_tone_json_str)
|
||||
# tupleを使うように変換
|
||||
for kana, tone in json_data:
|
||||
assert isinstance(kana, str) and tone in (0, 1), f"{kana}, {tone}"
|
||||
kata_tone.append((kana, tone))
|
||||
except Exception as e:
|
||||
logger.warning(f"Error occurred when parsing kana_tone_json: {e}")
|
||||
wrong_tone_message = f"アクセント指定が不正です: {e}"
|
||||
kata_tone = None
|
||||
|
||||
# toneは実際に音声合成に代入される際のみnot Noneになる
|
||||
tone: Optional[list[int]] = None
|
||||
if kata_tone is not None:
|
||||
phone_tone = kata_tone2phone_tone(kata_tone)
|
||||
tone = [t for _, t in phone_tone]
|
||||
|
||||
speaker_id = model_holder.current_model.spk2id[speaker]
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
|
||||
assert model_holder.current_model is not None
|
||||
|
||||
try:
|
||||
sr, audio = model_holder.current_model.infer(
|
||||
text=text,
|
||||
language=language,
|
||||
reference_audio_path=reference_audio_path,
|
||||
sdp_ratio=sdp_ratio,
|
||||
noise=noise_scale,
|
||||
noisew=noise_scale_w,
|
||||
length=length_scale,
|
||||
line_split=line_split,
|
||||
split_interval=split_interval,
|
||||
assist_text=assist_text,
|
||||
assist_text_weight=assist_text_weight,
|
||||
use_assist_text=use_assist_text,
|
||||
style=style,
|
||||
style_weight=style_weight,
|
||||
given_tone=tone,
|
||||
sid=speaker_id,
|
||||
pitch_scale=pitch_scale,
|
||||
intonation_scale=intonation_scale,
|
||||
)
|
||||
except InvalidToneError as e:
|
||||
logger.error(f"Tone error: {e}")
|
||||
return f"Error: アクセント指定が不正です:\n{e}", None, kata_tone_json_str
|
||||
except ValueError as e:
|
||||
logger.error(f"Value error: {e}")
|
||||
return f"Error: {e}", None, kata_tone_json_str
|
||||
|
||||
end_time = datetime.datetime.now()
|
||||
duration = (end_time - start_time).total_seconds()
|
||||
|
||||
if tone is None and language == "JP":
|
||||
# アクセント指定に使えるようにアクセント情報を返す
|
||||
norm_text = text_normalize(text)
|
||||
kata_tone = g2kata_tone(norm_text)
|
||||
kata_tone_json_str = json.dumps(kata_tone, ensure_ascii=False)
|
||||
elif tone is None:
|
||||
kata_tone_json_str = ""
|
||||
message = f"Success, time: {duration} seconds."
|
||||
if wrong_tone_message != "":
|
||||
message = wrong_tone_message + "\n" + message
|
||||
return message, (sr, audio), kata_tone_json_str
|
||||
|
||||
|
||||
initial_text = "こんにちは、初めまして。あなたの名前はなんていうの?"
|
||||
|
||||
examples = [
|
||||
@@ -202,9 +86,7 @@ examples = [
|
||||
]
|
||||
|
||||
initial_md = f"""
|
||||
# Style-Bert-VITS2 ver {LATEST_VERSION} 音声合成
|
||||
|
||||
- Ver 2.3で追加されたエディターのほうが実際に読み上げさせるには使いやすいかもしれません。`Editor.bat`か`python server_editor.py`で起動できます。
|
||||
- Ver 2.3で追加されたエディターのほうが実際に読み上げさせるには使いやすいかもしれません。`Editor.bat`か`python server_editor.py --inbrowser`で起動できます。
|
||||
|
||||
- 初期からある[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)です。
|
||||
"""
|
||||
@@ -254,43 +136,119 @@ def gr_util(item):
|
||||
return (gr.update(visible=False), gr.update(visible=True))
|
||||
|
||||
|
||||
def create_inference_app():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--cpu", action="store_true", help="Use CPU instead of GPU")
|
||||
parser.add_argument(
|
||||
"--dir", "-d", type=str, help="Model directory", default=assets_root
|
||||
)
|
||||
parser.add_argument(
|
||||
"--share", action="store_true", help="Share this app publicly", default=False
|
||||
)
|
||||
parser.add_argument(
|
||||
"--server-name",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Server name for Gradio app",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-autolaunch",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Do not launch app automatically",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
model_dir = Path(args.dir)
|
||||
def create_inference_app(model_holder: ModelHolder) -> gr.Blocks:
|
||||
def tts_fn(
|
||||
model_name,
|
||||
model_path,
|
||||
text,
|
||||
language,
|
||||
reference_audio_path,
|
||||
sdp_ratio,
|
||||
noise_scale,
|
||||
noise_scale_w,
|
||||
length_scale,
|
||||
line_split,
|
||||
split_interval,
|
||||
assist_text,
|
||||
assist_text_weight,
|
||||
use_assist_text,
|
||||
style,
|
||||
style_weight,
|
||||
kata_tone_json_str,
|
||||
use_tone,
|
||||
speaker,
|
||||
pitch_scale,
|
||||
intonation_scale,
|
||||
):
|
||||
model_holder.load_model(model_name, model_path)
|
||||
assert model_holder.current_model is not None
|
||||
|
||||
if args.cpu:
|
||||
device = "cpu"
|
||||
else:
|
||||
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||
wrong_tone_message = ""
|
||||
kata_tone: Optional[list[tuple[str, int]]] = None
|
||||
if use_tone and kata_tone_json_str != "":
|
||||
if language != "JP":
|
||||
logger.warning("Only Japanese is supported for tone generation.")
|
||||
wrong_tone_message = "アクセント指定は現在日本語のみ対応しています。"
|
||||
if line_split:
|
||||
logger.warning("Tone generation is not supported for line split.")
|
||||
wrong_tone_message = (
|
||||
"アクセント指定は改行で分けて生成を使わない場合のみ対応しています。"
|
||||
)
|
||||
try:
|
||||
kata_tone = []
|
||||
json_data = json.loads(kata_tone_json_str)
|
||||
# tupleを使うように変換
|
||||
for kana, tone in json_data:
|
||||
assert isinstance(kana, str) and tone in (0, 1), f"{kana}, {tone}"
|
||||
kata_tone.append((kana, tone))
|
||||
except Exception as e:
|
||||
logger.warning(f"Error occurred when parsing kana_tone_json: {e}")
|
||||
wrong_tone_message = f"アクセント指定が不正です: {e}"
|
||||
kata_tone = None
|
||||
|
||||
model_holder = ModelHolder(model_dir, device)
|
||||
# toneは実際に音声合成に代入される際のみnot Noneになる
|
||||
tone: Optional[list[int]] = None
|
||||
if kata_tone is not None:
|
||||
phone_tone = kata_tone2phone_tone(kata_tone)
|
||||
tone = [t for _, t in phone_tone]
|
||||
|
||||
speaker_id = model_holder.current_model.spk2id[speaker]
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
|
||||
try:
|
||||
sr, audio = model_holder.current_model.infer(
|
||||
text=text,
|
||||
language=language,
|
||||
reference_audio_path=reference_audio_path,
|
||||
sdp_ratio=sdp_ratio,
|
||||
noise=noise_scale,
|
||||
noisew=noise_scale_w,
|
||||
length=length_scale,
|
||||
line_split=line_split,
|
||||
split_interval=split_interval,
|
||||
assist_text=assist_text,
|
||||
assist_text_weight=assist_text_weight,
|
||||
use_assist_text=use_assist_text,
|
||||
style=style,
|
||||
style_weight=style_weight,
|
||||
given_tone=tone,
|
||||
sid=speaker_id,
|
||||
pitch_scale=pitch_scale,
|
||||
intonation_scale=intonation_scale,
|
||||
)
|
||||
except InvalidToneError as e:
|
||||
logger.error(f"Tone error: {e}")
|
||||
return f"Error: アクセント指定が不正です:\n{e}", None, kata_tone_json_str
|
||||
except ValueError as e:
|
||||
logger.error(f"Value error: {e}")
|
||||
return f"Error: {e}", None, kata_tone_json_str
|
||||
|
||||
end_time = datetime.datetime.now()
|
||||
duration = (end_time - start_time).total_seconds()
|
||||
|
||||
if tone is None and language == "JP":
|
||||
# アクセント指定に使えるようにアクセント情報を返す
|
||||
norm_text = text_normalize(text)
|
||||
kata_tone = g2kata_tone(norm_text)
|
||||
kata_tone_json_str = json.dumps(kata_tone, ensure_ascii=False)
|
||||
elif tone is None:
|
||||
kata_tone_json_str = ""
|
||||
message = f"Success, time: {duration} seconds."
|
||||
if wrong_tone_message != "":
|
||||
message = wrong_tone_message + "\n" + message
|
||||
return message, (sr, audio), kata_tone_json_str
|
||||
|
||||
model_names = model_holder.model_names
|
||||
if len(model_names) == 0:
|
||||
logger.error(
|
||||
f"モデルが見つかりませんでした。{model_dir}にモデルを置いてください。"
|
||||
f"モデルが見つかりませんでした。{model_holder.root_dir}にモデルを置いてください。"
|
||||
)
|
||||
sys.exit(1)
|
||||
with gr.Blocks() as app:
|
||||
gr.Markdown(
|
||||
f"Error: モデルが見つかりませんでした。{model_holder.root_dir}にモデルを置いてください。"
|
||||
)
|
||||
return app
|
||||
initial_id = 0
|
||||
initial_pth_files = model_holder.model_files_dict[model_names[initial_id]]
|
||||
|
||||
@@ -497,8 +455,4 @@ def create_inference_app():
|
||||
outputs=[style, ref_audio_path],
|
||||
)
|
||||
|
||||
# app.launch(
|
||||
# inbrowser=not args.no_autolaunch, share=args.share, server_name=args.server_name
|
||||
# )
|
||||
|
||||
return app
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import gradio as gr
|
||||
@@ -28,8 +27,6 @@ with open(os.path.join("configs", "paths.yml"), "r", encoding="utf-8") as f:
|
||||
# dataset_root = path_config["dataset_root"]
|
||||
assets_root = path_config["assets_root"]
|
||||
|
||||
model_holder = ModelHolder(Path(assets_root), device)
|
||||
|
||||
|
||||
def merge_style(model_name_a, model_name_b, weight, output_name, style_triple_list):
|
||||
"""
|
||||
@@ -331,13 +328,17 @@ Happy, Surprise, HappySurprise
|
||||
"""
|
||||
|
||||
|
||||
def create_merge_app():
|
||||
def create_merge_app(model_holder: ModelHolder) -> gr.Blocks:
|
||||
model_names = model_holder.model_names
|
||||
if len(model_names) == 0:
|
||||
logger.error(
|
||||
f"モデルが見つかりませんでした。{assets_root}にモデルを置いてください。"
|
||||
)
|
||||
sys.exit(1)
|
||||
with gr.Blocks() as app:
|
||||
gr.Markdown(
|
||||
f"Error: モデルが見つかりませんでした。{assets_root}にモデルを置いてください。"
|
||||
)
|
||||
return app
|
||||
initial_id = 0
|
||||
initial_model_files = model_holder.model_files_dict[model_names[initial_id]]
|
||||
|
||||
@@ -499,23 +500,4 @@ def create_merge_app():
|
||||
outputs=[audio_output],
|
||||
)
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--server-name",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Server name for Gradio app",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-autolaunch",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Do not launch app automatically",
|
||||
)
|
||||
parser.add_argument("--share", action="store_true", default=False)
|
||||
args = parser.parse_args()
|
||||
|
||||
# app.launch(
|
||||
# inbrowser=not args.no_autolaunch, server_name=args.server_name, share=args.share
|
||||
# )
|
||||
return app
|
||||
|
||||
@@ -277,9 +277,7 @@ def save_style_vectors_from_files(
|
||||
return f"成功!\n{style_vector_path}に保存し{config_path}を更新しました。"
|
||||
|
||||
|
||||
initial_md = f"""
|
||||
# Style Bert-VITS2 スタイルベクトルの作成
|
||||
|
||||
how_to_md = f"""
|
||||
Style-Bert-VITS2でこまかくスタイルを指定して音声合成するには、モデルごとにスタイルベクトルのファイル`style_vectors.npy`を手動で作成する必要があります。
|
||||
|
||||
ただし、学習の過程で自動的に平均スタイル「{DEFAULT_STYLE}」のみは作成されるので、それをそのまま使うこともできます(その場合はこのWebUIは使いません)。
|
||||
@@ -326,7 +324,8 @@ https://ja.wikipedia.org/wiki/DBSCAN
|
||||
|
||||
def create_style_vectors_app():
|
||||
with gr.Blocks(theme=GRADIO_THEME) as app:
|
||||
gr.Markdown(initial_md)
|
||||
with gr.Accordion("使い方", open=False):
|
||||
gr.Markdown(how_to_md)
|
||||
with gr.Row():
|
||||
model_name = gr.Textbox(placeholder="your_model_name", label="モデル名")
|
||||
reduction_method = gr.Radio(
|
||||
@@ -461,23 +460,4 @@ def create_style_vectors_app():
|
||||
outputs=[info2],
|
||||
)
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--server-name",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Server name for Gradio app",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-autolaunch",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Do not launch app automatically",
|
||||
)
|
||||
parser.add_argument("--share", action="store_true", default=False)
|
||||
args = parser.parse_args()
|
||||
|
||||
# app.launch(
|
||||
# inbrowser=not args.no_autolaunch, server_name=args.server_name, share=args.share
|
||||
# )
|
||||
return app
|
||||
|
||||
@@ -14,7 +14,6 @@ from pathlib import Path
|
||||
import gradio as gr
|
||||
import yaml
|
||||
|
||||
from common.constants import GRADIO_THEME, LATEST_VERSION
|
||||
from common.log import logger
|
||||
from common.stdout_wrapper import SAFE_STDOUT
|
||||
from common.subprocess_utils import run_script_with_log, second_elem_of
|
||||
@@ -398,9 +397,7 @@ def run_tensorboard(model_name):
|
||||
yield gr.Button("Tensorboardを開く")
|
||||
|
||||
|
||||
initial_md = f"""
|
||||
# Style-Bert-VITS2 ver {LATEST_VERSION} 学習用WebUI
|
||||
|
||||
how_to_md = f"""
|
||||
## 使い方
|
||||
|
||||
- データを準備して、モデル名を入力して、必要なら設定を調整してから、「自動前処理を実行」ボタンを押してください。進捗状況等はターミナルに表示されます。
|
||||
@@ -452,10 +449,11 @@ english_teacher.wav|Mary|EN|How are you? I'm fine, thank you, and you?
|
||||
|
||||
|
||||
def create_train_app():
|
||||
with gr.Blocks(theme=GRADIO_THEME).queue() as app:
|
||||
gr.Markdown(initial_md)
|
||||
with gr.Accordion(label="データの前準備", open=False):
|
||||
gr.Markdown(prepare_md)
|
||||
with gr.Blocks().queue() as app:
|
||||
with gr.Accordion("使い方", open=False):
|
||||
gr.Markdown(how_to_md)
|
||||
with gr.Accordion(label="データの前準備", open=False):
|
||||
gr.Markdown(prepare_md)
|
||||
model_name = gr.Textbox(label="モデル名")
|
||||
gr.Markdown("### 自動前処理")
|
||||
with gr.Row(variant="panel"):
|
||||
@@ -794,20 +792,5 @@ def create_train_app():
|
||||
outputs=[use_jp_extra_train],
|
||||
)
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--server-name",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Server name for Gradio app",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-autolaunch",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Do not launch app automatically",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# app.launch(inbrowser=not args.no_autolaunch, server_name=args.server_name)
|
||||
return app
|
||||
|
||||
Reference in New Issue
Block a user