From 455054552856d299e51ecb9e070574a76818d6e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Fri, 18 Oct 2024 10:27:53 -0700 Subject: [PATCH 1/2] examples: use EndFrame() when the participant leaves --- examples/foundational/01-say-one-thing.py | 13 +++++++++---- examples/foundational/02-llm-say-one-thing.py | 6 +++++- examples/foundational/03-still-frame.py | 12 ++++++------ examples/foundational/06a-image-sync.py | 2 +- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/examples/foundational/01-say-one-thing.py b/examples/foundational/01-say-one-thing.py index 288fcefc3..50ae1bad2 100644 --- a/examples/foundational/01-say-one-thing.py +++ b/examples/foundational/01-say-one-thing.py @@ -47,10 +47,15 @@ async def main(): # Register an event handler so we can play the audio when the # participant joins. - @transport.event_handler("on_participant_joined") - async def on_new_participant_joined(transport, participant): - participant_name = participant["info"]["userName"] or "" - await task.queue_frames([TextFrame(f"Hello there, {participant_name}!"), EndFrame()]) + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + participant_name = participant.get("info", {}).get("userName", "") + await task.queue_frame(TextFrame(f"Hello there, {participant_name}!")) + + # Register an event handler to exit the application when the user leaves. + @transport.event_handler("on_participant_left") + async def on_participant_left(transport, participant, reason): + await task.queue_frame(EndFrame()) await runner.run(task) diff --git a/examples/foundational/02-llm-say-one-thing.py b/examples/foundational/02-llm-say-one-thing.py index 8cce7a017..891628415 100644 --- a/examples/foundational/02-llm-say-one-thing.py +++ b/examples/foundational/02-llm-say-one-thing.py @@ -57,7 +57,11 @@ async def main(): @transport.event_handler("on_first_participant_joined") async def on_first_participant_joined(transport, participant): - await task.queue_frames([LLMMessagesFrame(messages), EndFrame()]) + await task.queue_frame(LLMMessagesFrame(messages)) + + @transport.event_handler("on_participant_left") + async def on_participant_left(transport, participant, reason): + await task.queue_frame(EndFrame()) await runner.run(task) diff --git a/examples/foundational/03-still-frame.py b/examples/foundational/03-still-frame.py index 46e333ba4..688146cb1 100644 --- a/examples/foundational/03-still-frame.py +++ b/examples/foundational/03-still-frame.py @@ -9,7 +9,7 @@ import aiohttp import os import sys -from pipecat.frames.frames import TextFrame +from pipecat.frames.frames import EndFrame, TextFrame from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner from pipecat.pipeline.task import PipelineTask @@ -51,11 +51,11 @@ async def main(): @transport.event_handler("on_first_participant_joined") async def on_first_participant_joined(transport, participant): - # Note that we do not put an EndFrame() item in the pipeline for this demo. - # This means that the bot will stay in the channel until it times out. - # An EndFrame() in the pipeline would cause the transport to shut - # down. - await task.queue_frames([TextFrame("a cat in the style of picasso")]) + await task.queue_frame(TextFrame("a cat in the style of picasso")) + + @transport.event_handler("on_participant_left") + async def on_participant_left(transport, participant, reason): + await task.queue_frame(EndFrame()) await runner.run(task) diff --git a/examples/foundational/06a-image-sync.py b/examples/foundational/06a-image-sync.py index 500fea3a5..b63c42674 100644 --- a/examples/foundational/06a-image-sync.py +++ b/examples/foundational/06a-image-sync.py @@ -129,7 +129,7 @@ async def main(): @transport.event_handler("on_first_participant_joined") async def on_first_participant_joined(transport, participant): - participant_name = participant["info"]["userName"] or "" + participant_name = participant.get("info", {}).get("userName", "") transport.capture_participant_transcription(participant["id"]) await task.queue_frames([TextFrame(f"Hi there {participant_name}!")]) From 8c006c24a3276d4d471b214901a0492f94254e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Fri, 18 Oct 2024 11:16:40 -0700 Subject: [PATCH 2/2] README: update example --- README.md | 61 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 1d8b5c431..32404e3f1 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,7 @@ Your project may or may not need these, so they're made available as optional re Here is a very basic Pipecat bot that greets a user when they join a real-time session. We'll use [Daily](https://daily.co) for real-time media transport, and [Cartesia](https://cartesia.ai/) for text-to-speech. ```python -#app.py - import asyncio -import aiohttp from pipecat.frames.frames import EndFrame, TextFrame from pipecat.pipeline.pipeline import Pipeline @@ -64,39 +61,43 @@ from pipecat.services.cartesia import CartesiaTTSService from pipecat.transports.services.daily import DailyParams, DailyTransport async def main(): - async with aiohttp.ClientSession() as session: - # Use Daily as a real-time media transport (WebRTC) - transport = DailyTransport( - room_url=..., - token=..., - bot_name="Bot Name", - params=DailyParams(audio_out_enabled=True)) + # Use Daily as a real-time media transport (WebRTC) + transport = DailyTransport( + room_url=..., + token=..., + bot_name="Bot Name", + params=DailyParams(audio_out_enabled=True)) - # Use Cartesia for Text-to-Speech - tts = CartesiaTTSService( - api_key=..., - voice_id=... - ) + # Use Cartesia for Text-to-Speech + tts = CartesiaTTSService( + api_key=..., + voice_id=... + ) - # Simple pipeline that will process text to speech and output the result - pipeline = Pipeline([tts, transport.output()]) + # Simple pipeline that will process text to speech and output the result + pipeline = Pipeline([tts, transport.output()]) - # Create Pipecat processor that can run one or more pipelines tasks - runner = PipelineRunner() + # Create Pipecat processor that can run one or more pipelines tasks + runner = PipelineRunner() - # Assign the task callable to run the pipeline - task = PipelineTask(pipeline) + # Assign the task callable to run the pipeline + task = PipelineTask(pipeline) - # Register an event handler to play audio when a - # participant joins the transport WebRTC session - @transport.event_handler("on_participant_joined") - async def on_new_participant_joined(transport, participant): - participant_name = participant["info"]["userName"] or '' - # Queue a TextFrame that will get spoken by the TTS service (Cartesia) - await task.queue_frames([TextFrame(f"Hello there, {participant_name}!"), EndFrame()]) + # Register an event handler to play audio when a + # participant joins the transport WebRTC session + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + participant_name = participant.get("info", {}).get("userName", "") + # Queue a TextFrame that will get spoken by the TTS service (Cartesia) + await task.queue_frame(TextFrame(f"Hello there, {participant_name}!")) - # Run the pipeline task - await runner.run(task) + # Register an event handler to exit the application when the user leaves. + @transport.event_handler("on_participant_left") + async def on_participant_left(transport, participant, reason): + await task.queue_frame(EndFrame()) + + # Run the pipeline task + await runner.run(task) if __name__ == "__main__": asyncio.run(main())