EmRa228's picture
Update app.py
a257b37 verified
raw
history blame
2.22 kB
import os
import gradio as gr
import asyncio
import edge_tts
import tempfile
# Load voices once
def load_voices():
loop = asyncio.get_event_loop()
voices = loop.run_until_complete(edge_tts.list_voices())
return {f"{v['ShortName']} - {v['Locale']} ({v['Gender']})": v['ShortName']
for v in voices}
VOICES = load_voices()
# Async TTS
async def _tts(text, short_name, rate_str, pitch_str):
comm = edge_tts.Communicate(text, short_name, rate=rate_str, pitch=pitch_str)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
await comm.save(tmp.name)
return tmp.name
# Sync wrapper
def tts_interface(text, voice, rate, pitch):
if not text.strip():
return None, "๐Ÿšจ Enter some text."
if not voice:
return None, "๐Ÿšจ Select a voice."
name = voice.split(" - ")[0]
rate_s = f"{rate:+d}%"
pitch_s = f"{pitch:+d}Hz"
try:
path = asyncio.get_event_loop().run_until_complete(
_tts(text, name, rate_s, pitch_s)
)
return path, ""
except Exception as e:
return None, f"โŒ TTS failed: {e}"
# Build UI
def create_app():
with gr.Blocks(analytics_enabled=False) as demo:
gr.Markdown("# ๐ŸŽ™๏ธ Edge TTS in Hugging Face Space")
gr.Markdown("Convert text to speech with Microsoft Edge voices.")
with gr.Row():
txt = gr.Textbox(lines=5, label="Input Text")
vox = gr.Dropdown(list(VOICES.keys()), label="Voice")
rate = gr.Slider(-50, 50, value=0, label="Rate (%)")
pit = gr.Slider(-20, 20, value=0, label="Pitch (Hz)")
btn = gr.Button("Generate")
out_audio = gr.Audio(type="filepath", label="Audio")
warn = gr.Markdown("", label="Warning")
btn.click(
fn=tts_interface,
inputs=[txt, vox, rate, pit],
outputs=[out_audio, warn]
)
demo.queue() # Register /api endpoints
return demo
if __name__ == "__main__":
demo = create_app()
port = int(os.environ.get("PORT", 7860))
demo.launch(
server_name="0.0.0.0",
server_port=port,
ssr_mode=False # disable SSR introspection errors
)