Merge pull request #1238 from pipecat-ai/aleix/stt-mute-filter-ignore-input-audio-frames

STTMuteFilter: ignore audio frames so no transcriptions are generated
This commit is contained in:
Aleix Conchillo Flaqué
2025-02-18 09:48:13 -08:00
committed by GitHub
3 changed files with 41 additions and 1 deletions

View File

@@ -5,6 +5,13 @@ All notable changes to **Pipecat** will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Fixed
- Fixed a `STTMuteFilter` issue that would not mute user audio frames causing
transcriptions to be generated by the STT service.
## [0.0.57] - 2025-02-14 ## [0.0.57] - 2025-02-14
### Added ### Added

View File

@@ -23,6 +23,7 @@ from pipecat.frames.frames import (
Frame, Frame,
FunctionCallInProgressFrame, FunctionCallInProgressFrame,
FunctionCallResultFrame, FunctionCallResultFrame,
InputAudioRawFrame,
StartFrame, StartFrame,
StartInterruptionFrame, StartInterruptionFrame,
StopInterruptionFrame, StopInterruptionFrame,
@@ -185,6 +186,7 @@ class STTMuteFilter(FrameProcessor):
StopInterruptionFrame, StopInterruptionFrame,
UserStartedSpeakingFrame, UserStartedSpeakingFrame,
UserStoppedSpeakingFrame, UserStoppedSpeakingFrame,
InputAudioRawFrame,
), ),
): ):
# Only pass VAD-related frames when not muted # Only pass VAD-related frames when not muted

View File

@@ -11,12 +11,13 @@ from pipecat.frames.frames import (
BotStoppedSpeakingFrame, BotStoppedSpeakingFrame,
FunctionCallInProgressFrame, FunctionCallInProgressFrame,
FunctionCallResultFrame, FunctionCallResultFrame,
InputAudioRawFrame,
STTMuteFrame, STTMuteFrame,
UserStartedSpeakingFrame, UserStartedSpeakingFrame,
UserStoppedSpeakingFrame, UserStoppedSpeakingFrame,
) )
from pipecat.processors.filters.stt_mute_filter import STTMuteConfig, STTMuteFilter, STTMuteStrategy from pipecat.processors.filters.stt_mute_filter import STTMuteConfig, STTMuteFilter, STTMuteStrategy
from pipecat.tests.utils import run_test from pipecat.tests.utils import SleepFrame, run_test
class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase): class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase):
@@ -26,10 +27,14 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase):
frames_to_send = [ frames_to_send = [
BotStartedSpeakingFrame(), # First bot speech starts BotStartedSpeakingFrame(), # First bot speech starts
UserStartedSpeakingFrame(), # Should be suppressed UserStartedSpeakingFrame(), # Should be suppressed
InputAudioRawFrame(
audio=b"", sample_rate=16000, num_channels=1
), # Should be suppressed
UserStoppedSpeakingFrame(), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed
BotStoppedSpeakingFrame(), # First bot speech ends BotStoppedSpeakingFrame(), # First bot speech ends
BotStartedSpeakingFrame(), # Second bot speech BotStartedSpeakingFrame(), # Second bot speech
UserStartedSpeakingFrame(), # Should pass through UserStartedSpeakingFrame(), # Should pass through
InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through
UserStoppedSpeakingFrame(), # Should pass through UserStoppedSpeakingFrame(), # Should pass through
BotStoppedSpeakingFrame(), BotStoppedSpeakingFrame(),
] ]
@@ -41,6 +46,7 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase):
STTMuteFrame, # mute=False STTMuteFrame, # mute=False
BotStartedSpeakingFrame, BotStartedSpeakingFrame,
UserStartedSpeakingFrame, # Now passes through UserStartedSpeakingFrame, # Now passes through
InputAudioRawFrame, # Now passes through
UserStoppedSpeakingFrame, # Now passes through UserStoppedSpeakingFrame, # Now passes through
BotStoppedSpeakingFrame, BotStoppedSpeakingFrame,
] ]
@@ -57,12 +63,19 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase):
frames_to_send = [ frames_to_send = [
BotStartedSpeakingFrame(), # First speech starts BotStartedSpeakingFrame(), # First speech starts
UserStartedSpeakingFrame(), # Should be suppressed UserStartedSpeakingFrame(), # Should be suppressed
InputAudioRawFrame(
audio=b"", sample_rate=16000, num_channels=1
), # Should be suppressed
UserStoppedSpeakingFrame(), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed
BotStoppedSpeakingFrame(), # First speech ends BotStoppedSpeakingFrame(), # First speech ends
UserStartedSpeakingFrame(), # Should pass through UserStartedSpeakingFrame(), # Should pass through
InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through
UserStoppedSpeakingFrame(), # Should pass through UserStoppedSpeakingFrame(), # Should pass through
BotStartedSpeakingFrame(), # Second speech starts BotStartedSpeakingFrame(), # Second speech starts
UserStartedSpeakingFrame(), # Should be suppressed again UserStartedSpeakingFrame(), # Should be suppressed again
InputAudioRawFrame(
audio=b"", sample_rate=16000, num_channels=1
), # Should be suppressed again
UserStoppedSpeakingFrame(), # Should be suppressed again UserStoppedSpeakingFrame(), # Should be suppressed again
BotStoppedSpeakingFrame(), # Second speech ends BotStoppedSpeakingFrame(), # Second speech ends
] ]
@@ -73,6 +86,7 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase):
BotStoppedSpeakingFrame, BotStoppedSpeakingFrame,
STTMuteFrame, # mute=False STTMuteFrame, # mute=False
UserStartedSpeakingFrame, UserStartedSpeakingFrame,
InputAudioRawFrame,
UserStoppedSpeakingFrame, UserStoppedSpeakingFrame,
BotStartedSpeakingFrame, BotStartedSpeakingFrame,
STTMuteFrame, # mute=True STTMuteFrame, # mute=True
@@ -134,15 +148,23 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase):
frames_to_send = [ frames_to_send = [
UserStartedSpeakingFrame(), # Should be suppressed (starts muted) UserStartedSpeakingFrame(), # Should be suppressed (starts muted)
InputAudioRawFrame(
audio=b"", sample_rate=16000, num_channels=1
), # Should be suppressed
UserStoppedSpeakingFrame(), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed
BotStartedSpeakingFrame(), # First bot speech BotStartedSpeakingFrame(), # First bot speech
UserStartedSpeakingFrame(), # Should be suppressed UserStartedSpeakingFrame(), # Should be suppressed
InputAudioRawFrame(
audio=b"", sample_rate=16000, num_channels=1
), # Should be suppressed
UserStoppedSpeakingFrame(), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed
BotStoppedSpeakingFrame(), # First speech ends, unmutes BotStoppedSpeakingFrame(), # First speech ends, unmutes
UserStartedSpeakingFrame(), # Should pass through UserStartedSpeakingFrame(), # Should pass through
InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through
UserStoppedSpeakingFrame(), # Should pass through UserStoppedSpeakingFrame(), # Should pass through
BotStartedSpeakingFrame(), # Second speech BotStartedSpeakingFrame(), # Second speech
UserStartedSpeakingFrame(), # Should pass through UserStartedSpeakingFrame(), # Should pass through
InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through
UserStoppedSpeakingFrame(), # Should pass through UserStoppedSpeakingFrame(), # Should pass through
BotStoppedSpeakingFrame(), BotStoppedSpeakingFrame(),
] ]
@@ -153,9 +175,11 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase):
BotStoppedSpeakingFrame, BotStoppedSpeakingFrame,
STTMuteFrame, # mute=False after first speech STTMuteFrame, # mute=False after first speech
UserStartedSpeakingFrame, UserStartedSpeakingFrame,
InputAudioRawFrame,
UserStoppedSpeakingFrame, UserStoppedSpeakingFrame,
BotStartedSpeakingFrame, BotStartedSpeakingFrame,
UserStartedSpeakingFrame, UserStartedSpeakingFrame,
InputAudioRawFrame,
UserStoppedSpeakingFrame, UserStoppedSpeakingFrame,
BotStoppedSpeakingFrame, BotStoppedSpeakingFrame,
] ]
@@ -190,23 +214,30 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase):
frames_to_send = [ frames_to_send = [
UserStartedSpeakingFrame(), # Should pass through UserStartedSpeakingFrame(), # Should pass through
InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through
UserStoppedSpeakingFrame(), # Should pass through UserStoppedSpeakingFrame(), # Should pass through
BotStartedSpeakingFrame(), # Bot starts speaking BotStartedSpeakingFrame(), # Bot starts speaking
UserStartedSpeakingFrame(), # Should be suppressed UserStartedSpeakingFrame(), # Should be suppressed
InputAudioRawFrame(
audio=b"", sample_rate=16000, num_channels=1
), # Should be suppressed
UserStoppedSpeakingFrame(), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed
BotStoppedSpeakingFrame(), # Bot stops speaking BotStoppedSpeakingFrame(), # Bot stops speaking
UserStartedSpeakingFrame(), # Should pass through UserStartedSpeakingFrame(), # Should pass through
InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through
UserStoppedSpeakingFrame(), # Should pass through UserStoppedSpeakingFrame(), # Should pass through
] ]
expected_returned_frames = [ expected_returned_frames = [
UserStartedSpeakingFrame, UserStartedSpeakingFrame,
InputAudioRawFrame,
UserStoppedSpeakingFrame, UserStoppedSpeakingFrame,
BotStartedSpeakingFrame, BotStartedSpeakingFrame,
STTMuteFrame, # mute=True STTMuteFrame, # mute=True
BotStoppedSpeakingFrame, BotStoppedSpeakingFrame,
STTMuteFrame, # mute=False STTMuteFrame, # mute=False
UserStartedSpeakingFrame, UserStartedSpeakingFrame,
InputAudioRawFrame,
UserStoppedSpeakingFrame, UserStoppedSpeakingFrame,
] ]