name: livekit-noise-cancellation
description: Implement AI-powered noise cancellation with Krisp for LiveKit voice AI and video calls
argument-hint: ""
allowed-tools: Read, Write, Bash(npm install, pip install), Glob, Grep, WebSearch
LiveKit Noise Cancellation
AI-powered audio enhancement: $ARGUMENTS
Expert Knowledge
You are a LiveKit noise cancellation specialist with expertise in:
- Krisp noise filter integration
- Client vs server-side noise cancellation
- Audio quality optimization
- Platform-specific configuration
- Voice AI agent audio processing
Noise Cancellation Options
| Location | Technology | Use Case |
|---|---|---|
| Client-side | Krisp SDK | Video calls, reduce upload |
| Server-side (Agent) | BVC/NC plugins | Voice AI, telephony |
| SIP Trunk | NC | Phone calls |
Client-Side (JavaScript)
Installation
npm install @livekit/krisp-noise-filter
React Integration
import { useKrispNoiseFilter } from '@livekit/react';
import { Room } from 'livekit-client';
function NoiseFilterControl() {
const { isEnabled, setEnabled, isSupported, isLoading } = useKrispNoiseFilter();
if (!isSupported) {
return <Text>Noise cancellation not supported</Text>;
}
if (isLoading) {
return <ActivityIndicator />;
}
return (
<TouchableOpacity
onPress={() => setEnabled(!isEnabled)}
style={[styles.button, isEnabled && styles.active]}
>
<Ionicons name="volume-mute" size={24} />
<Text>Noise Filter: {isEnabled ? 'ON' : 'OFF'}</Text>
</TouchableOpacity>
);
}
Manual Integration
import { KrispNoiseFilter, isKrispNoiseFilterSupported } from '@livekit/krisp-noise-filter';
import { Room } from 'livekit-client';
const room = new Room();
// Check support
if (isKrispNoiseFilterSupported()) {
const krisp = new KrispNoiseFilter();
// Enable noise filter
await krisp.setEnabled(true);
// Apply to room
room.setProcessor(krisp);
}
await room.connect(url, token);
Browser Compatibility
| Browser | Supported |
|---|---|
| Chrome | Yes |
| Firefox | Yes |
| Edge | Yes |
| Safari 17.4+ | Yes |
| Safari < 17.4 | No |
React Native
Installation
npm install @livekit/react-native-krisp-noise-filter
Usage
import { KrispNoiseFilter } from '@livekit/react-native-krisp-noise-filter';
import { useState, useEffect } from 'react';
function useNoiseFilter(room: Room | undefined) {
const [isEnabled, setIsEnabled] = useState(false);
const [filter] = useState(() => new KrispNoiseFilter());
const toggle = async () => {
if (isEnabled) {
await filter.disable();
setIsEnabled(false);
} else {
await filter.enable();
room?.setProcessor(filter);
setIsEnabled(true);
}
};
useEffect(() => {
return () => {
filter.disable();
};
}, []);
return { isEnabled, toggle };
}
// In component
function AudioControls() {
const room = useRoom();
const { isEnabled, toggle } = useNoiseFilter(room);
return (
<TouchableOpacity onPress={toggle}>
<Text>Noise Filter: {isEnabled ? 'ON' : 'OFF'}</Text>
</TouchableOpacity>
);
}
Server-Side (Agents)
Voice AI Agent
from livekit.agents import Agent, AgentSession, RtcSession, AgentServer
from livekit.plugins import noise_cancellation, silero
class VoiceAgent(Agent):
def __init__(self):
super().__init__(
instructions="You are a helpful voice assistant."
)
@RtcSession.factory
async def create_session(session: AgentSession):
await session.start(
agent=VoiceAgent(),
stt="deepgram/nova-3",
llm="openai/gpt-4o-mini",
tts="cartesia/sonic",
vad=silero.VAD.load(),
# Background Voice Cancellation (BVC)
# Best for general noise + background voices
noise_cancellation=noise_cancellation.BVC(),
)
Noise Cancellation Modes
from livekit.plugins.noise_cancellation import BVC, NC
# BVC - Background Voice Cancellation
# Removes background noise AND background voices
# Best for: offices, public spaces, multiple speakers
bvc = BVC()
# NC - Noise Cancellation
# Removes background noise only
# Best for: telephony, where voice clarity is priority
nc = NC()
# For telephony
await session.start(
agent=PhoneAgent(),
stt="deepgram/nova-3-phonecall",
llm="openai/gpt-4o-mini",
tts="cartesia/sonic",
noise_cancellation=NC(), # Better for phone audio
)
SIP Trunk Integration
Apply noise cancellation at the trunk level:
from livekit.api import LiveKitAPI
from livekit.protocol import sip as sip_proto
api = LiveKitAPI()
# Create trunk with noise cancellation
await api.sip.create_sip_inbound_trunk(
sip_proto.CreateSIPInboundTrunkRequest(
trunk=sip_proto.SIPInboundTrunkInfo(
name="nc-trunk",
numbers=["+1..."],
krisp_enabled=True, # Enable Krisp for all calls
)
)
)
Important: Don't Double-Process
# ⚠️ WARNING: Do NOT use client + server noise cancellation together
# If using noise cancellation in the agent:
# - Disable Krisp on the frontend
# - Noise cancellation models expect raw audio
# - Double processing can cause artifacts
@RtcSession.factory
async def create_session(session: AgentSession):
# Server-side NC
await session.start(
agent=MyAgent(),
noise_cancellation=noise_cancellation.BVC(),
...
)
# Frontend should NOT have Krisp enabled for this agent
Audio Quality Settings
// Optimize for voice clarity
const room = new Room({
audioCaptureDefaults: {
echoCancellation: true,
noiseSuppression: true, // Browser's built-in
autoGainControl: true,
},
});
// Add Krisp for enhanced NC
if (isKrispNoiseFilterSupported()) {
const krisp = new KrispNoiseFilter();
await krisp.setEnabled(true);
room.setProcessor(krisp);
}
Performance Considerations
// Krisp downloads models at runtime (~2MB)
// Show loading state during initialization
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initKrisp = async () => {
if (isKrispNoiseFilterSupported()) {
const krisp = new KrispNoiseFilter();
await krisp.init(); // Download models
setIsLoading(false);
}
};
initKrisp();
}, []);
Complete Client Example
import React, { useState, useEffect } from 'react';
import { Room, RoomEvent } from 'livekit-client';
import { KrispNoiseFilter, isKrispNoiseFilterSupported } from '@livekit/krisp-noise-filter';
interface NoiseFilterState {
isSupported: boolean;
isEnabled: boolean;
isLoading: boolean;
toggle: () => Promise<void>;
}
export function useNoiseFilter(room: Room | null): NoiseFilterState {
const [isSupported] = useState(isKrispNoiseFilterSupported());
const [isEnabled, setIsEnabled] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [filter, setFilter] = useState<KrispNoiseFilter | null>(null);
useEffect(() => {
if (!isSupported) {
setIsLoading(false);
return;
}
const init = async () => {
const krisp = new KrispNoiseFilter();
await krisp.init();
setFilter(krisp);
setIsLoading(false);
};
init();
return () => {
filter?.setEnabled(false);
};
}, [isSupported]);
const toggle = async () => {
if (!filter || !room) return;
if (isEnabled) {
await filter.setEnabled(false);
setIsEnabled(false);
} else {
await filter.setEnabled(true);
room.setProcessor(filter);
setIsEnabled(true);
}
};
return { isSupported, isEnabled, isLoading, toggle };
}
// UI Component
function NoiseFilterButton({ room }: { room: Room }) {
const { isSupported, isEnabled, isLoading, toggle } = useNoiseFilter(room);
if (!isSupported) return null;
return (
<button
onClick={toggle}
disabled={isLoading}
className={`noise-filter-btn ${isEnabled ? 'active' : ''}`}
>
{isLoading ? 'Loading...' : isEnabled ? 'NC: ON' : 'NC: OFF'}
</button>
);
}
Complete Agent Example
import logging
from dotenv import load_dotenv
from livekit.agents import Agent, AgentSession, RtcSession, AgentServer
from livekit.plugins import silero, noise_cancellation
load_dotenv()
logging.basicConfig(level=logging.INFO)
class ClearVoiceAgent(Agent):
def __init__(self):
super().__init__(
instructions="""You are a voice assistant optimized
for noisy environments. Speak clearly and confirm
understanding when audio quality is poor."""
)
async def on_enter(self):
await self.session.say("Hello! I can hear you clearly.")
@RtcSession.factory
async def create_session(session: AgentSession):
# Use BVC for best background noise removal
nc = noise_cancellation.BVC()
logging.info("Initializing noise cancellation")
await session.start(
agent=ClearVoiceAgent(),
stt="deepgram/nova-3",
llm="openai/gpt-4o-mini",
tts="cartesia/sonic",
vad=silero.VAD.load(),
noise_cancellation=nc,
)
if __name__ == "__main__":
AgentServer(create_session).run()
Best Practices
- Choose one location: Client OR server, not both
- Use BVC for agents: Better for varied audio sources
- Use NC for telephony: Optimized for phone audio
- Show loading state: Models take time to load
- Check browser support: Safari < 17.4 unsupported
Deliverables
For: $ARGUMENTS
Provide:
- NC location selection (client/server)
- Integration code
- Platform-specific setup
- Loading state handling
- Configuration options
- Error handling