Fix ElevenLabsRealtimeSTTService:

- Move `CommitStrategy` up in the file so it could be used by `ElevenLabsRealtimeSTTSettings`
- Fix a bug where `run_tts` would erroneously try to reconnect if a reconnection was already in flight (like a reconnection triggered by `_update_settings`)
This commit is contained in:
Paul Kompfner
2026-02-18 10:50:53 -05:00
parent 7910f20e14
commit a7ada79fd9

View File

@@ -11,6 +11,7 @@ using segmented audio processing. The service uploads audio files and receives
transcription results directly. transcription results directly.
""" """
import asyncio
import base64 import base64
import io import io
import json import json
@@ -169,6 +170,13 @@ def language_to_elevenlabs_language(language: Language) -> Optional[str]:
return resolve_language(language, LANGUAGE_MAP, use_base_code=False) return resolve_language(language, LANGUAGE_MAP, use_base_code=False)
class CommitStrategy(str, Enum):
"""Commit strategies for transcript segmentation."""
MANUAL = "manual"
VAD = "vad"
@dataclass @dataclass
class ElevenLabsSTTSettings(STTSettings): class ElevenLabsSTTSettings(STTSettings):
"""Settings for the ElevenLabs file-based STT service. """Settings for the ElevenLabs file-based STT service.
@@ -426,13 +434,6 @@ def audio_format_from_sample_rate(sample_rate: int) -> str:
return "pcm_16000" return "pcm_16000"
class CommitStrategy(str, Enum):
"""Commit strategies for transcript segmentation."""
MANUAL = "manual"
VAD = "vad"
class ElevenLabsRealtimeSTTService(WebsocketSTTService): class ElevenLabsRealtimeSTTService(WebsocketSTTService):
"""Speech-to-text service using ElevenLabs' Realtime WebSocket API. """Speech-to-text service using ElevenLabs' Realtime WebSocket API.
@@ -515,6 +516,9 @@ class ElevenLabsRealtimeSTTService(WebsocketSTTService):
self._audio_format = "" # initialized in start() self._audio_format = "" # initialized in start()
self._receive_task = None self._receive_task = None
self._connected_event = asyncio.Event()
self._connected_event.set()
self._settings = ElevenLabsRealtimeSTTSettings( self._settings = ElevenLabsRealtimeSTTSettings(
model=model, model=model,
language=params.language_code, language=params.language_code,
@@ -630,6 +634,9 @@ class ElevenLabsRealtimeSTTService(WebsocketSTTService):
Yields: Yields:
None - transcription results are handled via WebSocket responses. None - transcription results are handled via WebSocket responses.
""" """
# Wait for any in-flight _connect() to finish before checking state
await self._connected_event.wait()
# Reconnect if connection is closed # Reconnect if connection is closed
if not self._websocket or self._websocket.state is State.CLOSED: if not self._websocket or self._websocket.state is State.CLOSED:
await self._connect() await self._connect()
@@ -654,12 +661,18 @@ class ElevenLabsRealtimeSTTService(WebsocketSTTService):
async def _connect(self): async def _connect(self):
"""Establish WebSocket connection to ElevenLabs Realtime STT.""" """Establish WebSocket connection to ElevenLabs Realtime STT."""
await self._connect_websocket() self._connected_event.clear()
try:
await self._connect_websocket()
await super()._connect() await super()._connect()
if self._websocket and not self._receive_task: if self._websocket and not self._receive_task:
self._receive_task = self.create_task(self._receive_task_handler(self._report_error)) self._receive_task = self.create_task(
self._receive_task_handler(self._report_error)
)
finally:
self._connected_event.set()
async def _disconnect(self): async def _disconnect(self):
"""Close WebSocket connection and cleanup tasks.""" """Close WebSocket connection and cleanup tasks."""