Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions livekit-rtc/livekit/rtc/audio_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class AudioFrame:
"""
A class that represents a frame of audio data with specific properties such as sample rate,
number of channels, and samples per channel.

The format of the audio data is 16-bit signed integers (int16) interleaved by channel.
"""

def __init__(
Expand Down
10 changes: 8 additions & 2 deletions livekit-rtc/livekit/rtc/audio_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def __init__(
self._last_capture = 0.0
self._q_size = 0.0
self._join_handle: asyncio.TimerHandle | None = None
self._join_fut: asyncio.Future[None] = self._loop.create_future()
self._join_fut: asyncio.Future[None] | None = None

@property
def sample_rate(self) -> int:
Expand Down Expand Up @@ -118,6 +118,9 @@ async def capture_frame(self, frame: AudioFrame) -> None:
Exception: If there is an error during frame capture.
"""

if frame.samples_per_channel == 0:
return

now = time.monotonic()
elapsed = 0.0 if self._last_capture == 0.0 else now - self._last_capture
self._q_size += frame.samples_per_channel / self.sample_rate - elapsed
Expand All @@ -126,7 +129,7 @@ async def capture_frame(self, frame: AudioFrame) -> None:
if self._join_handle:
self._join_handle.cancel()

if self._join_fut.done():
if self._join_fut is None:
self._join_fut = self._loop.create_future()

self._join_handle = self._loop.call_later(self._q_size, self._release_waiter)
Expand Down Expand Up @@ -163,8 +166,11 @@ async def wait_for_playout(self) -> None:
await asyncio.shield(self._join_fut)

def _release_waiter(self) -> None:
assert self._join_fut is not None

if not self._join_fut.done():
self._join_fut.set_result(None)

self._last_capture = 0.0
self._q_size = 0.0
self._join_fut = None