From d913d954dbf65d4e9bd2d734704b8427fd9fadd2 Mon Sep 17 00:00:00 2001 From: Paul Kompfner Date: Wed, 18 Feb 2026 11:34:52 -0500 Subject: [PATCH] Fix `SpeechmaticsSTTService` settings update code, and augment test file to better exercise it --- .../55h-update-settings-speechmatics-stt.py | 27 ++++++++++++++++++- src/pipecat/services/speechmatics/stt.py | 20 +++++++++----- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/examples/foundational/55h-update-settings-speechmatics-stt.py b/examples/foundational/55h-update-settings-speechmatics-stt.py index 46ed44016..d041d69d2 100644 --- a/examples/foundational/55h-update-settings-speechmatics-stt.py +++ b/examples/foundational/55h-update-settings-speechmatics-stt.py @@ -51,7 +51,14 @@ transport_params = { async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): logger.info(f"Starting bot") - stt = SpeechmaticsSTTService(api_key=os.getenv("SPEECHMATICS_API_KEY")) + stt = SpeechmaticsSTTService( + api_key=os.getenv("SPEECHMATICS_API_KEY"), + params=SpeechmaticsSTTService.InputParams( + enable_diarization=True, + speaker_active_format="<{speaker_id}>{text}", + speaker_passive_format="<{speaker_id}>{text}", + ), + ) tts = CartesiaTTSService( api_key=os.getenv("CARTESIA_API_KEY"), @@ -106,6 +113,24 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): STTUpdateSettingsFrame(update=SpeechmaticsSTTSettings(language=Language.ES)) ) + await asyncio.sleep(10) + logger.info("Updating Speechmatics STT settings: focus_speakers=['S1']") + await task.queue_frame( + STTUpdateSettingsFrame(update=SpeechmaticsSTTSettings(focus_speakers=["S1"])) + ) + + await asyncio.sleep(10) + logger.info( + "Updating Speechmatics STT settings: speaker_active_format={text}" + ) + await task.queue_frame( + STTUpdateSettingsFrame( + update=SpeechmaticsSTTSettings( + speaker_active_format="{text}" + ) + ) + ) + @transport.event_handler("on_client_disconnected") async def on_client_disconnected(transport, client): logger.info(f"Client disconnected") diff --git a/src/pipecat/services/speechmatics/stt.py b/src/pipecat/services/speechmatics/stt.py index c6fe0d16e..166e19d97 100644 --- a/src/pipecat/services/speechmatics/stt.py +++ b/src/pipecat/services/speechmatics/stt.py @@ -508,12 +508,14 @@ class SpeechmaticsSTTService(STTService): needs_reconnect = bool(changed.keys() - no_reconnect) if needs_reconnect: + logger.debug(f"{self} settings update requires reconnect: {changed.keys()}") # Connection-level fields changed — rebuild the SDK config # from the now-updated self._settings, then reconnect. self._config = self._build_config() await self._disconnect() await self._connect() - elif changed & SpeechmaticsSTTSettings.HOT_FIELDS: + elif changed.keys() & SpeechmaticsSTTSettings.HOT_FIELDS: + logger.debug(f"{self} applying hot settings update: {changed.keys()}") if self._config.enable_diarization: # Only hot-updatable fields changed — push to the live session. self._config.speaker_config.focus_speakers = self._settings.focus_speakers @@ -522,11 +524,17 @@ class SpeechmaticsSTTService(STTService): if self._client: self._client.update_diarization_config(self._config.speaker_config) else: - # Diarization not enabled — need a full reconnect to apply. - self._config = self._build_config() - await self._disconnect() - await self._connect() - # LOCAL_FIELDS: already applied by super(); nothing else to do. + logger.debug( + f"{self} hot settings updated but diarization not enabled: {changed.keys()}. ignoring." + ) + # Diarization not enabled — the new settings will take effect + # if/when diarization is enabled, which does require a reconnect. + elif changed.keys() & SpeechmaticsSTTSettings.LOCAL_FIELDS: + logger.debug( + f"{self} local settings update, no special action required: {changed.keys()}" + ) + # Only local fields changed — no need to push to the STT engine, + # the new settings will take effect immediately. return changed