|
|
|
|
|
import gradio as gr |
|
import requests |
|
import tempfile |
|
from languages import languages |
|
|
|
def generate_audio(input_text, model, voice, output_format, base_url_input, api_key_input, request: gr.Request): |
|
|
|
query_params = request.query_params |
|
|
|
base_url = query_params.get("base_url", base_url_input) |
|
api_key = query_params.get("api_key", api_key_input) |
|
|
|
payload = { |
|
"model": model, |
|
"input": input_text, |
|
"voice": voice.lower(), |
|
"format": output_format |
|
} |
|
headers = { |
|
'Authorization': api_key, |
|
'Content-Type': 'application/json' |
|
} |
|
|
|
url = f"{base_url}/v1/audio/speech" |
|
|
|
response = requests.post(url, headers=headers, json=payload) |
|
|
|
if response.status_code != 200: |
|
raise gr.Error(f"错误:{response.status_code} {response.text}") |
|
|
|
audio_content = response.content |
|
|
|
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=f".{output_format}") |
|
with open(temp_file.name, 'wb') as f: |
|
f.write(audio_content) |
|
|
|
return temp_file.name |
|
|
|
def on_generate_click(input_text_value, model_value, voice_value, output_format_value, base_url_value, api_key_value, request: gr.Request): |
|
audio_path = generate_audio(input_text_value, model_value, voice_value, output_format_value, base_url_value, api_key_value, request) |
|
return audio_path |
|
|
|
def update_settings_from_url(request: gr.Request): |
|
|
|
query_params = request.query_params |
|
base_url = query_params.get("base_url", None) |
|
api_key = query_params.get("api_key", None) |
|
base_url_update = gr.update() |
|
api_key_update = gr.update() |
|
if base_url is not None: |
|
base_url_update = gr.update(value=base_url) |
|
if api_key is not None: |
|
api_key_update = gr.update(value=api_key) |
|
return base_url_update, api_key_update |
|
|
|
def update_language(language_choice): |
|
labels = languages[language_choice] |
|
updates = [ |
|
gr.update(value=f"# {labels['title']}"), |
|
gr.update(value=labels['intro']), |
|
gr.update(label=labels['input_text_label'], placeholder=labels['input_text_placeholder']), |
|
gr.update(label=labels['model_label']), |
|
gr.update(label=labels['voice_label']), |
|
gr.update(label=labels['output_format_label']), |
|
gr.update(value=labels['generate_button_label']), |
|
gr.update(label=labels['output_audio_label']), |
|
gr.update(label=labels['settings_label']), |
|
gr.update(label=labels['base_url_label']), |
|
gr.update(label=labels['api_key_label']), |
|
gr.update(value=labels['BOW']), |
|
gr.update(label=labels['language_label']), |
|
] |
|
return updates |
|
|
|
def toggle_dark_mode(current_mode): |
|
|
|
if current_mode == "light": |
|
return "dark" |
|
return "light" |
|
|
|
|
|
initial_mode = "light" |
|
|
|
|
|
with gr.Blocks(css=None, theme="Zarkel/IBM_Carbon_Theme", title="TTS Web") as demo: |
|
|
|
mode_state = gr.State(value=initial_mode) |
|
|
|
|
|
with gr.Row(): |
|
with gr.Column(scale=3): |
|
title_markdown = gr.Markdown("# OpenAI TTS Web") |
|
intro_text = gr.Markdown(languages["中文"]["intro"]) |
|
|
|
input_text = gr.Textbox(label="输入文本", placeholder="请输入要合成的文本") |
|
|
|
model = gr.Radio(choices=["tts-1", "tts-1-hd"], label="模型", value="tts-1") |
|
|
|
voice = gr.Radio(choices=["Alloy", "Echo", "Fable", "Onyx", "Nova", "Shimmer"], label="声音", value="Alloy") |
|
|
|
output_format = gr.Radio(choices=["mp3", "opus", "aac", "flac", "pcm"], label="输出格式", value="mp3") |
|
|
|
generate_button = gr.Button("生成") |
|
|
|
audio_output = gr.Audio(label="输出音频", type="filepath") |
|
with gr.Column(scale=1): |
|
|
|
with gr.Accordion("设置", open=True) as settings_accordion: |
|
|
|
mode_toggle_btn = gr.Button("切换黑白模式") |
|
|
|
language_choice_comp = gr.Radio(choices=["中文", "English"], label="界面语言", value="中文") |
|
|
|
base_url_input = gr.Textbox(label="Base URL", value="https://api.maktubcn.info") |
|
api_key_input = gr.Textbox(label="API Key", type="password") |
|
|
|
|
|
demo.load( |
|
update_settings_from_url, |
|
inputs=None, |
|
outputs=[base_url_input, api_key_input] |
|
) |
|
|
|
|
|
language_choice_comp.change( |
|
update_language, |
|
inputs=language_choice_comp, |
|
outputs=[ |
|
title_markdown, |
|
intro_text, |
|
input_text, |
|
model, |
|
voice, |
|
output_format, |
|
generate_button, |
|
audio_output, |
|
settings_accordion, |
|
base_url_input, |
|
api_key_input, |
|
mode_toggle_btn, |
|
language_choice_comp, |
|
] |
|
) |
|
|
|
|
|
mode_toggle_btn.click( |
|
lambda current_mode: toggle_dark_mode(current_mode), |
|
inputs=[mode_state], |
|
outputs=[mode_state], |
|
js=""" |
|
() => { |
|
if (document.body.classList.contains('dark')) { |
|
document.body.classList.remove('dark'); |
|
} else { |
|
document.body.classList.add('dark'); |
|
} |
|
} |
|
""" |
|
) |
|
|
|
|
|
generate_button.click( |
|
on_generate_click, |
|
inputs=[input_text, model, voice, output_format, base_url_input, api_key_input, gr.Request()], |
|
outputs=[audio_output] |
|
) |
|
|
|
demo.launch(server_name="0.0.0.0", server_port=7860) |