Pipecat

Add Krisp VIVA Voice Isolation and Turn-Taking to a Pipecat voice agent.

Pipecat ships Krisp VIVA support. You add two pieces to your bot:

  • KrispVivaFilter: Voice Isolation as an input audio filter on your transport. It removes background voices and noise before VAD, turn detection and speech-to-text.
  • KrispVivaTurn: Turn-Taking as the user turn stop strategy. It replaces Pipecat's default end-of-turn strategy.

You can use either one on its own, but Turn-Taking works best on Voice Isolation's output.

⚠️

This guide supersedes the Krisp guide published at docs.pipecat.ai/guides/features/krisp-viva.

Prerequisites

  • A working Pipecat bot. This guide starts from Pipecat's sample bot.py and uses the uv package manager, as the Pipecat installation guide recommends.
  • A Developers Portal account with access to the VIVA SDK, and an API key.

Install

  1. Download the latest VIVA SDK for Python (a wheel file) and the VIVA models from the Developers Portal, and unzip the models.
  2. Install the wheel into the virtual environment of your Pipecat project:
uv pip install <path to the Krisp wheel file>
  1. Add your API key and model paths to the .env file:
# Krisp SDK API key (required for SDK v1.6.1+)
KRISP_VIVA_API_KEY=your_api_key_here

# Voice Isolation model path
KRISP_VIVA_FILTER_MODEL_PATH=/PATH_TO_UNZIPPED_MODELS/krisp-viva-vi-tel-v2.5.1.kef

# Turn-Taking model path
KRISP_VIVA_TURN_MODEL_PATH=/PATH_TO_UNZIPPED_MODELS/krisp-viva-tp-v3.kef

Add Voice Isolation

Import the filter in bot.py:

from pipecat.audio.filters.krisp_viva_filter import KrispVivaFilter

Add KrispVivaFilter() as the audio_in_filter of every transport where you want Voice Isolation to run. For example, in the sample bot's transport parameters:

async def bot(runner_args: RunnerArguments):
    """Main bot entry point for the bot starter."""
    transport_params = {
        "daily": lambda: DailyParams(
            audio_in_filter=KrispVivaFilter(),
            audio_in_enabled=True,
            audio_out_enabled=True,
        ),
        "webrtc": lambda: TransportParams(
            audio_in_filter=KrispVivaFilter(),
            audio_in_enabled=True,
            audio_out_enabled=True,
        ),
    }
    transport = await create_transport(runner_args, transport_params)

Add Turn-Taking

Import Krisp Turn-Taking and Pipecat's turn strategy classes:

from pipecat.audio.turn.krisp_viva_turn import KrispVivaTurn
from pipecat.turns.user_stop import TurnAnalyzerUserTurnStopStrategy
from pipecat.turns.user_turn_strategies import UserTurnStrategies

Your context aggregator probably looks like this:

context = LLMContext()
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
    context,
    user_params=LLMUserAggregatorParams(vad_analyzer=SileroVADAnalyzer()),
)

Add user_turn_strategies with KrispVivaTurn to the user parameters. Keep the VAD analyzer: Turn-Taking uses its voice activity decisions.

context = LLMContext()
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
    context,
    user_params=LLMUserAggregatorParams(
        user_turn_strategies=UserTurnStrategies(
            stop=[TurnAnalyzerUserTurnStopStrategy(turn_analyzer=KrispVivaTurn())]
        ),
        vad_analyzer=SileroVADAnalyzer(),
    ),
)

Troubleshooting

  • KrispVivaFilter or KrispVivaTurn fails to load. Check that the Krisp wheel is installed in the same virtual environment as Pipecat, that KRISP_VIVA_API_KEY is set (SDK v1.6.1 and later), and that the model paths in .env point to the unzipped .kef files.
  • The bot still reacts to background speakers. Make sure KrispVivaFilter() is set on the transport the caller actually uses, for example both daily and webrtc.
  • The bot interrupts users or answers late. See the threshold guidance in Turn-Taking.

Did this page help you?