fciannella's picture
Working with service run on 7860
53ea588
raw
history blame
4.01 kB
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: BSD 2-Clause License
"""User presence detection and greeting processor for ACE conversation pipeline."""
from loguru import logger
from pipecat.frames.frames import (
ControlFrame,
Frame,
InputAudioRawFrame,
StartInterruptionFrame,
SystemFrame,
TTSSpeakFrame,
UserStartedSpeakingFrame,
)
from pipecat.processors.frame_processor import FrameDirection, FrameProcessor
from nvidia_pipecat.frames.action import FinishedPresenceUserActionFrame, StartedPresenceUserActionFrame
class UserPresenceProcesssor(FrameProcessor):
"""Manages user presence detection and automated greetings in the ACE conversation pipeline.
Manages automated greetings and pipeline activation based on user presence state.
Sends welcome/farewell messages and controls frame forwarding accordingly.
Input Frames:
StartedPresenceUserActionFrame: User becomes present
FinishedPresenceUserActionFrame: User leaves
UserStartedSpeakingFrame: User speech event
InputAudioRawFrame: Raw audio input
SystemFrame: System events
ControlFrame: Control events
"""
def __init__(self, welcome_msg="Hello", farewell_msg="Goodbye", **kwargs):
"""Initialize the user presence processor.
Args:
welcome_msg (str): Message spoken when user presence detected.
farewell_msg (str): Message spoken when user leaves.
**kwargs: Additional arguments passed to parent FrameProcessor.
"""
super().__init__(**kwargs)
self._welcome_msg = welcome_msg
self._farewell_msg = farewell_msg
self._is_user_present = False # At startup, it is assumed that the user is not present
async def _greet_welcome(self):
"""Internal method to handle welcome greeting."""
logger.debug("User detected. Greeting a welcome")
try:
await self.push_frame(TTSSpeakFrame(self._welcome_msg))
self._is_user_present = True
except Exception as e:
logger.error(e)
async def _greet_farewell(self):
"""Internal method to handle farewell greeting."""
logger.debug(f"User left. Bidding farewell. {self._farewell_msg}")
try:
await self.push_frame(TTSSpeakFrame(self._farewell_msg))
self._is_user_present = False
except Exception as e:
logger.error(e)
async def process_frame(self, frame: Frame, direction: FrameDirection):
"""Process incoming frames and manage user presence state.
Handles user presence detection, greeting messages, and controls frame forwarding
based on user presence state.
Args:
frame (Frame): Incoming frame to process.
direction (FrameDirection): Frame flow direction.
"""
await super().process_frame(frame, direction)
if isinstance(frame, StartedPresenceUserActionFrame):
# Welcome the user on detecting presence
await self.push_frame(frame, direction)
await self._greet_welcome()
elif isinstance(frame, FinishedPresenceUserActionFrame):
# Greet farewell to the user on detecting absence.
await self.push_frame(StartInterruptionFrame())
await self.push_frame(frame, direction)
await self._greet_farewell()
elif isinstance(frame, SystemFrame | ControlFrame):
if isinstance(frame, UserStartedSpeakingFrame | InputAudioRawFrame) and not self._is_user_present:
return
else:
await self.push_frame(frame, direction)
else:
# Pass all frames if user is present
if self._is_user_present:
await self.push_frame(frame, direction)
else:
logger.debug(f"Frame {frame} blocked as no user is present")