Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 79 additions & 60 deletions livekit-plugins/livekit-plugins-krisp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,46 @@ Real-time noise reduction for LiveKit voice agents using [Krisp's VIVA SDK](http
## Installation

```bash
# Install the plugin
pip install livekit-plugins-krisp

# Install krisp-audio SDK separately (required for actual usage)
```

**Note:** The `krisp-audio` package is a proprietary SDK not available on public PyPI.
It must be obtained and installed separately from Krisp (https://krisp.ai/developers/).

## Prerequisites

### Required for All Features

1. **Krisp Audio SDK**: `pip install krisp-audio`
2. **License Key**: Obtain a license key from Krisp and set it as an environment variable:
```bash
export KRISP_VIVA_SDK_LICENSE_KEY=your-license-key-here
```

### For Noise Reduction
That's it. The default backend is bundled with the plugin and authenticates through
LiveKit Cloud using the room's credentials — no separate SDK download, license key,
or model file is required.

1. **Noise Reduction Model**: Obtain a noise reduction or voice isolation `.kef` model file from Krisp
2. **Set environment variable**:
```bash
export KRISP_VIVA_FILTER_MODEL_PATH=/path/to/noise_model.kef
```
> Using your own [Krisp license](#alternative-krisp-license-auth) instead?
> That path has additional prerequisites — see below.

## Quick Start

### Human-to-Bot Noise Cancellation / Voice Isolation (Recommended)

For cleaning up user audio before STT/VAD processing using the FrameProcessor approach:
By default, `KrispVivaFilterFrameProcessor` uses **LiveKit Cloud** authentication: the
bundled backend ships the noise-reduction model and authenticates against LiveKit Cloud
using the room JWT the agent framework hands to the FrameProcessor automatically.

```python
from livekit.agents import AgentSession, Agent, JobContext, room_io
from livekit.plugins import krisp, silero, openai

@server.rtc_session()
async def entrypoint(ctx: JobContext):
# Create Krisp FrameProcessor
# Default: LiveKit Cloud auth + bundled model. No keys or model files.
processor = krisp.KrispVivaFilterFrameProcessor(
noise_suppression_level=100, # 0-100
frame_duration_ms=10,
sample_rate=16000,
)

session = AgentSession(
vad=silero.VAD.load(),
stt=openai.STT(),
llm=openai.LLM(model="gpt-4o-mini"),
tts=openai.TTS(),
)
# Start session with RoomIO and pass FrameProcessor directly

# Start session with RoomIO and pass the FrameProcessor directly
await session.start(
agent=MyAgent(),
room=ctx.room,
room_options=room_io.RoomOptions(
audio_input=room_io.AudioInputOptions(
sample_rate=16000,
frame_size_ms=10, # Must match Krisp frame_duration_ms
noise_cancellation=processor, # Pass FrameProcessor directly
),
),
Expand All @@ -78,70 +57,110 @@ async def entrypoint(ctx: JobContext):

**Audio Pipeline:** `Room → RoomIO (with KrispVivaFilterFrameProcessor) → VAD → STT → LLM`


## Configuration

### KrispVivaFilterFrameProcessor Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `model_path` | str | env var | Path to noise reduction `.kef` model |
| `auth_provider` | `LiveKitCloudAuthProvider \| KrispLicenseAuthProvider` | `LiveKitCloudAuthProvider` | Authentication backend. Defaults to LiveKit Cloud. See [the alternative](#alternative-krisp-license-auth). |
| `noise_suppression_level` | int | 100 | Noise reduction intensity (0-100) |
| `frame_duration_ms` | int | 10 | Frame size: 10, 15, 20, 30, or 32ms |
| `sample_rate` | int | None | Optional: pre-initialize with sample rate |
| `frame_duration_ms` | int | None | **Deprecated.** Input frames of any size are now buffered automatically. |
| `sample_rate` | int | None | **Deprecated.** The processor now adapts to the input sample rate automatically. |
| `model_path` | str | None | **Deprecated.** Use `auth_provider=krisp.auth.krisp_license(model_path=...)`. License-mode only. |

### Supported Sample Rates

8000, 16000, 24000, 32000, 44100, 48000 Hz

## Alternative: Krisp License Auth

## Important Notes
> **Most users should use the default LiveKit Cloud path above.** This alternative is for
> running the public Krisp SDK directly with your own Krisp license — for example, when
> using Livekit OSS server.

This path uses the public `krisp_audio` wheel together with a Krisp license key and a
`.kef` model file that you obtain from Krisp.

### Frame Size Requirements
### Prerequisites

⚠️ **Frames must match the configured duration exactly**
1. **Krisp Audio SDK** — proprietary, not on public PyPI. Obtain and install it
separately from [Krisp](https://krisp.ai/developers/):
```bash
pip install krisp-audio
```
2. **License key**:
```bash
export KRISP_VIVA_SDK_LICENSE_KEY=your-license-key-here
```
3. **Noise-reduction model** — a `.kef` model file from Krisp:
```bash
export KRISP_VIVA_FILTER_MODEL_PATH=/path/to/noise_model.kef
```

- 10ms @ 16kHz = 160 samples
- 20ms @ 16kHz = 320 samples
- 20ms @ 32kHz = 640 samples
### Usage

The filter validates frame sizes and raises `ValueError` if incorrect.
Select the license backend by passing `auth_provider`:

### Resource Management
```python
from livekit.plugins import krisp

processor = krisp.KrispVivaFilterFrameProcessor(
auth_provider=krisp.auth.krisp_license(
license_key="...", # or KRISP_VIVA_SDK_LICENSE_KEY
model_path="/path/to/noise_model.kef", # or KRISP_VIVA_FILTER_MODEL_PATH
),
noise_suppression_level=100,
)
```

- Session created once (on first use or if `sample_rate` provided)
- Call `close()` when done to free resources
`license_key` and `model_path` fall back to the environment variables above when omitted.

### Shared SDK Management
## Important Notes

The plugin uses `KrispSDKManager` to manage the Krisp SDK instance:
### Resource Management

- **Singleton Pattern**: SDK initialized only once, shared across all components and sessions
- **Reference Counting**: Tracks active users (filters)
- **Automatic Cleanup**: SDK destroyed when last component releases its reference
- Call `close()` when done to free resources

## Troubleshooting

### "Krisp SDK initialization failed" or Licensing Errors
### `RuntimeError`: bundled backend missing
If the default (LiveKit Cloud) backend reports a missing wheel, the install is likely
broken. Reinstall the plugin:
```bash
pip install --force-reinstall livekit-plugins-krisp
```
Alternatively, fall back to the [Krisp license auth](#alternative-krisp-license-auth) path.

### "Krisp SDK initialization failed" or licensing errors *(license auth only)*
Make sure the license key is set:
```bash
export KRISP_VIVA_SDK_LICENSE_KEY=your-license-key-here
```

### "Model path must be provided"
### "Model path must be provided" *(license auth only)*
```bash
export KRISP_VIVA_FILTER_MODEL_PATH=/path/to/model.kef
```

### "Unsupported sample rate"
Supported: 8000, 16000, 24000, 32000, 44100, 48000 Hz

### Silent output
- Verify the model file is valid *(license auth only)*
- Test with known noisy audio

### "Frame size mismatch"
Ensure your audio frames match the configured `frame_duration_ms`.
## License

For 20ms @ 16kHz, each frame must have exactly 320 samples.
The source code in this package (`livekit-plugins-krisp`) is licensed under the
**Apache-2.0** license.

### Silent output
- Verify model file is valid
- Test with known noisy audio
The **default backend** is a separate, closed-source wheel (`livekit-plugins-krisp-internal`)
that is installed automatically as a dependency. It is **proprietary** and distributed under
the [LiveKit Terms of Service](https://livekit.io/legal/terms-of-service). That wheel bundles
the Krisp VIVA SDK along with its third-party open-source components, whose attribution
notices are shipped inside the wheel.

The **Krisp license alternative** (`KrispLicenseAuthProvider`) instead needs a manual install of the proprietary Krisp
Audio SDK together with your own Krisp license key and model file, governed by your agreement
with [Krisp](https://krisp.ai).
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@
The audio pipeline:
Room → RoomIO (with KrispVivaFilterFrameProcessor) → VAD → STT → LLM → TTS → Room

Authentication:
By default the plugin uses ``krisp.auth.livekit_cloud()`` — auth + metering
happen via the room's existing JWT, which the agent framework hands to the
FrameProcessor automatically. No Krisp env vars are required when running
against LiveKit Cloud. To use your own Krisp license + ``.kef`` model file
instead, see the commented ``auth_provider=`` block below.

Prerequisites:
1. Set KRISP_VIVA_FILTER_MODEL_PATH environment variable to your .kef model file
1. Standard agent env: LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET
2. Install required packages:
- livekit-agents (with PR #4145 support for FrameProcessor)
- livekit-plugins-krisp
Expand Down Expand Up @@ -77,13 +84,31 @@ async def entrypoint(ctx: JobContext):

logger.info("Starting agent session with RoomIO and Krisp noise cancellation")

# Create Krisp FrameProcessor for noise cancellation
# Create Krisp FrameProcessor for noise cancellation.
# Defaults to krisp.auth.livekit_cloud() — the framework pushes the room's
# JWT to the FrameProcessor via _on_credentials_updated and auto-refreshes
# it on token rotation. No manual credential plumbing required.
processor = krisp.KrispVivaFilterFrameProcessor(
noise_suppression_level=100, # 0-100, where 100 is maximum suppression
frame_duration_ms=10,
sample_rate=16000, # Pre-load model at this sample rate
)

# To use a Krisp license key + .kef model file instead, supply an explicit
# auth provider:
#
# processor = krisp.KrispVivaFilterFrameProcessor(
# auth_provider=krisp.auth.krisp_license(
# # Both default to env vars KRISP_VIVA_SDK_LICENSE_KEY and
# # KRISP_VIVA_FILTER_MODEL_PATH if omitted.
# license_key="...",
# model_path="/path/to/model.kef",
# ),
# noise_suppression_level=100,
# frame_duration_ms=10,
# sample_rate=16000,
# )

# Start the session with RoomIO configuration
# IMPORTANT: frame_size_ms must match Krisp's frame_duration_ms
await session.start(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
This is a minimal example to test that Krisp filtering works
without requiring a full agent setup. Good for testing and debugging.

Because this script runs outside an agent context, it cannot use the default
``LiveKitCloudAuthProvider`` (that path needs the framework to push the room's
JWT into the FrameProcessor at runtime). It uses ``KrispLicenseAuthProvider``
with a Krisp license key + ``.kef`` model file.

Prerequisites:
1. Set KRISP_VIVA_FILTER_MODEL_PATH environment variable
1. Set KRISP_VIVA_SDK_LICENSE_KEY and KRISP_VIVA_FILTER_MODEL_PATH environment variables
2. Install: pip install livekit-plugins-krisp krisp-audio numpy

Usage:
Expand All @@ -19,7 +24,7 @@
import numpy as np

from livekit import rtc
from livekit.plugins.krisp import KrispVivaFilterFrameProcessor
from livekit.plugins.krisp import KrispLicenseAuthProvider, KrispVivaFilterFrameProcessor

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("krisp-minimal-test")
Expand All @@ -33,9 +38,11 @@ async def test_krisp_filter():
logger.info("=" * 60)

try:
# Create the frame processor
# Create the frame processor with explicit license auth (no framework
# available in this standalone script).
logger.info("\n1. Creating Krisp frame processor...")
krisp_processor = KrispVivaFilterFrameProcessor(
auth_provider=KrispLicenseAuthProvider(),
noise_suppression_level=100,
frame_duration_ms=10,
sample_rate=16000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,32 @@

"""Krisp VIVA plugin for LiveKit Agents

This plugin provides real-time noise reduction
using Krisp's proprietary algorithms via the VIVA SDK.
This plugin provides real-time noise reduction using Krisp's proprietary
algorithms. Two authentication backends are supported, exposed under the
``auth`` sub-namespace:

Features:
- KrispVivaFilterFrameProcessor: Real-time noise reduction FrameProcessor
- ``krisp.auth.livekit_cloud()`` (default): LiveKit Cloud-managed auth +
bundled model. No Krisp env vars required.
- ``krisp.auth.krisp_license(...)``: Krisp-direct auth using a license key
and a ``.kef`` model file.

The PascalCase classes (:class:`LiveKitCloudAuthProvider`,
:class:`KrispLicenseAuthProvider`) remain available for type annotations.
"""

from livekit.agents import Plugin

from .krisp_instance import (
KRISP_FRAME_DURATIONS,
KRISP_SAMPLE_RATES,
KrispSDKManager,
int_to_krisp_frame_duration,
int_to_krisp_sample_rate,
)
from . import auth
from .auth import KrispLicenseAuthProvider, LiveKitCloudAuthProvider
from .log import logger
from .version import __version__
from .viva_filter import KrispVivaFilterFrameProcessor

__all__ = [
"KrispVivaFilterFrameProcessor",
"KrispSDKManager",
"KRISP_SAMPLE_RATES",
"KRISP_FRAME_DURATIONS",
"int_to_krisp_sample_rate",
"int_to_krisp_frame_duration",
"LiveKitCloudAuthProvider",
"KrispLicenseAuthProvider",
"auth",
"__version__",
]

Expand Down
Loading
Loading