Spaces:
Runtime error
Runtime error
SayaSS
commited on
Commit
·
f8ec1c0
1
Parent(s):
81b7cbf
update app.py
Browse files- app.py +142 -119
- pretrained_models/info.json +23 -23
app.py
CHANGED
|
@@ -111,12 +111,18 @@ if __name__ == '__main__':
|
|
| 111 |
parser.add_argument("--share", action="store_true", default=False, help="share gradio app")
|
| 112 |
args = parser.parse_args()
|
| 113 |
device = torch.device(args.device)
|
| 114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
models = []
|
| 116 |
with open("pretrained_models/info.json", "r", encoding="utf-8") as f:
|
| 117 |
models_info = json.load(f)
|
| 118 |
for i, info in models_info.items():
|
| 119 |
-
if not info['enable']:
|
| 120 |
continue
|
| 121 |
sid = info['sid']
|
| 122 |
name_en = info['name_en']
|
|
@@ -138,127 +144,144 @@ if __name__ == '__main__':
|
|
| 138 |
gr.Markdown(
|
| 139 |
"# <center> vits-models\n"
|
| 140 |
"## <center> Please do not generate content that could infringe upon the rights or cause harm to individuals or organizations.\n"
|
| 141 |
-
"## <center>
|
| 142 |
"\n\n"
|
| 143 |
-
"[
|
| 144 |
-
"(https://
|
| 145 |
-
"
|
| 146 |
-
"[Finetune your own model](https://github.com/SayaSS/vits-finetuning)"
|
| 147 |
)
|
| 148 |
|
| 149 |
with gr.Tabs():
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
with gr.TabItem(
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
f'<img style="width:auto;height:300px;" src="file/{cover}">' if cover else ""
|
| 158 |
-
'</div>'
|
| 159 |
-
)
|
| 160 |
-
with gr.Row():
|
| 161 |
-
with gr.Column():
|
| 162 |
-
input_text = gr.Textbox(label="Text (100 words limitation)" if limitation else "Text", lines=5, value=example, elem_id=f"input-text-en-{name_en.replace(' ','')}")
|
| 163 |
-
lang = gr.Dropdown(label="Language", choices=["Chinese", "Japanese", "Mix(wrap the Chinese text with [ZH][ZH], wrap the Japanese text with [JA][JA])"],
|
| 164 |
-
type="index", value=language)
|
| 165 |
-
with gr.Accordion(label="Advanced Options", open=False):
|
| 166 |
-
symbol_input = gr.Checkbox(value=False, label="Symbol input")
|
| 167 |
-
symbol_list = gr.Dataset(label="Symbol list", components=[input_text],
|
| 168 |
-
samples=[[x] for x in hps_ms.symbols])
|
| 169 |
-
symbol_list_json = gr.Json(value=hps_ms.symbols, visible=False)
|
| 170 |
-
btn = gr.Button(value="Generate", variant="primary")
|
| 171 |
with gr.Row():
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
download = gr.Button("Download Audio")
|
| 179 |
-
btn.click(tts_fn, inputs=[input_text, lang, ns, nsw, ls, symbol_input], outputs=[o1, o2], api_name=f"tts-{name_en}")
|
| 180 |
-
download.click(None, [], [], _js=download_audio_js.format(audio_id=f"en-{name_en.replace(' ', '')}"))
|
| 181 |
-
lang.change(change_lang, inputs=[lang], outputs=[ns, nsw, ls])
|
| 182 |
-
symbol_input.change(
|
| 183 |
-
to_symbol_fn,
|
| 184 |
-
[symbol_input, input_text, lang],
|
| 185 |
-
[input_text]
|
| 186 |
-
)
|
| 187 |
-
symbol_list.click(None, [symbol_list, symbol_list_json], [input_text],
|
| 188 |
-
_js=f"""
|
| 189 |
-
(i,symbols) => {{
|
| 190 |
-
let root = document.querySelector("body > gradio-app");
|
| 191 |
-
if (root.shadowRoot != null)
|
| 192 |
-
root = root.shadowRoot;
|
| 193 |
-
let text_input = root.querySelector("#input-text-en-{name_en.replace(' ', '')}").querySelector("textarea");
|
| 194 |
-
let startPos = text_input.selectionStart;
|
| 195 |
-
let endPos = text_input.selectionEnd;
|
| 196 |
-
let oldTxt = text_input.value;
|
| 197 |
-
let result = oldTxt.substring(0, startPos) + symbols[i] + oldTxt.substring(endPos);
|
| 198 |
-
text_input.value = result;
|
| 199 |
-
let x = window.scrollX, y = window.scrollY;
|
| 200 |
-
text_input.focus();
|
| 201 |
-
text_input.selectionStart = startPos + symbols[i].length;
|
| 202 |
-
text_input.selectionEnd = startPos + symbols[i].length;
|
| 203 |
-
text_input.blur();
|
| 204 |
-
window.scrollTo(x, y);
|
| 205 |
-
return text_input.value;
|
| 206 |
-
}}""")
|
| 207 |
-
with gr.TabItem("中文"):
|
| 208 |
-
for (sid, name_en, name_zh, title, cover, example, language, net_g_ms, tts_fn, to_symbol_fn) in models:
|
| 209 |
-
with gr.TabItem(name_zh):
|
| 210 |
-
with gr.Row():
|
| 211 |
-
gr.Markdown(
|
| 212 |
-
'<div align="center">'
|
| 213 |
-
f'<a><strong>{title}</strong></a>'
|
| 214 |
-
f'<img style="width:auto;height:300px;" src="file/{cover}">' if cover else ""
|
| 215 |
-
'</div>'
|
| 216 |
-
)
|
| 217 |
-
with gr.Row():
|
| 218 |
-
with gr.Column():
|
| 219 |
-
input_text = gr.Textbox(label="文本 (100字上限)" if limitation else "文本", lines=5, value=example, elem_id=f"input-text-zh-{name_zh}")
|
| 220 |
-
lang = gr.Dropdown(label="语言", choices=["中文", "日语", "中日混合(中文用[ZH][ZH]包裹起来,日文用[JA][JA]包裹起来)"],
|
| 221 |
-
type="index", value="中文"if language == "Chinese" else "日语")
|
| 222 |
-
with gr.Accordion(label="高级选项", open=False):
|
| 223 |
-
symbol_input = gr.Checkbox(value=False, label="符号输入")
|
| 224 |
-
symbol_list = gr.Dataset(label="符号列表", components=[input_text],
|
| 225 |
-
samples=[[x] for x in hps_ms.symbols])
|
| 226 |
-
symbol_list_json = gr.Json(value=hps_ms.symbols, visible=False)
|
| 227 |
-
btn = gr.Button(value="生成", variant="primary")
|
| 228 |
with gr.Row():
|
| 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 |
app.queue(concurrency_count=1, api_open=args.api).launch(share=args.share)
|
|
|
|
| 111 |
parser.add_argument("--share", action="store_true", default=False, help="share gradio app")
|
| 112 |
args = parser.parse_args()
|
| 113 |
device = torch.device(args.device)
|
| 114 |
+
categories = ["Blue Archive", "Lycoris Recoil"]
|
| 115 |
+
others = {
|
| 116 |
+
"Princess Connect! Re:Dive": "https://huggingface.co/spaces/sayashi/vits-models",
|
| 117 |
+
"Genshin Impact": "https://huggingface.co/spaces/sayashi/vits-models",
|
| 118 |
+
"Honkai Impact 3rd": "https://huggingface.co/spaces/sayashi/vits-models",
|
| 119 |
+
"Overwatch 2": "https://huggingface.co/spaces/sayashi/vits-models",
|
| 120 |
+
}
|
| 121 |
models = []
|
| 122 |
with open("pretrained_models/info.json", "r", encoding="utf-8") as f:
|
| 123 |
models_info = json.load(f)
|
| 124 |
for i, info in models_info.items():
|
| 125 |
+
if info['title'].split("-")[0] not in categories or not info['enable']:
|
| 126 |
continue
|
| 127 |
sid = info['sid']
|
| 128 |
name_en = info['name_en']
|
|
|
|
| 144 |
gr.Markdown(
|
| 145 |
"# <center> vits-models\n"
|
| 146 |
"## <center> Please do not generate content that could infringe upon the rights or cause harm to individuals or organizations.\n"
|
| 147 |
+
"## <center> 请不要生成会对个人以及组织造成侵害的内容\n"
|
| 148 |
"\n\n"
|
| 149 |
+
"[](https://colab.research.google.com/drive/10QOk9NPgoKZUXkIhhuVaZ7SYra1MPMKH?usp=share_link)\n\n"
|
| 150 |
+
"[](https://huggingface.co/spaces/sayashi/vits-models?duplicate=true)"
|
| 151 |
+
"[](https://github.com/SayaSS/vits-finetuning)"
|
|
|
|
| 152 |
)
|
| 153 |
|
| 154 |
with gr.Tabs():
|
| 155 |
+
for category in categories:
|
| 156 |
+
with gr.TabItem(category):
|
| 157 |
+
with gr.TabItem("EN"):
|
| 158 |
+
for (sid, name_en, name_zh, title, cover, example, language, net_g_ms, tts_fn, to_symbol_fn) in models:
|
| 159 |
+
if title.split("-")[0] != category:
|
| 160 |
+
continue
|
| 161 |
+
with gr.TabItem(name_en):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
with gr.Row():
|
| 163 |
+
gr.Markdown(
|
| 164 |
+
'<div align="center">'
|
| 165 |
+
f'<a><strong>{title}</strong></a>'
|
| 166 |
+
f'<img style="width:auto;height:300px;" src="file/{cover}">' if cover else ""
|
| 167 |
+
'</div>'
|
| 168 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
with gr.Row():
|
| 170 |
+
with gr.Column():
|
| 171 |
+
input_text = gr.Textbox(label="Text (100 words limitation)" if limitation else "Text", lines=5, value=example, elem_id=f"input-text-en-{name_en.replace(' ','')}")
|
| 172 |
+
lang = gr.Dropdown(label="Language", choices=["Chinese", "Japanese", "Mix(wrap the Chinese text with [ZH][ZH], wrap the Japanese text with [JA][JA])"],
|
| 173 |
+
type="index", value=language)
|
| 174 |
+
with gr.Accordion(label="Advanced Options", open=False):
|
| 175 |
+
symbol_input = gr.Checkbox(value=False, label="Symbol input")
|
| 176 |
+
symbol_list = gr.Dataset(label="Symbol list", components=[input_text],
|
| 177 |
+
samples=[[x] for x in hps_ms.symbols])
|
| 178 |
+
symbol_list_json = gr.Json(value=hps_ms.symbols, visible=False)
|
| 179 |
+
btn = gr.Button(value="Generate", variant="primary")
|
| 180 |
+
with gr.Row():
|
| 181 |
+
ns = gr.Slider(label="noise_scale", minimum=0.1, maximum=1.0, step=0.1, value=0.6, interactive=True)
|
| 182 |
+
nsw = gr.Slider(label="noise_scale_w", minimum=0.1, maximum=1.0, step=0.1, value=0.668, interactive=True)
|
| 183 |
+
ls = gr.Slider(label="length_scale", minimum=0.1, maximum=2.0, step=0.1, value=1.2 if language=="Chinese" else 1, interactive=True)
|
| 184 |
+
with gr.Column():
|
| 185 |
+
o1 = gr.Textbox(label="Output Message")
|
| 186 |
+
o2 = gr.Audio(label="Output Audio", elem_id=f"tts-audio-en-{name_en.replace(' ','')}")
|
| 187 |
+
download = gr.Button("Download Audio")
|
| 188 |
+
btn.click(tts_fn, inputs=[input_text, lang, ns, nsw, ls, symbol_input], outputs=[o1, o2], api_name=f"tts-{name_en}")
|
| 189 |
+
download.click(None, [], [], _js=download_audio_js.format(audio_id=f"en-{name_en.replace(' ', '')}"))
|
| 190 |
+
lang.change(change_lang, inputs=[lang], outputs=[ns, nsw, ls])
|
| 191 |
+
symbol_input.change(
|
| 192 |
+
to_symbol_fn,
|
| 193 |
+
[symbol_input, input_text, lang],
|
| 194 |
+
[input_text]
|
| 195 |
+
)
|
| 196 |
+
symbol_list.click(None, [symbol_list, symbol_list_json], [input_text],
|
| 197 |
+
_js=f"""
|
| 198 |
+
(i,symbols) => {{
|
| 199 |
+
let root = document.querySelector("body > gradio-app");
|
| 200 |
+
if (root.shadowRoot != null)
|
| 201 |
+
root = root.shadowRoot;
|
| 202 |
+
let text_input = root.querySelector("#input-text-en-{name_en.replace(' ', '')}").querySelector("textarea");
|
| 203 |
+
let startPos = text_input.selectionStart;
|
| 204 |
+
let endPos = text_input.selectionEnd;
|
| 205 |
+
let oldTxt = text_input.value;
|
| 206 |
+
let result = oldTxt.substring(0, startPos) + symbols[i] + oldTxt.substring(endPos);
|
| 207 |
+
text_input.value = result;
|
| 208 |
+
let x = window.scrollX, y = window.scrollY;
|
| 209 |
+
text_input.focus();
|
| 210 |
+
text_input.selectionStart = startPos + symbols[i].length;
|
| 211 |
+
text_input.selectionEnd = startPos + symbols[i].length;
|
| 212 |
+
text_input.blur();
|
| 213 |
+
window.scrollTo(x, y);
|
| 214 |
+
return text_input.value;
|
| 215 |
+
}}""")
|
| 216 |
+
with gr.TabItem("中文"):
|
| 217 |
+
for (sid, name_en, name_zh, title, cover, example, language, net_g_ms, tts_fn, to_symbol_fn) in models:
|
| 218 |
+
if title.split("-")[0] != category:
|
| 219 |
+
continue
|
| 220 |
+
with gr.TabItem(name_zh):
|
| 221 |
+
with gr.Row():
|
| 222 |
+
gr.Markdown(
|
| 223 |
+
'<div align="center">'
|
| 224 |
+
f'<a><strong>{title}</strong></a>'
|
| 225 |
+
f'<img style="width:auto;height:300px;" src="file/{cover}">' if cover else ""
|
| 226 |
+
'</div>'
|
| 227 |
+
)
|
| 228 |
+
with gr.Row():
|
| 229 |
+
with gr.Column():
|
| 230 |
+
input_text = gr.Textbox(label="文本 (100字上限)" if limitation else "文本", lines=5, value=example, elem_id=f"input-text-zh-{name_zh}")
|
| 231 |
+
lang = gr.Dropdown(label="语言", choices=["中文", "日语", "中日混合(中文用[ZH][ZH]包裹起来,日文用[JA][JA]包裹起来)"],
|
| 232 |
+
type="index", value="中文"if language == "Chinese" else "日语")
|
| 233 |
+
with gr.Accordion(label="高级选项", open=False):
|
| 234 |
+
symbol_input = gr.Checkbox(value=False, label="符号输入")
|
| 235 |
+
symbol_list = gr.Dataset(label="符号列表", components=[input_text],
|
| 236 |
+
samples=[[x] for x in hps_ms.symbols])
|
| 237 |
+
symbol_list_json = gr.Json(value=hps_ms.symbols, visible=False)
|
| 238 |
+
btn = gr.Button(value="生成", variant="primary")
|
| 239 |
+
with gr.Row():
|
| 240 |
+
ns = gr.Slider(label="控制感情变化程度", minimum=0.1, maximum=1.0, step=0.1, value=0.6, interactive=True)
|
| 241 |
+
nsw = gr.Slider(label="控制音素发音长度", minimum=0.1, maximum=1.0, step=0.1, value=0.668, interactive=True)
|
| 242 |
+
ls = gr.Slider(label="控制整体语速", minimum=0.1, maximum=2.0, step=0.1, value=1.2 if language=="Chinese" else 1, interactive=True)
|
| 243 |
+
with gr.Column():
|
| 244 |
+
o1 = gr.Textbox(label="输出信息")
|
| 245 |
+
o2 = gr.Audio(label="输出音频", elem_id=f"tts-audio-zh-{name_zh}")
|
| 246 |
+
download = gr.Button("下载音频")
|
| 247 |
+
btn.click(tts_fn, inputs=[input_text, lang, ns, nsw, ls, symbol_input], outputs=[o1, o2])
|
| 248 |
+
download.click(None, [], [], _js=download_audio_js.format(audio_id=f"zh-{name_zh}"))
|
| 249 |
+
lang.change(change_lang, inputs=[lang], outputs=[ns, nsw, ls])
|
| 250 |
+
symbol_input.change(
|
| 251 |
+
to_symbol_fn,
|
| 252 |
+
[symbol_input, input_text, lang],
|
| 253 |
+
[input_text]
|
| 254 |
+
)
|
| 255 |
+
symbol_list.click(None, [symbol_list, symbol_list_json], [input_text],
|
| 256 |
+
_js=f"""
|
| 257 |
+
(i,symbols) => {{
|
| 258 |
+
let root = document.querySelector("body > gradio-app");
|
| 259 |
+
if (root.shadowRoot != null)
|
| 260 |
+
root = root.shadowRoot;
|
| 261 |
+
let text_input = root.querySelector("#input-text-zh-{name_zh}").querySelector("textarea");
|
| 262 |
+
let startPos = text_input.selectionStart;
|
| 263 |
+
let endPos = text_input.selectionEnd;
|
| 264 |
+
let oldTxt = text_input.value;
|
| 265 |
+
let result = oldTxt.substring(0, startPos) + symbols[i] + oldTxt.substring(endPos);
|
| 266 |
+
text_input.value = result;
|
| 267 |
+
let x = window.scrollX, y = window.scrollY;
|
| 268 |
+
text_input.focus();
|
| 269 |
+
text_input.selectionStart = startPos + symbols[i].length;
|
| 270 |
+
text_input.selectionEnd = startPos + symbols[i].length;
|
| 271 |
+
text_input.blur();
|
| 272 |
+
window.scrollTo(x, y);
|
| 273 |
+
return text_input.value;
|
| 274 |
+
}}""")
|
| 275 |
+
for category, link in others.items():
|
| 276 |
+
with gr.TabItem(category):
|
| 277 |
+
gr.Markdown(
|
| 278 |
+
f'''
|
| 279 |
+
<center>
|
| 280 |
+
<h2>Click to Go</h2>
|
| 281 |
+
<a href="{link}">
|
| 282 |
+
<img src="https://huggingface.co/datasets/huggingface/badges/raw/main/open-in-hf-spaces-xl-dark.svg"
|
| 283 |
+
</a>
|
| 284 |
+
</center>
|
| 285 |
+
'''
|
| 286 |
+
)
|
| 287 |
app.queue(concurrency_count=1, api_open=args.api).launch(share=args.share)
|
pretrained_models/info.json
CHANGED
|
@@ -22,7 +22,7 @@
|
|
| 22 |
"type": "single"
|
| 23 |
},
|
| 24 |
"misora": {
|
| 25 |
-
"enable":
|
| 26 |
"name_en": "Misora",
|
| 27 |
"name_zh": "美空",
|
| 28 |
"title": "Princess Connect! Re:Dive-ミソラ",
|
|
@@ -33,7 +33,7 @@
|
|
| 33 |
"type": "single"
|
| 34 |
},
|
| 35 |
"kyoka": {
|
| 36 |
-
"enable":
|
| 37 |
"name_en": "Kyoka",
|
| 38 |
"name_zh": "镜华",
|
| 39 |
"title": "Princess Connect! Re:Dive-キョウカ",
|
|
@@ -44,7 +44,7 @@
|
|
| 44 |
"type": "multi"
|
| 45 |
},
|
| 46 |
"hiyori": {
|
| 47 |
-
"enable":
|
| 48 |
"name_en": "Hiyori",
|
| 49 |
"name_zh": "日和莉",
|
| 50 |
"title": "Princess Connect! Re:Dive-ヒヨリ",
|
|
@@ -66,7 +66,7 @@
|
|
| 66 |
"type": "single"
|
| 67 |
},
|
| 68 |
"hatsune": {
|
| 69 |
-
"enable":
|
| 70 |
"name_en": "Hatsune",
|
| 71 |
"name_zh": "柏崎初音",
|
| 72 |
"title": "Princess Connect! Re:Dive-柏崎初音",
|
|
@@ -77,7 +77,7 @@
|
|
| 77 |
"type": "multi"
|
| 78 |
},
|
| 79 |
"eriko": {
|
| 80 |
-
"enable":
|
| 81 |
"name_en": "Eriko",
|
| 82 |
"name_zh": "惠理子",
|
| 83 |
"title": "Princess Connect! Re:Dive-倉石恵理子",
|
|
@@ -143,7 +143,7 @@
|
|
| 143 |
"type": "single"
|
| 144 |
},
|
| 145 |
"ayaka-jp": {
|
| 146 |
-
"enable":
|
| 147 |
"name_en": "ayaka-jp",
|
| 148 |
"name_zh": "神里绫华-日语",
|
| 149 |
"title": "Genshin Impact-神里綾華",
|
|
@@ -154,7 +154,7 @@
|
|
| 154 |
"type": "multi"
|
| 155 |
},
|
| 156 |
"nahida-jp": {
|
| 157 |
-
"enable":
|
| 158 |
"name_en": "nahida-jp",
|
| 159 |
"name_zh": "纳西妲-日语",
|
| 160 |
"title": "Genshin Impact-ナヒーダ",
|
|
@@ -198,7 +198,7 @@
|
|
| 198 |
"type": "multi"
|
| 199 |
},
|
| 200 |
"karin": {
|
| 201 |
-
"enable":
|
| 202 |
"name_en": "Kakudate Karin",
|
| 203 |
"name_zh": "角楯花凛",
|
| 204 |
"title": "Blue Archive-角楯カリン",
|
|
@@ -209,7 +209,7 @@
|
|
| 209 |
"type": "multi"
|
| 210 |
},
|
| 211 |
"asuna": {
|
| 212 |
-
"enable":
|
| 213 |
"name_en": "Ichinose Asuna",
|
| 214 |
"name_zh": "一之濑明日奈",
|
| 215 |
"title": "Blue Archive-一之瀬アスナ",
|
|
@@ -253,7 +253,7 @@
|
|
| 253 |
"type": "multi"
|
| 254 |
},
|
| 255 |
"hoshino": {
|
| 256 |
-
"enable":
|
| 257 |
"name_en": "Takanasi Hosino",
|
| 258 |
"name_zh": "小鸟游星野",
|
| 259 |
"title": "Blue Archive-小鳥遊 ホシノ",
|
|
@@ -308,7 +308,7 @@
|
|
| 308 |
"type": "multi"
|
| 309 |
},
|
| 310 |
"doom": {
|
| 311 |
-
"enable":
|
| 312 |
"name_en": "Doomfist",
|
| 313 |
"name_zh": "末日铁拳",
|
| 314 |
"title": "Overwatch 2-Doomfist",
|
|
@@ -319,7 +319,7 @@
|
|
| 319 |
"type": "multi"
|
| 320 |
},
|
| 321 |
"echo": {
|
| 322 |
-
"enable":
|
| 323 |
"name_en": "Echo",
|
| 324 |
"name_zh": "回声",
|
| 325 |
"title": "Overwatch 2-Echo",
|
|
@@ -330,7 +330,7 @@
|
|
| 330 |
"type": "multi"
|
| 331 |
},
|
| 332 |
"zenyatta": {
|
| 333 |
-
"enable":
|
| 334 |
"name_en": "Zenyatta",
|
| 335 |
"name_zh": "禅雅塔",
|
| 336 |
"title": "Overwatch 2-Zenyatta",
|
|
@@ -341,10 +341,10 @@
|
|
| 341 |
"type": "multi"
|
| 342 |
},
|
| 343 |
"abyssinvoker": {
|
| 344 |
-
"enable":
|
| 345 |
"name_en": "Abyss Invoker",
|
| 346 |
"name_zh": "深渊使徒",
|
| 347 |
-
"title": "
|
| 348 |
"cover": "cover.png",
|
| 349 |
"sid": 94,
|
| 350 |
"example": "今天晚上吃啥好呢",
|
|
@@ -352,10 +352,10 @@
|
|
| 352 |
"type": "multi"
|
| 353 |
},
|
| 354 |
"keqing": {
|
| 355 |
-
"enable":
|
| 356 |
"name_en": "Keqing",
|
| 357 |
"name_zh": "刻晴",
|
| 358 |
-
"title": "
|
| 359 |
"cover": "cover.png",
|
| 360 |
"sid": 115,
|
| 361 |
"example": "今天晚上吃啥好呢",
|
|
@@ -363,10 +363,10 @@
|
|
| 363 |
"type": "multi"
|
| 364 |
},
|
| 365 |
"eula": {
|
| 366 |
-
"enable":
|
| 367 |
"name_en": "Eula",
|
| 368 |
"name_zh": "优菈",
|
| 369 |
-
"title": "
|
| 370 |
"cover": "cover.png",
|
| 371 |
"sid": 124,
|
| 372 |
"example": "今天晚上吃啥好呢",
|
|
@@ -374,10 +374,10 @@
|
|
| 374 |
"type": "multi"
|
| 375 |
},
|
| 376 |
"bronya": {
|
| 377 |
-
"enable":
|
| 378 |
"name_en": "Herrscher of Reason",
|
| 379 |
"name_zh": "理之律者",
|
| 380 |
-
"title": "
|
| 381 |
"cover": "cover.png",
|
| 382 |
"sid": 193,
|
| 383 |
"example": "今天晚上吃啥好呢",
|
|
@@ -385,10 +385,10 @@
|
|
| 385 |
"type": "multi"
|
| 386 |
},
|
| 387 |
"theresa": {
|
| 388 |
-
"enable":
|
| 389 |
"name_en": "Theresa",
|
| 390 |
"name_zh": "德丽莎",
|
| 391 |
-
"title": "
|
| 392 |
"cover": "cover.png",
|
| 393 |
"sid": 193,
|
| 394 |
"example": "今天晚上吃啥好呢",
|
|
|
|
| 22 |
"type": "single"
|
| 23 |
},
|
| 24 |
"misora": {
|
| 25 |
+
"enable": true,
|
| 26 |
"name_en": "Misora",
|
| 27 |
"name_zh": "美空",
|
| 28 |
"title": "Princess Connect! Re:Dive-ミソラ",
|
|
|
|
| 33 |
"type": "single"
|
| 34 |
},
|
| 35 |
"kyoka": {
|
| 36 |
+
"enable": true,
|
| 37 |
"name_en": "Kyoka",
|
| 38 |
"name_zh": "镜华",
|
| 39 |
"title": "Princess Connect! Re:Dive-キョウカ",
|
|
|
|
| 44 |
"type": "multi"
|
| 45 |
},
|
| 46 |
"hiyori": {
|
| 47 |
+
"enable": true,
|
| 48 |
"name_en": "Hiyori",
|
| 49 |
"name_zh": "日和莉",
|
| 50 |
"title": "Princess Connect! Re:Dive-ヒヨリ",
|
|
|
|
| 66 |
"type": "single"
|
| 67 |
},
|
| 68 |
"hatsune": {
|
| 69 |
+
"enable": true,
|
| 70 |
"name_en": "Hatsune",
|
| 71 |
"name_zh": "柏崎初音",
|
| 72 |
"title": "Princess Connect! Re:Dive-柏崎初音",
|
|
|
|
| 77 |
"type": "multi"
|
| 78 |
},
|
| 79 |
"eriko": {
|
| 80 |
+
"enable": true,
|
| 81 |
"name_en": "Eriko",
|
| 82 |
"name_zh": "惠理子",
|
| 83 |
"title": "Princess Connect! Re:Dive-倉石恵理子",
|
|
|
|
| 143 |
"type": "single"
|
| 144 |
},
|
| 145 |
"ayaka-jp": {
|
| 146 |
+
"enable": true,
|
| 147 |
"name_en": "ayaka-jp",
|
| 148 |
"name_zh": "神里绫华-日语",
|
| 149 |
"title": "Genshin Impact-神里綾華",
|
|
|
|
| 154 |
"type": "multi"
|
| 155 |
},
|
| 156 |
"nahida-jp": {
|
| 157 |
+
"enable": true,
|
| 158 |
"name_en": "nahida-jp",
|
| 159 |
"name_zh": "纳西妲-日语",
|
| 160 |
"title": "Genshin Impact-ナヒーダ",
|
|
|
|
| 198 |
"type": "multi"
|
| 199 |
},
|
| 200 |
"karin": {
|
| 201 |
+
"enable": true,
|
| 202 |
"name_en": "Kakudate Karin",
|
| 203 |
"name_zh": "角楯花凛",
|
| 204 |
"title": "Blue Archive-角楯カリン",
|
|
|
|
| 209 |
"type": "multi"
|
| 210 |
},
|
| 211 |
"asuna": {
|
| 212 |
+
"enable": true,
|
| 213 |
"name_en": "Ichinose Asuna",
|
| 214 |
"name_zh": "一之濑明日奈",
|
| 215 |
"title": "Blue Archive-一之瀬アスナ",
|
|
|
|
| 253 |
"type": "multi"
|
| 254 |
},
|
| 255 |
"hoshino": {
|
| 256 |
+
"enable": true,
|
| 257 |
"name_en": "Takanasi Hosino",
|
| 258 |
"name_zh": "小鸟游星野",
|
| 259 |
"title": "Blue Archive-小鳥遊 ホシノ",
|
|
|
|
| 308 |
"type": "multi"
|
| 309 |
},
|
| 310 |
"doom": {
|
| 311 |
+
"enable": true,
|
| 312 |
"name_en": "Doomfist",
|
| 313 |
"name_zh": "末日铁拳",
|
| 314 |
"title": "Overwatch 2-Doomfist",
|
|
|
|
| 319 |
"type": "multi"
|
| 320 |
},
|
| 321 |
"echo": {
|
| 322 |
+
"enable": true,
|
| 323 |
"name_en": "Echo",
|
| 324 |
"name_zh": "回声",
|
| 325 |
"title": "Overwatch 2-Echo",
|
|
|
|
| 330 |
"type": "multi"
|
| 331 |
},
|
| 332 |
"zenyatta": {
|
| 333 |
+
"enable": true,
|
| 334 |
"name_en": "Zenyatta",
|
| 335 |
"name_zh": "禅雅塔",
|
| 336 |
"title": "Overwatch 2-Zenyatta",
|
|
|
|
| 341 |
"type": "multi"
|
| 342 |
},
|
| 343 |
"abyssinvoker": {
|
| 344 |
+
"enable": true,
|
| 345 |
"name_en": "Abyss Invoker",
|
| 346 |
"name_zh": "深渊使徒",
|
| 347 |
+
"title": "Genshin Impact-深渊使徒",
|
| 348 |
"cover": "cover.png",
|
| 349 |
"sid": 94,
|
| 350 |
"example": "今天晚上吃啥好呢",
|
|
|
|
| 352 |
"type": "multi"
|
| 353 |
},
|
| 354 |
"keqing": {
|
| 355 |
+
"enable": true,
|
| 356 |
"name_en": "Keqing",
|
| 357 |
"name_zh": "刻晴",
|
| 358 |
+
"title": "Genshin Impact-刻晴",
|
| 359 |
"cover": "cover.png",
|
| 360 |
"sid": 115,
|
| 361 |
"example": "今天晚上吃啥好呢",
|
|
|
|
| 363 |
"type": "multi"
|
| 364 |
},
|
| 365 |
"eula": {
|
| 366 |
+
"enable": true,
|
| 367 |
"name_en": "Eula",
|
| 368 |
"name_zh": "优菈",
|
| 369 |
+
"title": "Genshin Impact-优菈",
|
| 370 |
"cover": "cover.png",
|
| 371 |
"sid": 124,
|
| 372 |
"example": "今天晚上吃啥好呢",
|
|
|
|
| 374 |
"type": "multi"
|
| 375 |
},
|
| 376 |
"bronya": {
|
| 377 |
+
"enable": true,
|
| 378 |
"name_en": "Herrscher of Reason",
|
| 379 |
"name_zh": "理之律者",
|
| 380 |
+
"title": "Honkai Impact 3rd-理之律者",
|
| 381 |
"cover": "cover.png",
|
| 382 |
"sid": 193,
|
| 383 |
"example": "今天晚上吃啥好呢",
|
|
|
|
| 385 |
"type": "multi"
|
| 386 |
},
|
| 387 |
"theresa": {
|
| 388 |
+
"enable": true,
|
| 389 |
"name_en": "Theresa",
|
| 390 |
"name_zh": "德丽莎",
|
| 391 |
+
"title": "Honkai Impact 3rd-德丽莎",
|
| 392 |
"cover": "cover.png",
|
| 393 |
"sid": 193,
|
| 394 |
"example": "今天晚上吃啥好呢",
|