This commit is contained in:
freddyaboulton
2024-10-29 11:24:37 -04:00
parent b9cd3a4703
commit d48ae3a825
5 changed files with 11 additions and 11 deletions

View File

@@ -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.

View File

@@ -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:

View File

@@ -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:

View File

@@ -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:

View File

@@ -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"