From 5a682f8c1ff2cfa9c98f2b9f13a7e983609a12f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Wed, 18 Jun 2025 19:00:14 -0700 Subject: [PATCH] AudioBufferProcessor: record with lowest sample rate Fixes #1653 --- CHANGELOG.md | 16 ++++++++++------ .../processors/audio/audio_buffer_processor.py | 11 ++++++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4747fc03..cec82b73e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,13 +37,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgraded `daily-python` to 0.19.3. +### Deprecated + +- `AudioBufferProcessor` parameter `user_continuos_stream` is deprecated. + ### Fixed +- Fixed an `AudioBufferProcessor` issue that was causing crackling on the audio + stream with lower sample rate (due to upsampling the other stream). We now + record with the lowest sample rate to avoid upsampling. + - Fixed an issue that would cause multiple `PipelineTask.on_idle_timeout` events to be triggered repeatedly. -- Fixed an issue that was causing user and bot speech to not be synchronized - during recordings. +- Fixed an `AudioBufferProcessor` issue that was causing user and bot speech to + not be synchronized during recordings. - Fixed an issue where voice settings weren't applied to ElevenLabsTTSService. @@ -55,10 +63,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed an issue where `GoogleLLMService`'s TTFB value was incorrect. -### Deprecated - -- `AudioBufferProcessor` parameter `user_continuos_stream` is deprecated. - ### Other - Rename `14e-function-calling-gemini.py` to `14e-function-calling-google.py`. diff --git a/src/pipecat/processors/audio/audio_buffer_processor.py b/src/pipecat/processors/audio/audio_buffer_processor.py index 13d5a84bc..201a2d1bd 100644 --- a/src/pipecat/processors/audio/audio_buffer_processor.py +++ b/src/pipecat/processors/audio/audio_buffer_processor.py @@ -7,6 +7,8 @@ import time from typing import Optional +from loguru import logger + from pipecat.audio.utils import create_default_resampler, interleave_stereo_audio, mix_audio from pipecat.frames.frames import ( AudioRawFrame, @@ -181,7 +183,14 @@ class AudioBufferProcessor(FrameProcessor): await self.push_frame(frame, direction) def _update_sample_rate(self, frame: StartFrame): - self._sample_rate = self._init_sample_rate or frame.audio_out_sample_rate + # Record to the minimum sample rate to avoid possible downsampling + # artifacts. + min_sample_rate = min(frame.audio_in_sample_rate, frame.audio_out_sample_rate) + if frame.audio_in_sample_rate != frame.audio_out_sample_rate: + logger.debug( + f"{self} Input and output sample rates don't match, recording with smaller sample rate: {min_sample_rate} (this might get fixed in the future)" + ) + self._sample_rate = self._init_sample_rate or min_sample_rate self._audio_buffer_size_1s = self._sample_rate * 2 async def _process_recording(self, frame: Frame):