File size: 5,862 Bytes
42966de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3020c69
42966de
 
3020c69
42966de
 
3020c69
42966de
 
 
 
dfb71ed
 
42966de
 
 
dac7224
 
 
 
 
 
 
 
 
 
 
 
 
 
42966de
dac7224
 
 
42966de
dfb71ed
3020c69
42966de
 
dfb71ed
42966de
 
 
 
 
 
3020c69
42966de
 
 
 
 
 
 
 
 
3020c69
dac7224
3020c69
 
 
42966de
 
 
 
 
 
 
 
 
 
 
 
 
3020c69
 
 
dac7224
3020c69
42966de
 
 
3020c69
 
dac7224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3020c69
dac7224
 
3020c69
42966de
dfb71ed
dac7224
42966de
 
dac7224
 
3020c69
42966de
dfb71ed
dac7224
dfb71ed
 
dac7224
 
42966de
 
dfb71ed
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import gradio as gr
import tempfile
import openai

def tts(input_text: str, model: str, voice: str, api_key: str) -> str:
    """
    Convert input text to speech using OpenAI's Text-to-Speech API.

    :param input_text: The text to be converted to speech.
    :type input_text: str
    :param model: The model to use for synthesis (e.g., 'tts-1', 'tts-1-hd').
    :type model: str
    :param voice: The voice profile to use (e.g., 'alloy', 'echo', 'fable', etc.).
    :type voice: str
    :param api_key: OpenAI API key.
    :type api_key: str
    :return: File path to the generated audio file.
    :rtype: str
    :raises gr.Error: If input parameters are invalid or API call fails.
    """
    if not input_text.strip():
        raise gr.Error("Input text cannot be empty.")

    if not api_key.strip():
        raise gr.Error("API key is required.")

    openai.api_key = api_key

    try:
        response = openai.Audio.create(
            text=input_text,
            voice=voice,
            model=model
        )
    except openai.error.Timeout as e:
        raise gr.Error(f"OpenAI API request timed out: {e}")
    except openai.error.APIError as e:
        raise gr.Error(f"OpenAI API returned an API Error: {e}")
    except openai.error.APIConnectionError as e:
        raise gr.Error(f"OpenAI API request failed to connect: {e}")
    except openai.error.InvalidRequestError as e:
        raise gr.Error(f"OpenAI API request was invalid: {e}")
    except openai.error.AuthenticationError as e:
        raise gr.Error(f"OpenAI API request was not authorized: {e}")
    except openai.error.PermissionError as e:
        raise gr.Error(f"OpenAI API request was not permitted: {e}")
    except openai.error.RateLimitError as e:
        raise gr.Error(f"OpenAI API request exceeded rate limit: {e}")
    except openai.error.OpenAIError as e:
        raise gr.Error(f"OpenAI API Error: {e}")
    except Exception as e:
        raise gr.Error(f"An unexpected error occurred: {e}")

    if not hasattr(response, 'audio'):
        raise gr.Error("Invalid response from OpenAI API. The response does not contain audio content.")

    with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as temp_file:
        temp_file.write(response.audio)
        temp_file_path = temp_file.name

    return temp_file_path

def main():
    """
    Main function to create and launch the Gradio interface with input validation and error handling.
    """
    # Define model and voice options
    MODEL_OPTIONS = ["tts-1", "tts-1-hd"]
    VOICE_OPTIONS = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"]

    with gr.Blocks() as demo:
        with gr.Row():
            with gr.Column(scale=1):
                api_key_input = gr.Textbox(
                    label="API Key",
                    info="Get API key at: [https://platform.openai.com/account/api-keys](https://platform.openai.com/account/api-keys)",
                    type="password",
                    placeholder="Enter your OpenAI API Key",
                    value="",
                )
                model_dropdown = gr.Dropdown(
                    choices=MODEL_OPTIONS, label="Model", value="tts-1"
                )
                voice_dropdown = gr.Dropdown(
                    choices=VOICE_OPTIONS, label="Voice Options", value="echo"
                )
            with gr.Column(scale=2):
                input_textbox = gr.Textbox(
                    label="Input Text",
                    lines=10,
                    placeholder="Type your text here..."
                )
                submit_button = gr.Button(
                    "Convert Text to Speech",
                    variant="primary",
                    interactive=False  # Initially disabled
                )
            with gr.Column(scale=1):
                output_audio = gr.Audio(label="Output Audio")

        # Define the event handler for the submit button with error handling
        def on_submit(input_text, model, voice, api_key):
            try:
                audio_file = tts(input_text, model, voice, api_key)
                return audio_file
            except gr.Error as err:
                # Re-raise gr.Error exceptions to display message without traceback
                raise err
            except Exception as e:
                # Handle any other exceptions and display error message
                raise gr.Error(f"An unexpected error occurred: {e}")

        # Function to update the submit button state
        def update_submit_button_state(api_key, input_text):
            if api_key.strip() and input_text.strip():
                return gr.update(interactive=True)
            else:
                return gr.update(interactive=False)

        # Update the submit button state when the API key or input text changes
        api_key_input.change(
            fn=update_submit_button_state,
            inputs=[api_key_input, input_textbox],
            outputs=submit_button
        )
        input_textbox.change(
            fn=update_submit_button_state,
            inputs=[api_key_input, input_textbox],
            outputs=submit_button
        )

        # Allow pressing Enter in the input textbox to trigger the conversion
        input_textbox.submit(
            fn=on_submit,
            inputs=[input_textbox, model_dropdown, voice_dropdown, api_key_input],
            outputs=output_audio,
            api_name="tts",
        )

        # Trigger the conversion when the submit button is clicked
        submit_button.click(
            fn=on_submit,
            inputs=[input_textbox, model_dropdown, voice_dropdown, api_key_input],
            outputs=output_audio,
            api_name="tts",
        )

    # Launch the Gradio app with error display enabled
    demo.launch(share=True, show_error=True)

if __name__ == "__main__":
    main()