From d48ae3a82521b08b5c308d50fdf9b2fb12c073bc Mon Sep 17 00:00:00 2001 From: freddyaboulton Date: Tue, 29 Oct 2024 11:24:37 -0400 Subject: [PATCH] code --- README.md | 5 ++++- backend/gradio_webrtc/utils.py | 2 +- backend/gradio_webrtc/webrtc.py | 10 ++-------- demo/echo_conversation.py | 3 +++ pyproject.toml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 078db92..f13f121 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,9 @@ class EchoHandler(StreamHandler): def emit(self) -> None: return self.queue.get() + + def copy(self) -> StreamHandler: + return EchoHandler() with gr.Blocks() as demo: @@ -178,7 +181,7 @@ if __name__ == "__main__": ``` * Instead of passing a function to the `stream` event's `fn` parameter, pass a `StreamHandler` implementation. The `StreamHandler` above simply echoes the audio back to the client. -* The `StreamHandler` class has two methods: `receive` and `emit`. The `receive` method is called when a new frame is received from the client, and the `emit` method returns the next frame to send to the client. +* The `StreamHandler` class has two methods: `receive` and `emit` and `copy`. The `receive` method is called when a new frame is received from the client, and the `emit` method returns the next frame to send to the client. The `copy` method is called at the beginning of the stream to ensure each user has a unique stream handler. * An audio frame is represented as a tuple of (frame_rate, audio_samples) where `audio_samples` is a numpy array of shape (num_channels, num_samples). * You can also specify the audio layout ("mono" or "stereo") in the emit method by retuning it as the third element of the tuple. If not specified, the default is "mono". * The `time_limit` parameter is the maximum time in seconds the conversation will run. If the time limit is reached, the audio stream will stop. diff --git a/backend/gradio_webrtc/utils.py b/backend/gradio_webrtc/utils.py index 38f62af..6e27fe6 100644 --- a/backend/gradio_webrtc/utils.py +++ b/backend/gradio_webrtc/utils.py @@ -108,7 +108,7 @@ async def player_worker_decode( except (TimeoutError, asyncio.TimeoutError): logger.warning( - "Timeout in frame processing cycle after %s seconds - resetting", 5 + "Timeout in frame processing cycle after %s seconds - resetting", 60 ) continue except Exception as e: diff --git a/backend/gradio_webrtc/webrtc.py b/backend/gradio_webrtc/webrtc.py index 1ac17ff..3989b00 100644 --- a/backend/gradio_webrtc/webrtc.py +++ b/backend/gradio_webrtc/webrtc.py @@ -10,11 +10,9 @@ import time import traceback from abc import ABC, abstractmethod from collections.abc import Callable -from copy import deepcopy from typing import ( TYPE_CHECKING, Any, - Callable, Concatenate, Generator, Iterable, @@ -146,13 +144,9 @@ class StreamHandler(ABC): self.output_frame_size = output_frame_size self._resampler = None + @abstractmethod def copy(self) -> "StreamHandler": - try: - return deepcopy(self) - except Exception: - raise ValueError( - "Current StreamHandler implementation cannot be deepcopied. Implement the copy method." - ) + pass def resample(self, frame: AudioFrame) -> Generator[AudioFrame, None, None]: if self._resampler is None: diff --git a/demo/echo_conversation.py b/demo/echo_conversation.py index 1737ed5..7a8879d 100644 --- a/demo/echo_conversation.py +++ b/demo/echo_conversation.py @@ -35,6 +35,9 @@ class EchoHandler(StreamHandler): def emit(self) -> None: return self.queue.get() + + def copy(self) -> StreamHandler: + return EchoHandler() with gr.Blocks() as demo: diff --git a/pyproject.toml b/pyproject.toml index 5e12922..c318662 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "hatchling.build" [project] name = "gradio_webrtc" -version = "0.0.9" +version = "0.0.10" description = "Stream images in realtime with webrtc" readme = "README.md" license = "apache-2.0"