From 989252bb52238c2f41ac1a4e2a48a8e59f3dd6bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Tue, 9 Apr 2024 14:56:41 -0700 Subject: [PATCH 1/3] daily: always check camera/mic/speaker enabled --- src/dailyai/transports/daily_transport.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/dailyai/transports/daily_transport.py b/src/dailyai/transports/daily_transport.py index d48f9d8ed..8eb23d23b 100644 --- a/src/dailyai/transports/daily_transport.py +++ b/src/dailyai/transports/daily_transport.py @@ -162,16 +162,20 @@ class DailyTransport(ThreadedTransport, EventHandler): return decorator def write_frame_to_camera(self, frame: bytes): - self.camera.write_frame(frame) + if self._camera_enabled: + self.camera.write_frame(frame) def write_frame_to_mic(self, frame: bytes): - self.mic.write_frames(frame) + if self._mic_enabled: + self.mic.write_frames(frame) def send_app_message(self, message: Any, participantId: str | None): self.client.send_app_message(message, participantId) def read_audio_frames(self, desired_frame_count): - bytes = self._speaker.read_frames(desired_frame_count) + bytes = b"" + if self._speaker_enabled or self._vad_enabled: + bytes = self._speaker.read_frames(desired_frame_count) return bytes def _prerun(self): From 0bf15fd6eb54e04a88eb358eb2ab6e06ab7392f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Tue, 9 Apr 2024 14:57:22 -0700 Subject: [PATCH 2/3] daily: only subscribe to participant video source --- src/dailyai/transports/daily_transport.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/dailyai/transports/daily_transport.py b/src/dailyai/transports/daily_transport.py index 8eb23d23b..3adbf57a2 100644 --- a/src/dailyai/transports/daily_transport.py +++ b/src/dailyai/transports/daily_transport.py @@ -244,9 +244,12 @@ class DailyTransport(ThreadedTransport, EventHandler): ) self._my_participant_id = self.client.participants()["local"]["id"] + # For performance reasons, never subscribe to video streams (unless a + # video renderer is registered). self.client.update_subscription_profiles({ "base": { - "camera": "subscribed" if self._video_rendering_enabled else "unsubscribed", + "camera": "unsubscribed", + "screenVideo": "unsubscribed" } }) @@ -285,6 +288,16 @@ class DailyTransport(ThreadedTransport, EventHandler): color_format="RGB") -> None: if not self._video_rendering_enabled: self._logger.warn("Video rendering is not enabled") + return + + # Only enable camera subscription on this participant + self.client.update_subscriptions(participant_settings={ + participant_id: { + "media": { + video_source: "subscribed" + } + } + }) self._video_renderers[participant_id] = { "framerate": framerate, From 9fcbb36997ca185ea1924208a2c59a12e1f40ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Tue, 9 Apr 2024 14:58:06 -0700 Subject: [PATCH 3/3] examples: add 14a-local-render-remote-participant --- examples/foundational/03a-image-local.py | 2 +- .../14-render-remote-participant.py | 7 +- .../14a-local-render-remote-participant.py | 72 +++++++++++++++++++ 3 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 examples/foundational/14a-local-render-remote-participant.py diff --git a/examples/foundational/03a-image-local.py b/examples/foundational/03a-image-local.py index 46f811471..b98d0dc76 100644 --- a/examples/foundational/03a-image-local.py +++ b/examples/foundational/03a-image-local.py @@ -5,7 +5,7 @@ import os import tkinter as tk -from dailyai.pipeline.frames import TextFrame, EndFrame +from dailyai.pipeline.frames import TextFrame from dailyai.pipeline.pipeline import Pipeline from dailyai.services.fal_ai_services import FalImageGenService from dailyai.transports.local_transport import LocalTransport diff --git a/examples/foundational/14-render-remote-participant.py b/examples/foundational/14-render-remote-participant.py index 1802bd037..88311f502 100644 --- a/examples/foundational/14-render-remote-participant.py +++ b/examples/foundational/14-render-remote-participant.py @@ -4,8 +4,6 @@ import logging from typing import AsyncGenerator -from PIL import Image - from dailyai.pipeline.aggregators import FrameProcessor from dailyai.pipeline.frames import ImageFrame, Frame, UserImageFrame @@ -25,14 +23,13 @@ logger.setLevel(logging.DEBUG) class UserImageProcessor(FrameProcessor): async def process_frame(self, frame: Frame) -> AsyncGenerator[Frame, None]: - print(frame) if isinstance(frame, UserImageFrame): yield ImageFrame(frame.image, frame.size) else: yield frame -async def main(room_url): +async def main(room_url: str, token): transport = DailyTransport( room_url, token, @@ -53,4 +50,4 @@ async def main(room_url): if __name__ == "__main__": (url, token) = configure() - asyncio.run(main(url)) + asyncio.run(main(url, token)) diff --git a/examples/foundational/14a-local-render-remote-participant.py b/examples/foundational/14a-local-render-remote-participant.py new file mode 100644 index 000000000..979b19f9d --- /dev/null +++ b/examples/foundational/14a-local-render-remote-participant.py @@ -0,0 +1,72 @@ +import asyncio +import io +import logging +import tkinter as tk + +from typing import AsyncGenerator + +from dailyai.pipeline.aggregators import FrameProcessor + +from dailyai.pipeline.frames import ImageFrame, Frame, UserImageFrame +from dailyai.pipeline.pipeline import Pipeline +from dailyai.transports.daily_transport import DailyTransport + +from dailyai.transports.local_transport import LocalTransport +from runner import configure + +from dotenv import load_dotenv +load_dotenv(override=True) + +logging.basicConfig(format=f"%(levelno)s %(asctime)s %(message)s") +logger = logging.getLogger("dailyai") +logger.setLevel(logging.DEBUG) + + +class UserImageProcessor(FrameProcessor): + + async def process_frame(self, frame: Frame) -> AsyncGenerator[Frame, None]: + if isinstance(frame, UserImageFrame): + yield ImageFrame(frame.image, frame.size) + else: + yield frame + + +async def main(room_url: str, token): + tk_root = tk.Tk() + tk_root.title("dailyai") + + local_transport = LocalTransport( + tk_root=tk_root, + camera_enabled=True, + camera_width=1280, + camera_height=720 + ) + + transport = DailyTransport( + room_url, + token, + "Render participant video", + video_rendering_enabled=True + ) + + @transport.event_handler("on_first_other_participant_joined") + async def on_first_other_participant_joined(transport, participant): + transport.render_participant_video(participant["id"]) + + async def run_tk(): + while not transport._stop_threads.is_set(): + tk_root.update() + tk_root.update_idletasks() + await asyncio.sleep(0.1) + + local_pipeline = Pipeline([UserImageProcessor()], source=transport.receive_queue) + + await asyncio.gather( + transport.run(), + local_transport.run(local_pipeline, override_pipeline_source_queue=False), + run_tk() + ) + +if __name__ == "__main__": + (url, token) = configure() + asyncio.run(main(url, token))