is there a way i can improve the audio of my clien...
# ask-ai
f
is there a way i can improve the audio of my client with AudioOptions when i am making outbound calls with sip?
t
Thanks for reaching out, ullaimlu. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — yes, you can improve client audio for outbound SIP calls by configuring AudioOptions with the appropriate noise-cancellation filter. Quick summary of what to do: • Use the telephony-optimized background voice cancellation for SIP participants: BVCTelephony() (optimized for narrowband 8 kHz/phone audio). • Use the regular BVC filter for full-bandwidth WebRTC participants: BVC(). • Apply the chosen filter in your audio input options when starting the session so outbound audio goes through the correct noise-cancellation model. Examples: 1) Python
Copy code
from livekit import rtc
from livekit.plugins import noise_cancellation

filter = (
    noise_cancellation.BVCTelephony()
    if participant.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP
    else noise_cancellation.BVC()
)

await session.start(
    room_options=room_io.RoomOptions(
        audio_input=room_io.AudioInputOptions(noise_cancellation=filter),
    ),
)
2) Node.js / TypeScript
Copy code
import { BackgroundVoiceCancellation, TelephonyBackgroundVoiceCancellation } from '@livekit/noise-cancellation-node';

const filter = participant.kind === ParticipantKind.SIP
  ? TelephonyBackgroundVoiceCancellation()
  : BackgroundVoiceCancellation();

await session.start({
  inputOptions: {
    noiseCancellation: filter,
  },
});
Additional note: • You can also enable Krisp noise cancellation at the SIP trunk level (for inbound processing) by setting
krisp_enabled: true
when creating an inbound trunk — this affects inbound audio processing rather than the outbound client-side filter. If you’d like, tell me: • which SDK / language you’re using, and • whether this is for outbound only or both inbound/outbound SIP calls — and I’ll provide a tailored code snippet or next steps to integrate it into your flow. Sources: examples/voice_agents | livekit/livekit_composite | DeepWiki | Choosing the right noise cancellation for your agent | LiveKit
f
i already have that noise cancelation, but the audio of the client is so bad, there is not audio options for the room? like num of chanels or something
t
Thanks — I hear your frustration. You already have noise cancellation, but the client audio is still poor and you want room-level audio options (like number of channels) or other ways to improve it. I can help narrow this down and suggest actionable changes. What you can configure right now • You can set room-level audio output options when starting an AgentSession:
sample_rate
and
num_channels
via
AudioOutputOptions
. For example, you can request 16000 Hz and mono (
num_channels=1
) so the agent side publishes audio in a known format. • SIP calls are typically constrained by telephony limits: many SIP paths are mono and narrowband (8 kHz) or wideband (16 kHz). Stereo or very high sample rates may not be preserved end-to-end with a SIP provider. • Use the telephony-optimized noise cancellation (
BVCTelephony()
) for SIP participants — it’s optimized for phone-band audio and may sound better than full-band filters for outbound SIP. Other practical steps to improve perceived audio quality • Match sample rate to the SIP codec: If your trunk and endpoints support wideband (16 kHz), set
sample_rate=16000
. If the SIP path is narrowband, higher sample rates won’t help. • Force mono (
num_channels=1
) for SIP endpoints to avoid channel mismatch artifacts. • Avoid double-processing: if you enable Krisp on the trunk (
krisp_enabled: true
) then disable agent-side noise-cancellation to prevent artifacts from multiple filters. • Check SIP codec negotiation: ensure your trunk supports a higher-quality codec (e.g., Opus or G.722) rather than a very low-bitrate narrowband codec like some G.729 setups. • Test with other SIP endpoints: isolate whether the problem is with a specific provider, device, or network path by calling different phones or trunks. • Diagnose directionality: confirm whether the poor audio is (a) client -> agent, (b) agent -> client, or (c) both. That changes which side you should tune. Quick Python example (setting audio output on session start)
Copy code
await session.start(
    room_options=room_io.RoomOptions(
        audio_output=room_io.AudioOutputOptions(
            sample_rate=16000,
            num_channels=1
        )
    )
)
Questions to narrow this down • Which SDK and platform are you using (Python Agents, Node, browser SDK, mobile)? • Is the poor audio one-way (agent can’t hear client well) or two-way? • Which SIP codec(s) does your trunk negotiate (if known) and is
krisp_enabled
set on the trunk? • Do you see packet loss, jitter, or network issues on the agent/client side? If you share those details I’ll suggest concrete settings and next steps (SDK-specific code or diagnostic checks) to improve the audio. Sources: Agent session | LiveKit Documentation | sip | livekit/livekit_composite | DeepWiki | Using Noise Cancellation for SIP and WebRTC Participants | Choosing the right noise cancellation for your agent | LiveKit
f
i dont understand how sample rate works, what is the default value? and why i should change it?
t
Thanks — good question. I’ll explain what sample rate is, what LiveKit uses by default for SIP, and when you should change it. What sample rate is • The sample rate is how many audio samples are captured per second, measured in Hz. • Higher sample rates (e.g., 16000, 48000 Hz) capture more of the audio waveform and can sound clearer and more natural. Lower rates (e.g., 8000 Hz) capture less detail but use less bandwidth. What LiveKit uses by default for SIP • For SIP/telephony calls LiveKit uses 8000 Hz (8 kHz) by default. 8 kHz is the standard narrowband telephony rate and is common across phone networks. Why you might change the sample rate • Improve clarity (if supported): If your SIP provider and endpoints support wideband audio (16 kHz or higher), increasing the sample rate to 16000 Hz can make voices sound clearer and more natural. • Match downstream processing: If you run speech-to-text (STT), text-to-speech (TTS), or other audio processing that expects 16 kHz (or another rate), matching that rate avoids resampling artifacts and can improve quality. • Help noise-cancellation models: Some processing works better when the audio is in the expected band; using a wideband rate for wideband models can help. • Trade-offs: Higher sample rates use more bandwidth and CPU. If the SIP path is narrowband (8 kHz), raising the sample rate will not improve end-to-end audio and may add unnecessary processing. Practical guidance • If your trunk negotiates only narrowband codecs, keep 8000 Hz—that’s normal for phone calls. • If your trunk supports wideband (Opus, G.722, etc.), set sample_rate=16000 to get better voice quality. • For SIP, also set
num_channels=1
(mono) to avoid channel mismatch artifacts. How to set it (Python AgentSession example)
Copy code
await session.start(
    room_options=room_io.RoomOptions(
        audio_output=room_io.AudioOutputOptions(
            sample_rate=16000,   # or 8000 if your SIP path is narrowband
            num_channels=1
        )
    )
)
If you want, tell me: • Which sample rate your SIP trunk/codecs currently negotiate (or the SIP provider), and • Whether the poor audio is client→agent, agent→client, or both. I’ll recommend the concrete sample_rate value and settings to try next. Sources: Choosing the right noise cancellation for your agent | LiveKit | Smallest AI TTS plugin guide | LiveKit Documentation | Agent session | LiveKit Documentation
f
its twilio
t
Thanks — that’s helpful. Since you’re using Twilio, here’s a concise explanation of what’s happening with sample rate and what you can (and should) do next to improve audio quality. What Twilio and LiveKit use by default • Twilio’s SIP trunks typically use G.711 (PCMU/PCMA) at 8 kHz (narrowband). • LiveKit transcodes SIP audio to/from WebRTC. Incoming SIP audio (8 kHz) is converted to Opus for WebRTC, and outgoing audio from agents is downsampled/transcoded back to the SIP format Twilio expects (usually 8 kHz mono). • Because of that path, the effective end-to-end audio for a Twilio SIP call is usually 8 kHz mono. Changing sample rate on the agent side won’t magically make the SIP leg higher quality if Twilio is negotiating 8 kHz. Why sample rate matters (brief) • Sample rate = samples per second (Hz). Higher rates (16 kHz, 48 kHz) capture more detail and can sound clearer, but they’re only useful if the entire chain (agent → LiveKit → Twilio → caller) supports wideband codecs. • If Twilio and the SIP endpoint only support narrowband (8 kHz), higher sample rates won’t improve the caller’s audio and can add CPU/bandwidth overhead. What you can do (practical steps) • Confirm Twilio codec support: Check your Twilio trunk settings to see if Opus or a wideband codec (G.722) is offered. If Twilio only uses G.711 at 8 kHz, the SIP path is narrowband. • Use telephony-optimized processing: On the agent side use
BVCTelephony()
noise cancellation to avoid artifacts when sending to SIP. • Match mono channel: Force mono (
num_channels=1
) in your agent audio output so there’s no channel mismatch during transcoding. • Avoid double processing: If you enable
krisp_enabled
on the trunk, disable agent-side noise cancellation to prevent double filtering artifacts. • Test with clean audio: Play a clean 8 kHz test file into the pipeline (or record and send) to determine if the problem is transcoding vs. source quality vs. network. • Check network/metrics: High packet loss, jitter, or CPU spikes can make audio sound bad even with correct codecs. Inspect WebRTC stats and LiveKit metrics on the agent’s session. If you want, I can: • Show the exact AgentSession code for forcing `sample_rate`/`num_channels` in your SDK (Python or Node). • Walk you through what to check in your Twilio trunk config to see if wideband codecs are available. • Provide a short test plan (playback of a clean file, capture of codec negotiation) to isolate whether the issue is source, network, or transcoding. Which would help most right now—SDK code, Twilio trunk checks, or a step-by-step test plan? Sources: Choosing the right noise cancellation for your agent | LiveKit | sip | livekit/livekit_composite | DeepWiki | Smallest AI TTS plugin guide | LiveKit Documentation | Playing Audio | LiveKit Documentation
f
pero no seria en audio input?
t
Buena pregunta — gracias por señalarlo. Te explico brevemente la diferencia y qué debes configurar en cada lado para mejorar el audio con Twilio. Resumen corto • Las opciones de
sample_rate
y
num_channels
que puedes fijar desde LiveKit se aplican en AudioOutputOptions (lo que el agente publica hacia la red/SIP), no en la entrada física del micrófono. • La señal de entrada del micrófono (audio input) viene del dispositivo del usuario y su sample rate real lo controla el SO/driver del micrófono; LiveKit no puede forzar el sample rate físico del micrófono, pero sí puede procesar/filtrar esa entrada (p. ej. noise cancellation). • Para llamadas SIP con Twilio, la legada final en el trunk suele ser 8 kHz mono (G.711), por lo que cambiar el sample rate del output del agente solo ayudará si la cadena SIP soporta wideband. Qué poner en cada lado y por qué • Audio input (mic): ◦ No puedes cambiar el sample rate físico desde LiveKit; mejora la calidad del input con: ▪︎ Noise cancellation apropiado (para SIP usar
BVCTelephony()
). ▪︎ Asegurarte de que el micrófono del agente tenga buena ganancia y poca latencia. • Audio output (lo que publica el agente hacia LiveKit/SIP): ◦ Aquí sí puedes fijar
sample_rate
y
num_channels
con
AudioOutputOptions
al iniciar la sesión/AgentSession. Esto controla el formato en el que LiveKit enviará audio hacia el puente y eventualmente se transcodificará al formato SIP. ◦ Ejemplo en Python (fija 16 kHz mono si tu trunk soporta wideband):
Copy code
await session.start(
        room_options=room_io.RoomOptions(
            audio_output=room_io.AudioOutputOptions(
                sample_rate=16000,
                num_channels=1
            )
        )
    )
• Si Twilio negocia 8 kHz (G.711), fijar 16 kHz no mejorará la calidad en el extremo SIP; la plataforma downsampleará a 8 kHz. Recomendaciones prácticas para Twilio • Verifica qué codecs ofrece tu trunk Twilio (G.711 vs Opus/G.722). Si solo ofrece G.711 (8 kHz), la llamada será narrowband. • Usa
BVCTelephony()
en el agente para evitar artefactos con audio telephony. • Mantén
num_channels=1
(mono) para evitar problemas de canal. • Evita duplicar procesado: si activas
krisp_enabled
en el trunk, considera desactivar el noise cancellation del agente para no generar artefactos por doble filtrado. • Si sospechas que el problema es la entrada (mic del cliente), pide al usuario probar con otro dispositivo o hacer una llamada de prueba a un número diferente para aislar si es proveedor/dispositivo/red. ¿Te ayudo con el SDK que estés usando? Dime qué SDK/stack usas (Python Agent, Node, browser, mobile) y si quieres que te genere el snippet ajustado para aplicar
AudioOutputOptions
y
BVCTelephony()
en tu flujo actual.
f
es q el agente se escucha bien, el que se escucha mal es el participante
t
Gracias — muy útil esa aclaración. Resumo lo que entendí y te doy pasos concretos para diagnosticar y mejorar el audio del participante (la otra parte que escucha mal). Lo que está pasando (resumen) • El agente suena bien, pero el participante (caller) suena mal para el agente. • Con Twilio, la legada SIP suele ser narrowband (8 kHz, G.711) y LiveKit transcodifica esa señal para WebRTC. Eso significa que si Twilio/ el endpoint SIP entrega audio a 8 kHz mono, LiveKit no puede “crear” más calidad desde la nada — el límite viene del lado del participante/SIP. Qué revisar y acciones concretas 1. Verificar dirección del problema ◦ Confirma si el problema es: participante → agente (el agente oye mal al participante), agente → participante, o ambos. Según lo que dijiste, el problema es participante → agente. 1. Chequear codecs negociados en la llamada ◦ Revisa los logs/SDP para ver qué codec está usando Twilio en la sesión (G.711 PCMU/PCMA a 8 kHz es lo típico). ◦ Si Twilio negocia solo G.711 8 kHz, eso explica la calidad limitada. Si aparece Opus o G.722, puede haber posibilidad de mayor calidad. 1. Probar activar/ajustar procesamiento en el trunk ◦ Si tienes la opción
krisp_enabled
en el trunk, puedes probar activarla para mejorar la limpieza del audio entrante antes de llegar a LiveKit. ◦ Ten cuidado con doble filtrado: si
krisp_enabled
está ON, evita aplicar filtros agresivos del lado del agente que puedan introducir artefactos. 1. Ajustes en LiveKit (lo que sí puedes controlar) ◦ Aunque la entrada física del participante viene de Twilio, puedes: ▪︎ Monitorizar la calidad con WebRTC stats / LiveKit logs (packet loss, jitter) para ver si la degradación es de red. ▪︎ Asegurarte que en el lado del agente uses
BVCTelephony()
si vas a procesar audio de voz telephony, para evitar modelos full-band inappropriate. ◦ No hay un setting para “forzar sample rate” del audio entrante de SIP: LiveKit adapta el formato según lo que negocie el SIP trunk. 1. Diagnósticos prácticos (pasos recomendados) ◦ Haz una llamada de prueba desde Twilio a varios endpoints (otro teléfono, softphone) para ver si el problema es un device específico. ◦ Graba (o pide que se grabe) el audio entrante en el punto más temprano posible (Twilio SIP RTP o cuando llega a LiveKit) y escucha el archivo: ¿suena comprimido/robótico (indicador de 8 kHz) o suena con más banda? ◦ Revisa WebRTC stats en la sesión del agente: packet loss, jitter, round-trip time. Problemas de red causan audio degradado. ◦ Si tienes control sobre el cliente del participante (p. ej. es un softphone/WebRTC), verifica su mic, ganancia y codecs ofrecidos. 1. Opciones si necesitas mejor calidad ◦ Configurar Twilio para ofrecer wideband codecs (Opus o G.722) si Twilio y el endpoint del participante lo soportan. ◦ Si no es posible cambiar el codec en Twilio/endpoint, enfócate en limpieza: activar
krisp_enabled
en trunk y/o mejorar la fuente (mic del participante). Para ayudarte mejor, dime: • El problema es definitivamente participante → agente, ¿correcto? • El participante es un teléfono clásico vía Twilio SIP trunk, un softphone o un cliente WebRTC en el navegador/app? • ¿Puedes revisar / pegar aquí (si está disponible) el SDP negociado o decir qué codec aparece (G.711, Opus, G.722)? • ¿Quieres que te pase un pequeño plan de pruebas (comandos/qué logs mirar) para identificar si es codec vs. red vs. dispositivo? Con esa info te doy pasos más precisos (y el snippet de configuración si necesitas tocar
krisp_enabled
o cambiar algo en la sesión del agente).
s
using deepgram.stt there is one option of enable_diarization but then how to prompt llm to reply based on diarization (will llm have context of input speaker) can you give me an example
t
Perfecto — te explico paso a paso cómo usar la diarización de Deepgram para que tu LLM responda con contexto de quién habló (es decir, que el LLM distinga y use los IDs de orador). Resumen rápido • Habilita
enable_diarization
en Deepgram para que la transcripción final incluya etiquetas de orador (ej. S1, S2). • Asegúrate de recibir las transcripciones finales (evento
user_input_transcribed
). • Construye el prompt/contexto del LLM incluyendo el texto diarizado (con las etiquetas) y unas instrucciones de sistema que indiquen cómo interpretar esas etiquetas. • El LLM no “adivina” quién habló: solo sabrá si tú le das las etiquetas en el contexto y le indicas cómo usarlas. Flujo práctico (conceptual) 1) Deepgram → produce texto diarizado: por ejemplo <s1>Hola, necesito ayuda</s1> <s2>¿Cuál es el número de pedido?</s2> 2) Al recibir la transcripción final, formateas un mensaje para el LLM que incluya esas líneas y unas instrucciones de sistema claras: • “S1 es el cliente; S2 es el agente; responde al que preguntó y mantén el rol apropiado”. 3) Envías ese contexto al LLM para generar la respuesta; el LLM podrá mencionar o dirigirse al orador correcto porque las etiquetas están en el prompt. Ejemplo en Python (esqueleto) • Asume que ya configuraste Deepgram con
enable_diarization=True
y recibes la transcripción final como string en
diarized_text
.
Copy code
# ejemplo simplificado
from some_llm_client import LLMClient

def handle_diarized_transcript(diarized_text: str):
    # diarized_text puede ser: "<s1>Hola</s1> <s2>Hola, ¿en qué puedo ayudar?</s2>"
    system_instructions = (
        "Eres un asistente en una conversación con múltiples oradores. "
        "Recibirás texto etiquetado como <s1>, <s2>, etc. "
        "Interpreta <s1> como Cliente y <s2> como Agente. "
        "Responde la última pregunta dirigida al Cliente (S1) de forma concisa."
    )

    user_message = f"Transcripción diarizada:\n{diarized_text}"

    llm = LLMClient(api_key="...")

    response = llm.chat(
        system=system_instructions,
        user=user_message,
        # otros parámetros según tu LLM
    )

    return response.text
Consejos de formato para mejores resultados • Usa un formato de etiquetas claro y consistente (por ejemplo:
[S1]: Hola
o
<s1>Hola</s1>
). Evita formatos ambiguos que puedan confundirse con instrucciones del LLM. • Añade una breve “leyenda” en las instrucciones de sistema que mapee IDs a roles (ej. “S1 = cliente, S2 = agente”). • Si quieres respuestas dirigidas, indica explícitamente: “Si S1 hace una pregunta, responde a S1. Si S2 interrumpe, resume y responde a S1 si corresponde.” • Concisa la transcripción si es muy larga: puedes enviar sólo los últimos N turns o un resumen + el último turno diarizado. Cómo manejar múltiples oradores o contextos largos • Para muchas etiquetas (S1..S5), incluye en el prompt el mapeo de IDs a nombres/roles. • Si el historial es largo, pasa un resumen del contexto anterior y añade el último bloque diarizado completo. Ejemplo de prompt final (texto que recibe el LLM) • System: "Eres un asistente. Interpreta etiquetas <s1>, <s2>. S1=Cliente, S2=Agente. Responde a las preguntas del Cliente." • User: "Transcripción: <s1>Mi pedido no llegó</s1> <s2>Lo siento, ¿puedes darme tu número?</s2> <s1>12345</s1>" Respuesta esperada del LLM: "S1 (Cliente): Gracias. He encontrado tu pedido 12345 y veo que está en tránsito..." Validaciones y pruebas • Prueba con ejemplos simples para verificar que el LLM respeta las etiquetas. • Si el LLM no sigue las etiquetas, haz las instrucciones de sistema más explícitas y da un ejemplo de formato dentro del prompt (few-shot). • Asegúrate de enviar solo transcripciones finales (la diarización aparece en los segments finales). ¿Te ayudo a generar: • un snippet específico para la librería LLM que usas (OpenAI, Anthropic, o tu LLM self-hosted), o • un ejemplo con el formato de salida exacto de Deepgram que tienes ahora? Dime qué LLM usas y cómo recibes la transcripción (formato exacto), y te doy el prompt y el código final listos para integrar. Sources: Deepgram STT plugin guide | LiveKit Documentation | Speechmatics STT plugin guide | LiveKit Documentation