livekit-noise-cancellation

star 0

Implement AI-powered noise cancellation with Krisp for LiveKit voice AI and video calls

FutureAtoms By FutureAtoms schedule Updated 3/11/2026

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

  1. Choose one location: Client OR server, not both
  2. Use BVC for agents: Better for varied audio sources
  3. Use NC for telephony: Optimized for phone audio
  4. Show loading state: Models take time to load
  5. Check browser support: Safari < 17.4 unsupported

Deliverables

For: $ARGUMENTS

Provide:

  1. NC location selection (client/server)
  2. Integration code
  3. Platform-specific setup
  4. Loading state handling
  5. Configuration options
  6. Error handling
Install via CLI
npx skills add https://github.com/FutureAtoms/claude-skills-backup --skill livekit-noise-cancellation
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator