joelazo Claude commited on
Commit
0e5ba43
·
1 Parent(s): 77ccd33

Remove Edge-TTS provider due to HuggingFace Spaces incompatibility

Browse files

Edge-TTS has persistent asyncio event loop conflicts in containerized
environments that cannot be resolved. Removing it simplifies the codebase
and eliminates all asyncio errors.

Changes:
- Removed EdgeTTSProvider class and all Edge-TTS code
- Removed edge-tts from dependencies (pyproject.toml, requirements.txt)
- Updated default TTS provider to OpenAI TTS
- Removed asyncio and threading imports (no longer needed)
- Updated comments and documentation

Remaining TTS providers (both fully working on HF Spaces):
✓ OpenAI TTS (paid, high quality, default)
✓ gTTS (free, good quality)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Files changed (4) hide show
  1. config.py +0 -1
  2. pyproject.toml +0 -1
  3. requirements.txt +0 -1
  4. voice_handler.py +3 -76
config.py CHANGED
@@ -198,7 +198,6 @@ class VoiceConfig:
198
  # Note: Voice choices are dynamically loaded based on selected TTS provider
199
  # See voice_handler.py for provider-specific voice lists:
200
  # - OpenAI TTS: alloy, echo, fable, onyx, nova, shimmer
201
- # - Edge-TTS: en-US-AriaNeural, en-US-GuyNeural, en-US-JennyNeural, etc.
202
  # - gTTS: default
203
 
204
  # OpenAI TTS voices (kept for reference, not used in UI)
 
198
  # Note: Voice choices are dynamically loaded based on selected TTS provider
199
  # See voice_handler.py for provider-specific voice lists:
200
  # - OpenAI TTS: alloy, echo, fable, onyx, nova, shimmer
 
201
  # - gTTS: default
202
 
203
  # OpenAI TTS voices (kept for reference, not used in UI)
pyproject.toml CHANGED
@@ -8,7 +8,6 @@ authors = [
8
  readme = "README.md"
9
  requires-python = ">=3.10"
10
  dependencies = [
11
- "edge-tts>=7.2.3",
12
  "gradio>=5.0.0",
13
  "gtts>=2.5.4",
14
  "huggingface-hub>=1.1.4",
 
8
  readme = "README.md"
9
  requires-python = ">=3.10"
10
  dependencies = [
 
11
  "gradio>=5.0.0",
12
  "gtts>=2.5.4",
13
  "huggingface-hub>=1.1.4",
requirements.txt CHANGED
@@ -2,7 +2,6 @@ gradio
2
  huggingface_hub
3
  python-dotenv
4
  openai
5
- edge-tts
6
  openai-whisper
7
  gtts
8
  langdetect
 
2
  huggingface_hub
3
  python-dotenv
4
  openai
 
5
  openai-whisper
6
  gtts
7
  langdetect
voice_handler.py CHANGED
@@ -9,11 +9,8 @@ import tempfile
9
  from abc import ABC, abstractmethod
10
  from pathlib import Path
11
  from typing import Optional, List, Dict
12
- import asyncio
13
- import threading
14
 
15
  # Import voice processing libraries
16
- # Note: edge_tts is imported lazily to avoid asyncio event loop issues at module import time
17
  from openai import OpenAI
18
  import whisper
19
  from gtts import gTTS
@@ -50,19 +47,6 @@ class VoiceConfig:
50
 
51
  # TTS Provider definitions
52
  TTS_PROVIDERS = {
53
- "Edge-TTS (Free)": {
54
- "id": "edge_tts",
55
- "cost_tier": "free",
56
- "cost_per_1k_chars": 0.0,
57
- "requires_api_key": False,
58
- "voices": [
59
- "en-US-AriaNeural",
60
- "en-US-GuyNeural",
61
- "en-US-JennyNeural",
62
- "en-GB-SoniaNeural",
63
- "en-GB-RyanNeural",
64
- ]
65
- },
66
  "OpenAI TTS": {
67
  "id": "openai_tts",
68
  "cost_tier": "medium",
@@ -81,8 +65,8 @@ class VoiceConfig:
81
 
82
  # Default selections
83
  DEFAULT_STT = "OpenAI Whisper API"
84
- DEFAULT_TTS = "Edge-TTS (Free)"
85
- DEFAULT_TTS_VOICE = "en-US-JennyNeural"
86
 
87
 
88
  # ============================================================================
@@ -188,61 +172,6 @@ class LocalWhisperSTT(STTProvider):
188
  # TTS Provider Implementations
189
  # ============================================================================
190
 
191
- class EdgeTTSProvider(TTSProvider):
192
- """Microsoft Edge TTS implementation (free)."""
193
-
194
- def __init__(self, voice: str = "en-US-JennyNeural"):
195
- self.voice = voice
196
-
197
- def synthesize(self, text: str, output_path: Optional[str] = None) -> str:
198
- """Synthesize speech using Edge TTS."""
199
-
200
- if output_path is None:
201
- output_path = os.path.join(tempfile.gettempdir(), f"tts_{os.getpid()}.mp3")
202
-
203
- try:
204
- # Import edge_tts lazily to avoid asyncio issues at module import time
205
- import edge_tts
206
-
207
- # Edge TTS requires async
208
- async def _synthesize():
209
- communicate = edge_tts.Communicate(text, self.voice)
210
- await communicate.save(output_path)
211
-
212
- # Run async code in a separate thread to completely isolate event loop
213
- # This prevents conflicts with Gradio/HuggingFace Spaces event loops
214
- exception_holder = [None]
215
-
216
- def run_in_thread():
217
- try:
218
- loop = asyncio.new_event_loop()
219
- asyncio.set_event_loop(loop)
220
- try:
221
- loop.run_until_complete(_synthesize())
222
- finally:
223
- loop.close()
224
- except Exception as e:
225
- exception_holder[0] = e
226
-
227
- thread = threading.Thread(target=run_in_thread)
228
- thread.start()
229
- thread.join(timeout=30) # 30 second timeout
230
-
231
- if thread.is_alive():
232
- raise Exception("Edge TTS synthesis timed out")
233
-
234
- if exception_holder[0]:
235
- raise exception_holder[0]
236
-
237
- return output_path
238
- except Exception as e:
239
- raise Exception(f"Edge TTS synthesis failed: {str(e)}")
240
-
241
- def get_available_voices(self) -> List[str]:
242
- """Get available Edge TTS voices."""
243
- return VoiceConfig.TTS_PROVIDERS["Edge-TTS (Free)"]["voices"]
244
-
245
-
246
  class OpenAITTSProvider(TTSProvider):
247
  """OpenAI TTS implementation."""
248
 
@@ -346,9 +275,7 @@ def create_tts_provider(provider_name: str, voice: Optional[str] = None) -> TTSP
346
  if voice is None:
347
  voice = provider_info["voices"][0]
348
 
349
- if provider_id == "edge_tts":
350
- return EdgeTTSProvider(voice=voice)
351
- elif provider_id == "openai_tts":
352
  return OpenAITTSProvider(voice=voice)
353
  elif provider_id == "gtts":
354
  return GTTSProvider(voice=voice)
 
9
  from abc import ABC, abstractmethod
10
  from pathlib import Path
11
  from typing import Optional, List, Dict
 
 
12
 
13
  # Import voice processing libraries
 
14
  from openai import OpenAI
15
  import whisper
16
  from gtts import gTTS
 
47
 
48
  # TTS Provider definitions
49
  TTS_PROVIDERS = {
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  "OpenAI TTS": {
51
  "id": "openai_tts",
52
  "cost_tier": "medium",
 
65
 
66
  # Default selections
67
  DEFAULT_STT = "OpenAI Whisper API"
68
+ DEFAULT_TTS = "OpenAI TTS"
69
+ DEFAULT_TTS_VOICE = "nova"
70
 
71
 
72
  # ============================================================================
 
172
  # TTS Provider Implementations
173
  # ============================================================================
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  class OpenAITTSProvider(TTSProvider):
176
  """OpenAI TTS implementation."""
177
 
 
275
  if voice is None:
276
  voice = provider_info["voices"][0]
277
 
278
+ if provider_id == "openai_tts":
 
 
279
  return OpenAITTSProvider(voice=voice)
280
  elif provider_id == "gtts":
281
  return GTTSProvider(voice=voice)