From 0dd413ee90d8998932f26f4cdf898b0ca0ed3737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Mon, 21 Oct 2024 17:06:16 -0700 Subject: [PATCH] audio(filters): add noisereduce filter --- CHANGELOG.md | 2 + pyproject.toml | 1 + .../audio/filters/noisereduce_filter.py | 49 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 src/pipecat/audio/filters/noisereduce_filter.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d9d90df3..01a0d3fa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added audio filter `NoisereduceFilter`. + - Introduce input transport audio filters (`BaseAudioFilter`). Audio filters can be used to remove background noises before audio is sent to VAD. diff --git a/pyproject.toml b/pyproject.toml index 115822cbf..81c4113e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,7 @@ livekit = [ "livekit~=0.17.5", "livekit-api~=0.7.1", "tenacity~=8.5.0" ] lmnt = [ "lmnt~=1.1.4" ] local = [ "pyaudio~=0.2.14" ] moondream = [ "einops~=0.8.0", "timm~=1.0.8", "transformers~=4.44.0" ] +noisereduce = [ "noisereduce~=3.0.3" ] openai = [ "openai~=1.50.2", "websockets~=13.1", "python-deepcompare~=1.0.1" ] openpipe = [ "openpipe~=4.24.0" ] playht = [ "pyht~=0.1.4", "websockets~=13.1" ] diff --git a/src/pipecat/audio/filters/noisereduce_filter.py b/src/pipecat/audio/filters/noisereduce_filter.py new file mode 100644 index 000000000..9e4a577d2 --- /dev/null +++ b/src/pipecat/audio/filters/noisereduce_filter.py @@ -0,0 +1,49 @@ +# +# Copyright (c) 2024, Daily +# +# SPDX-License-Identifier: BSD 2-Clause License +# + +import numpy as np + +from pipecat.audio.filters.base_audio_filter import BaseAudioFilter + +from loguru import logger + +from pipecat.frames.frames import FilterControlFrame + +try: + import noisereduce as nr +except ModuleNotFoundError as e: + logger.error(f"Exception: {e}") + logger.error( + "In order to use the noisereduce filter, you need to `pip install pipecat-ai[noisereduce]`." + ) + raise Exception(f"Missing module: {e}") + + +class NoisereduceFilter(BaseAudioFilter): + def __init__(self) -> None: + self._sample_rate = 0 + + async def start(self, sample_rate: int): + self._sample_rate = sample_rate + + async def stop(self): + pass + + async def process_frame(self, frame: FilterControlFrame): + pass + + async def filter(self, audio: bytes) -> bytes: + data = np.frombuffer(audio, dtype=np.int16) + + # Add a small epsilon to avoid division by zero. + epsilon = 1e-10 + data = data.astype(np.float32) + epsilon + + # Noise reduction + reduced_noise = nr.reduce_noise(y=data, sr=self._sample_rate) + audio = np.clip(reduced_noise, -32768, 32767).astype(np.int16).tobytes() + + return audio