AzureTTSService: Handle first chunk only for timestamps and TTFB metrics
This commit is contained in:
@@ -283,6 +283,7 @@ class AzureTTSService(WordTTSService, AzureBaseTTSService):
|
|||||||
self._word_boundary_queue = asyncio.Queue()
|
self._word_boundary_queue = asyncio.Queue()
|
||||||
self._word_processor_task = None
|
self._word_processor_task = None
|
||||||
self._started = False
|
self._started = False
|
||||||
|
self._first_chunk = True
|
||||||
self._cumulative_audio_offset: float = 0.0 # Cumulative audio duration in seconds
|
self._cumulative_audio_offset: float = 0.0 # Cumulative audio duration in seconds
|
||||||
|
|
||||||
async def start(self, frame: StartFrame):
|
async def start(self, frame: StartFrame):
|
||||||
@@ -425,10 +426,16 @@ class AzureTTSService(WordTTSService, AzureBaseTTSService):
|
|||||||
"""
|
"""
|
||||||
await super().push_frame(frame, direction)
|
await super().push_frame(frame, direction)
|
||||||
if isinstance(frame, (TTSStoppedFrame, InterruptionFrame)):
|
if isinstance(frame, (TTSStoppedFrame, InterruptionFrame)):
|
||||||
self._started = False
|
self._reset_state()
|
||||||
if isinstance(frame, TTSStoppedFrame):
|
if isinstance(frame, TTSStoppedFrame):
|
||||||
await self.add_word_timestamps([("Reset", 0)])
|
await self.add_word_timestamps([("Reset", 0)])
|
||||||
|
|
||||||
|
def _reset_state(self):
|
||||||
|
"""Reset TTS state between turns."""
|
||||||
|
self._started = False
|
||||||
|
self._first_chunk = True
|
||||||
|
self._cumulative_audio_offset = 0.0
|
||||||
|
|
||||||
async def flush_audio(self):
|
async def flush_audio(self):
|
||||||
"""Flush any pending audio data."""
|
"""Flush any pending audio data."""
|
||||||
logger.trace(f"{self}: flushing audio")
|
logger.trace(f"{self}: flushing audio")
|
||||||
@@ -453,8 +460,8 @@ class AzureTTSService(WordTTSService, AzureBaseTTSService):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
await self.push_error(error_msg=f"Unknown error occurred: {e}", exception=e)
|
await self.push_error(error_msg=f"Unknown error occurred: {e}", exception=e)
|
||||||
|
|
||||||
# Reset cumulative audio offset on interruption
|
# Reset state on interruption
|
||||||
self._cumulative_audio_offset = 0.0
|
self._reset_state()
|
||||||
# Clear the audio queue
|
# Clear the audio queue
|
||||||
while not self._audio_queue.empty():
|
while not self._audio_queue.empty():
|
||||||
try:
|
try:
|
||||||
@@ -498,19 +505,23 @@ class AzureTTSService(WordTTSService, AzureBaseTTSService):
|
|||||||
await self.start_ttfb_metrics()
|
await self.start_ttfb_metrics()
|
||||||
yield TTSStartedFrame()
|
yield TTSStartedFrame()
|
||||||
self._started = True
|
self._started = True
|
||||||
|
self._first_chunk = True
|
||||||
|
|
||||||
ssml = self._construct_ssml(text)
|
ssml = self._construct_ssml(text)
|
||||||
self._speech_synthesizer.speak_ssml_async(ssml)
|
self._speech_synthesizer.speak_ssml_async(ssml)
|
||||||
await self.start_tts_usage_metrics(text)
|
await self.start_tts_usage_metrics(text)
|
||||||
|
|
||||||
# Stream audio chunks as they arrive
|
# Stream audio chunks as they arrive
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
chunk = await self._audio_queue.get()
|
chunk = await self._audio_queue.get()
|
||||||
if chunk is None: # End of stream
|
if chunk is None: # End of stream
|
||||||
break
|
break
|
||||||
|
|
||||||
await self.stop_ttfb_metrics()
|
if self._first_chunk:
|
||||||
await self.start_word_timestamps()
|
await self.stop_ttfb_metrics()
|
||||||
|
await self.start_word_timestamps()
|
||||||
|
self._first_chunk = False
|
||||||
|
|
||||||
frame = TTSAudioRawFrame(
|
frame = TTSAudioRawFrame(
|
||||||
audio=chunk,
|
audio=chunk,
|
||||||
@@ -522,8 +533,7 @@ class AzureTTSService(WordTTSService, AzureBaseTTSService):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
yield ErrorFrame(error=f"Unknown error occurred: {e}")
|
yield ErrorFrame(error=f"Unknown error occurred: {e}")
|
||||||
yield TTSStoppedFrame()
|
yield TTSStoppedFrame()
|
||||||
self._started = False
|
self._reset_state()
|
||||||
# Could add reconnection logic here if needed
|
|
||||||
return
|
return
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user