Skip to content

Commit

Permalink
Merge pull request #327 from pipecat-ai/aleix/bot-start-stop-speaking…
Browse files Browse the repository at this point in the history
…-frames

bot start stop speaking frames
  • Loading branch information
aconchillo authored Jul 28, 2024
2 parents 028e38a + 76aca32 commit f816897
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 14 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added new `BotStartedSpeakingFrame` and `BotStoppedSpeakingFrame` control
frames. These frames are pushed upstream and they should wrap
`BotSpeakingFrame`.

- Transports now allow you to register event handlers without decorators.

### Changed

- `BotSpeakingFrame` is now a control frame.

- `StartFrame` is now a control frame similar to `EndFrame`.

- `DeepgramTTSService` now is more customizable. You can adjust the encoding and
Expand Down
38 changes: 27 additions & 11 deletions src/pipecat/frames/frames.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,17 +270,6 @@ class BotInterruptionFrame(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.
Expand Down Expand Up @@ -348,6 +337,33 @@ class UserStoppedSpeakingFrame(ControlFrame):
pass


@dataclass
class BotStartedSpeakingFrame(ControlFrame):
"""Emitted upstream by transport outputs to indicate the bot started speaking.
"""
pass


@dataclass
class BotStoppedSpeakingFrame(ControlFrame):
"""Emitted upstream by transport outputs to indicate the bot stopped speaking.
"""
pass


@dataclass
class BotSpeakingFrame(ControlFrame):
"""Emitted upstream 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 TTSStartedFrame(ControlFrame):
"""Used to indicate the beginning of a TTS response. Following
Expand Down
11 changes: 8 additions & 3 deletions src/pipecat/processors/user_idle_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@

from typing import Awaitable, Callable

from pipecat.frames.frames import BotSpeakingFrame, Frame, StartInterruptionFrame, StopInterruptionFrame, SystemFrame
from pipecat.frames.frames import (
BotSpeakingFrame,
Frame,
SystemFrame,
UserStartedSpeakingFrame,
UserStoppedSpeakingFrame)
from pipecat.processors.async_frame_processor import AsyncFrameProcessor
from pipecat.processors.frame_processor import FrameDirection

Expand Down Expand Up @@ -47,10 +52,10 @@ async def process_frame(self, frame: Frame, direction: FrameDirection):
await self.queue_frame(frame, direction)

# We shouldn't call the idle callback if the user or the bot are speaking.
if isinstance(frame, StartInterruptionFrame):
if isinstance(frame, UserStartedSpeakingFrame):
self._interrupted = True
self._idle_event.set()
elif isinstance(frame, StopInterruptionFrame):
elif isinstance(frame, UserStoppedSpeakingFrame):
self._interrupted = False
self._idle_event.set()
elif isinstance(frame, BotSpeakingFrame):
Expand Down
10 changes: 10 additions & 0 deletions src/pipecat/transports/base_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from pipecat.frames.frames import (
AudioRawFrame,
BotSpeakingFrame,
BotStartedSpeakingFrame,
BotStoppedSpeakingFrame,
CancelFrame,
MetricsFrame,
SpriteFrame,
Expand All @@ -25,6 +27,8 @@
StartInterruptionFrame,
StopInterruptionFrame,
SystemFrame,
TTSStartedFrame,
TTSStoppedFrame,
TransportMessageFrame)
from pipecat.transports.base_transport import TransportParams

Expand Down Expand Up @@ -172,6 +176,12 @@ async def _sink_task_handler(self):
await self._set_camera_images(frame.images)
elif isinstance(frame, TransportMessageFrame):
await self.send_message(frame)
elif isinstance(frame, TTSStartedFrame):
await self._internal_push_frame(BotStartedSpeakingFrame(), FrameDirection.UPSTREAM)
await self._internal_push_frame(frame)
elif isinstance(frame, TTSStoppedFrame):
await self._internal_push_frame(BotStoppedSpeakingFrame(), FrameDirection.UPSTREAM)
await self._internal_push_frame(frame)
else:
await self._internal_push_frame(frame)

Expand Down

0 comments on commit f816897

Please sign in to comment.