File size: 2,663 Bytes
1b41e6d
 
 
 
 
 
 
abd911f
 
 
 
1b41e6d
 
 
 
 
 
 
100a302
1b41e6d
 
100a302
1b41e6d
100a302
 
 
1b41e6d
100a302
 
 
 
 
 
 
 
 
 
1b41e6d
 
 
 
 
 
100a302
 
 
 
1b41e6d
 
100a302
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
abd911f
100a302
abd911f
1b41e6d
 
 
 
100a302
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import gradio as gr
import edge_tts
import asyncio
import tempfile

async def get_voices():
    voices = await edge_tts.list_voices()
    return {
        f"{v['ShortName']} - {v['Locale']} ({v['Gender']})": v['ShortName']
        for v in voices
    }

async def text_to_speech(text, voice, rate, pitch):
    if not text.strip():
        return None, "Please enter text to convert."
    if not voice:
        return None, "Please select a voice."
    
    short_name = voice.split(" - ")[0]
    rate_str = f"{rate:+d}%"
    pitch_str = f"{pitch:+d}Hz"
    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, ""

def tts_interface(text, voice, rate, pitch):
    # Run asyncio in sync function
    audio_path, warning_text = asyncio.get_event_loop().run_until_complete(
        text_to_speech(text, voice, rate, pitch)
    )
    # Return the file path (or None) and the warning string
    return audio_path, warning_text

def build_ui():
    voices = asyncio.get_event_loop().run_until_complete(get_voices())

    with gr.Blocks(analytics_enabled=False) as demo:
        gr.Markdown("# 🎙️ Edge TTS Text-to-Speech")
        
        with gr.Row():
            with gr.Column():
                gr.Markdown("## Text-to-Speech with Microsoft Edge TTS")
                gr.Markdown(
                    "Convert text to speech using Microsoft Edge TTS. "
                    "Adjust rate/pitch: 0 is default, +/− to change."
                )
        
        with gr.Row():
            text_input = gr.Textbox(label="Input Text", lines=5)
            voice_dropdown = gr.Dropdown(
                choices=list(voices.keys()),
                label="Select Voice"
            )
            rate_slider = gr.Slider(-50, 50, value=0, label="Rate (%)")
            pitch_slider = gr.Slider(-20, 20, value=0, label="Pitch (Hz)")
        
        generate_btn = gr.Button("Generate Speech")
        audio_out = gr.Audio(type="filepath", label="Output Audio")
        warning_md = gr.Markdown("", label="Warning")
        
        generate_btn.click(
            fn=tts_interface,
            inputs=[text_input, voice_dropdown, rate_slider, pitch_slider],
            outputs=[audio_out, warning_md]
        )
        
        gr.Markdown(
            "Try our Text-to-Video converter, or tweak rate/pitch for the perfect delivery!"
        )
    
    return demo

if __name__ == "__main__":
    ui = build_ui()
    # Launch synchronously—no .queue(), so no internal API schema error
    ui.launch()