Merge pull request #3328 from speechmatics/fix/speectmatics-vad

Update to SpeechmaticsSTTService for `0.0.99`
This commit is contained in:
Mark Backman
2026-01-07 14:42:21 -05:00
committed by GitHub
3 changed files with 31 additions and 9 deletions

1
changelog/3328.added.md Normal file
View File

@@ -0,0 +1 @@
- Added `split_sentences` parameter to `SpeechmaticsSTTService` to control sentence splitting behavior for finals on sentence boundaries.

4
changelog/3328.fixed.md Normal file
View File

@@ -0,0 +1,4 @@
- Updated `SpeechmaticsSTTService` for version `0.0.99+`:
- Fixed `SpeechmaticsSTTService` to listen for `VADUserStoppedSpeakingFrame` in order to finalize transcription.
- Default to `TurnDetectionMode.FIXED` for Pipecat-controlled end of turn detection.
- Only emit VAD + interruption frames if VAD is enabled within the plugin (modes other than `TurnDetectionMode.FIXED` or `TurnDetectionMode.EXTERNAL`).

View File

@@ -29,6 +29,7 @@ from pipecat.frames.frames import (
TranscriptionFrame, TranscriptionFrame,
UserStartedSpeakingFrame, UserStartedSpeakingFrame,
UserStoppedSpeakingFrame, UserStoppedSpeakingFrame,
VADUserStoppedSpeakingFrame,
) )
from pipecat.processors.frame_processor import FrameDirection from pipecat.processors.frame_processor import FrameDirection
from pipecat.services.stt_service import STTService from pipecat.services.stt_service import STTService
@@ -46,6 +47,7 @@ try:
SpeakerFocusConfig, SpeakerFocusConfig,
SpeakerFocusMode, SpeakerFocusMode,
SpeakerIdentifier, SpeakerIdentifier,
SpeechSegmentConfig,
VoiceAgentClient, VoiceAgentClient,
VoiceAgentConfig, VoiceAgentConfig,
VoiceAgentConfigPreset, VoiceAgentConfigPreset,
@@ -65,13 +67,14 @@ class TurnDetectionMode(str, Enum):
"""Endpoint and turn detection handling mode. """Endpoint and turn detection handling mode.
How the STT engine handles the endpointing of speech. If using Pipecat's built-in endpointing, How the STT engine handles the endpointing of speech. If using Pipecat's built-in endpointing,
then use `TurnDetectionMode.EXTERNAL` (default). then use `TurnDetectionMode.FIXED` (default).
To use the STT engine's built-in endpointing, then use `TurnDetectionMode.ADAPTIVE` for simple To use the STT engine's built-in endpointing, then use `TurnDetectionMode.ADAPTIVE` for simple
voice activity detection or `TurnDetectionMode.SMART_TURN` for more advanced ML-based voice activity detection or `TurnDetectionMode.SMART_TURN` for more advanced ML-based
endpointing. endpointing.
""" """
FIXED = "fixed"
EXTERNAL = "external" EXTERNAL = "external"
ADAPTIVE = "adaptive" ADAPTIVE = "adaptive"
SMART_TURN = "smart_turn" SMART_TURN = "smart_turn"
@@ -102,9 +105,9 @@ class SpeechmaticsSTTService(STTService):
language: Language code for transcription. Defaults to `Language.EN`. language: Language code for transcription. Defaults to `Language.EN`.
turn_detection_mode: Endpoint handling, one of `TurnDetectionMode.EXTERNAL`, turn_detection_mode: Endpoint handling, one of `TurnDetectionMode.FIXED`,
`TurnDetectionMode.ADAPTIVE` and `TurnDetectionMode.SMART_TURN`. `TurnDetectionMode.EXTERNAL`, `TurnDetectionMode.ADAPTIVE` and
Defaults to `TurnDetectionMode.EXTERNAL`. `TurnDetectionMode.SMART_TURN`. Defaults to `TurnDetectionMode.FIXED`.
speaker_active_format: Formatter for active speaker ID. This formatter is used to format speaker_active_format: Formatter for active speaker ID. This formatter is used to format
the text output for individual speakers and ensures that the context is clear for the text output for individual speakers and ensures that the context is clear for
@@ -177,6 +180,10 @@ class SpeechmaticsSTTService(STTService):
speaker activity detection. This setting is used only for the formatted text output speaker activity detection. This setting is used only for the formatted text output
of individual segments. of individual segments.
split_sentences: Emit finalized sentences mid-turn. When enabled, as soon as a sentence
is finalized, it will be emitted as a final segment. This is useful for applications
that need to process sentences as they are finalized. Defaults to False.
enable_diarization: Enable speaker diarization. When enabled, the STT engine will enable_diarization: Enable speaker diarization. When enabled, the STT engine will
determine and attribute words to unique speakers. The speaker_sensitivity determine and attribute words to unique speakers. The speaker_sensitivity
parameter can be used to adjust the sensitivity of diarization. parameter can be used to adjust the sensitivity of diarization.
@@ -201,7 +208,7 @@ class SpeechmaticsSTTService(STTService):
language: Language | str = Language.EN language: Language | str = Language.EN
# Endpointing mode # Endpointing mode
turn_detection_mode: TurnDetectionMode = TurnDetectionMode.EXTERNAL turn_detection_mode: TurnDetectionMode = TurnDetectionMode.FIXED
# Output formatting # Output formatting
speaker_active_format: str | None = None speaker_active_format: str | None = None
@@ -230,6 +237,7 @@ class SpeechmaticsSTTService(STTService):
end_of_utterance_max_delay: float | None = None end_of_utterance_max_delay: float | None = None
punctuation_overrides: dict | None = None punctuation_overrides: dict | None = None
include_partials: bool | None = None include_partials: bool | None = None
split_sentences: bool | None = None
# Diarization # Diarization
enable_diarization: bool | None = None enable_diarization: bool | None = None
@@ -326,7 +334,10 @@ class SpeechmaticsSTTService(STTService):
) )
# Framework options # Framework options
self._enable_vad: bool = self._config.end_of_utterance_mode != EndOfUtteranceMode.EXTERNAL self._enable_vad: bool = self._config.end_of_utterance_mode not in [
EndOfUtteranceMode.FIXED,
EndOfUtteranceMode.EXTERNAL,
]
self._speaker_active_format: str = params.speaker_active_format self._speaker_active_format: str = params.speaker_active_format
self._speaker_passive_format: str = ( self._speaker_passive_format: str = (
params.speaker_passive_format or params.speaker_active_format params.speaker_passive_format or params.speaker_active_format
@@ -487,6 +498,7 @@ class SpeechmaticsSTTService(STTService):
"end_of_utterance_max_delay", "end_of_utterance_max_delay",
"punctuation_overrides", "punctuation_overrides",
"include_partials", "include_partials",
"split_sentences",
"enable_diarization", "enable_diarization",
"speaker_sensitivity", "speaker_sensitivity",
"max_speakers", "max_speakers",
@@ -501,6 +513,11 @@ class SpeechmaticsSTTService(STTService):
if hasattr(config, key): if hasattr(config, key):
setattr(config, key, value) setattr(config, key, value)
# Enable sentences
config.speech_segment_config = SpeechSegmentConfig(
emit_sentences=params.split_sentences or False
)
# Return the complete config # Return the complete config
return config return config
@@ -604,9 +621,9 @@ class SpeechmaticsSTTService(STTService):
message: the message payload. message: the message payload.
""" """
logger.debug(f"{self} StartOfTurn received") logger.debug(f"{self} StartOfTurn received")
# await self.start_processing_metrics()
await self.broadcast_frame(UserStartedSpeakingFrame) await self.broadcast_frame(UserStartedSpeakingFrame)
await self.push_interruption_task_frame_and_wait() await self.push_interruption_task_frame_and_wait()
# await self.start_processing_metrics()
async def _handle_end_of_turn(self, message: dict[str, Any]) -> None: async def _handle_end_of_turn(self, message: dict[str, Any]) -> None:
"""Handle EndOfTurn events. """Handle EndOfTurn events.
@@ -660,10 +677,10 @@ class SpeechmaticsSTTService(STTService):
self._bot_speaking = False self._bot_speaking = False
# Force finalization # Force finalization
if isinstance(frame, UserStoppedSpeakingFrame): if isinstance(frame, VADUserStoppedSpeakingFrame):
if self._enable_vad: if self._enable_vad:
logger.warning( logger.warning(
f"{self} UserStoppedSpeakingFrame received but internal VAD is being used" f"{self} VADUserStoppedSpeakingFrame received but internal VAD is being used"
) )
elif not self._enable_vad and self._client is not None: elif not self._enable_vad and self._client is not None:
self._client.finalize() self._client.finalize()