Skip to content

Commit fe805f4

Browse files
committed
Merge branch 'lukas/frame-processor' into lukas/token-refresh
2 parents 97c018b + cb8745c commit fe805f4

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

livekit-rtc/livekit/rtc/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
ByteStreamWriter,
109109
ByteStreamReader,
110110
)
111+
from .frame_processor import FrameProcessor
111112

112113
__all__ = [
113114
"ConnectionQuality",
@@ -184,6 +185,7 @@
184185
"ByteStreamReader",
185186
"ByteStreamWriter",
186187
"AudioProcessingModule",
188+
"FrameProcessor",
187189
"__version__",
188190
]
189191

livekit-rtc/livekit/rtc/audio_stream.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from .audio_frame import AudioFrame
2828
from .participant import Participant
2929
from .track import Track
30+
from .frame_processor import FrameProcessor
3031

3132

3233
@dataclass
@@ -62,7 +63,7 @@ def __init__(
6263
sample_rate: int = 48000,
6364
num_channels: int = 1,
6465
frame_size_ms: int | None = None,
65-
noise_cancellation: Optional[NoiseCancellationOptions] = None,
66+
noise_cancellation: Optional[NoiseCancellationOptions | FrameProcessor[AudioFrame]] = None,
6667
**kwargs,
6768
) -> None:
6869
"""Initialize an `AudioStream` instance.
@@ -76,8 +77,8 @@ def __init__(
7677
sample_rate (int, optional): The sample rate for the audio stream in Hz.
7778
Defaults to 48000.
7879
num_channels (int, optional): The number of audio channels. Defaults to 1.
79-
noise_cancellation (Optional[NoiseCancellationOptions], optional):
80-
If noise cancellation is used, pass a `NoiseCancellationOptions` instance
80+
noise_cancellation (Optional[NoiseCancellationOptions | FrameProcessor[AudioFrame]], optional):
81+
If noise cancellation is used, pass a `NoiseCancellationOptions` or `FrameProcessor[AudioFrame]` instance
8182
created by the noise cancellation module.
8283
8384
Example:
@@ -105,9 +106,12 @@ def __init__(
105106

106107
self._audio_filter_module = None
107108
self._audio_filter_options = None
108-
if noise_cancellation is not None:
109+
if isinstance(noise_cancellation, NoiseCancellationOptions):
109110
self._audio_filter_module = noise_cancellation.module_id
110111
self._audio_filter_options = noise_cancellation.options
112+
elif isinstance(noise_cancellation, FrameProcessor):
113+
self._processor = noise_cancellation
114+
111115
self._task = self._loop.create_task(self._run())
112116
self._task.add_done_callback(task_done_logger)
113117

@@ -268,6 +272,8 @@ async def _run(self):
268272
if audio_event.HasField("frame_received"):
269273
owned_buffer_info = audio_event.frame_received.frame
270274
frame = AudioFrame._from_owned_info(owned_buffer_info)
275+
if self._processor is not None:
276+
frame = self._processor._process(frame)
271277
event = AudioFrameEvent(frame)
272278
self._queue.put(event)
273279
elif audio_event.HasField("eos"):
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from abc import ABC, abstractmethod
2+
from typing import Generic, TypeVar, Union
3+
from .audio_frame import AudioFrame
4+
from .video_frame import VideoFrame
5+
6+
7+
T = TypeVar("T", bound=Union[AudioFrame, VideoFrame])
8+
9+
10+
class FrameProcessor(Generic[T], ABC):
11+
@property
12+
@abstractmethod
13+
def is_enabled(self) -> bool: ...
14+
15+
@abstractmethod
16+
def set_enabled(self, enable: bool): ...
17+
18+
@abstractmethod
19+
def _update_stream_info(
20+
self,
21+
*,
22+
room_name: str,
23+
participant_identity: str,
24+
publication_sid: str,
25+
): ...
26+
27+
@abstractmethod
28+
def _update_credentials(self, *, token: str, url: str): ...
29+
30+
@abstractmethod
31+
def _process(self, frame: T) -> T: ...
32+
33+
@abstractmethod
34+
def _close(self): ...

0 commit comments

Comments
 (0)