Daily Pipecat
Krisp SDK integration guide published at https://docs.pipecat.ai/guides/features/krisp is not compatible with the latest Krisp Server SDK and models.
Integrating Krisp Server SDK with Pipecat
- Download the latest Python SDK from the SDK Portal..
- Install Python wheel file into your venv of the Pipecat installation.
pip install <path to the Krisp wheel file>
- When following Daily guide https://docs.pipecat.ai/server/utilities/audio/krisp-filter on Krisp installation replace the
KrispFilter
with theNoiseFilterFromKrisp
.
transport = DailyTransport(
room_url,
token,
"Respond bot",
DailyParams(
audio_in_filter=KrispFilter(), # Enable Krisp noise reduction
audio_in_enabled=True,
audio_out_enabled=True,
vad_analyzer=SileroVADAnalyzer(),
),
)
Check the NoiseFilterFromKrisp
in the code snippet.
import os
import numpy as np
from pipecat.audio.filters.base_audio_filter import BaseAudioFilter
from pipecat.frames.frames import FilterControlFrame, FilterEnableFrame
import krisp_audio
class NoiseFilterFromKrisp(BaseAudioFilter):
krisp_audio.globalInit("")
SDK_VERSION = krisp_audio.getVersion()
print(f"Krisp Audio Python SDK Version: {SDK_VERSION.major}."
f"{SDK_VERSION.minor}.{SDK_VERSION.patch}")
SAMPLE_RATES = {
8000: krisp_audio.SamplingRate.Sr8000Hz,
16000: krisp_audio.SamplingRate.Sr16000Hz,
24000: krisp_audio.SamplingRate.Sr24000Hz,
32000: krisp_audio.SamplingRate.Sr32000Hz,
44100: krisp_audio.SamplingRate.Sr44100Hz,
48000: krisp_audio.SamplingRate.Sr48000Hz
}
def __init__(self, model_path: str):
super().__init__()
if not model_path:
raise Exception("Model path is not set")
if not model_path.endswith(".kef"):
raise Exception("Model is expected with .kef extension")
if not os.path.isfile(model_path):
raise FileNotFoundError(f"Model file not found: {model_path}")
self._model_path = model_path
self._filtering = True
self._session = None
self._samples_per_frame = None
self._noise_suppression_level = 100
def _int_to_sample_rate(self, sample_rate):
if sample_rate not in self.SAMPLE_RATES:
raise ValueError("Unsupported sample rate")
return self.SAMPLE_RATES[sample_rate]
async def start(self, sample_rate: int):
model_info = krisp_audio.ModelInfo()
model_info.path = self._model_path
nc_cfg = krisp_audio.NcSessionConfig()
nc_cfg.inputSampleRate = self._int_to_sample_rate(sample_rate)
nc_cfg.inputFrameDuration = krisp_audio.FrameDuration.Fd10ms
nc_cfg.outputSampleRate = nc_cfg.inputSampleRate
nc_cfg.modelInfo = model_info
self._samples_per_frame = int((sample_rate * 10) / 1000)
self._session = krisp_audio.NcInt16.create(nc_cfg)
async def stop(self):
self._session = None
async def process_frame(self, frame: FilterControlFrame):
if isinstance(frame, FilterEnableFrame):
self._filtering = frame.enable
async def filter(self, audio: bytes) -> bytes:
if not self._filtering:
return audio
samples = np.frombuffer(audio, dtype=np.int16)
if samples.size % self._samples_per_frame:
raise ValueError(f"Audio length {samples.size} samples is not a multiple of {self._samples_per_frame}")
frames = samples.reshape(-1, self._samples_per_frame)
processed_samples = np.empty_like(samples)
for i, frame in enumerate(frames):
cleaned_frame = self._session.process(frame, self._noise_suppression_level)
processed_samples[i*self._samples_per_frame:(i+1)*self._samples_per_frame] = cleaned_frame
return processed_samples.tobytes()
The NoiseFilterFromKrisp
does not use KRISP_SDK_PATH
and KRISP_MODEL_PATH
environment variables. The class constructor has the model_path
mandatory argument .
Updated 4 days ago