|
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", |
|
], |
|
] |
|
|
|
|
|
|
|
@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}<voice" |
|
if spk: |
|
ssml += f' spk="{spk}"' |
|
if style: |
|
ssml += f' style="{style}"' |
|
ssml += ">\n" |
|
ssml += f"{indent}{indent}{text_normalize(text)}\n" |
|
ssml += f"{indent}</voice>\n" |
|
|
|
return msg, spk, style, f"<speak version='0.1'>\n{ssml}</speak>" |
|
|
|
|
|
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, |
|
|
|
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, |
|
], |
|
) |
|
|