From 90b9dce71043f5c771cc989ed1540f0838994edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Mon, 17 Feb 2025 18:59:13 -0800 Subject: [PATCH] STTMuteFilter: ignore audio frames so no transcriptions are generated --- CHANGELOG.md | 7 ++++ .../processors/filters/stt_mute_filter.py | 2 ++ tests/test_stt_mute_filter.py | 33 ++++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8731571f..373a03ebd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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/), 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 ### Added diff --git a/src/pipecat/processors/filters/stt_mute_filter.py b/src/pipecat/processors/filters/stt_mute_filter.py index fb1753263..937f3b075 100644 --- a/src/pipecat/processors/filters/stt_mute_filter.py +++ b/src/pipecat/processors/filters/stt_mute_filter.py @@ -23,6 +23,7 @@ from pipecat.frames.frames import ( Frame, FunctionCallInProgressFrame, FunctionCallResultFrame, + InputAudioRawFrame, StartFrame, StartInterruptionFrame, StopInterruptionFrame, @@ -185,6 +186,7 @@ class STTMuteFilter(FrameProcessor): StopInterruptionFrame, UserStartedSpeakingFrame, UserStoppedSpeakingFrame, + InputAudioRawFrame, ), ): # Only pass VAD-related frames when not muted diff --git a/tests/test_stt_mute_filter.py b/tests/test_stt_mute_filter.py index 62bdd03c9..a55c4609e 100644 --- a/tests/test_stt_mute_filter.py +++ b/tests/test_stt_mute_filter.py @@ -11,12 +11,13 @@ from pipecat.frames.frames import ( BotStoppedSpeakingFrame, FunctionCallInProgressFrame, FunctionCallResultFrame, + InputAudioRawFrame, STTMuteFrame, UserStartedSpeakingFrame, UserStoppedSpeakingFrame, ) 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): @@ -26,10 +27,14 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase): frames_to_send = [ BotStartedSpeakingFrame(), # First bot speech starts UserStartedSpeakingFrame(), # Should be suppressed + InputAudioRawFrame( + audio=b"", sample_rate=16000, num_channels=1 + ), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed BotStoppedSpeakingFrame(), # First bot speech ends BotStartedSpeakingFrame(), # Second bot speech UserStartedSpeakingFrame(), # Should pass through + InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through UserStoppedSpeakingFrame(), # Should pass through BotStoppedSpeakingFrame(), ] @@ -41,6 +46,7 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase): STTMuteFrame, # mute=False BotStartedSpeakingFrame, UserStartedSpeakingFrame, # Now passes through + InputAudioRawFrame, # Now passes through UserStoppedSpeakingFrame, # Now passes through BotStoppedSpeakingFrame, ] @@ -57,12 +63,19 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase): frames_to_send = [ BotStartedSpeakingFrame(), # First speech starts UserStartedSpeakingFrame(), # Should be suppressed + InputAudioRawFrame( + audio=b"", sample_rate=16000, num_channels=1 + ), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed BotStoppedSpeakingFrame(), # First speech ends UserStartedSpeakingFrame(), # Should pass through + InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through UserStoppedSpeakingFrame(), # Should pass through BotStartedSpeakingFrame(), # Second speech starts UserStartedSpeakingFrame(), # Should be suppressed again + InputAudioRawFrame( + audio=b"", sample_rate=16000, num_channels=1 + ), # Should be suppressed again UserStoppedSpeakingFrame(), # Should be suppressed again BotStoppedSpeakingFrame(), # Second speech ends ] @@ -73,6 +86,7 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase): BotStoppedSpeakingFrame, STTMuteFrame, # mute=False UserStartedSpeakingFrame, + InputAudioRawFrame, UserStoppedSpeakingFrame, BotStartedSpeakingFrame, STTMuteFrame, # mute=True @@ -134,15 +148,23 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase): frames_to_send = [ UserStartedSpeakingFrame(), # Should be suppressed (starts muted) + InputAudioRawFrame( + audio=b"", sample_rate=16000, num_channels=1 + ), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed BotStartedSpeakingFrame(), # First bot speech UserStartedSpeakingFrame(), # Should be suppressed + InputAudioRawFrame( + audio=b"", sample_rate=16000, num_channels=1 + ), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed BotStoppedSpeakingFrame(), # First speech ends, unmutes UserStartedSpeakingFrame(), # Should pass through + InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through UserStoppedSpeakingFrame(), # Should pass through BotStartedSpeakingFrame(), # Second speech UserStartedSpeakingFrame(), # Should pass through + InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through UserStoppedSpeakingFrame(), # Should pass through BotStoppedSpeakingFrame(), ] @@ -153,9 +175,11 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase): BotStoppedSpeakingFrame, STTMuteFrame, # mute=False after first speech UserStartedSpeakingFrame, + InputAudioRawFrame, UserStoppedSpeakingFrame, BotStartedSpeakingFrame, UserStartedSpeakingFrame, + InputAudioRawFrame, UserStoppedSpeakingFrame, BotStoppedSpeakingFrame, ] @@ -190,23 +214,30 @@ class TestSTTMuteFilter(unittest.IsolatedAsyncioTestCase): frames_to_send = [ UserStartedSpeakingFrame(), # Should pass through + InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through UserStoppedSpeakingFrame(), # Should pass through BotStartedSpeakingFrame(), # Bot starts speaking UserStartedSpeakingFrame(), # Should be suppressed + InputAudioRawFrame( + audio=b"", sample_rate=16000, num_channels=1 + ), # Should be suppressed UserStoppedSpeakingFrame(), # Should be suppressed BotStoppedSpeakingFrame(), # Bot stops speaking UserStartedSpeakingFrame(), # Should pass through + InputAudioRawFrame(audio=b"", sample_rate=16000, num_channels=1), # Should pass through UserStoppedSpeakingFrame(), # Should pass through ] expected_returned_frames = [ UserStartedSpeakingFrame, + InputAudioRawFrame, UserStoppedSpeakingFrame, BotStartedSpeakingFrame, STTMuteFrame, # mute=True BotStoppedSpeakingFrame, STTMuteFrame, # mute=False UserStartedSpeakingFrame, + InputAudioRawFrame, UserStoppedSpeakingFrame, ]