creamy-scientist-61602
03/23/2026, 10:42 AMlivekit-agents==1.4.6 (Python) with a SIP inbound trunk through Asterisk 20.5.0 (IncrediblePBX). Our agent works well for MTN and AirtelTigo callers in Ghana, but we’ve had persistent audio issues specifically with Telecel Ghana callers (number prefixes 020/050) and would love input from anyone who has navigated carrier-specific audio differences in telephony setups.
Architecture / audio path
Telecel handset
→ VoipNow SIP (PCMA/8000, plain RTP, ptime=20ms)
→ Asterisk 20.5.0 (SIP trunk, transcodes to PCMU or Opus)
→ LiveKit SIP trunk (WebRTC/ICE, offers PCMU + Opus/48000)
→ Agent (Python, livekit-agents 1.4.6)
The key distinction vs. other Ghanaian carriers: Telecel’s network uses AMR-NB internally, which VoipNow transcodes to PCMA/G.711 before it reaches Asterisk. This AMR→G.711 transcoding introduces spectral characteristics that differ from a clean G.711 call.
Current config for Telecel sessions:
silero.VAD.load(activation_threshold=0.35, min_silence_duration=0.7)
AgentSession(
vad=session_vad,
turn_detection=None, # English EOU model rejects AMR-transcoded audio
preemptive_generation=False,
min_interruption_duration=0.5,
false_interruption_timeout=4.0,
min_endpointing_delay=0.7,
max_endpointing_delay=2.0,
)
And in the agent class, for Telecel we omit turn_detection from super().__init__() entirely (pass NOT_GIVEN, not None) so the agent inherits the session’s VAD-only setting rather than overriding it.
Questions / things we’re unsure about
1. Recommended VAD parameters for G.711 telephony?
Is there a known-good activation_threshold / min_silence_duration combination for standard SIP telephony where comfort noise is present? We tuned empirically but would love a reference baseline.
2. Correct RoomOptions API in 1.4.6?
We’re seeing this deprecation warning:
RoomInputOptions and RoomOutputOptions are deprecated, use RoomOptions instead
We’re currently using room_io.RoomOptions(noise_cancellation=noise_cancellation.BVCTelephony()) for non-Telecel and room_io.RoomOptions() for Telecel — is this the right structure? Is noise_cancellation a direct field on RoomOptions, or should it be nested (e.g. input=RoomInputOptions(noise_cancellation=...))?
3. Silero “inference is slower than realtime” warnings
{"message": "inference is slower than realtime", "delay": 0.45, ...}
{"message": "inference is slower than realtime", "delay": 0.48, ...}
These appear during the first ~20s of the call while a background RAG cache warm-up task runs (20 async HTTP calls). They resolve once warm-up completes. Is this expected resource contention, or should we move the warm-up to a separate worker/process? Would force_cpu=True on Silero help or hurt here?
4. “Input is shorter by X samples; silence prepended” warning
Input is shorter by 27638 samples; silence has been prepended to align the input channel.
We see this once per Telecel call. Is this a symptom of Telecel’s RTP jitter causing packet gaps that the framework pads with silence? Should we be configuring a jitter buffer anywhere in the Asterisk/LiveKit pipeline, or is this handled automatically?
5. turn_detection=None at both session and agent level — is omitting from Agent correct?
We found that passing turn_detection=None explicitly to Agent.super().__init__() overrides the session’s VAD-only setting (as opposed to NOT_GIVEN which inherits). Is there documentation on the precedence rules between Agent and AgentSession for vad, turn_detection, and stt? We couldn’t find this spelled out clearly.
Environment
• livekit-agents==1.4.6, livekit-rtc==1.1.2
livekit-plugins-deepgram, livekit-plugins-silero, livekit-plugins-cartesia
Python 3.11, Docker (Linux/amd64)
Asterisk 20.5.0 (IncrediblePBX), SIP trunk to LiveKit cloud (Germany region)
• STT: Deepgram nova-3 (English), TTS: Cartesia, LLM: Gemini 2.0 Flashtall-airline-16756
03/23/2026, 10:42 AMtall-airline-16756
03/23/2026, 10:43 AMRoomOptions usage in livekit-agents 1.4.6 (where to set noise_cancellation)
• Silero “inference is slower than realtime” warnings and whether to move warm-up to another process or use force_cpu=True
• The “Input is shorter by X samples; silence prepended” warning and whether you need jitter-buffer changes
• turn_detection precedence between Agent and AgentSession
If you want, I can answer all five briefly and then we can iterate. Tell me which you'd like first (or say “All” if you want the full pass now).
, with interactive elementscreamy-scientist-61602
03/23/2026, 10:44 AMtall-airline-16756
03/23/2026, 10:45 AMactivation_threshold (default 0.5), min_silence_duration (default ~0.55s), min_speech_duration (default 0.05s), and prefix_padding_duration (default 0.5s). AssemblyAI/other STT thresholds can be aligned (example: AssemblyAI default vad_threshold 0.3) and alignment matters for barge-in behavior.
• Observations for AMR→G.711:
◦ AMR→G.711 transcoding often introduces spectral/artifacts and lower SNR compared with native G.711; this can raise false-negative VAD (speech missed) or false-positive (comfort noise mistaken for speech) depending on threshold.
◦ Comfort noise and DTX downstream (if Opus with DTX is used) also change energy profile.
• Recommended starting baseline to tune from (apply only to Telecel sessions):
◦ activation_threshold: 0.30 — 0.40 (start at 0.35, you’re already using 0.35)
◦ min_silence_duration: 0.55 — 0.8 s (start at 0.7, as you have)
◦ min_speech_duration: keep at 0.05 — 0.1 s
◦ prefix_padding_duration: 0.4 — 0.6 s
• Why these values:
◦ Lowering activation_threshold to ~0.3–0.35 makes VAD more permissive to the lower-energy / spectrally-altered speech from AMR→G.711 while preventing too many false starts if not too low.
◦ Increasing min_silence_duration to 0.7–0.8s helps avoid premature endpointing when AMR artifacts produce brief low-energy dips inside speech.
• Practical tuning approach:
a. Keep your current config as the control (activation=0.35, min_silence=0.7).
b. Create two experiment branches:
• Branch A (more permissive): activation=0.30, min_silence=0.6
• Branch B (more conservative): activation=0.40, min_silence=0.8
a. Run representative Telecel calls and measure:
• Missed starts (agent not responding to short user speech)
• False endpointing (agent cuts in during user's phrase)
• Per-call latency (silence timeout contribution)
a. Prefer the setting with fewer missed starts while keeping endpoint latency acceptable.
• If you use STT-based endpointing in other environments, align thresholds with STT service (example AssemblyAI vad 0.3). Consistency avoids unexpected barge-in behavior.
2) Correct RoomOptions API in livekit-agents 1.4.6 and noise_cancellation placement
• What I’m answering: whether noise_cancellation is a direct field on RoomOptions or should be nested in input=RoomInputOptions(...).
• Key facts: RoomInputOptions and RoomOutputOptions are deprecated; RoomOptions is the current replacement. Noise cancellation (e.g., Krisp/BVCTelephony) is configured through the room/telephony options and Krisp can be enabled on inbound trunks via krisp_enabled when interacting with telephony.
• Recommendation for 1.4.6 usage:
◦ Use RoomOptions(...) rather than RoomInputOptions / RoomOutputOptions.
◦ Set noise cancellation as a direct argument on RoomOptions if your code paths accept it (your current room_io.RoomOptions(noise_cancellation=noise_cancellation.BVCTelephony()) is the correct pattern for non-Telecel sessions).
◦ For Telecel sessions where you want to avoid aggressive NC that might remove spectral cues, use RoomOptions() (no noise_cancellation) or a milder/no-op NC.
• Practical check: if you still see deprecation warnings mentioning RoomInputOptions / RoomOutputOptions, search your call path for anywhere those types are still constructed (session.start or publish helpers). Migrate all such construction to RoomOptions(...).
• Quick code example (non-Telecel):
from livekit.agents.room_io import RoomOptions
from livekit.agents import noise_cancellation
room_opts = RoomOptions(noise_cancellation=noise_cancellation.BVCTelephony())
• Quick code example (Telecel):
room_opts = RoomOptions() # avoid NC for Telecel calls
• Note: If you need inbound trunk-level Krisp, ensure the telephony inbound config (krisp_enabled) is set at trunk configuration rather than only RoomOptions.
3) Silero “inference is slower than realtime” warnings and warm-up strategy
• What I’m answering: whether these warnings during first ~20s while your RAG cache warm-up runs are expected, and whether to move warm-up to another worker or set force_cpu=True.
• Key facts: Silero VAD runs locally on CPU and is lightweight; the agent server prewarm pattern exists so you can load VAD into proc.userdata before jobs start. When CPU contention occurs (e.g., many async HTTP RAG warm-ups), you may see “inference is slower than realtime” warnings. Agent jobs run in separate processes and you can prewarm resources per process.
• Recommendations:
◦ Move heavy non-real-time work (the RAG cache warm-up with 20 async HTTP calls) out of the audio-processing critical path. Options:
▪︎ Run warm-up in a separate worker/process prior to accepting calls.
▪︎ Prewarm within the agent process but perform network-bound warm-up before the audio stream is live (i.e., at job start but before starting real-time audio).
▪︎ Use server.setup_fnc / prewarm to load Silero VAD model into proc.userdata so spawn overhead doesn’t coincide with first audio.
◦ Use separate worker/process for RAG warm-up if warm-up uses CPU or network and runs concurrently with the first seconds of audio. This prevents contention and avoids early inference slowdowns.
◦ Regarding force_cpu=True for Silero:
▪︎ Silero already runs on CPU; force_cpu=True ensures the model uses CPU even if GPU is available. If your inference slowdown is caused by CPU contention, forcing CPU will not help. If you have a GPU and Silero could use it (rare for Silero), forcing CPU could hurt. In short: force_cpu=True is unlikely to help your situation and may be unnecessary — instead reduce contention or prewarm models.
• Practical steps:
a. Prewarm Silero VAD in process startup:
• Use a prewarm function to load silero.VAD.load() into proc.userdata.
a. Move RAG warm-up to a dedicated warm-up worker or run it before you join the room audio flow.
b. Monitor the frequency of “inference is slower than realtime” after these changes; they should disappear.
4) “Input is shorter by X samples; silence prepended” warning and jitter buffer concerns
• What I’m answering: cause of the single warning per Telecel call and whether this indicates RTP jitter/packet gaps and if you should configure jitter buffers in Asterisk/LiveKit.
• Key facts:
◦ WebRTC receivers maintain jitter buffers; LiveKit supports playout delay adjustments and audio source queue sizing (queue_size_ms) to handle variability.
◦ The warning “Input is shorter by N samples; silence has been prepended to align the input channel” indicates the framework aligned mismatched channel lengths by prepending silence — commonly caused by truncated or late frames (packet loss/jitter) or different capture chunk boundaries.
◦ Telecel/AMR→G.711 plus RTP network conditions can create short packet gaps or frame length mismatches that the receiver pads.
• What to do:
◦ Asterisk side:
▪︎ Ensure Asterisk RTP jitter buffer is enabled and sized reasonably (e.g., default up to ~100–200ms). If you control Asterisk RTP jitter buffer settings, try increasing the jitter buffer slightly to see if it reduces the warning.
▪︎ Verify the trunk’s ptime and any translator/transcoder settings preserve packet boundaries (ptime=20ms is fine). Avoid additional forced frame chopping where possible.
◦ LiveKit/agent side:
▪︎ Increase audio_source.queue_size_ms incrementally (e.g., 2000 ms is an option in the docs) if you see frame capture failures. This gives the pipeline more headroom to align audio.
▪︎ Use RoomOptions/playout delay adjustments if available for the call to increase jitter buffer on the WebRTC side.
◦ Practical diagnostic steps:
i. Capture RTP logs on Asterisk for a problematic Telecel call and measure packet loss/jitter and inter-arrival times.
ii. If you see packet gaps or reordering from VoipNow→Asterisk, contact VoipNow settings (if possible) to reduce transcoder packetization changes.
3
Sources: Turn Detection for Voice Agents: VAD, Endpointing, and Model-Based Detectio... | Silero VAD plugin | LiveKit Documentation | examples/voice_agents | livekit/livekit_composite | DeepWiki | How does end-of-utterance detection work in conversations? | Models overview | LiveKit Documentation, with interactive elements