careful-tiger-18580
02/24/2026, 8:00 AMtall-airline-16756
02/24/2026, 8:00 AMtall-airline-16756
02/24/2026, 8:01 AMnoise_cancellation.BVCTelephony() is failing. I’ll explain why that happens and give practical, open-source alternatives you can use with a self-hosted setup.
Why BVCTelephony() isn’t working for self-hosted
• The BVCTelephony() and BVC() models are part of LiveKit’s Enhanced Noise Cancellation, which is a server-side inference feature available only in LiveKit Cloud. That functionality is not supported on self-hosted LiveKit, which is why your call to noise_cancellation.BVCTelephony() fails.
What you can do instead (self-hosted friendly options)
• Client-side noise suppression (recommended)
◦ Use WebRTC’s built-in noise suppression on the client (browser or mobile) so audio is cleaned before it’s published to the server. This uses the browser/device audio pipeline (e.g., enabling noise suppression in getUserMedia constraints or using platform audio APIs).
◦ Advantage: Low-latency and offloads processing from your server.
• Agent-side (preprocessing) open-source denoisers
◦ Run noise suppression inside your agent process (before sending audio onward). You can integrate open-source denoisers such as RNNoise or other Python wrappers that implement denoising.
◦ Advantage: Centralized control on your infrastructure; works for recorded or streaming audio paths you manage in the agent.
• Voice Activity Detection (VAD) + filtering
◦ Use Silero VAD (supported in agent workflows) to drop non-speech segments and reduce background noise impact on downstream processing (STT, recording).
◦ Combine VAD with a denoiser for better quality.
Suggested next steps (practical)
1. Decide where you want processing:
◦ If you can change the client app: implement WebRTC noise suppression or process MediaStream audio with an RNNoise-based processor.
◦ If you prefer server/agent processing: remove BVCTelephony() and add a preprocessing step in your agent that runs RNNoise (or another open-source denoiser) and/or Silero VAD.
1. If you want a concrete code example, tell me:
◦ Which client SDK (browser JS, iOS, Android) or which agent runtime you’re using (Python version, agent framework).
◦ Whether you prefer client-side or agent-side processing.
1. I can then provide:
◦ A short example of enabling WebRTC noise suppression in the browser or
◦ A Python example showing how to run RNNoise or Silero VAD in your agent pipeline.
If you share your environment (client SDK and agent language/runtime) I’ll give a targeted code snippet and recommended libraries to integrate.
Sources: Voice AI quickstart | LiveKit Documentation | Client SDKs | livekit/livekit_composite | DeepWiki | Agent session | LiveKit Documentation | Choosing the right noise cancellation for your agent | LiveKitcareful-tiger-18580
02/24/2026, 8:26 AMtall-airline-16756
02/24/2026, 8:26 AMrnnoise-python), or must we build from source / use a specific wrapper?
5. What audio format and sample rate are you working with? (e.g., mono PCM16 at 16 kHz or 48 kHz)
6. Do you want the denoiser to run inside the LiveKit agent process or as a separate preprocessing service?
7. Any CPU/latency constraints or target deployment (Docker, ARM, low-power devices)?
If you prefer, answer just 1–3 and 5 and I’ll provide two examples:
• A short offline (file) example showing installation and processing a WAV file with rnnoise-python.
• A simple streaming example that reads PCM frames, runs RNNoise per-frame, and writes output (suitable to adapt into an agent).
Once you reply, I’ll send a ready-to-run Python snippet, required install steps, and notes about sample rates and buffering for low-latency usage.careful-tiger-18580
02/24/2026, 8:29 AMtall-airline-16756
02/24/2026, 8:30 AMrnnoise-python (which typically needs building native code), or do you want instructions to build RNNoise from source and call it with ctypes?
7. Where to hook it in your code: Do you want denoising applied just before STT receives frames (pre-STT in your AgentSession), or earlier when LiveKit hands you participant audio frames? If unsure, say “uncertain.”
If you prefer, answer 1–4 and 6 only and I’ll provide:
• A streaming (real-time) Python example showing how to wrap incoming PCM frames with RNNoise and feed the cleaned frames into the STT path, plus install/build steps.
• An offline WAV example that shows file-based denoising.
Once you reply I’ll produce the appropriate code snippet and installation steps tailored to your environment.
Sources: Agent session | LiveKit Documentation | Pipeline nodes and hooks | LiveKit Documentationcareful-tiger-18580
02/24/2026, 8:35 AMtall-airline-16756
02/24/2026, 8:35 AMNC noise-cancellation filter that uses RNNoise internally and is suitable for real-time, pre-STT denoising in the agent process.
Below I’ll show a compact, ready-to-drop-in example you can adapt in your agent.py. It:
• Instantiates the RNNoise-based NC filter inside the agent.
• Applies the filter to incoming audio frames before calling the agent’s default STT node.
• Assumes mono PCM16 audio at 16 kHz.
Installation
• Add the noise-cancellation plugin into your Docker image:
◦ pip install livekit livekit-plugins-noise-cancellation
• Build your Docker image for x86_64 as you normally would.
Example integration (insert into your agent file)
1. Replace or extend your Agent subclass to override the stt_node and apply denoising:
from typing import AsyncIterable, Optional
from livekit import rtc
from livekit.agents import Agent, ModelSettings, stt
class NoisyAgent(Agent):
def __init__(self, system_prompt: str = None) -> None:
super().__init__(instructions=system_prompt)
async def stt_node(
self,
audio: AsyncIterable[rtc.AudioFrame],
model_settings: ModelSettings
) -> Optional[AsyncIterable[stt.SpeechEvent]]:
# Import the NC (RNNoise-based) denoiser from the plugin
from livekit.plugins import noise_cancellation
# Instantiate denoiser (NC uses RNNoise under the hood)
denoiser = <http://noise_cancellation.NC|noise_cancellation.NC>()
# The filter method returns an async iterable of AudioFrame-like objects.
# num_channels=1 because you indicated mono PCM16 at 16 kHz.
denoised_audio = denoiser.filter(audio, num_channels=1)
# Forward the denoised audio to the default STT node for transcription
async for event in Agent.default.stt_node(self, denoised_audio, model_settings):
yield event
1. Hook this Agent in your existing flow
• In your entry/session code where you create an AgentSession, use this agent class:
session = AgentSession(
stt=stt_engine,
llm=llm_engine,
tts=tts_engine,
turn_detection=MultilingualModel(),
vad=ctx.proc.userdata["vad"],
preemptive_generation=True,
)
await session.start(
agent=NoisyAgent(system_prompt=SYSTEM_PROMPT),
room=ctx.room,
room_options=room_io.RoomOptions(
audio_input=room_io.AudioInputOptions(),
),
)
Notes and best practices
• Sample rate: Your audio is 16 kHz PCM16 mono — the NC filter is suitable for this sample rate. Confirm the frames coming from LiveKit are indeed mono PCM16 @ 16 kHz to avoid resampling issues.
• Latency: RNNoise is designed for low-latency denoising and works well for streaming/real-time scenarios. Keep buffer sizes small to minimize added latency.
• Resource use: Running denoising inside the agent process consumes CPU; test under expected concurrency to size your host appropriately.
• Fallback: If you see issues or need different noise characteristics, you can combine VAD (Silero VAD is already loaded in your prewarm) with denoising to avoid processing silence and reduce CPU.
If you want, I can:
• Provide a small Dockerfile snippet showing installation and how to build the container.
• Add a concrete example of how to read/inspect the incoming AudioFrame sample rate/format to validate frames are 16 kHz PCM16.
• Show how to integrate Silero VAD to only run the denoiser when speech is active (saves CPU).
Which follow-up would help most: Dockerfile + build steps, or validating audio frame format in your current agent?
Sources: Choosing the right noise cancellation for your agent | LiveKit