Spaces:
Running
Running
# coding: utf8 | |
import argparse | |
import json | |
import os | |
import random | |
import re | |
import tempfile | |
from pathlib import Path | |
import librosa | |
import numpy as np | |
import torch | |
from torch import no_grad, LongTensor | |
import commons | |
import utils | |
import gradio as gr | |
import gradio.utils as gr_utils | |
import gradio.processing_utils as gr_processing_utils | |
from models import SynthesizerTrn | |
from text import text_to_sequence, _clean_text | |
from mel_processing import spectrogram_torch | |
limitation = os.getenv("SYSTEM") == "spaces" # limit text and audio length in huggingface spaces | |
audio_postprocess_ori = gr.Audio.postprocess | |
def fill_text(tts_input): | |
tts_input.value = random.choice(text_list) | |
def audio_postprocess(self, y): | |
data = audio_postprocess_ori(self, y) | |
if data is None: | |
return None | |
return gr_processing_utils.encode_url_or_file_to_base64(data["name"]) | |
gr.Audio.postprocess = audio_postprocess | |
def get_text(text, hps, is_symbol): | |
text_norm = text_to_sequence(text, hps.symbols, [] if is_symbol else hps.data.text_cleaners) | |
if hps.data.add_blank: | |
text_norm = commons.intersperse(text_norm, 0) | |
text_norm = LongTensor(text_norm) | |
return text_norm | |
def create_tts_fn(model, hps, speaker_ids): | |
def tts_fn(text, speaker, speed, is_symbol): | |
if limitation: | |
text_len = len(re.sub("\[([A-Z]{2})\]", "", text)) | |
max_len = 150 | |
if is_symbol: | |
max_len *= 3 | |
if text_len > max_len: | |
return "Error: Text is too long", None | |
speaker_id = speaker_ids[speaker] | |
stn_tst = get_text(text, hps, is_symbol) | |
with no_grad(): | |
x_tst = stn_tst.unsqueeze(0).to(device) | |
x_tst_lengths = LongTensor([stn_tst.size(0)]).to(device) | |
sid = LongTensor([speaker_id]).to(device) | |
audio = model.infer(x_tst, x_tst_lengths, sid=sid, noise_scale=.667, noise_scale_w=0.8, | |
length_scale=1.0 / speed)[0][0, 0].data.cpu().float().numpy() | |
del stn_tst, x_tst, x_tst_lengths, sid | |
return "Success", (hps.data.sampling_rate, audio) | |
return tts_fn | |
def create_vc_fn(model, hps, speaker_ids): | |
def vc_fn(original_speaker, target_speaker, input_audio): | |
if input_audio is None: | |
return "You need to upload an audio", None | |
sampling_rate, audio = input_audio | |
duration = audio.shape[0] / sampling_rate | |
if limitation and duration > 30: | |
return "Error: Audio is too long", None | |
original_speaker_id = speaker_ids[original_speaker] | |
target_speaker_id = speaker_ids[target_speaker] | |
audio = (audio / np.iinfo(audio.dtype).max).astype(np.float32) | |
if len(audio.shape) > 1: | |
audio = librosa.to_mono(audio.transpose(1, 0)) | |
if sampling_rate != hps.data.sampling_rate: | |
audio = librosa.resample(audio, orig_sr=sampling_rate, target_sr=hps.data.sampling_rate) | |
with no_grad(): | |
y = torch.FloatTensor(audio) | |
y = y.unsqueeze(0) | |
spec = spectrogram_torch(y, hps.data.filter_length, | |
hps.data.sampling_rate, hps.data.hop_length, hps.data.win_length, | |
center=False).to(device) | |
spec_lengths = LongTensor([spec.size(-1)]).to(device) | |
sid_src = LongTensor([original_speaker_id]).to(device) | |
sid_tgt = LongTensor([target_speaker_id]).to(device) | |
audio = model.voice_conversion(spec, spec_lengths, sid_src=sid_src, sid_tgt=sid_tgt)[0][ | |
0, 0].data.cpu().float().numpy() | |
del y, spec, spec_lengths, sid_src, sid_tgt | |
return "Success", (hps.data.sampling_rate, audio) | |
return vc_fn | |
def create_soft_vc_fn(model, hps, speaker_ids): | |
def soft_vc_fn(target_speaker, input_audio1, input_audio2): | |
input_audio = input_audio1 | |
if input_audio is None: | |
input_audio = input_audio2 | |
if input_audio is None: | |
return "You need to upload an audio", None | |
sampling_rate, audio = input_audio | |
duration = audio.shape[0] / sampling_rate | |
if limitation and duration > 30: | |
return "Error: Audio is too long", None | |
target_speaker_id = speaker_ids[target_speaker] | |
audio = (audio / np.iinfo(audio.dtype).max).astype(np.float32) | |
if len(audio.shape) > 1: | |
audio = librosa.to_mono(audio.transpose(1, 0)) | |
if sampling_rate != 16000: | |
audio = librosa.resample(audio, orig_sr=sampling_rate, target_sr=16000) | |
with torch.inference_mode(): | |
units = hubert.units(torch.FloatTensor(audio).unsqueeze(0).unsqueeze(0).to(device)) | |
with no_grad(): | |
unit_lengths = LongTensor([units.size(1)]).to(device) | |
sid = LongTensor([target_speaker_id]).to(device) | |
audio = model.infer(units, unit_lengths, sid=sid, noise_scale=.667, | |
noise_scale_w=0.8)[0][0, 0].data.cpu().float().numpy() | |
del units, unit_lengths, sid | |
return "Success", (hps.data.sampling_rate, audio) | |
return soft_vc_fn | |
def create_to_symbol_fn(hps): | |
def to_symbol_fn(is_symbol_input, input_text, temp_text): | |
return (_clean_text(input_text, hps.data.text_cleaners), input_text) if is_symbol_input \ | |
else (temp_text, temp_text) | |
return to_symbol_fn | |
download_audio_js = """ | |
() =>{{ | |
let root = document.querySelector("body > gradio-app"); | |
if (root.shadowRoot != null) | |
root = root.shadowRoot; | |
let audio = root.querySelector("#{audio_id}").querySelector("audio"); | |
if (audio == undefined) | |
return; | |
audio = audio.src; | |
let oA = document.createElement("a"); | |
oA.download = Math.floor(Math.random()*100000000)+'.wav'; | |
oA.href = audio; | |
document.body.appendChild(oA); | |
oA.click(); | |
oA.remove(); | |
}} | |
""" | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser() | |
parser.add_argument('--device', type=str, default='cpu') | |
parser.add_argument("--share", action="store_true", default=False, help="share gradio app") | |
args = parser.parse_args() | |
device = torch.device(args.device) | |
models_tts = [] | |
models_vc = [] | |
models_soft_vc = [] | |
with open("saved_model/info.json", "r", encoding="utf-8") as f: | |
models_info = json.load(f) | |
for i, info in models_info.items(): | |
name = info["title"] | |
author = info["author"] | |
lang = info["lang"] | |
example = info["example"] | |
config_path = f"saved_model/{i}/config.json" | |
model_path = f"saved_model/{i}/model.pth" | |
cover = info["cover"] | |
cover_path = f"saved_model/{i}/{cover}" if cover else None | |
hps = utils.get_hparams_from_file(config_path) | |
model = SynthesizerTrn( | |
len(hps.symbols), | |
hps.data.filter_length // 2 + 1, | |
hps.train.segment_size // hps.data.hop_length, | |
n_speakers=hps.data.n_speakers, | |
**hps.model) | |
utils.load_checkpoint(model_path, model, None) | |
model.eval().to(device) | |
speaker_ids = [sid for sid, name in enumerate(hps.speakers) if name != "None"] | |
speakers = [name for sid, name in enumerate(hps.speakers) if name != "None"] | |
t = info["type"] | |
if t == "vits": | |
models_tts.append((name, author, cover_path, speakers, lang, example, | |
hps.symbols, create_tts_fn(model, hps, speaker_ids), | |
create_to_symbol_fn(hps))) | |
models_vc.append((name, author, cover_path, speakers, create_vc_fn(model, hps, speaker_ids))) | |
elif t == "soft-vits-vc": | |
models_soft_vc.append((name, author, cover_path, speakers, create_soft_vc_fn(model, hps, speaker_ids))) | |
hubert = torch.hub.load("bshall/hubert:main", "hubert_soft", trust_repo=True).to(device) | |
app = gr.Blocks() | |
with app: | |
with gr.Tabs(): | |
with gr.TabItem("TTS"): | |
with gr.Tabs(): | |
for i, (name, author, cover_path, speakers, lang, example, symbols, tts_fn, | |
to_symbol_fn) in enumerate(models_tts): | |
with gr.TabItem(f"model{i}"): | |
with gr.Column(): | |
cover_markdown = f"\n\n" if cover_path else "" | |
gr.Markdown(f"## {name}\n\n" | |
f"{cover_markdown}" | |
f"model author: {author}\n\n" | |
f"language: {lang}\n\n") | |
tts_input1 = gr.TextArea(label="Text (150 words limitation)", value=example, | |
elem_id=f"tts-input{i}") | |
# def fill_text(tts_input1): | |
# tts_input1.value = random.choice(text_list) | |
tts_input2 = gr.Dropdown(label="Speaker", choices=speakers, | |
type="index", value=speakers[0]) | |
tts_input3 = gr.Slider(label="Speed", value=1, minimum=0.5, maximum=2, step=0.1) | |
with gr.Accordion(label="Advanced Options", open=False): | |
temp_text_var = gr.Variable() | |
symbol_input = gr.Checkbox(value=False, label="Symbol input") | |
symbol_list = gr.Dataset(label="Symbol list", components=[tts_input1], | |
samples=[[x] for x in symbols], | |
elem_id=f"symbol-list{i}") | |
symbol_list_json = gr.Json(value=symbols, visible=False) | |
fill_button = gr.Button("Random Quotes") | |
fill_button.click(None, [tts_input1], [],_js=f""" | |
(i,symbols) => {{ | |
let root = document.querySelector("body > gradio-app"); | |
if (root.shadowRoot != null) | |
root = root.shadowRoot; | |
let text_input = root.querySelector("#tts-input{i}").querySelector("textarea"); | |
let text_list = ['大変なことに気づきました 姉さまが素敵です','良くない香りがしませんか','お夕食にしましょう 今日はp 丸は抜きです','レムはとても不愉快です','社会の窓が開いていても素敵です','ゆっくり休んで、明日もカッコいいところを見せてください。','お姉ちゃん…あ… たまに言い間違えると照れてしまいます','レムはきっとこの日々のために生まれてきたんですね。','今日も素敵な一日になるといいですね、姉さまが','窓の外を見てください気持ちのいい朝ですよ','物をお持ちしないところも、姉様の魅力です','学校お疲れ様でした レムの方もみはいかがですか','赤ん坊みたいな寝顔…いえ、こっちの話です。','これ以上遅れると姉様に怒られてしまいます','ダメダメなところも素敵です','レムも少し、とても少し、かなり少し気になります。','こんなこともあろうかとレムがすべてやっておきました','困らせないでください。か、顔が赤くなってしまいます。','鬼が飼ってますね','二人で笑いながら未来の話をしましょう','ほら遅刻してしまいますよ','もういけませんよ レムを困らせないでください','大丈夫です レムはいつもあなたの後ろで見守っていますから','絶対領域…何でしょう?後で姉様に聞いてみます','紙のお手入れ レムに手伝わせてくださいませんか','はい、鬼が飼ってます','強引なのもレムは嫌ではありませんけど','膝枕ですか? レムで良ければ喜んで','あ、あまり優しくされては、レムはどうしていいのか……','おはようございます','そんな完璧でお嫁さんにしたい…ったなんて、照れます。','寝顔とても可愛らしかったです','そんな凛々しい目で見つめられると困ってしまいます','そろそろお休みの時間ですよ','レムも眠くなってきてしまいました','お仕事お疲れ様でしたお風呂の準備も万端です','それでは始めましょう。1から…いいえ、0から!','デムに内緒で、どこにも行かないでくださいね。','安心してください。レムが筆跡を真似て仕事は済ませておきました。','にょんにょんにょんにょんにょんにょんにょんにょんにょんにょんにょん','そんな可愛いだなんて照れます','寝癖がすごくて、よだれの跡がついていても素敵です。','窓の外を見てください気持ちのいい朝ですよ','良くない香りがしませんか','そんな凛々しい目で見つめられると困ってしまいます','強引なのもレムは嫌ではありませんけど','デムに内緒で、どこにも行かないでくださいね。','お仕事お疲れ様でしたお風呂の準備も万端です','学校お疲れ様でした レムの方もみはいかがですか','膝枕ですか? レムで良ければ喜んで','眠れるまで手を握っていてもいいですか?','こうしている時間も嫌いじゃありませんけど','大変なことに気づきました 姉さまが素敵です','二人で笑いながら未来の話をしましょう','好きな食べ物は何ですか? レムが知っておきたいんです','そんな完璧でお嫁さんにしたい…だなんて、照れます。','赤ん坊みたいな寝顔…いえ、こっちの話です。','寝顔とても可愛らしかったです','お疲れ様ですお茶の時間にしませんか','いかがですか?褒めてくれても構いませんよ','今朝の着替えは一人で大丈夫ですか? レムもお手伝いましょうか?','おはようございます','そ、催眠ですか?もー、冗談が過ぎます','本当に困った人ですね','はぁ… 姉さま可愛い…','好き嫌いはいけません れむがあーんしてあげます','命じられていなくても、レムはいつでもそばにいますよ。','もういけませんよ レムを困らせないでください','困らせないでください。か、顔が赤くなってしまいます。','そろそろお休みの時間ですよ','スティックスヘリックス!えへへっ!ちゃんと言えますよ!','あっすみません寝顔に夢中で起こすのを忘れてしまいました','これ以上遅れると姉様に怒られてしまいます','物をお辞しないところも姉様の魅力です','鬼が飼ってますね','あ、あまり優しくされては、レムはどうしていいのか……','そろそろ起きてくれないとレムも困ってしまいます','ゆっくり休んで、明日もカッコいいところを見せてください。','すごいです れむは完服しました','素敵です、姉様と同じぐらい','はい、鬼が飼ってます','お帰りなさい 今日は甘い焼き菓子がありますよ','お客様ったらまだ寝ぼけていらっしゃるみたいです。','姉様は、凛々しくて自信満々なところがたまりません','今日はレーって始まってムーで終わる名前の女の子と一緒にいるといいことがありますよ','今日も素敵な一日になるといいですね、姉さまが','ダメダメなところも素敵です','はぁ…いつまで見ていても可愛い…','絶対領域…何でしょう?後で姉様に聞いてみます','ほら遅刻してしまいますよ','レムはとても不愉快です','レムも眠くなってきてしまいました','社会の窓が開いていても素敵です','安心してください。レムが筆跡を真似て仕事は済ませておきました。','レムはきっとこの日々のために生まれてきたんですね。','レムでよかったらいつでも呼んでください。','姉様は、凛々しくて自信満々なところがたまりません','おかえりなさい 今日は甘い焼き菓子がありますよ','お客様ったらまだ寝ぼけていらっしゃるみたいです。','そんな、可愛いだなんて照れます?','レムでよかったらいつでも呼んでください','好き嫌いはいけません。レムがあーんしてあげます。','寝癖がすごくて、よだれの跡がついていても素敵です。','いかがですか?褒めてくれても構いませんよ','急いでお支度を服の着替えはレムが','命じられていなくても、レムはいつでもそばにいますよ。','今日はレーって始まってムーで終わる名前の女の子と一緒にいるといいことがありますよ','はぁ…いつまで見ていても可愛い…','どうやって武器を持ち歩いているかですか?乙女の秘密、と姉さまが','好きな食べ物は何ですか? レムが知っておきたいんです','にょんにょんにょんにょんにょんにょんにょんにょんにょんにょんにょんにょん','お疲れ様ですお茶の時間にしませんか','そろそろ起きてくれないとレムも困ってしまいます','本当に困った人ですね','そ、催眠ですか?もー、冗談が過ぎます','スティックスヘリックス!えへへっ!ちゃんと言えますよ!','角はその…敏感なのでむやめに触らないでください','疲れていませんか?治癒魔法が必要ですか?','角に触ったら責任を取ってもらいます 冗談ですよ','素敵です。姉様と同じぐらい。','すごいです れむは完服しました','眠れるまで手を握っていてもいいですか?','毎日楽しく過ごせていますか? レムはとても幸せです','こうしている時間も嫌いじゃありませんけど','はぁ… 姉さま可愛い…','あっすみません寝顔に夢中で起こすのを忘れてしまいました','今朝の着替えは一人で大丈夫ですか? レムもお手伝いましょうか?','リムの…リムのせいなんです','はい','スバル君…','やめてください それじゃ…レムは…','スバル君は…なんでそこまで…','起きてくれましたか?','いえ、あの、これはその…','レムの方からです','眠っているすばる君が苦しんでるように見えたから…手を…','こういう時に何をしてあげたらいいのかわかりません','わからないから レムがされて一番嬉しかったこと','はい 魔獣はロズワール様がすべて相当なさいました','なので呪いの発動の心配はありません','わかってはいるんです','レムは非力で 被災で 鬼族の落ちこぼれです','だからどうしても姉様に届かない','レムは姉様の代替品','それもずっとずっと劣った','適損ないなんです','どうして… レムの方に角が残ってしまったんですか','どうして 姉様の方の角が残らなかったんですか','どうして、姉さまは生まれながらに角を一本しか持っていなかったんですか?','ごめんなさい おかしなことを言ってしまいました','忘れてください','ち、違うんです!','本当のお姉様はもっと…','角があればそんな評価には','本当の姉様ならもっとうまく…','レムは…レムは姉様の代替品だってずっと…','でも…','明日のこと?','レムは とっても弱いです','ですからきっと、寄りかかってしまいますよ','お姉ちゃんは角を折られ','次も失った','これからはお姉ちゃん 姉さまができたことをすべて','レムが代わりに やれるようにしなくては','姉さまなら こうしたはず','姉様ならもっとよくやる','姉妻ならできたことをなぞるだけ','それすら満足にできない自分に','価値なんてない','そんな言葉 故郷で何度ももらった','無理を絞り出しても まるで足りない','決まってる 何もかもが足りてないから','何のために生きるのか','すべてはあの炎の夜に思ってしまった','自分への食材のために','何をすれば食材になるのか','レムが奪ってしまった 姉さまが歩くはずだった道を','信念を落として切り開くことで','レムのすべては姉様の劣化品なのだから','大体 日に過ぎないのだから','どうしたんですか','な、なんですかスバル君','そんなリリシー目で見つめられると困ってしまいます','場所は王城','警備は万全と思いますけど','スバル君…','今からレムは急な思いつきでリンガを使った新しい料理の開発に入ります','ものすごい集中力を必要とするので','きっと誰かが部屋を抜け出したりしても','オートにはスバル君がお世話になった方々もいらっしゃるみたいですし','この機会にお礼に伺うのも良いかと','大事なお話が','レムが感じたのは','姉様の千里眼なら','もっと詳しい状況も拾えたはずですけど','い、いけません スバル君','エミリア様の言いつけを守らなくては','m も同意見です','今は体の治療が最優先で','ダメなんです','街道に霧がかかってしまって','迂回する必要があります','霧を生むのは白ゲーです','万が一遭遇した場合','命がありません','竜舎を貸していただき 本当にありがとうございます','感謝を申し上げます','今朝の場合も','姉様の自生を通り越してレムに伝わってしまったものだと思います','寝つけないので','少し話したくて','はい れむはすばるくんを信じています','そうしたいからです','フェリックス様と同じ','時間をかけて ちゃんと向き合って','自分の気持ちを言葉にすれば','きっとわかってもらえます','スバル君は素敵な人ですから','ですから、その本の片隅に、レムのことも。','どこにも行かないでくださいね、スバル君','すばるくんへ','この手紙をスバル君が読んでいる時','きっとスバル君はレムのことをとても怒っていると思います','スバル君を置いて','稽古お疲れ様でしたすばるくん','思いますよ','情けないと思うことと','一緒にいることとは矛盾したりしませんよ','それに命じられていなくても','でもはきっと残ってました','レムがそうしたいからです','明日出かけませんかすばるくん','ここに来てから3日間どこにも行ってないでしょ','シュバル君!','しばらく','はい','どうしたんですか','はよ','まるで市民に会ったような顔して','はい','すばらくんちょっといいですか','いや…','こちらこそ寛大なご配慮に言葉もありません','確かにマナの干渉はない','おわり','魔女の正気','お世話になりました','今日までのご好意、主に代わりお礼を申し上げます。','時々ですけど名前を口にするんです','レムの名前や姉さま','それに…エメリア様…','あのお方にお会いできたら','何か変化があるかもしれません','ただ、なんと言葉にしていいのか…','スバル君が特別だからでしょうか','あの…','本当は史上を差し挟んだらいけないはずなんですけどね','クリス様のところで','スバル君を独り占めてきて、ちょっぴりレムは幸せに思っていたんです。','お屋敷ではスバル君を特選なんてできませんから','すばらくんが悩んでいたのを知っていたのに','スバル君がエミリア様と交論したって、そう聞いていたのに','大丈夫ですよね、スバル君','鬼が食って','すごい人なんですから','お世話になりました 桃家の主に代わり','お礼を申し上げます','言うよもありません','ロズワール様は 寮内の関係者のところを訪問することになっていて','数日は逗留している予定で','昨日 ご挨拶のおりに','オートにはしばらくご不在だとおっしゃっていました','騎士団詰書の方に 魔女卿の暗躍を報告してきました','ロズワール様のお名前を出したのですけど','魔女卿は背景が不鮮明ですから','確かめようのない密告が後を絶たないらしくて','どうしますか?','油がどうかされたんですか','すばるくんそれって','もう少し走った先に','フリオゲルの大樹が見えてくるはずです','そこから北東に向かえばもうすぐメイザースリアですよ','ありません','デムが勇者を降りて迎撃します','その間にスバル君は霧を抜け出してください','こんな案しか思いつきません','レムは今この時のために生まれてきたんですね','大丈夫です','レムはずっとスバル君の後ろで見守っていますから','暗すぎてとても無理です','えっ','今のスバル君の言い方だとまるで','ルグニカではない違う国へ向かおうとしているような','はっ!','スバル君のことですから ひょっとして何かまたすごいことを思いついたんですね','エミリア様やロズワール様の助けになる!','そんなこと急に言われても…','選ぶ…','レムはスバル君と逃げることはできません','未来のお話は','笑いながらじゃなきゃダメなんですよ','唐揚ぎに到着して','まず宿を借ります','生活の基盤は家とお仕事があれば','幸い レムはロズワール様の儚いで教育を受けていますから','カララギでもいくらか仕事を見つけるのは容易だと思います','スバル君は肉体労働を探してもらうか','レムの身の回りのお世話をしてもらうことに なるかもしれませんね','収入が安定したら','もう少しまともな住居を探しましょう','スバル君にはその間','ちゃんとしたお仕事に就くために勉強してもらって','実際に働けるようになるのに1年かそのぐらい','二人で働いて','ある程度のお金が貯まったら家を買ってもいいかもしれませんね','何かお見せをしてもいいかもしれません','唐揚ぎは商業の盛んな場所ですから','きっとスバルくんのとっぴな発想が活かせることもありますよ','仕事が軌道に乗ったら','うっその恥ずかしいですけど','子供とか…','鬼と人のハーフになるので','きっとわんぱくな子が生まれます','あたこの子でもあんなの子でも','双子でも三子でも','かわいい子になりますよ','きっと楽しいことばかりじゃないですし','こんなに想像通りに上手くいくことばかりじゃないと思います','男の子が生まれずに女の子ばっかりが続いてしまって','スバル君が家庭内で肩身が狭くなることもあるかもしれません','でもでも子供たちが大きくなって','スバル君を邪剣に扱うようなお年頃になっても','レムはスバル君の味方です','ご近所では有名な押し取り夫婦なんて言われてしまって','ゆっくり同じように時を過ごしておいてい','スバル君にはごめんなさいですけど','できればレムを先に行かせてください','ペットの上で…','すばるくんに手を握られて','子供たちやその子供たちに囲まれて','静かに エムは幸せでしたって','そう言って見送られて','幸せに幸せに 人生を終えることができるんです','スバル君が笑ってその未来を望んでくれるなら','レムはそうやって死んでもよかったと本気で思います','スバル君と生きていけるなら','スバル君が逃げようと思った時 エムと一緒にいたいと思ってくれたことが','今は心の底から嬉しい','でもダメなんです','エムが一番好きなスバル君を置き去りにしてしまうような気がしますから','何があったのかレムに話してください','話せないのなら 信じてください','でもせめて今は戻りましょう','ゆっくり時間をかけて落ち着いて考えれば','今とは違う答えが見つかるかもしれません','すばるくん','でも スバル君には似合わない','スバル君がどんなに辛い思いをしたのか','何を知ってそんなに苦しんでいるのか エムにはわかりません','わかります、なんて…','軽はずみに行ってはいけないとも思います','でも それでも','テムにだってわかっていることがあります','スバル君は途中で何かを諦めるなんてできない人だってことです','レムは知っています スバル君は未来を望む時','その未来を笑って話せる人だって知っています','レムは知っています','スバル君が未来を諦められない人だって知っています','スバル君はみんなを','エミリア様も、姉様も','ロズワール様やベアトリス様 他の人のことも諦めてなんかいないはずです','レムは知っています','スバル君がどんなに先の見えない暗闇の中でも','手を伸ばしてくれる勇気がある人だってこと','スバル君に頭を撫でられるのが好きです','手のひらと髪の毛を通して','スバル君と通じ合っている気がするんです','スバル君の声が好きです','言葉一つ聞くたびに','心が温かくなるのを感じるんです','スバル君の目が好きです','普段は鋭いんですけど','誰かに優しくしようとしている時','柔らかくなるその目が好きです','スバル君の指が好きです','男の子なのに綺麗な指をしていて','でも握るとやっぱり男の子なんだって思わせてくれる','強くて細い指なんです','スバルくんの歩き方が好きです','一緒に隣を歩いていると','たまにちゃんとついてきているか確かめるみたいに振り向いてくれる そんな歩き方が好きです','スバル君の寝顔が好きです','赤ん坊みたいに無防備で','まつげなんかちょっと長くて','頬に触れると穏やかになって','いたずらで唇に触れても気づかなくて','すごく胸が痛くなって…','スバル君が自分のことを嫌いだってそういうのなら','スバル君のいいところがこんなにあるって','Mが知っていることを知ってほしくなったんです','あの薄暗い森で','自分のこともわからなくなった世界で','勝ち目なんてなくて','てむが一番欲しかった言葉を','demがいます','スバル君が救ってくれたレムが今ここにいます','レムがいます','スバル君の言葉なら何だって聞きます','ないんですよ','そんな自分が許せないなら','謹んでお受けします','それでスバル君が','レムの英雄が','スバル君','ごめんなさい 気づかなくて','人混みに疲れてしまったんですね','もう困ります','スバル君がいろいろ考えてくれてるのは レムにだってわかっています','強引なのも嫌いじゃありませんけど','やっとわかったですか?','そこがスバル君の 素敵なところだと思いますけど','はいっ さすがスバル君は素敵です','驚きました','この地理気ぐらいが高いことで有名な種類だと思ったんですけど','別に拗ねてませんよ','嬉しそうですね スバルくん','怒られますよ','本当はレムは反対なんです','魔女の残りがで白毛を引き寄せるなんて','危険すぎます','スバル君は素敵です','そのミーティアが白原の存在を知らせてくれる','その嘘の理由が話せないでいることもわかります','だから信じさせようだとか','嘘で丸めこもうだとか','そんな風に自分を追い詰めたりする必要どこにもないんですよ','だってレムは スバル君を丸ごと信じていますから','はい、そうですね','はい、そうですね','どういたしまして ですよ','それにでもの方がずっとずっとすばるくんに感謝しているんですから','おあいこです','奥様を愛していらっしゃるんですね','魔女キョウ…','確かに その可能性は ロズワール様も 敗れまれていました','今の奇襲で地に落としてしまいたかったです','ごちそうさまです','嫌なんです','スバル君が困っている時','はいお客様','当家の食卓はレムが預かっています','姉様は料理があまり得意ではないのだ','はいそうです','いいえ、レムは基本的に家事全般が得意です','掃除洗濯も得意ですよ、姉さまより','申し訳ありませんお客様改めすばるくん','肩回りがおかしいのと足が短いことと目つきが怖いことです','あまり変な声を出さないでください不愉快です','ロズワール様の衣装だったら丁寧さを優先ですけど','スバルくんのでしたので','その灰色の服の珍しさと合わせて','持ってきています 今やってしまいましょうか','あら、目覚めましたね、姉さま','姉さま姉さまどうやら少し混乱されているみたいですお客様','まあ 極潰しの発言ですよ','聞きました姉様','大変ですよ 今お客様の頭の中で卑猥な恥ずかし目を受けています 姉様が','聞いてくださいエミリア様','あの方に酷い恥ずかし目を受けました姉様が','はいエミリア様姉様も反省しています','裁縫スキル','スバル君はお裁縫が好きなんですか?','必要ありません','レムと姉様はこの制服だけあれば十分ですから','ロズワール様の公務に同行する時や','屋敷での仕事では問題ありません','身分を示す意味でも説明する必要がなくて','合理的だと思いますよ','姉様ならともかく','レムが着飾っても誰も喜びませんよ','スバル君を喜ばせて何か良いことがあるんですか?','何がスバル君をそこまで言わせるのかレムには分かりかねますね','余計なお世話です','はいそうです','ちょっとすいて毛先を整えるだけでも','見栄えが変わると','いえ、そんなことは。','レムも少しかなり少し','とても少し気になるのは事実ですから','いえ 差し出がましいことを言ってしまったと思い','申し訳ありませんでした','同僚といってもスバル君はエミリア様の恩人で','立場が違うのに','いいえ、こちらこそ仕方のないことを言いました。','忘れてください','条件ですか','わかりました。なんなりとお聞きします。','エミリア様もおっしゃってましたけど','スバル君は欲のない人なんですね','条件受けたまわりました','スバル君の狙いに乗ってあげます','約束?','子供は動物と同じで人間性に順位付けしますから','本能的に侮っていい相手かどうかわかるんですよ','うやまんに足りるだけのものをスバル君はちゃんと子供たちに見せたんですか','物応じしないところも姉様の魅力です','そういえばスバル君の勉強の進み具合はどうですか','姉様はスバル君のやる気を発分させようと、あえてそう振れまってるんですよ。','鬼っかかる','鬼好きなんですか?','エミリア様に言いつけますよ','大丈夫ですか?','はい、姉さま','ねえさまねえさまちょっと見ない間に','お客様が濡れネズミになってます','当主ロズワール様がお戻りになられました','どうぞお屋敷へ','はい失礼します客様','おせじが絶望的に下手くそですよ','抵抗しないでくれたら楽に終わりにしてあげることもできますよ','お聞きします','疑わしきは罰せよ','そんなこと記憶にあります','メイドとしての心得です','ねえさまねえさま','お客様ったらひょっとしてなじられて喜ぶ困ったお方','その心がけは立派だと思いますけど','花瓶を落としたのもスバルくんでしょ','貝の花瓶を持ってきます','自分で増やして自分で片付けたお仕事でしたけど','今日はスバル君にこれ以上の仕事はできそうにありませんね','こうして見てるとその気も失せますね','姉様にスバル君が今日は役立たずだと伝えておきます','膝枕ですね','膝枕ですね','具合が悪いんですか','勝手なしキリを','そもそもロズワール様のご命令を守るなら','スバル君にレムや姉様が付き合う理由は?','ねえさま','姉さまあまりその目は','結界が切れてる','魔獣が境界線を超えてきてしまいます','魔獣は魔女が生み出した生物で','魔力を持つ人類の外敵です','待ってくださいそんな判断を勝手に','ロズワール様がご不在の機に','これがお屋敷を狙った 用道でないと断言できますか?','どうしてそこまで','スバル君とこの村にどれほど関係が','えっ','仕方ないですね','デムの命じられている仕事は スバル君の監視ですから','はい','ご信用です','近い生き物の匂いがします','わかりませんが獣臭くありません','いえ 今はまだ息がありますが','衰弱がひどいです','せめて姉様がこの場を見てくれていれば','とにかく気休めでも中魔法をかけます','落ち着いてから運び出しましょう','それに魔獣に連れて行かれたなら もう…','欲張りすぎて','拾って戻れるはずだったものまで零れ落とすかもしれませんよ','それとレムに何の関係が','相手の脅威も吐かれていません 村人がいつ合流するかも','最悪 レムがスバル君を 見つけられない可能性だって','何を根拠に','スバル君はどこまで知って…','わかりました 約束しましたよ','本当に色々と聞かせてもらいますからね','子供たちを預けたら すぐに合流します','絶対に無茶はしないでくださいね','鬼っかかる','子供たちは無事村に戻しました','時間稼ぎお疲れ様です','まっすぐ正面です','警戒を抜ければ勝負がつきます','村の篝火を目指して','死なないで… 死なないで…','姉様がそう言うのなら','はいはいお疲れ様','来客ですか','レムは状況の悪化を防いだだけです','スバル君はすでに救える見込みのない状況でした','嘘じゃありません','スバル君専属の万能お役立ちメイドですよ','大丈夫ですか疲れてしまいましたか','すばらくん','愛しています','愛しています スバルくん','だから全部大丈夫なんですよ','待ってますよ','こうしてレムがスバル君を抱きしめていることが','全部の答えです','大変だったんですね スバル君','一人でこんな傷ついて','でも、もうこんな悲しい思いばかりしなくて大丈夫ですよ','すばるくんの思い レムが変わります','何もかも全部、レムに預けて','今はゆっくり休んで','眠ってしまっていいんです','えっ','す、すばるくん、何を','違います聞いてくださいそばるくん'] | |
let randomIndex = Math.floor(Math.random() * text_list.length); | |
text_input.value = text_list[randomIndex]; | |
let x = window.scrollX, y = window.scrollY; | |
text_input.focus(); | |
window.scrollTo(x, y); | |
return []; | |
}}""") | |
tts_submit = gr.Button("Generate", variant="primary") | |
tts_output1 = gr.Textbox(label="Output Message") | |
tts_output2 = gr.Audio(label="Output Audio", elem_id=f"tts-audio{i}") | |
download = gr.Button("Download Audio") | |
download.click(None, [], [], _js=download_audio_js.format(audio_id=f"tts-audio{i}")) | |
tts_submit.click(tts_fn, [tts_input1, tts_input2, tts_input3, symbol_input], | |
[tts_output1, tts_output2],api_name="generate") | |
symbol_input.change(to_symbol_fn, | |
[symbol_input, tts_input1, temp_text_var], | |
[tts_input1, temp_text_var]) | |
symbol_list.click(None, [symbol_list, symbol_list_json], [], | |
_js=f""" | |
(i,symbols) => {{ | |
let root = document.querySelector("body > gradio-app"); | |
if (root.shadowRoot != null) | |
root = root.shadowRoot; | |
let text_input = root.querySelector("#tts-input{i}").querySelector("textarea"); | |
let startPos = text_input.selectionStart; | |
let endPos = text_input.selectionEnd; | |
let oldTxt = text_input.value; | |
let result = oldTxt.substring(0, startPos) + symbols[i] + oldTxt.substring(endPos); | |
text_input.value = result; | |
let x = window.scrollX, y = window.scrollY; | |
text_input.focus(); | |
text_input.selectionStart = startPos + symbols[i].length; | |
text_input.selectionEnd = startPos + symbols[i].length; | |
text_input.blur(); | |
window.scrollTo(x, y); | |
return []; | |
}}""") | |
with gr.TabItem("Voice Conversion"): | |
with gr.Tabs(): | |
for i, (name, author, cover_path, speakers, vc_fn) in enumerate(models_vc): | |
with gr.TabItem(f"model{i}"): | |
cover_markdown = f"\n\n" if cover_path else "" | |
gr.Markdown(f"## {name}\n\n" | |
f"{cover_markdown}" | |
f"model author: {author}") | |
vc_input1 = gr.Dropdown(label="Original Speaker", choices=speakers, type="index", | |
value=speakers[0]) | |
vc_input2 = gr.Dropdown(label="Target Speaker", choices=speakers, type="index", | |
value=speakers[min(len(speakers) - 1, 1)]) | |
vc_input3 = gr.Audio(label="Input Audio (30s limitation)") | |
vc_submit = gr.Button("Convert", variant="primary") | |
vc_output1 = gr.Textbox(label="Output Message") | |
vc_output2 = gr.Audio(label="Output Audio", elem_id=f"vc-audio{i}") | |
download = gr.Button("Download Audio") | |
download.click(None, [], [], _js=download_audio_js.format(audio_id=f"vc-audio{i}")) | |
vc_submit.click(vc_fn, [vc_input1, vc_input2, vc_input3], [vc_output1, vc_output2]) | |
with gr.TabItem("Soft Voice Conversion"): | |
with gr.Tabs(): | |
for i, (name, author, cover_path, speakers, soft_vc_fn) in enumerate(models_soft_vc): | |
with gr.TabItem(f"model{i}"): | |
cover_markdown = f"\n\n" if cover_path else "" | |
gr.Markdown(f"## {name}\n\n" | |
f"{cover_markdown}" | |
f"model author: {author}") | |
vc_input1 = gr.Dropdown(label="Target Speaker", choices=speakers, type="index", | |
value=speakers[0]) | |
source_tabs = gr.Tabs() | |
with source_tabs: | |
with gr.TabItem("microphone"): | |
vc_input2 = gr.Audio(label="Input Audio (30s limitation)", source="microphone") | |
with gr.TabItem("upload"): | |
vc_input3 = gr.Audio(label="Input Audio (30s limitation)", source="upload") | |
vc_submit = gr.Button("Convert", variant="primary") | |
vc_output1 = gr.Textbox(label="Output Message") | |
vc_output2 = gr.Audio(label="Output Audio", elem_id=f"svc-audio{i}") | |
download = gr.Button("Download Audio") | |
download.click(None, [], [], _js=download_audio_js.format(audio_id=f"svc-audio{i}")) | |
# clear inputs | |
source_tabs.set_event_trigger("change", None, [], [vc_input2, vc_input3], | |
js="()=>[null,null]") | |
vc_submit.click(soft_vc_fn, [vc_input1, vc_input2, vc_input3], | |
[vc_output1, vc_output2]) | |
app.queue(concurrency_count=3).launch(show_api=False, share=args.share) | |