transport: allow requesting a user frame

This commit is contained in:
Aleix Conchillo Flaqué
2024-04-09 22:16:05 -07:00
parent b117a185e3
commit a5eba0106b
2 changed files with 35 additions and 13 deletions

View File

@@ -169,8 +169,12 @@ class DailyTransport(ThreadedTransport, EventHandler):
if self._mic_enabled: if self._mic_enabled:
self.mic.write_frames(frame) self.mic.write_frames(frame)
def send_app_message(self, message: Any, participantId: str | None): def request_participant_image(self, participant_id: str):
self.client.send_app_message(message, participantId) if participant_id in self._video_renderers:
self._video_renderers[participant_id]["render_next_frame"] = True
def send_app_message(self, message: Any, participant_id: str | None):
self.client.send_app_message(message, participant_id)
def read_audio_frames(self, desired_frame_count): def read_audio_frames(self, desired_frame_count):
bytes = b"" bytes = b""
@@ -302,6 +306,7 @@ class DailyTransport(ThreadedTransport, EventHandler):
self._video_renderers[participant_id] = { self._video_renderers[participant_id] = {
"framerate": framerate, "framerate": framerate,
"timestamp": 0, "timestamp": 0,
"render_next_frame": False,
} }
self.client.set_video_renderer( self.client.set_video_renderer(
participant_id, participant_id,
@@ -310,17 +315,28 @@ class DailyTransport(ThreadedTransport, EventHandler):
color_format=color_format) color_format=color_format)
def on_participant_video_frame(self, participant_id, video_frame): def on_participant_video_frame(self, participant_id, video_frame):
if not self._loop:
return
render_frame = False
curr_time = time.time() curr_time = time.time()
prev_time = self._video_renderers[participant_id]["timestamp"] framerate = self._video_renderers[participant_id]["framerate"]
diff_time = curr_time - prev_time
period = 1 / self._video_renderers[participant_id]["framerate"] if framerate > 0:
if diff_time > period and self._loop: prev_time = self._video_renderers[participant_id]["timestamp"]
self._video_renderers[participant_id]["timestamp"] = curr_time next_time = prev_time + 1 / framerate
render_frame = curr_time > next_time
elif self._video_renderers[participant_id]["render_next_frame"]:
self._video_renderers[participant_id]["render_next_frame"] = False
render_frame = True
if render_frame:
frame = UserImageFrame(participant_id, video_frame.buffer, frame = UserImageFrame(participant_id, video_frame.buffer,
(video_frame.width, video_frame.height)) (video_frame.width, video_frame.height))
asyncio.run_coroutine_threadsafe( asyncio.run_coroutine_threadsafe(self.receive_queue.put(frame), self._loop)
self.receive_queue.put(frame), self._loop
) self._video_renderers[participant_id]["timestamp"] = curr_time
def on_error(self, error): def on_error(self, error):
self._logger.error(f"on_error: {error}") self._logger.error(f"on_error: {error}")

View File

@@ -20,6 +20,7 @@ from dailyai.pipeline.frames import (
SpriteFrame, SpriteFrame,
StartFrame, StartFrame,
TextFrame, TextFrame,
UserImageRequestFrame,
UserStartedSpeakingFrame, UserStartedSpeakingFrame,
UserStoppedSpeakingFrame, UserStoppedSpeakingFrame,
) )
@@ -382,7 +383,11 @@ class ThreadedTransport(AbstractTransport):
def _set_images(self, images: list[bytes], start_frame=0): def _set_images(self, images: list[bytes], start_frame=0):
self._images = itertools.cycle(images) self._images = itertools.cycle(images)
def send_app_message(self, message: Any, participantId: str | None): def request_participant_image(self, participant_id: str):
""" Child classes should override this to force an image from a user. """
pass
def send_app_message(self, message: Any, participant_id: str | None):
""" Child classes should override this to send a custom message to the room. """ """ Child classes should override this to send a custom message to the room. """
pass pass
@@ -458,9 +463,10 @@ class ThreadedTransport(AbstractTransport):
self._set_image(frame.image) self._set_image(frame.image)
elif isinstance(frame, SpriteFrame): elif isinstance(frame, SpriteFrame):
self._set_images(frame.images) self._set_images(frame.images)
elif isinstance(frame, UserImageRequestFrame):
self.request_participant_image(frame.user_id)
elif isinstance(frame, SendAppMessageFrame): elif isinstance(frame, SendAppMessageFrame):
self.send_app_message( self.send_app_message(frame.message, frame.participant_id)
frame.message, frame.participantId)
elif len(b): elif len(b):
self.write_frame_to_mic(bytes(b)) self.write_frame_to_mic(bytes(b))
b = bytearray() b = bytearray()