import gradio as gr
import pandas as pd
import torch
from modules.normalization import text_normalize
from modules.webui import webui_utils
from modules.hf import spaces
podcast_default_case = [
[1, "female2", "你好,欢迎收听今天的播客内容。今天我们要聊的是中华料理。", "chat"],
[2, "Alice", "嗨,我特别期待这个话题!中华料理真的是博大精深。", "chat"],
[
3,
"Bob",
"没错,中华料理有着几千年的历史,而且每个地区都有自己的特色菜。",
"chat",
],
[
4,
"female2",
"那我们先从最有名的川菜开始吧。川菜以其麻辣著称,是很多人的最爱。",
"chat",
],
[
5,
"Alice",
"对,我特别喜欢吃麻婆豆腐和辣子鸡。那种麻辣的感觉真是让人难以忘怀。",
"chat",
],
[
6,
"Bob",
"除了川菜,粤菜也是很受欢迎的。粤菜讲究鲜美,像是白切鸡和蒸鱼都是经典。",
"chat",
],
[7, "female2", "对啊,粤菜的烹饪方式比较清淡,更注重食材本身的味道。", "chat"],
[8, "Alice", "还有北京的京菜,像北京烤鸭,那可是来北京必吃的美食。", "chat"],
[
9,
"Bob",
"不仅如此,还有淮扬菜、湘菜、鲁菜等等,每个菜系都有其独特的风味。",
"chat",
],
[
10,
"female2",
"对对对,像淮扬菜的狮子头,湘菜的剁椒鱼头,都是让人垂涎三尺的美味。",
"chat",
],
]
# NOTE: 因为 text_normalize 需要使用 tokenizer
@torch.inference_mode()
@spaces.GPU
def merge_dataframe_to_ssml(msg, spk, style, df: pd.DataFrame):
ssml = ""
indent = " " * 2
for i, row in df.iterrows():
text = row.get("text")
spk = row.get("speaker")
style = row.get("style")
ssml += f"{indent}\n"
ssml += f"{indent}{indent}{text_normalize(text)}\n"
ssml += f"{indent}\n"
# 原封不动输出回去是为了触发 loadding 效果
return msg, spk, style, f"\n{ssml}"
def create_ssml_podcast_tab(ssml_input: gr.Textbox, tabs1: gr.Tabs, tabs2: gr.Tabs):
def get_spk_choices():
speakers, speaker_names = webui_utils.get_speaker_names()
speaker_names = ["-1"] + speaker_names
return speaker_names
styles = ["*auto"] + [s.get("name") for s in webui_utils.get_styles()]
with gr.Row():
with gr.Column(scale=1):
with gr.Group():
spk_input_dropdown = gr.Dropdown(
choices=get_spk_choices(),
interactive=True,
value="female : female2",
show_label=False,
)
style_input_dropdown = gr.Dropdown(
choices=styles,
# label="Choose Style",
interactive=True,
show_label=False,
value="*auto",
)
with gr.Group():
msg = gr.Textbox(
lines=5, label="Message", placeholder="Type speaker message here"
)
add = gr.Button("Add")
undo = gr.Button("Undo")
clear = gr.Button("Clear")
with gr.Column(scale=5):
with gr.Group():
gr.Markdown("📔Script")
script_table = gr.DataFrame(
headers=["index", "speaker", "text", "style"],
datatype=["number", "str", "str", "str"],
interactive=False,
wrap=True,
value=podcast_default_case,
row_count=(0, "dynamic"),
)
send_to_ssml_btn = gr.Button("📩Send to SSML", variant="primary")
def add_message(msg, spk, style, sheet: pd.DataFrame):
if not msg:
return "", sheet
data = pd.DataFrame(
{
"index": [sheet.shape[0]],
"speaker": [spk.split(" : ")[1].strip()],
"text": [msg],
"style": [style],
},
)
# 如果只有一行 并且是空的
is_empty = sheet.empty or (sheet.shape[0] == 1 and "text" not in sheet.iloc[0])
if is_empty:
sheet = data
else:
sheet = pd.concat(
[
sheet,
data,
],
ignore_index=True,
)
return "", sheet
def undo_message(msg, spk, style, sheet: pd.DataFrame):
if sheet.empty:
return msg, spk, style, sheet
data = sheet.iloc[-1]
sheet = sheet.iloc[:-1]
spk = ""
for choice in get_spk_choices():
if choice.endswith(data["speaker"]) and " : " in choice:
spk = choice
break
return data["text"], spk, data["style"], sheet
def clear_message():
return "", pd.DataFrame(
columns=["index", "speaker", "text", "style"],
)
def send_to_ssml(msg, spk, style, sheet: pd.DataFrame):
if sheet.empty:
return gr.Error("Please add some text to the script table.")
msg, spk, style, ssml = merge_dataframe_to_ssml(msg, spk, style, sheet)
return [
msg,
spk,
style,
gr.Textbox(value=ssml),
gr.Tabs(selected="ssml"),
gr.Tabs(selected="ssml.editor"),
]
msg.submit(
add_message,
inputs=[msg, spk_input_dropdown, style_input_dropdown, script_table],
outputs=[msg, script_table],
)
add.click(
add_message,
inputs=[msg, spk_input_dropdown, style_input_dropdown, script_table],
outputs=[msg, script_table],
)
undo.click(
undo_message,
inputs=[msg, spk_input_dropdown, style_input_dropdown, script_table],
outputs=[msg, spk_input_dropdown, style_input_dropdown, script_table],
)
clear.click(
clear_message,
outputs=[msg, script_table],
)
send_to_ssml_btn.click(
send_to_ssml,
inputs=[msg, spk_input_dropdown, style_input_dropdown, script_table],
outputs=[
msg,
spk_input_dropdown,
style_input_dropdown,
ssml_input,
tabs1,
tabs2,
],
)