From 2814aaedd1fa69ad83206008a05ddb5282700953 Mon Sep 17 00:00:00 2001 From: ANDROIDHASSAN <84630851+ANDROIDHASSAN@users.noreply.github.com> Date: Thu, 12 Nov 2026 19:37:18 +0530 Subject: [PATCH] fix(rtc): return no frames from AudioResampler.flush() when nothing is buffered The FFI flush reply carries a non-zero output_ptr with size 0 when the resampler has no data left, so the ptr check never matched and flush() returned one 0-sample frame. Check the size instead, as the docstring promises an empty list. --- .changeset/resampler-flush-empty.md | 5 +++++ livekit-rtc/livekit/rtc/audio_resampler.py | 2 +- tests/rtc/test_resampler.py | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 .changeset/resampler-flush-empty.md diff --git a/.changeset/resampler-flush-empty.md b/.changeset/resampler-flush-empty.md new file mode 100644 index 000000000..3d2d57018 --- /dev/null +++ b/.changeset/resampler-flush-empty.md @@ -0,0 +1,5 @@ +--- +"livekit-rtc": patch +--- + +Return no frames from `AudioResampler.flush()` when nothing is buffered, instead of one empty frame. diff --git a/livekit-rtc/livekit/rtc/audio_resampler.py b/livekit-rtc/livekit/rtc/audio_resampler.py index 4d4c02c52..b9ef74635 100644 --- a/livekit-rtc/livekit/rtc/audio_resampler.py +++ b/livekit-rtc/livekit/rtc/audio_resampler.py @@ -142,7 +142,7 @@ def flush(self) -> list[AudioFrame]: resp = FfiClient.instance.request(req) - if not resp.flush_sox_resampler.output_ptr: + if not resp.flush_sox_resampler.size: return [] cdata = (ctypes.c_int8 * resp.flush_sox_resampler.size).from_address( diff --git a/tests/rtc/test_resampler.py b/tests/rtc/test_resampler.py index db05c4fd1..4261e73c0 100644 --- a/tests/rtc/test_resampler.py +++ b/tests/rtc/test_resampler.py @@ -65,3 +65,12 @@ def test_audio_resampler() -> None: wf_out.setsampwidth(sampwidth) wf_out.setframerate(8000) wf_out.writeframes(output_data) + + +def test_flush_with_nothing_buffered_returns_no_frames() -> None: + resampler = AudioResampler(48000, 16000) + assert resampler.flush() == [] + + resampler.push(AudioFrame(bytes(9600), 48000, 1, 4800)) + assert sum(f.samples_per_channel for f in resampler.flush()) > 0 # the buffered tail + assert resampler.flush() == []