From ea59695551894ff2ed4821ef5438b2a77f0caea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6kmen=20G=C3=B6rgen?= Date: Mon, 2 Mar 2026 10:55:25 +0100 Subject: [PATCH] don't use memoryview for concurrency safety. Snapshot the blocks into immutable bytes and trim the buffer BEFORE any await, so no memoryview is held across async yield points. Without this, a concurrent filter() or stop() call could try to extend() or clear() the bytearray while a memoryview still exports it, raising "Existing exports of data: object cannot be re-sized". --- src/pipecat/audio/filters/aic_filter.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pipecat/audio/filters/aic_filter.py b/src/pipecat/audio/filters/aic_filter.py index 723b3da8f..f0675577e 100644 --- a/src/pipecat/audio/filters/aic_filter.py +++ b/src/pipecat/audio/filters/aic_filter.py @@ -458,13 +458,16 @@ class AICFilter(BaseAudioFilter): if num_blocks == 0: return b"" - filtered_chunks: List[bytes] = [] - mv = memoryview(self._audio_buffer) block_size = self._frames_per_block * self._bytes_per_sample + total_size = num_blocks * block_size + blocks_data = bytes(self._audio_buffer[:total_size]) + self._audio_buffer = self._audio_buffer[total_size:] + + filtered_chunks: List[bytes] = [] for i in range(num_blocks): start = i * block_size - block_i16 = np.frombuffer(mv[start : start + block_size], dtype=self._dtype) + block_i16 = np.frombuffer(blocks_data[start : start + block_size], dtype=self._dtype) # Reuse input buffer, in-place divide np.copyto(self._in_f32[0], block_i16) @@ -479,5 +482,4 @@ class AICFilter(BaseAudioFilter): filtered_chunks.append(self._out_i16.tobytes()) - self._audio_buffer = self._audio_buffer[num_blocks * block_size :] return b"".join(filtered_chunks)