diff --git a/CHANGELOG.md b/CHANGELOG.md index 60f30806f..546550365 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added new frame `BotSpeakingFrame`. This frame will be continuously pushed + upstream while the bot is talking. + - Added `XTTSService`. This is a local Text-To-Speech service. See https://github.com/coqui-ai/TTS diff --git a/src/pipecat/frames/frames.py b/src/pipecat/frames/frames.py index 0b013dbfb..a581055be 100644 --- a/src/pipecat/frames/frames.py +++ b/src/pipecat/frames/frames.py @@ -240,6 +240,17 @@ class StopInterruptionFrame(SystemFrame): pass +@dataclass +class BotSpeakingFrame(SystemFrame): + """Emitted by transport outputs while the bot is still speaking. This can be + used, for example, to detect when a user is idle. That is, while the bot is + speaking we don't want to trigger any user idle timeout since the user might + be listening. + + """ + pass + + @dataclass class MetricsFrame(SystemFrame): """Emitted by processor that can compute metrics like latencies. diff --git a/src/pipecat/transports/base_output.py b/src/pipecat/transports/base_output.py index c0ea8cdd1..41f2df79e 100644 --- a/src/pipecat/transports/base_output.py +++ b/src/pipecat/transports/base_output.py @@ -14,6 +14,7 @@ from typing import List from pipecat.processors.frame_processor import FrameDirection, FrameProcessor from pipecat.frames.frames import ( AudioRawFrame, + BotSpeakingFrame, CancelFrame, MetricsFrame, SpriteFrame, @@ -263,4 +264,5 @@ class BaseOutputTransport(FrameProcessor): if len(buffer) >= self._audio_chunk_size: await self.write_raw_audio_frames(bytes(buffer[:self._audio_chunk_size])) buffer = buffer[self._audio_chunk_size:] + await self.push_frame(BotSpeakingFrame(), FrameDirection.UPSTREAM) return buffer