teamseven commited on
Commit
562ae29
Β·
verified Β·
1 Parent(s): 6fa18df

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +165 -31
app.py CHANGED
@@ -1,11 +1,15 @@
1
  import os
 
2
  import tempfile
3
  import logging
4
 
5
  import gradio as gr
6
  import requests
7
 
8
- logging.basicConfig(level=logging.INFO)
 
 
 
9
 
10
  logger = logging.getLogger("edge-tts-bridge")
11
 
@@ -19,23 +23,14 @@ VOICES = {
19
  }
20
 
21
 
22
- def generate_audio(text, voice_name):
23
- text = (text or "").strip()
24
-
25
- if not text:
26
- raise gr.Error("Please enter text.")
27
-
28
- if len(text) > 3000:
29
- raise gr.Error("Maximum 3000 characters per request.")
30
-
31
- if voice_name not in VOICES:
32
- raise gr.Error("Unsupported voice.")
33
 
34
- voice = VOICES[voice_name]
35
 
36
  try:
37
  logger.info(
38
- "Generating audio: voice=%s, characters=%d",
39
  voice,
40
  len(text),
41
  )
@@ -49,16 +44,93 @@ def generate_audio(text, voice_name):
49
  timeout=120,
50
  )
51
 
 
 
 
 
 
 
 
52
  if response.status_code != 200:
53
  raise RuntimeError(
54
  f"Go TTS HTTP {response.status_code}: "
55
- f"{response.text[:400]}"
56
  )
57
 
58
- audio_data = response.content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  if len(audio_data) < 100:
61
- raise RuntimeError("Audio response is too small.")
 
 
 
62
 
63
  with tempfile.NamedTemporaryFile(
64
  suffix=".mp3",
@@ -68,34 +140,82 @@ def generate_audio(text, voice_name):
68
  output_path = temp.name
69
 
70
  logger.info(
71
- "Audio generated successfully: %d bytes",
 
72
  len(audio_data),
73
  )
74
 
75
  return output_path
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  except Exception as exc:
78
- logger.exception("TTS failed")
 
 
 
79
 
80
  raise gr.Error(
81
- f"TTS failed ({type(exc).__name__}): {str(exc)[:400]}"
 
82
  )
83
 
84
 
85
  with gr.Blocks(title=APP_TITLE) as demo:
86
- gr.Markdown("# Edge TTS Bridge β€” Go Test")
 
 
87
 
88
- text_input = gr.Textbox(
89
- label="Text",
90
- placeholder="α€™α€„α€Ία€Ήα€‚α€œα€¬α€•α€«αŠ α€‘α€žα€Άα€…α€™α€Ία€Έα€žα€•α€Ία€”α€±α€•α€«α€α€šα€Ία‹",
91
- lines=4,
92
  )
93
 
94
- voice_input = gr.Dropdown(
95
- choices=list(VOICES.keys()),
96
- value="Myanmar Female",
97
- label="Voice",
98
- )
 
 
 
 
 
 
 
 
99
 
100
  generate_button = gr.Button(
101
  "Generate Audio",
@@ -109,11 +229,25 @@ with gr.Blocks(title=APP_TITLE) as demo:
109
 
110
  generate_button.click(
111
  fn=generate_audio,
112
- inputs=[text_input, voice_input],
 
 
 
113
  outputs=audio_output,
114
  api_name="generate",
115
  )
116
 
 
 
 
 
 
 
 
 
 
 
 
117
 
118
  if __name__ == "__main__":
119
  demo.queue(max_size=5).launch(
 
1
  import os
2
+ import base64
3
  import tempfile
4
  import logging
5
 
6
  import gradio as gr
7
  import requests
8
 
9
+ logging.basicConfig(
10
+ level=logging.INFO,
11
+ format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
12
+ )
13
 
14
  logger = logging.getLogger("edge-tts-bridge")
15
 
 
23
  }
24
 
25
 
26
+ def synthesize(text: str, voice: str) -> str:
27
+ """Generate audio through the Go Edge TTS server."""
 
 
 
 
 
 
 
 
 
28
 
29
+ output_path = None
30
 
31
  try:
32
  logger.info(
33
+ "TTS request started | voice=%s | characters=%d",
34
  voice,
35
  len(text),
36
  )
 
44
  timeout=120,
45
  )
46
 
47
+ logger.info(
48
+ "Go TTS response | status=%s | content_type=%s | bytes=%d",
49
+ response.status_code,
50
+ response.headers.get("content-type", ""),
51
+ len(response.content),
52
+ )
53
+
54
  if response.status_code != 200:
55
  raise RuntimeError(
56
  f"Go TTS HTTP {response.status_code}: "
57
+ f"{response.text[:500]}"
58
  )
59
 
60
+ content_type = response.headers.get(
61
+ "content-type",
62
+ "",
63
+ ).lower()
64
+
65
+ # Case 1: Server returns audio directly.
66
+ if content_type.startswith("audio/"):
67
+ audio_data = response.content
68
+
69
+ # Case 2: Server returns JSON.
70
+ else:
71
+ try:
72
+ result = response.json()
73
+ except ValueError:
74
+ raise RuntimeError(
75
+ "Unexpected response from Go TTS: "
76
+ f"{response.text[:500]}"
77
+ )
78
+
79
+ logger.info(
80
+ "Go TTS JSON response: %s",
81
+ str(result)[:1000],
82
+ )
83
+
84
+ if not isinstance(result, dict):
85
+ raise RuntimeError(
86
+ "Go TTS returned unexpected JSON format."
87
+ )
88
+
89
+ # Surface server-side errors.
90
+ if result.get("error"):
91
+ raise RuntimeError(
92
+ str(result["error"])[:500]
93
+ )
94
+
95
+ # Common Base64 audio fields.
96
+ audio_data = None
97
+
98
+ for key in (
99
+ "audio",
100
+ "data",
101
+ "audioContent",
102
+ "audio_content",
103
+ ):
104
+ value = result.get(key)
105
+
106
+ if isinstance(value, str) and value:
107
+ try:
108
+ if value.startswith("data:") and "," in value:
109
+ value = value.split(",", 1)[1]
110
+
111
+ audio_data = base64.b64decode(
112
+ value,
113
+ validate=True,
114
+ )
115
+
116
+ if audio_data:
117
+ break
118
+
119
+ except Exception:
120
+ audio_data = None
121
+
122
+ if not audio_data:
123
+ raise RuntimeError(
124
+ "Go TTS did not return recognizable audio. "
125
+ "Response: "
126
+ f"{str(result)[:500]}"
127
+ )
128
 
129
  if len(audio_data) < 100:
130
+ raise RuntimeError(
131
+ "Audio response is too small: "
132
+ f"{len(audio_data)} bytes."
133
+ )
134
 
135
  with tempfile.NamedTemporaryFile(
136
  suffix=".mp3",
 
140
  output_path = temp.name
141
 
142
  logger.info(
143
+ "TTS succeeded | voice=%s | bytes=%d",
144
+ voice,
145
  len(audio_data),
146
  )
147
 
148
  return output_path
149
 
150
+ except Exception:
151
+ if output_path and os.path.exists(output_path):
152
+ try:
153
+ os.remove(output_path)
154
+ except OSError:
155
+ pass
156
+
157
+ logger.exception(
158
+ "TTS synthesis failed | voice=%s",
159
+ voice,
160
+ )
161
+ raise
162
+
163
+
164
+ def generate_audio(text, voice_name):
165
+ """Gradio interface handler."""
166
+
167
+ text = (text or "").strip()
168
+
169
+ if not text:
170
+ raise gr.Error("Please enter text.")
171
+
172
+ if len(text) > 3000:
173
+ raise gr.Error(
174
+ "Maximum 3000 characters per request."
175
+ )
176
+
177
+ if voice_name not in VOICES:
178
+ raise gr.Error("Unsupported voice.")
179
+
180
+ voice = VOICES[voice_name]
181
+
182
+ try:
183
+ return synthesize(text, voice)
184
+
185
  except Exception as exc:
186
+ logger.exception(
187
+ "TTS handler failed | type=%s",
188
+ type(exc).__name__,
189
+ )
190
 
191
  raise gr.Error(
192
+ f"TTS failed ({type(exc).__name__}): "
193
+ f"{str(exc)[:500]}"
194
  )
195
 
196
 
197
  with gr.Blocks(title=APP_TITLE) as demo:
198
+ gr.Markdown(
199
+ """
200
+ # Edge TTS Bridge β€” Go Test
201
 
202
+ Test Microsoft Edge TTS using the Go server.
203
+ """
 
 
204
  )
205
 
206
+ with gr.Row():
207
+ text_input = gr.Textbox(
208
+ label="Text",
209
+ placeholder="α€™α€„α€Ία€Ήα€‚α€œα€¬α€•α€«αŠ α€‘α€žα€Άα€…α€™α€Ία€Έα€žα€•α€Ία€”α€±α€•α€«α€α€šα€Ία‹",
210
+ lines=4,
211
+ max_lines=10,
212
+ )
213
+
214
+ voice_input = gr.Dropdown(
215
+ choices=list(VOICES.keys()),
216
+ value="Myanmar Female",
217
+ label="Voice",
218
+ )
219
 
220
  generate_button = gr.Button(
221
  "Generate Audio",
 
229
 
230
  generate_button.click(
231
  fn=generate_audio,
232
+ inputs=[
233
+ text_input,
234
+ voice_input,
235
+ ],
236
  outputs=audio_output,
237
  api_name="generate",
238
  )
239
 
240
+ gr.Markdown(
241
+ """
242
+ ## Test instructions
243
+
244
+ 1. Enter a short Myanmar sentence.
245
+ 2. Select a voice.
246
+ 3. Click Generate Audio.
247
+ 4. Check whether the MP3 is playable.
248
+ """
249
+ )
250
+
251
 
252
  if __name__ == "__main__":
253
  demo.queue(max_size=5).launch(