Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,22 @@ async def _connect_ws(self, timeout: float) -> aiohttp.ClientWebSocketResponse:
)

async def _close_ws(self, ws: aiohttp.ClientWebSocketResponse) -> None:
await ws.close()
try:
# Send Flush and Close messages to ensure Deepgram processes all remaining audio
# and properly terminates the session, preventing lingering TTS sessions
await ws.send_str(SynthesizeStream._FLUSH_MSG)
await ws.send_str(SynthesizeStream._CLOSE_MSG)

# Wait for server acknowledgment to prevent race conditions and ensure
# proper cleanup, avoiding 429 Too Many Requests errors from lingering sessions
try:
await asyncio.wait_for(ws.receive(), timeout=1.0)
except asyncio.TimeoutError:
pass
except Exception as e:
logger.warning(f"Error during WebSocket close sequence: {e}")
finally:
await ws.close()

def _ensure_session(self) -> aiohttp.ClientSession:
if not self._session:
Expand Down Expand Up @@ -220,6 +235,9 @@ async def _run(self, output_emitter: tts.AudioEmitter) -> None:


class SynthesizeStream(tts.SynthesizeStream):
_FLUSH_MSG: str = json.dumps({"type": "Flush"})
_CLOSE_MSG: str = json.dumps({"type": "Close"})

def __init__(self, *, tts: TTS, conn_options: APIConnectOptions):
super().__init__(tts=tts, conn_options=conn_options)
self._tts: TTS = tts
Expand Down