tall-businessperson-30911
02/16/2026, 9:24 AMtall-airline-16756
02/16/2026, 9:24 AMtall-airline-16756
02/16/2026, 9:24 AMtall-businessperson-30911
02/16/2026, 9:24 AMtall-airline-16756
02/16/2026, 9:25 AMbypassVoiceProcessing in the SDK? If so, is it enabled or disabled?
• Which encoder/codec configuration are you using (if custom)? Are you forcing Opus parameters?
4) Call topology and participants
• Typical call size (1:1, small group, large rooms)?
• Do you use Agents/AI in calls? If yes, which noise cancellation model is configured?
5) Logs and metrics (highly helpful)
• Can you share relevant SDK logs around the time distortion occurs (RtcError, warnings about audio, reconnections, track state changes)? If you can’t paste logs, summary of repeated warnings is useful.
• Do you see spikes/drops in connection quality (uplink/downlink scores) when distortion happens? Any jitter/packet loss or bitrate drops reported?
6) Quick reproduction tests I recommend trying (these will quickly indicate the likely layer)
• Reproduce with bypassed processing: enable bypassVoiceProcessing (or disable if already enabled) to see if system audio processing is causing artifacts.
• Test with a simple reference device/setup: reproduce on a known-good device, on stable Wi‑Fi, with no Bluetooth/headset, 1:1 call—does distortion persist?
• Disable any extra noise cancellation chains: if you use Agents + device processing + app filters, disable extras and test with a single cancellation model (for Agents: use BVC() or BVCTelephony() as recommended).
• Record a raw sample: ask an affected user to record local audio (before sending) and the received audio. If local recording is clean but received is distorted, the problem is network/codec/processing on the server or receiver. If local recording is distorted, it’s device/processing on the sender.
What I can do next once you share details
• If you provide SDK logs, room ID, and timestamps I can help interpret errors and spot network/codec issues.
• If you share your audio-init and publish code snippets (Android LiveKit client init, track publish, any noise-cancel config), I’ll review for misconfiguration (for example multiple processing layers or incorrect flags).
• I can outline specific step-by-step tests to isolate sender vs network vs receiver causes and follow-up fixes we can try.
If you prefer, start by telling me:
• One example incident: device model + OS, room ID (or timestamp), whether sender/receiver noticed distortion, and any SDK warnings in logs around that time.
Once I have that, I’ll give a prioritized diagnostic plan and likely fixes.
Sources: How is Connection Quality determined? | LiveKit | client-sdk-android | livekit/livekit_composite | DeepWiki | client-sdk-flutter | livekit/livekit_composite | DeepWiki | Choosing the right noise cancellation for your agent | LiveKittall-businessperson-30911
02/16/2026, 9:42 AMtall-airline-16756
02/16/2026, 9:43 AMbypassVoiceProcessing (if you haven’t tried already): run one test with it enabled and one with it disabled.
Why: system-level voice processing + app-level processing can interact badly under load and create artifacts.
4) Simplify audio processing chain
• Temporarily disable any extra noise cancellation, echo cancellation, or third-party audio filters. If you use LiveKit Agents/noise models, disable them for the test.
Why: multiple stages of noise cancellation (device + app + AI) can produce distortion when the processing pipeline is stressed.
5) Try lower codec bitrate / single-stream publish
• Publish with a lower or fixed Opus bitrate and/or single audio stream (no simulcast-like features). If you currently use a custom Opus config, try the SDK defaults.
Why: bitrate spikes and encoder reconfiguration during multiple simultaneous publishes can cause artifacts.
6) Network behavior and packet statistics
• Collect connection stats in the SDK during a reproduce (uplink/downlink bitrate, packetLoss, jitter). Note any sudden packet loss or bitrate drops when distortion begins.
Why: simultaneous joins can cause transient congestion on the SFU or client uplink, producing distorted audio on both ends.
7) Capture recordings to isolate sender vs network
• On an affected sender, save a local raw audio recording before sending. Also save the received audio on a receiving client.
• Compare: if local recording is clean but received is distorted, the issue is network/SFU/receiver processing. If local is distorted as well, it’s device or local processing.
Why: this isolates the origin of distortion.
Information to share back (these items let me give precise guidance)
• SDK version, Android OS version(s), and example device models that reproduce.
• A short code snippet showing how you initialize audio, publish tracks, and any audio-related flags (e.g., bypassVoiceProcessing, noise-cancel model).
• Connection stats (u/d bitrate, packet loss, jitter) around the time distortion happens, or screenshots of profiler CPU spikes.
• One sample log excerpt (timestamped) from SDK logs showing warnings/errors during the incident (if available).
• Room ID and approximate timestamps of an incident (so I can correlate logs if you paste them).
Immediate mitigations to try now
• Limit concurrent simultaneous join spikes: if your app does a lot at join-time, stagger joins by a few hundred ms client-side to reduce burst load on clients and SFU.
• Reduce client-side processing: temporarily disable extra noise cancellation and use a single, recommended cancellation model only.
• Lower encoder bitrate during high-concurrency periods to reduce encoder load and SFU forwarding bitrate.
What I can do once you reply
• Review logs/connection stats and code snippets to identify misconfiguration (e.g., multiple processing layers, wrong flags).
• Recommend concrete config values (Opus bitrate, recommended noise model) and step-by-step changes to test.
• Help interpret SDK connection stats and profiler outputs to pinpoint CPU vs network vs SFU issues.
If you want, start by sharing:
• SDK version, one device model and Android version that reproduces, and a short code snippet showing audio initialization and publish. I’ll review for likely misconfigurations and suggest the next exact test to run.tall-businessperson-30911
02/16/2026, 9:46 AMtall-airline-16756
02/16/2026, 9:46 AMbypassVoiceProcessing (or disable if you already enabled it previously) on the Android SDK and remove any extra in-app noise/echo processing. If you use Agents/noise models, disable them for the test.
• What to look for: If distortion stops, audio processing chain interaction was the cause.
5) Test with lowered/fixed Opus bitrate and single stream
• Cause targeted: encoder reconfiguration / bitrate spikes under join load.
• Action: Force a conservative Opus bitrate (e.g., 24–32 kbps) and publish only a single audio stream. Use the SDK defaults if you used custom settings.
• What to look for: If distortion improves, encoder bitrate/reconfig or SFU bandwidth handling under burst join is implicated.
6) Check SFU/server metrics and packet buffer behavior
• Cause targeted: SFU-side buffering or resource limits.
• Action: Inspect LiveKit server logs and metrics (CPU, memory, network) during an incident. Pay attention to packet buffer utilization and any warnings around packet drops or rate limiting.
• What to look for: server CPU spikes, high packet buffer occupancy, or logs indicating packet drops. Your packet_buffer_size_audio: 1000 is generous; check whether buffer churn occurs during join spikes.
7) Stagger client joins as a practical mitigation
• Cause targeted: burst load on clients and SFU.
• Action: Implement a small randomized join delay (100–500 ms) when many users join the same room concurrently.
• Why: Reduces simultaneous encoding/publishing bursts to both clients and SFU and often eliminates transient artifacts quickly.
Immediate mitigations you can try now
• Stagger joins client-side by 100–500 ms.
• Temporarily disable extra noise cancellation and use only one cancellation approach.
• Lower the audio bitrate to a conservative fixed value during high concurrency.
• Limit per-client CPU load: avoid heavy UI work on join, perform heavy tasks off the audio threads.
Information I need from you to pinpoint root cause
• Android SDK version you’re using and exact LiveKit client version.
• Example affected Android device model(s) and OS versions.
• A short code snippet showing how you initialize audio, set bypassVoiceProcessing (if present), and publish the audio track.
• Collected SDK connection stats around an incident (1–2s samples for ~30s spanning the join).
• One or two short log excerpts from the server and client around a reproduce (timestamps help).
• If possible, the local and received audio clips for one reproduce.
Why each item matters
• SDK version can reveal known bugs or behavior changes.
• Device/OS and profiler info will confirm CPU saturation or audio-route problems.
• Connection stats show whether distortion correlates with packet loss/jitter/bitrate drops.
• Audio clips immediately show whether distortion originates before or after the network.
If you want, start by pasting:
• SDK version, one sample device + OS, and the audio initialization/publish code snippet. I’ll review that for misconfigurations (multiple processing layers, wrong flags) and give the exact small code changes to test next.
I’m ready to review your logs, stats, code, or audio samples whenever you paste them, and I’ll recommend the next exact action based on what they show.tall-businessperson-30911
02/16/2026, 9:52 AMtall-airline-16756
02/16/2026, 9:52 AMbypassVoiceProcessing anywhere (true/false) in your Android initialization.
• A short copy-paste of how you create and publish the local audio track (the publish call and any audioOptions/opus settings).
• SDK connection stats from a reproduce (1–2s interval samples for ~30s around the join): uplink/downlink bitrate, packetLoss, jitter, rtt, and audio track send/recv state.
• A short client SDK log excerpt around an incident (timestamps help), and any server LiveKit logs for the same timeframe if possible.
• Optional but very helpful: a 10–30s raw local recording from a sender and the corresponding received recording from a receiver for one reproduce.
Priority tests to run (ordered — each isolates one root area) 1) Single-device baseline then controlled 7-user burst
• Confirm 1:1 is clean, then reproduce the 7-user simultaneous join on a single Wi‑Fi network. Note exact time when distortion starts.
2) Capture local vs received audio
• Record local microphone output on a sender before send, and record received audio on a receiver. If local is clean but received is distorted, the problem is network/SFU/receiver; if local is distorted, it’s the sender or its local processing.
3) Watch CPU/memory during join bursts
• Use Android Studio Profiler or adb to capture CPU/memory while 6–7 users join. Look for CPU spikes, GC pauses, or main-thread stalls at the moment distortion starts.
4) Toggle voice processing
• Run two tests: one with bypassVoiceProcessing = true and one with false (or the opposite if you already use one). Also temporarily disable any other app-level noise cancellation or filters. This shows whether audio processing chains cause artifacts under load.
5) Lower and fix Opus bitrate / single stream publish
• Force a conservative Opus bitrate (e.g., 24–32 kbps) and publish one audio stream. If distortion improves, encoder bitrate or SFU forwarding during bursts is implicated.
6) Collect connection stats from all clients during a reproduce
• Look for synchronized packetLoss, jitter spikes, or bitrate drops right when the join burst occurs.
7) Stagger join times as a practical immediate mitigation
• Add a 100–500 ms randomized delay on join for clients that join en masse. This often removes burst-related artifacts quickly while you debug.
Small code/config checks from what you sent
• Your microphone toggling and subscribe/unsubscribe logic looks fine; you avoid unpublishing which reduces negotiation overhead (good).
• Your AudioSession configuration uses voice chat attributes which is correct; confirm Android audio routing behavior matches expected (Bluetooth vs speakerphone differences).
• On server side you have congestion_control enabled, TURN enabled, and a wide UDP port range. Check LiveKit server CPU/network during bursts for spikes and check whether your TURN server becomes overloaded when many clients connect simultaneously.
If you want, start by pasting:
• Your Android LiveKit client initialization snippet (where you set audio options and publish the microphone) and the SDK version.
• One short SDK log excerpt (client) and the corresponding server log timestamps for the same event.
What I’ll do once you share those
• Review the client publish/init code for misconfiguration (multiple processing layers, opus settings, bypass flags).
• Interpret the connection stats and logs to tell if the issue is CPU, network/SFU, or audio-processing.
• Recommend exact config changes (Opus bitrate, buffer sizes, process flags), and if needed a plan to profile server/client to fix the root cause.
If you prefer, run the local vs received recording test first — that single test will most quickly tell us whether the problem originates on the sender or in the network/SFU/receiver. Tell me the results and paste any logs you can, and I’ll give the next exact steps.tall-businessperson-30911
02/16/2026, 9:52 AMtall-airline-16756
02/16/2026, 9:53 AMadaptiveStream and dynacast are disabled, and simulcast for video is off — so the SFU will handle full audio streams for each participant.
• Audio encoding uses a maxBitrate of 48,000 (48 kbps) which is reasonable, but simultaneous immediate publishes from many clients could cause encoder and SFU bitrate/congestion spikes.
• noiseSuppression is false, but echoCancellation and autoGainControl are enabled; system-level processing plus SDK processing could interact under load.
• Server-side packet buffer sizes are large (1000), congestion control is enabled, and TURN is on — good, but bursts of simultaneous joins can still strain client CPU or cause transient SFU churn.
Recommended next steps — quick tests to run now (ordered by what will likely isolate cause fastest) 1) Reproduce with delayed publish (fast check)
• Change the client to delay publishing the microphone for ~300–700 ms after connect (or stagger joins on clients) and reproduce the 6–7 simultaneous join scenario.
• Why: your current fastConnect + immediate publish causes a burst of encoder startup work on many clients and many concurrent publishes to the SFU. Staggering often removes artifacts quickly and confirms a burst-load cause.
2) Run the local vs received audio test
• Record a short local raw audio clip on a sender before sending and record the received audio on a receiver during the same incident.
• Outcome: If local is clean but received is distorted, focus on SFU/network/receiver. If local is distorted, focus on sender device or local processing/encoding.
3) Toggle audio processing flags
• Test A: set defaultAudioCaptureOptions.noiseSuppression = true and bypassVoiceProcessing = true (if available in your Android client) — or run the inverse (enable bypass if currently not set).
• Test B: temporarily disable echoCancellation and autoGainControl to see if artifacts change.
• Why: audio processing chains can interact poorly under CPU pressure and produce distortion.
4) Lower/fix Opus bitrate for a reproduce
• Temporarily lower AudioEncoding(maxBitrate: 24000) and test. Also try forcing a fixed bitrate (if supported).
• Why: reducing encoder load and SFU bandwidth can eliminate distortion caused by encoder reconfig or congestion bursts.
5) Capture SDK connection stats and client CPU during reproduce
• Collect connection stats at 1–2s intervals for ~30s around the join: uplink/downlink bitrate, packetLoss, jitter, rtt, audio track send/recv state.
• Simultaneously capture Android CPU/threads/GC (Android Studio Profiler or adb) on at least one joining client.
• What to look for:
◦ Synchronous packet loss/jitter/bitrate drops across clients at the join spike → SFU/network issue.
◦ CPU spikes/GC pauses on clients at the join spike → client-side encoding/mixing overload.
6) Server logs & metrics during reproduce
• Check LiveKit server CPU/memory and network usage when the join burst happens. Look for logs indicating packet drops, rate limiting, or high buffer occupancy despite packet_buffer_size_audio being large.
Immediate mitigations to try now
• Stagger clients’ publishes/joins by 100–700 ms.
• Temporarily lower maxBitrate to 24 kbps for testing.
• Temporarily disable client-side echo cancellation or auto gain control to see if artifacts change.
• If you have control over client behavior at join, avoid heavy UI or background work when publishing starts.
What I need from you to diagnose further
• Android LiveKit SDK version and the exact client library version (package + version).
• One or two example device models (and Android OS versions) where this reproduces.
• Whether you use any LiveKit Agents or other server-side audio processing / AI noise cancellation.
• Whether you use bypassVoiceProcessing on Android (and if so, its current value).
• A short snippet showing how you call publish/create local audio track on Android (if different from the Flutter wrapper you shared).
• Connection stats (1–2s samples) and one short client SDK log excerpt around a reproduce attempt (timestamps help).
• Optional but highly useful: local vs received audio samples for one reproduce.
If you want to start with one thing that will give the fastest answer, do this:
• Stagger the immediate publishes by ~500 ms (client-side) or add a 500 ms delay before the fastConnect microphone publish, then reproduce the 6–7 join scenario and report whether distortion persists.
Paste the SDK version, one device model + OS, and the results of the staggered-publish test or the local vs received recording test, and I’ll analyze the logs/stats you provide and give exact config changes and code suggestions to eliminate the distortion.tall-businessperson-30911
02/16/2026, 10:08 AMbypassVoiceProcessing
2026-02-15T155700.305Z INFO livekit service/roommanager.go:413 starting RTC session {"room": "StressRoom", "roomID": "RM_XPm6VRNgrgig", "participant": "uqaot_90", "pID": "PA_Noqa7fDA26gi", "remote": false, "room": "StressRoom", "nodeID": "ND_8SK7WcmxYRHA", "numParticipants": 50, "participantInit": {"Identity": "uqaot_90", "Reconnect": false, "ReconnectReason": "RR_UNKNOWN", "AutoSubscribe": false, "AutoSubscribeDataTrack": "not-set", "Client": {"sdk": "GO", "version": "2.13.3", "protocol": 16, "os": "linux"}, "Grants": {"Identity": "uqaot_90", "Kind": "standard", "KindDetails": [], "Video": {"RoomCreate": false, "RoomList": false, "RoomRecord": false, "RoomAdmin": false, "RoomJoin": true, "Room": "StressRoom", "CanPublish": "not-set", "CanSubscribe": "not-set", "CanPublishData": "not-set", "CanPublishSources": [], "CanUpdateOwnMetadata": "not-set", "IngressAdmin": false, "Hidden": false, "Recorder": false, "Agent": false, "CanSubscribeMetrics": "not-set", "DestinationRoom": ""}, "SIP": {}, "Agent": {}, "Inference": {}, "Observability": {}, "RoomConfig": {}, "RoomPreset": ""}, "Region": "", "AdaptiveStream": false, "ID": "", "SubscriberAllowPause": "not-set", "DisableICELite": false, "CreateRoom": {"name": "StressRoom"}, "AddTrackRequests": [], "PublisherOffer": {}, "SyncState": {}, "UseSinglePeerConnection": false}}
2026-02-15T155700.305Z INFO livekit service/roommanager.go:1006 created TURN password {"username": "pdmNyEERmdTYx9mTfKIo4LvyW7L7KjsvWjN", "password": "6QFvyPvhlMcM2XBT4tee45R9Ob68Vc5nw7X9G8zw7JZ"}
2026-02-15T155700.305Z ERROR livekit service/roommanager.go:526 could not join room {"room": "StressRoom", "roomID": "RM_XPm6VRNgrgig", "participant": "uqaot_90", "pID": "PA_Noqa7fDA26gi", "remote": false, "error": "room has exceeded its max participants"}
github.com/livekit/livekit-server/pkg/service.(*RoomManager).StartSession
/workspace/pkg/service/roommanager.go:526
github.com/livekit/livekit-server/pkg/service.(*defaultSessionHandler).HandleSession
/workspace/pkg/service/signal.go:115
github.com/livekit/livekit-server/pkg/service.(*signalService).RelaySignal
/workspace/pkg/service/signal.go:183
github.com/livekit/psrpc/pkg/server.(*streamHandler[...]).handleOpenRequest
/go/pkg/mod/github.com/livekit/psrpc@v0.7.1/pkg/server/stream.go:202
github.com/livekit/psrpc/pkg/server.(*streamHandler[...]).handleRequest.func1
/go/pkg/mod/github.com/livekit/psrpc@v0.7.1/pkg/server/stream.go:141
2026-02-15T155700.305Z INFO livekit rtc/participant.go:1367 participant closing {"room": "StressRoom", "roomID": "RM_XPm6VRNgrgig", "participant": "uqaot_90", "pID": "PA_Noqa7fDA26gi", "remote": false, "sendLeave": true, "reason": "JOIN_FAILED", "isExpectedToResume": false}
2026-02-15T155700.305Z ERROR livekit service/signal.go:186 could not handle new participant {"room": "StressRoom", "participant": "uqaot_90", "connID": "CO_KkVRvTrNPVts", "error": "room has exceeded its max participants"}
github.com/livekit/livekit-server/pkg/service.(*signalService).RelaySignal
/workspace/pkg/service/signal.go:186
github.com/livekit/psrpc/pkg/server.(*streamHandler[...]).handleOpenRequest
/go/pkg/mod/github.com/livekit/psrpc@v0.7.1/pkg/server/stream.go:202
github.com/livekit/psrpc/pkg/server.(*streamHandler[...]).handleRequest.func1
/go/pkg/mod/github.com/livekit/psrpc@v0.7.1/pkg/server/stream.go:141
2026-02-15T155700.306Z INFO livekit service/roommanager.go:413 starting RTC session {"room": "StressRoom", "roomID": "RM_XPm6VRNgrgig", "participant": "uqaot_83", "pID": "PA_2pX5YC3MaFAD", "remote": false, "room": "StressRoom", "nodeID": "ND_8SK7WcmxYRHA", "numParticipants": 50, "participantInit": {"Identity": "uqaot_83", "Reconnect": false, "ReconnectReason": "RR_UNKNOWN", "AutoSubscribe": false, "AutoSubscribeDataTrack": "not-set", "Client": {"sdk": "GO", "version": "2.13.3", "protocol": 16, "os": "linux"}, "Grants": {"Identity": "uqaot_83", "Kind": "standard", "KindDetails": [], "Video": {"RoomCreate": false, "RoomList": false, "RoomRecord": false, "RoomAdmin": false, "RoomJoin": true, "Room": "StressRoom", "CanPublish": "not-set", "CanSubscribe": "not-set", "CanPublishData": "not-set", "CanPublishSources": [], "CanUpdateOwnMetadata": "not-set", "IngressAdmin": false, "Hidden": false, "Recorder": false, "Agent": false, "CanSubscribeMetrics": "not-set", "DestinationRoom": ""}, "SIP": {}, "Agent": {}, "Inference": {}, "Observability": {}, "RoomConfig": {}, "RoomPreset": ""}, "Region": "", "AdaptiveStream": false, "ID": "", "SubscriberAllowPause": "not-set", "DisableICELite": false, "CreateRoom": {"name": "StressRoom"}, "AddTrackRequests": [], "PublisherOffer": {}, "SyncState": {}, "UseSinglePeerConnection": false}}
2026-02-15T155700.306Z INFO livekit service/roommanager.go:1006 created TURN password {"username": "EFkRh10MDlVNYBnMfKIo4LvyW7L7KjsvWjN", "password": "fJXjr5jeJ0EJC64Md1u7XeO9P9pKlewbhfukkoJvQ1cF"}
2026-02-15T155700.306Z ERROR livekit service/roommanager.go:526 could not join room {"room": "StressRoom", "roomID": "RM_XPm6VRNgrgig", "participant": "uqaot_83", "pID": "PA_2pX5YC3MaFAD", "remote": false, "error": "room has exceeded its max participants"}
github.com/livekit/livekit-server/pkg/service.(*RoomManager).StartSession
/workspace/pkg/service/roommanager.go:526
github.com/livekit/livekit-server/pkg/service.(*defaultSessionHandler).HandleSession
admin joins then users joins one by one not at the same timetall-airline-16756
02/16/2026, 10:09 AMadb CPU/heap traces while reproducing the join spike.
• Look for CPU saturation, GC pauses, or main-thread stalls when the 6th–7th participant joins.
• Why: High CPU/GC correlates strongly with encoder artifacts.
4) Collect per-client connection stats during reproduce
• Capture SDK stats at 1–2s intervals for ~30s around the join spike: uplink/downlink bitrate, packetLoss, jitter, rtt, and audio track send/recv state.
• What to look for:
◦ Simultaneous packetLoss/jitter spikes across clients → SFU/network problem.
◦ Bitrate drops or re-negotiations coinciding with distortion → encoder/SFU handling.
5) Try conservative audio config changes
• Temporarily set AudioEncoding(maxBitrate: 24000) and test. Also try disabling `dtx`/`red` temporarily to compare.
• Temporarily disable echoCancellation and autoGainControl in defaultAudioCaptureOptions (you currently have noiseSuppression: false, echoCancellation: true, autoGainControl: true).
• Why: Reducing encoder load and simplifying capture pipeline helps isolate codec vs processing issues.
6) Server-side checks (simultaneously)
• Watch LiveKit server CPU, memory, network, and packet-buffer occupancy during the spike. Your server log shows many join failures due to max participants — ensure your stress test isn’t inadvertently hitting that limit and causing churn.
• Check whether TURN is being used heavily (TURN CPU/network could be a bottleneck if many clients relay).
Immediate mitigations to apply now
• Stagger client publishes / add randomized small join delays (100–700 ms). This is the fastest change likely to reduce distortion.
• Lower audio maxBitrate to 24–32 kbps for testing.
• Temporarily disable echo cancellation / auto gain control to see if artifacts change.
• Avoid heavy UI or background processing on join which could increase CPU load.
Exactly what to send me next (so I can analyze and advise precise fixes)
• Results of the staggered-publish test (did distortion go away or reduce?).
• One local vs received audio pair (10–30s) from a reproduce attempt.
• Per-client connection stats (1–2s interval) spanning ~30s around the incident: uplink/downlink bitrate, packetLoss, jitter, rtt, audio send/recv state.
• Android profiling output (CPU%/threads or a short screenshot) from a joining client during reproduce.
• Client SDK logs (timestamped) around the incident and server LiveKit logs for the same window. The server logs you pasted show many join attempts and “room has exceeded its max participants” — confirm whether your stress test room maxParticipants is being reached and adjust if needed.
Small configuration notes based on your current setup
• Publishing immediately via fastConnect reduces negotiation delays but creates an encoder/publish burst across users. A short publish delay or stagger prevents simultaneous encoder startups.
• Your audio maxBitrate 48 kbps is fine normally, but under burst load lowering it helps the SFU and clients handle multiple incoming/outgoing streams.
• echoCancellation and autoGainControl are enabled; on Android default system processing plus SDK processing may interact under stress—toggle these while testing.
If you want, try the staggered publish test now and paste:
• One short client SDK log around the reproduce,
• The connection stats for that reproduce,
• And whether distortion improved when staggered.
I’ll review those and give the exact configuration and code changes to remove the artifact (or the next server-side checks if it looks like SFU/network).
Sources: [Flutter iOS] SoundWaveformWidget / AudioVisualizerWidget Not Working (Miss... | Optimizing Video Calls for Low-Powered Devices | LiveKit | How to support rooms over 1000 users | LiveKit | client-sdk-flutter | livekit/livekit_composite | DeepWiki