DARKWICK commited on
Commit
783eb4d
·
verified ·
1 Parent(s): eef9bd9

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +13 -0
  2. app.py +216 -0
  3. gitattributes +35 -0
README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Realistic Text To Speech Unlimited
3
+ emoji: 🔥
4
+ colorFrom: indigo
5
+ colorTo: purple
6
+ sdk: gradio
7
+ sdk_version: 5.28.0
8
+ app_file: app.py
9
+ pinned: true
10
+ short_description: Free Text-To-Speech generator with Emotion control (OpenAI)
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ import gradio as gr
3
+ import requests
4
+ import random
5
+ import urllib.parse
6
+ import tempfile
7
+ import os
8
+
9
+ NSFW_URL_TEMPLATE = os.getenv("NSFW_API_URL_TEMPLATE")
10
+ TTS_URL_TEMPLATE = os.getenv("TTS_API_URL_TEMPLATE")
11
+
12
+
13
+ if not NSFW_URL_TEMPLATE:
14
+ raise ValueError("Missing Secret: NSFW_API_URL_TEMPLATE is not set in Hugging Face Space secrets.")
15
+ if not TTS_URL_TEMPLATE:
16
+ raise ValueError("Missing Secret: TTS_API_URL_TEMPLATE is not set in Hugging Face Space secrets.")
17
+ # VOICES
18
+ VOICES = [
19
+ "alloy", "echo", "fable", "onyx", "nova", "shimmer", # Standard OpenAI Voices
20
+ "coral", "verse", "ballad", "ash", "sage", "amuch", "dan" # Some additional pre-trained
21
+ ]
22
+
23
+
24
+
25
+ def check_nsfw(prompt: str) -> bool:
26
+ global NSFW_URL_TEMPLATE
27
+ try:
28
+ encoded_prompt = urllib.parse.quote(prompt)
29
+ url = NSFW_URL_TEMPLATE.format(prompt=encoded_prompt)
30
+ print(f"DEBUG: Checking NSFW URL: {url.split('?')[0]}... (query params hidden)")
31
+
32
+ response = requests.get(url, timeout=20)
33
+ response.raise_for_status()
34
+
35
+ result = response.text.strip().upper()
36
+ print(f"DEBUG: NSFW Check Response: '{result}'")
37
+
38
+ if result == "YES":
39
+ return True
40
+ elif result == "NO":
41
+ return False
42
+ else:
43
+ print(f"Warning: Unexpected response from NSFW checker: {response.text}")
44
+ return True # unexpected responses = potentially NSFW
45
+
46
+ except requests.exceptions.RequestException as e:
47
+ print(f"Error during NSFW check: {e}")
48
+ raise gr.Error(f"Failed to check prompt safety.")
49
+ except Exception as e:
50
+ print(f"Unexpected error during NSFW check: {e}")
51
+ raise gr.Error(f"An unexpected error occurred during safety check. Please wait for a second and try again.")
52
+
53
+
54
+ def generate_audio(prompt: str, voice: str, emotion: str, seed: int) -> bytes:
55
+ # Generates audio using the API from server
56
+ global TTS_URL_TEMPLATE
57
+ try:
58
+ encoded_prompt = urllib.parse.quote(prompt)
59
+ encoded_emotion = urllib.parse.quote(emotion)
60
+
61
+ url = TTS_URL_TEMPLATE.format(
62
+ prompt=encoded_prompt,
63
+ emotion=encoded_emotion,
64
+ voice=voice,
65
+ seed=seed
66
+ )
67
+ print(f"DEBUG: Generating Audio URL: {url.split('?')[0]}... (query params hidden)")
68
+
69
+ response = requests.get(url, timeout=60)
70
+ response.raise_for_status()
71
+
72
+ content_type = response.headers.get('content-type', '').lower()
73
+ if 'audio' not in content_type:
74
+ print(f"Warning: Unexpected content type received: {content_type}")
75
+ print(f"Response Text: {response.text[:500]}")
76
+ raise gr.Error(f"API did not return audio.")
77
+
78
+ return response.content
79
+
80
+ except requests.exceptions.RequestException as e:
81
+ print(f"Error during audio generation: {e}")
82
+ error_details = ""
83
+ if hasattr(e, 'response') and e.response is not None:
84
+ error_details = e.response.text[:200]
85
+ raise gr.Error(f"Failed to generate audio. Please wait for a second and try again.")
86
+ except Exception as e:
87
+ print(f"Unexpected error during audio generation: {e}")
88
+ raise gr.Error(f"An unexpected error occurred during audio generation. Please wait for a second and try again.")
89
+
90
+
91
+
92
+ def text_to_speech_app(prompt: str, voice: str, emotion: str, use_random_seed: bool, specific_seed: int):
93
+
94
+ print("\n\n\n"+prompt+"\n\n\n")
95
+ if not prompt:
96
+ raise gr.Error("Prompt cannot be empty.")
97
+ if not emotion:
98
+ emotion = "neutral"
99
+ print("Warning: No emotion provided, defaulting to 'neutral'.")
100
+ if not voice:
101
+ raise gr.Error("Please select a voice.")
102
+
103
+ seed = random.randint(0, 2**32 - 1) if use_random_seed else int(specific_seed)
104
+ print(f"Using Seed: {seed}")
105
+
106
+ # check NSFW
107
+ print("Checking prompt safety...")
108
+ try:
109
+ # is_nsfw = check_nsfw(prompt)
110
+ is_nsfw = False
111
+ except gr.Error as e:
112
+ return None, f"There was an error. Please wait for a second and try again."
113
+
114
+ if is_nsfw:
115
+ print("Prompt flagged as inappropriate.")
116
+ return None, "Error: The prompt was flagged as inappropriate and cannot be processed."
117
+
118
+ # if not nsfw
119
+ print("Prompt is safe. Generating audio...")
120
+ try:
121
+ audio_bytes = generate_audio(prompt, voice, emotion, seed)
122
+
123
+ # audio save to a temporary file
124
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_audio_file:
125
+ temp_audio_file.write(audio_bytes)
126
+ temp_file_path = temp_audio_file.name
127
+ print(f"Audio saved temporarily to: {temp_file_path}")
128
+
129
+ return temp_file_path, f"Audio generated successfully with voice '{voice}', emotion '{emotion}', and seed {seed}."
130
+
131
+ except gr.Error as e:
132
+ return None, str(e)
133
+ except Exception as e:
134
+ print(f"Unexpected error in main function: {e}")
135
+ return None, f"An unexpected error occurred: {e}"
136
+
137
+
138
+
139
+
140
+ def toggle_seed_input(use_random_seed):
141
+
142
+ return gr.update(visible=not use_random_seed, value=12345)
143
+
144
+ with gr.Blocks() as app:
145
+ gr.Markdown("# Advanced OpenAI Text-To-Speech Unlimited")
146
+ gr.Markdown(
147
+ """Enter text, choose a voice and emotion, and generate audio.
148
+ The text will be checked for appropriateness before generation.
149
+ Use it as much as you want.
150
+
151
+
152
+ **Like & follow** for more AI projects:
153
+
154
+
155
+ • Instagram: [@nihal_gazi_io](https://www.instagram.com/nihal_gazi_io/)
156
+ • X.com: [@NihalGazi_](https://x.com/NihalGazi_?t=f9UtAv005GppiIIXFEWMSQ&s=09)
157
+ • Discord: nihal_gazi_io"""
158
+ )
159
+
160
+ with gr.Row():
161
+ with gr.Column(scale=2):
162
+ prompt_input = gr.Textbox(label="Prompt", placeholder="Enter the text you want to convert to speech...")
163
+ emotion_input = gr.Textbox(label="Emotion Style", placeholder="e.g., happy, sad, excited, calm...")
164
+ voice_dropdown = gr.Dropdown(label="Voice", choices=VOICES, value="alloy")
165
+ with gr.Column(scale=1):
166
+ random_seed_checkbox = gr.Checkbox(label="Use Random Seed", value=True)
167
+ seed_input = gr.Number(label="Specific Seed", value=12345, visible=False, precision=0)
168
+
169
+ submit_button = gr.Button("Generate Audio", variant="primary")
170
+
171
+ with gr.Row():
172
+ audio_output = gr.Audio(label="Generated Audio", type="filepath")
173
+ status_output = gr.Textbox(label="Status")
174
+
175
+
176
+ random_seed_checkbox.change(
177
+ fn=toggle_seed_input,
178
+ inputs=[random_seed_checkbox],
179
+ outputs=[seed_input]
180
+ )
181
+
182
+ submit_button.click(
183
+ fn=text_to_speech_app,
184
+ inputs=[
185
+ prompt_input,
186
+ voice_dropdown,
187
+ emotion_input,
188
+ random_seed_checkbox,
189
+ seed_input
190
+ ],
191
+ outputs=[audio_output, status_output],
192
+ concurrency_limit=30
193
+ )
194
+
195
+
196
+ gr.Examples(
197
+ examples=[
198
+ ["Hello there! This is a test of the text-to-speech system.", "alloy", "neutral", False, 12345],
199
+ ["Surely *you* wouldn't want *that*. [laughs]", "shimmer", "sarcastic and mocking", True, 12345],
200
+ ["[sobbing] I am feeling... [sighs] a bit down today [cry]", "ballad", "sad and depressed, with stammering", True, 662437],
201
+ ["This technology is absolutely amazing!", "nova", "excited and joyful", True, 12345],
202
+ ],
203
+ inputs=[prompt_input, voice_dropdown, emotion_input, random_seed_checkbox, seed_input],
204
+ outputs=[audio_output, status_output],
205
+ fn=text_to_speech_app,
206
+ cache_examples=False,
207
+ )
208
+
209
+
210
+ if __name__ == "__main__":
211
+
212
+ if NSFW_URL_TEMPLATE and TTS_URL_TEMPLATE:
213
+ app.launch()
214
+ else:
215
+ print("ERROR: Cannot launch app. Required API URL secrets are missing.")
216
+
gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text