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
uvpackage manager, as the Pipecat installation guide recommends. - A Developers Portal account with access to the VIVA SDK, and an API key.
Install
- Download the latest VIVA SDK for Python (a wheel file) and the VIVA models from the Developers Portal, and unzip the models.
- Install the wheel into the virtual environment of your Pipecat project:
uv pip install <path to the Krisp wheel file>- Add your API key and model paths to the
.envfile:
# 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.kefAdd Voice Isolation
Import the filter in bot.py:
from pipecat.audio.filters.krisp_viva_filter import KrispVivaFilterAdd 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 UserTurnStrategiesYour 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
KrispVivaFilterorKrispVivaTurnfails to load. Check that the Krisp wheel is installed in the same virtual environment as Pipecat, thatKRISP_VIVA_API_KEYis set (SDK v1.6.1 and later), and that the model paths in.envpoint to the unzipped.keffiles.- The bot still reacts to background speakers. Make sure
KrispVivaFilter()is set on the transport the caller actually uses, for example bothdailyandwebrtc. - The bot interrupts users or answers late. See the threshold guidance in Turn-Taking.
Updated 3 days ago

