audio(filters): add noisereduce filter
This commit is contained in:
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Added audio filter `NoisereduceFilter`.
|
||||||
|
|
||||||
- Introduce input transport audio filters (`BaseAudioFilter`). Audio filters can
|
- Introduce input transport audio filters (`BaseAudioFilter`). Audio filters can
|
||||||
be used to remove background noises before audio is sent to VAD.
|
be used to remove background noises before audio is sent to VAD.
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ livekit = [ "livekit~=0.17.5", "livekit-api~=0.7.1", "tenacity~=8.5.0" ]
|
|||||||
lmnt = [ "lmnt~=1.1.4" ]
|
lmnt = [ "lmnt~=1.1.4" ]
|
||||||
local = [ "pyaudio~=0.2.14" ]
|
local = [ "pyaudio~=0.2.14" ]
|
||||||
moondream = [ "einops~=0.8.0", "timm~=1.0.8", "transformers~=4.44.0" ]
|
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" ]
|
openai = [ "openai~=1.50.2", "websockets~=13.1", "python-deepcompare~=1.0.1" ]
|
||||||
openpipe = [ "openpipe~=4.24.0" ]
|
openpipe = [ "openpipe~=4.24.0" ]
|
||||||
playht = [ "pyht~=0.1.4", "websockets~=13.1" ]
|
playht = [ "pyht~=0.1.4", "websockets~=13.1" ]
|
||||||
|
|||||||
49
src/pipecat/audio/filters/noisereduce_filter.py
Normal file
49
src/pipecat/audio/filters/noisereduce_filter.py
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user