Skip to content

AIC Voice Focus version update & concurrency safety issue on audio buffer.#3889

Merged
markbackman merged 5 commits intopipecat-ai:mainfrom
ai-coustics:goedev/aic-voice-focus-and-memoryview-fix
Mar 3, 2026
Merged

AIC Voice Focus version update & concurrency safety issue on audio buffer.#3889
markbackman merged 5 commits intopipecat-ai:mainfrom
ai-coustics:goedev/aic-voice-focus-and-memoryview-fix

Conversation

@gkmngrgn
Copy link
Copy Markdown
Contributor

@gkmngrgn gkmngrgn commented Mar 2, 2026

Summary

  • Fix BufferError: Existing exports of data: object cannot be re-sized that occurs in production when concurrent filter() or stop() calls interleave with an in-flight filter() holding a memoryview on the mutable _audio_buffer bytearray across await yield points.
  • The fix snapshots the needed audio blocks into immutable bytes and trims the buffer before any await, so no memoryview (or any reference to the mutable bytearray) is held across async yield points.
  • Add two regression tests that reproduce the exact concurrency scenarios: concurrent filter()/filter() interleaving and stop() during filter().

Problem

AICFilter.filter() created a memoryview on self._audio_buffer (a bytearray) and held it alive across await self._processor.process_async(...). In production with concurrent calls, another task could run filter() (calling _audio_buffer.extend()) or stop() (calling _audio_buffer.clear()) while the memoryview still exported the buffer, causing Python to raise:

    BufferError: Existing exports of data: object cannot be re-sized

It's not easy to reproduce locally because it requires concurrent async interleaving but wrote a test for simulate it.

Fix

Replace the memoryview on the mutable bytearray with a bytes snapshot taken before any await:

    blocks_data = bytes(self._audio_buffer[:total_size])
    self._audio_buffer = self._audio_buffer[total_size:]
    # all awaits below only reference the immutable blocks_data

The extra copy is negligible — typical block size is 320 bytes (10ms of 16kHz 16-bit audio).

gkmngrgn added 3 commits March 2, 2026 10:34
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".
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 2, 2026

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/pipecat/audio/filters/aic_filter.py 0.00% 6 Missing ⚠️
Files with missing lines Coverage Δ
src/pipecat/audio/filters/aic_filter.py 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@markbackman markbackman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you 🙇

@markbackman markbackman merged commit ca0ec16 into pipecat-ai:main Mar 3, 2026
10 checks passed
@gkmngrgn gkmngrgn deleted the goedev/aic-voice-focus-and-memoryview-fix branch March 6, 2026 12:51
markbackman pushed a commit to pipecat-ai/docs that referenced this pull request Mar 11, 2026
- Updated model ID examples to include Voice Focus 2.0 format
- Updated usage examples to use quail-vf-2.0-l-16khz model
- Added note about Voice Focus 2.0 support with aic-sdk 2.1.0+

Reflects changes from pipecat-ai/pipecat#3889
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants