File size: 12,251 Bytes
060d192 c35ff71 060d192 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
import datetime
import os
import gradio as gr
import numpy as np
import torch
from infer import infer
from server_fastapi import Models
is_hf_spaces = os.getenv("SYSTEM") == "spaces"
limit = 100
root_dir = "weights"
model_holder = Models()
def refresh_model():
global model_holder
model_holder = Models()
model_dirs = [
d for d in os.listdir(root_dir) if os.path.isdir(os.path.join(root_dir, d))
]
model_names = []
for model_name in model_dirs:
model_dir = os.path.join(root_dir, model_name)
pth_files = [f for f in os.listdir(model_dir) if f.endswith(".pth")]
if len(pth_files) != 1:
print(f"{root_dir}/{model_name}のpthファイルの数が1つではないので無視します")
continue
model_path = os.path.join(model_dir, pth_files[0])
config_path = os.path.join(model_dir, "config.json")
try:
model_holder.init_model(
config_path=config_path,
model_path=model_path,
device=device,
language="JP",
)
model_names.append(model_name)
except Exception as e:
print(f"{root_dir}/{model_name}の初期化に失敗しました\n{e}")
continue
return model_names
def update_model_dropdown():
model_names = refresh_model()
return gr.Dropdown(choices=model_names, value=model_names[0])
# `server_fastapi.py`から取ってきて微修正
def _voice(
model_id: int,
text: str,
language: str = "JP",
emotion: int = 0,
sdp_ratio: float = 0.2,
noise: float = 0.6,
noisew: float = 0.8,
length: float = 1.0,
line_split: bool = True,
split_interval: float = 0.2,
speaker_id: int = 0,
):
if model_id not in model_holder.models.keys():
return f"エラー、model_id={model_id}は存在しません", None
speaker_name = model_holder.models[model_id].id2spk[speaker_id]
start_time = datetime.datetime.now()
print("-----")
print(datetime.datetime.now())
print(
f"model_id={model_id}, speaker_id={speaker_id}, speaker_name={speaker_name}, language={language}"
)
print(f"text:\n{text}")
if is_hf_spaces and len(text) > limit:
print(f"Error: 文字数が{limit}文字を超えています")
return f"エラー、文字数が{limit}文字を超えています", None
try:
if not line_split:
with torch.no_grad():
audio = infer(
text=text,
sdp_ratio=sdp_ratio,
noise_scale=noise,
noise_scale_w=noisew,
length_scale=length,
sid=speaker_name,
language=language,
hps=model_holder.models[model_id].hps,
net_g=model_holder.models[model_id].net_g,
device=model_holder.models[model_id].device,
emotion=emotion,
)
else:
texts = text.split("\n")
texts = [t for t in texts if t != ""] # 空行を削除
audios = []
with torch.no_grad():
for i, t in enumerate(texts):
audios.append(
infer(
text=t,
sdp_ratio=sdp_ratio,
noise_scale=noise,
noise_scale_w=noisew,
length_scale=length,
sid=speaker_name,
language=language,
hps=model_holder.models[model_id].hps,
net_g=model_holder.models[model_id].net_g,
device=model_holder.models[model_id].device,
emotion=emotion,
)
)
if i != len(texts) - 1:
audios.append(np.zeros(int(44100 * split_interval)))
audio = np.concatenate(audios)
end_time = datetime.datetime.now()
duration = (end_time - start_time).total_seconds()
print(f"{end_time}: Done, {duration} seconds.")
return f"Success, time: {duration} seconds.", (
model_holder.models[model_id].hps.data.sampling_rate,
audio,
)
except Exception as e:
print(f"Error: {e}")
return f"エラー\n{e}", None
initial_text = "日本よ、日本人よ、世界の真ん中で咲きほこれ"
example_local = [
[initial_text, "JP"],
[ # ChatGPTに考えてもらった告白セリフ
"""私、ずっと前からあなたのことを見てきました。あなたの笑顔、優しさ、強さに、心惹かれていたんです。
友達として過ごす中で、あなたのことがだんだんと特別な存在になっていくのがわかりました。
えっと、私、あなたのことが好きです!もしよければ、私と付き合ってくれませんか?""",
"JP",
],
[ # 夏目漱石『吾輩は猫である』
"""吾輩は猫である。名前はまだ無い。
どこで生れたかとんと見当がつかぬ。なんでも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。しかもあとで聞くと、それは書生という、人間中で一番獰悪な種族であったそうだ。
この書生というのは時々我々を捕まえて煮て食うという話である。""",
"JP",
],
[ # 梶井基次郎『桜の樹の下には』
"""桜の樹の下には屍体が埋まっている!これは信じていいことなんだよ。
何故って、桜の花があんなにも見事に咲くなんて信じられないことじゃないか。俺はあの美しさが信じられないので、このにさんにち不安だった。
しかしいま、やっとわかるときが来た。桜の樹の下には屍体が埋まっている。これは信じていいことだ。""",
"JP",
],
[ # ChatGPTと考えた、感情を表すセリフ
"""やったー!テストで満点取れたよ!私とっても嬉しいな!
どうして私の意見を無視するの?許せない!ムカつく!あんたなんか死ねばいいのに。
あはははっ!この漫画めっちゃ笑える、見てよこれ、ふふふ、あはは。
あなたがいなくなって、私は一人になっちゃって、泣いちゃいそうなほど悲しい。""",
"JP",
],
[ # 上の丁寧語バージョン
"""やりました!テストで満点取れましたよ!私とっても嬉しいです!
どうして私の意見を無視するんですか?許せません!ムカつきます!あんたなんか死んでください。
あはははっ!この漫画めっちゃ笑えます、見てくださいこれ、ふふふ、あはは。
あなたがいなくなって、私は一人になっちゃって、泣いちゃいそうなほど悲しいです。""",
"JP",
],
[ # ChatGPTに考えてもらった音声合成の説明文章
"""音声合成は、機械学習を活用して、テキストから人の声を再現する技術です。この技術は、言語の構造を解析し、それに基づいて音声を生成します。
この分野の最新の研究成果を使うと、より自然で表現豊かな音声の生成が可能である。深層学習の応用により、感情やアクセントを含む声質の微妙な変化も再現することが出来る。""",
"JP",
],
[
"Speech synthesis is the artificial production of human speech. A computer system used for this purpose is called a speech synthesizer, and can be implemented in software or hardware products.",
"EN",
],
]
example_hf_spaces = [
[initial_text, "JP"],
["えっと、私、あなたのことが好きです!もしよければ付き合ってくれませんか?", "JP"],
["吾輩は猫である。名前はまだ無い。", "JP"],
["どこで生れたかとんと見当がつかぬ。なんでも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。", "JP"],
["やったー!テストで満点取れたよ!私とっても嬉しいな!", "JP"],
["どうして私の意見を無視するの?許せない!ムカつく!あんたなんか死ねばいいのに。", "JP"],
["あはははっ!この漫画めっちゃ笑える、見てよこれ、ふふふ、あはは。", "JP"],
["あなたがいなくなって、私は一人になっちゃって、泣いちゃいそうなほど悲しい。", "JP"],
["深層学習の応用により、感情やアクセントを含む声質の微妙な変化も再現されている。", "JP"],
]
initial_md = """
# AI晋さん&AI菅義偉&AI岸田文雄メーカー(Bert-VITS2)
意味のないAIだよ
モデル一覧から首相経験者1人を選択するのであります
"""
if __name__ == "__main__":
device = "cuda" if torch.cuda.is_available() else "cpu"
# device = "cpu"
languages = ["JP", "EN", "ZH"]
examples = example_hf_spaces if is_hf_spaces else example_local
model_names = refresh_model()
with gr.Blocks() as app:
gr.Markdown(initial_md)
with gr.Row():
with gr.Column():
with gr.Row():
model_input = gr.Dropdown(
label="モデル一覧",
choices=model_names,
type="index",
scale=3,
)
if not is_hf_spaces:
refresh_button = gr.Button("モデル一覧を更新", scale=1)
refresh_button.click(
update_model_dropdown, outputs=[model_input]
)
text_input = gr.TextArea(label="テキスト", value=initial_text)
language = gr.Dropdown(choices=languages, value="JP", label="言語")
line_split = gr.Checkbox(label="改行で分けて生成", value=not is_hf_spaces)
split_interval = gr.Slider(
minimum=0.1, maximum=2, value=0.5, step=0.1, label="分けた場合に挟む無音の長さ"
)
with gr.Accordion(label="詳細設定", open=False):
emotion = gr.Slider(
minimum=0, maximum=9, value=0, step=1, label="Emotion"
)
sdp_ratio = gr.Slider(
minimum=0, maximum=1, value=0.2, step=0.1, label="SDP Ratio"
)
noise_scale = gr.Slider(
minimum=0.1, maximum=2, value=0.6, step=0.1, label="Noise"
)
noise_scale_w = gr.Slider(
minimum=0.1, maximum=2, value=0.8, step=0.1, label="Noise_W"
)
length_scale = gr.Slider(
minimum=0.1, maximum=2, value=1.0, step=0.1, label="Length"
)
with gr.Column():
button = gr.Button("実行", variant="primary")
text_output = gr.Textbox(label="情報")
audio_output = gr.Audio(label="結果")
Image = gr.Image('./abe_suga_kishida.jpg')
button.click(
_voice,
inputs=[
model_input, # model_id
text_input, # text
language, # language
emotion, # emotion
sdp_ratio, # sdp_ratio
noise_scale, # noise
noise_scale_w, # noise_w
length_scale, # length
line_split, # auto_split
split_interval, # interval
],
outputs=[text_output, audio_output],
)
app.launch(inbrowser=True)
|