Spaces:
Running
Running
zach
commited on
Commit
·
63ef86b
1
Parent(s):
a41231d
Improve ElevenLabs API error handling
Browse files- src/app.py +6 -1
- src/integrations/__init__.py +1 -1
- src/integrations/elevenlabs_api.py +7 -6
src/app.py
CHANGED
|
@@ -29,6 +29,7 @@ from src.constants import (
|
|
| 29 |
)
|
| 30 |
from src.integrations import (
|
| 31 |
AnthropicError,
|
|
|
|
| 32 |
generate_text_with_claude,
|
| 33 |
text_to_speech_with_hume,
|
| 34 |
text_to_speech_with_elevenlabs
|
|
@@ -145,10 +146,14 @@ def text_to_speech(prompt: str, generated_text: str) -> tuple[gr.update, gr.upda
|
|
| 145 |
options_map, # Set option mapping state
|
| 146 |
option_2_audio # Set option 2 audio state
|
| 147 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
except Exception as e:
|
| 150 |
logger.error(f'Unexpected error during TTS generation: {e}')
|
| 151 |
-
return gr.update(), gr.update(), {}, None
|
| 152 |
|
| 153 |
|
| 154 |
def vote(
|
|
|
|
| 29 |
)
|
| 30 |
from src.integrations import (
|
| 31 |
AnthropicError,
|
| 32 |
+
ElevenLabsError,
|
| 33 |
generate_text_with_claude,
|
| 34 |
text_to_speech_with_hume,
|
| 35 |
text_to_speech_with_elevenlabs
|
|
|
|
| 146 |
options_map, # Set option mapping state
|
| 147 |
option_2_audio # Set option 2 audio state
|
| 148 |
)
|
| 149 |
+
|
| 150 |
+
except ElevenLabsError as ee:
|
| 151 |
+
logger.error(f"ElevenLabsError while synthesizing speech: {str(ee)}")
|
| 152 |
+
return gr.update(value=None), gr.update(value=None), {}, None
|
| 153 |
|
| 154 |
except Exception as e:
|
| 155 |
logger.error(f'Unexpected error during TTS generation: {e}')
|
| 156 |
+
return gr.update(value=None), gr.update(value=None), {}, None
|
| 157 |
|
| 158 |
|
| 159 |
def vote(
|
src/integrations/__init__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
from .anthropic_api import generate_text_with_claude, AnthropicError
|
| 2 |
-
from .elevenlabs_api import text_to_speech_with_elevenlabs
|
| 3 |
from .hume_api import text_to_speech_with_hume
|
|
|
|
| 1 |
from .anthropic_api import generate_text_with_claude, AnthropicError
|
| 2 |
+
from .elevenlabs_api import text_to_speech_with_elevenlabs, ElevenLabsError
|
| 3 |
from .hume_api import text_to_speech_with_hume
|
src/integrations/elevenlabs_api.py
CHANGED
|
@@ -12,7 +12,7 @@ Key Features:
|
|
| 12 |
|
| 13 |
Classes:
|
| 14 |
- ElevenLabsConfig: Immutable configuration for interacting with the TTS API.
|
| 15 |
-
-
|
| 16 |
|
| 17 |
Functions:
|
| 18 |
- text_to_speech_with_elevenlabs: Converts text to speech using the ElevenLabs TTS API.
|
|
@@ -73,7 +73,7 @@ class ElevenLabsConfig:
|
|
| 73 |
return random.choice(self.top_voices)
|
| 74 |
|
| 75 |
|
| 76 |
-
class
|
| 77 |
"""Custom exception for errors related to the ElevenLabs TTS API."""
|
| 78 |
def __init__(self, message: str, original_exception: Optional[Exception] = None):
|
| 79 |
super().__init__(message)
|
|
@@ -89,6 +89,7 @@ elevenlabs_config = ElevenLabsConfig()
|
|
| 89 |
wait=wait_fixed(2),
|
| 90 |
before=before_log(logger, logging.DEBUG),
|
| 91 |
after=after_log(logger, logging.DEBUG),
|
|
|
|
| 92 |
)
|
| 93 |
def text_to_speech_with_elevenlabs(text: str) -> bytes:
|
| 94 |
"""
|
|
@@ -101,7 +102,7 @@ def text_to_speech_with_elevenlabs(text: str) -> bytes:
|
|
| 101 |
bytes: The raw binary audio data for playback.
|
| 102 |
|
| 103 |
Raises:
|
| 104 |
-
|
| 105 |
"""
|
| 106 |
logger.debug(f'Generating speech with ElevenLabs. Text length: {len(text)} characters.')
|
| 107 |
|
|
@@ -117,7 +118,7 @@ def text_to_speech_with_elevenlabs(text: str) -> bytes:
|
|
| 117 |
# Ensure the response is an iterator
|
| 118 |
if not hasattr(audio_iterator, '__iter__') or not hasattr(audio_iterator, '__next__'):
|
| 119 |
logger.error('Invalid audio iterator response.')
|
| 120 |
-
raise
|
| 121 |
|
| 122 |
# Combine chunks into a single bytes object
|
| 123 |
audio = b''.join(chunk for chunk in audio_iterator)
|
|
@@ -125,14 +126,14 @@ def text_to_speech_with_elevenlabs(text: str) -> bytes:
|
|
| 125 |
# Validate audio
|
| 126 |
if not audio:
|
| 127 |
logger.error('No audio data received from ElevenLabs API.')
|
| 128 |
-
raise
|
| 129 |
|
| 130 |
logger.info(f'Received ElevenLabs audio ({len(audio)} bytes).')
|
| 131 |
return audio
|
| 132 |
|
| 133 |
except Exception as e:
|
| 134 |
logger.exception(f'Error generating speech: {e}')
|
| 135 |
-
raise
|
| 136 |
message=f'Failed to generate audio with ElevenLabs: {e}',
|
| 137 |
original_exception=e,
|
| 138 |
)
|
|
|
|
| 12 |
|
| 13 |
Classes:
|
| 14 |
- ElevenLabsConfig: Immutable configuration for interacting with the TTS API.
|
| 15 |
+
- ElevenLabsError: Custom exception for TTS API-related errors.
|
| 16 |
|
| 17 |
Functions:
|
| 18 |
- text_to_speech_with_elevenlabs: Converts text to speech using the ElevenLabs TTS API.
|
|
|
|
| 73 |
return random.choice(self.top_voices)
|
| 74 |
|
| 75 |
|
| 76 |
+
class ElevenLabsError(Exception):
|
| 77 |
"""Custom exception for errors related to the ElevenLabs TTS API."""
|
| 78 |
def __init__(self, message: str, original_exception: Optional[Exception] = None):
|
| 79 |
super().__init__(message)
|
|
|
|
| 89 |
wait=wait_fixed(2),
|
| 90 |
before=before_log(logger, logging.DEBUG),
|
| 91 |
after=after_log(logger, logging.DEBUG),
|
| 92 |
+
reraise=True
|
| 93 |
)
|
| 94 |
def text_to_speech_with_elevenlabs(text: str) -> bytes:
|
| 95 |
"""
|
|
|
|
| 102 |
bytes: The raw binary audio data for playback.
|
| 103 |
|
| 104 |
Raises:
|
| 105 |
+
ElevenLabsError: If there is an error communicating with the ElevenLabs API or processing the response.
|
| 106 |
"""
|
| 107 |
logger.debug(f'Generating speech with ElevenLabs. Text length: {len(text)} characters.')
|
| 108 |
|
|
|
|
| 118 |
# Ensure the response is an iterator
|
| 119 |
if not hasattr(audio_iterator, '__iter__') or not hasattr(audio_iterator, '__next__'):
|
| 120 |
logger.error('Invalid audio iterator response.')
|
| 121 |
+
raise ElevenLabsError('Invalid audio iterator received from ElevenLabs API.')
|
| 122 |
|
| 123 |
# Combine chunks into a single bytes object
|
| 124 |
audio = b''.join(chunk for chunk in audio_iterator)
|
|
|
|
| 126 |
# Validate audio
|
| 127 |
if not audio:
|
| 128 |
logger.error('No audio data received from ElevenLabs API.')
|
| 129 |
+
raise ElevenLabsError('Empty audio data received from ElevenLabs API.')
|
| 130 |
|
| 131 |
logger.info(f'Received ElevenLabs audio ({len(audio)} bytes).')
|
| 132 |
return audio
|
| 133 |
|
| 134 |
except Exception as e:
|
| 135 |
logger.exception(f'Error generating speech: {e}')
|
| 136 |
+
raise ElevenLabsError(
|
| 137 |
message=f'Failed to generate audio with ElevenLabs: {e}',
|
| 138 |
original_exception=e,
|
| 139 |
)
|