echoing-lamp-18687
02/19/2026, 9:22 AMtall-airline-16756
02/19/2026, 9:22 AMtall-airline-16756
02/19/2026, 9:23 AMroom_input_option code and that you use BVCTelephony() for SIP participants. Let’s isolate likely causes and walk through targeted checks you can run.
Key suspects
• Codec / sample-rate mismatch (SIP often uses 8 kHz codecs like G.711; WebRTC/agent code may assume 16/48 kHz).
• Over‑aggressive or double noise-cancellation/transcoding in the recording chain.
• Incorrect participant-kind detection causing the wrong processing model to be applied.
• Additional processing/resampling during egress/recording.
Steps to troubleshoot (run these in order)
1. Temporarily disable noise cancellation
• Change your AudioInputOptions to use noise_cancellation=None and make a test call/recording.
• If the recording becomes clear, noise cancellation is likely over‑processing telephony audio.
1. Verify sample rate and codec for SIP participants
• Confirm the SIP leg uses 8 kHz (narrowband) codecs (e.g., G.711). Ensure your recording/playback path is not resampling 8 kHz audio to 16/48 kHz without proper conversion — that can create slow or low-pitch playback.
• If your agent or downstream pipeline expects 8 kHz for SIP, ensure you keep that sample rate for processing and recording for SIP participants.
1. Ensure the right noise model is actually applied
• Add logging in the lambda so you can confirm which model is selected for each participant:
def noise_filter(params):
kind = params.participant.kind
print(f"Participant kind: {kind}")
if kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP or merged_data.get("kind") == "phone_call":
print("Using BVCTelephony()")
return noise_cancellation.BVCTelephony()
print("Using BVC()")
return noise_cancellation.BVC()
• This confirms whether BVCTelephony() is applied when you expect it.
1. Check for double processing in the audio chain
• Make sure no other component (egress/recorder/telephony gateway) applies additional noise suppression, gain control, or resampling after your agent’s processing.
• Test with a minimal pipeline that preserves the inbound codec to see if the issue persists.
1. Compare with the known-good endpoint
• Since the same call to another number is clear, test both endpoints while:
◦ Logging codec and sample rate used on each SIP leg.
◦ Recording raw inbound RTP (if possible) to confirm whether distortion is present before agent processing or only after.
1. Egress/recording settings
• Ensure your recording/egress settings preserve original encoding or correctly convert sample rates. Unintended resampling at egress can slow/pitch-shift audio.
What to try next (recommended sequence)
1. Disable noise cancellation and make a test recording.
2. If problem disappears, re-enable only BVCTelephony() for SIP and retest (no other noise filters).
3. If problem remains, capture a short sample of the affected recording and a sample of the raw inbound SIP RTP (or log codec/sample rate) so we can see whether distortion happens pre- or post-agent processing.
4. Share logs that show participant kind detection and the audio pipeline chosen for the affected call.
If you’d like, tell me:
• The participant kind you see in logs for the problematic calls (what your print/log shows).
• The SIP codec and sample rate negotiated for that call (e.g., G.711 @ 8kHz, Opus @ 48kHz).
• Whether disabling noise cancellation changed the symptom.
With those details I can help pinpoint whether it’s a sample-rate mismatch, noise model over-processing, or an egress/resampling issue and provide exact config/code changes.
Sources: Choosing the right noise cancellation for your agent | LiveKit | Troubleshooting STT not picking up utterances | LiveKit | Why is there extra audio at the end of my recordings of an agent session? |... | Python SDKs | livekit/livekit_composite | DeepWiki | Building the all-in-one platform for voice AI agentsechoing-lamp-18687
02/19/2026, 9:25 AMtall-airline-16756
02/19/2026, 9:26 AMBVCTelephony() vs BVC()) are designed for different kinds of audio; picking the wrong processing for a telephony call can degrade clarity.
What you should verify and adjust
1. Confirm the codec and sample rate negotiated by Twilio for the problematic calls (e.g., G.711 @ 8 kHz vs Opus @ 48 kHz).
2. Ensure your LiveKit agent and recording/egress path preserve or correctly convert that sample rate:
◦ For SIP (narrowband) prefer processing and recording at 8 kHz, or apply a proper resampler if converting to 16/48 kHz.
1. Make sure the telephony-optimized noise model is actually applied for SIP callers:
◦ Log the participant kind and which noise model your lambda returns so you know BVCTelephony() is used for SIP.
1. Disable other noise suppression or duplicate processing layers while testing (to rule out over‑processing).
2. Check egress/recorder settings so they don’t introduce resampling or additional processing that changes pitch/speed.
Next steps I can help with
• If you share the negotiated codec and sample rate from Twilio for a problematic call, I’ll recommend exact settings to preserve audio or resample correctly.
• If you can paste the logs that show participant kind and the noise model selection, I’ll confirm whether your lambda is applying BVCTelephony() as intended.
• I can provide a minimal AudioInputOptions example to test (no noise cancellation, and explicit handling for SIP) if you want to try that quickly.
Tell me which of those you can provide (Twilio codec/sample-rate, participant-kind logs, or a recording sample), and I’ll guide you step‑by‑step.echoing-lamp-18687
02/19/2026, 9:28 AMtall-airline-16756
02/19/2026, 9:28 AMBVCTelephony() only when appropriate. Below are simple, reliable ways to detect SIP participants and a short code example you can drop into your lambda to log and act on the participant kind.
How to identify a SIP participant
• Use the participant’s kind property and compare it to rtc.ParticipantKind.PARTICIPANT_KIND_SIP.
• If you also attach metadata when creating participants (e.g., merged_data["kind"] = "phone_call"), check that too as a fallback.
• Add logging where you choose the noise model so you can confirm which branch runs for each participant.
Example: logging inside your noise-cancellation lambda
def noise_filter(params):
kind = params.participant.kind
meta_kind = merged_data.get("kind") # if you use merged metadata
print(f"Participant id={params.participant.sid} kind={kind} meta_kind={meta_kind}")
if kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP or meta_kind == "phone_call":
print("Detected SIP participant — using BVCTelephony()")
return noise_cancellation.BVCTelephony()
print("Non-SIP participant — using BVC()")
return noise_cancellation.BVC()
What to check in logs
• Confirm the printed kind equals PARTICIPANT_KIND_SIP for the calls you expect to be telephony.
• If kind is not SIP but you still expect a phone call, check that your system attaches merged_data["kind"] = "phone_call" when creating that participant.
If the participant kind isn’t SIP when you expect it to be
• Share how the SIP participant is created (any metadata you pass) and the logs you see — I can help adjust where to set merged_data or how to detect SIP reliably.
• If you want, I can provide a minimal test that creates a SIP participant and demonstrates the expected kind value.