wonderful-airport-21213
04/29/2026, 10:41 AMtall-airline-16756
04/29/2026, 10:42 AMtall-airline-16756
04/29/2026, 10:42 AMwonderful-airport-21213
04/29/2026, 10:46 AMFuture<void> toggleAudioMute() async {
if (_isChangingAudioDevice) return;
_isChangingAudioDevice = true;
_notify();
try {
final lp = _room?.localParticipant;
if (lp == null) return;
final bool isMicEnabled = lp.isMicrophoneEnabled();
if (isMicEnabled) {
await lp.setMicrophoneEnabled(false);
_enableAudioJustForPreJoinStatus = false;
} else {
await lp.setMicrophoneEnabled(true);
_enableAudioJustForPreJoinStatus = true;
}
} catch (e, st) {
await Logger.logException(e, st);
fw.debugPrint('toggleAudioMute error: $e');
} finally {
_isChangingAudioDevice = false;
_notify();
}
}tall-airline-16756
04/29/2026, 10:46 AMtoggleAudioMute method. The code looks correct for toggling the local microphone with the LiveKit SDK: calling lp.setMicrophoneEnabled(false) should stop sending actual audio data, and true should resume it.
A few diagnostic suggestions to narrow down why you still see packets:
• Confirm which SDK and version you’re using (Web/iOS/Android/Flutter).
• Verify there are no other active local audio tracks besides the microphone.
• Check whether the packets you see are actual audio vs. silence/keep‑alive: use getStats() on the PeerConnection to inspect RTP/packet sizes and audio levels.
• Remember Opus DTX can send very small packets during silence (low bitrate) — that’s not the same as sending actual audio while muted.
Can you tell me your SDK/platform and whether getStats() shows nonzero audio level/bytes while muted? I can then suggest specific commands or next steps.
, with interactive elementswonderful-airport-21213
04/29/2026, 10:47 AMtall-airline-16756
04/29/2026, 10:47 AMsetMicrophoneEnabled(false) still stops sending audio data entirely. Disabling DTX does not cause audio to be sent while the track is muted.
• If you still see packets while muted, it likely means the track isn’t actually muted at the peer connection level or you have another active audio track.
If you want, tell me which SDK/platform and version you’re using (Flutter/web/iOS/Android) and I’ll show how to disable DTX for that SDK and how to inspect getStats() to confirm whether packets are truly audio vs. DTX/keep‑alive.
Sources: Bringing Zoom's end-to-end optimizations to WebRTC | LiveKit, with interactive elementswonderful-airport-21213
05/06/2026, 9:58 AMtall-airline-16756
05/06/2026, 9:59 AMparticipantDisconnected (or participant_left) and trackUnpublished — remove the participant and UI entry when those fire.
2. Check server logs/webhooks for mismatched join/leave events for that participant SID.
3. Ensure you explicitly unpublish/stop and dispose local tracks when leaving: unpublish track -> stop track -> close/ dispose participant object in your client.
4. Enable verbose SDK logging and capture the signaling messages around when that participant joined/left; look for missing disconnect events or errors.
5. If you see a participant with a track SID but zero published tracks, remove them from the UI and confirm the server reports them as disconnected.
If you share SDK/platform+version and a sample participant SID or trimmed logs (events around join/leave), I’ll tell you the exact events/API calls to inspect or a client-side snippet to force-clean the ghost.
Sources: Bringing Zoom's end-to-end optimizations to WebRTC | LiveKit, with interactive elementswonderful-airport-21213
05/06/2026, 10:02 AMtall-airline-16756
05/06/2026, 10:02 AMparticipantDisconnected / trackUnpublished (or an error occurs while processing those events), the local cache/UI may not remove the participant.
• Intermittent signaling delivery issues can cause some clients to process events slightly later than others.
Immediate troubleshooting steps
1. Confirm you handle these events and remove participants from your UI/cache when they fire:
◦ participantDisconnected (or SDK equivalent)
◦ trackUnpublished / trackUpdated
1. After receiving a leave event, add a short guard delay (50–200 ms) before re-reading the participant list to avoid a race when the SDK applies updates.
2. Enable verbose SDK logging on the clients that show the stale participant and capture the sequence around the leave (join/leave events, track updates). Inspect timestamps/order.
3. Check for concurrent calls that read or modify the participant list; serialize those operations if needed.
4. Verify there are no additional active tracks published with the same identity (e.g., reconnection attempts or duplicate publishes).
5. If you can reproduce reliably, capture client logs showing the leave event arrival and the subsequent participant-list query.
If you’d like, share a trimmed log showing: the leave event timestamp, the SDK event handling logs on a client that still lists the participant, and the exact moment you query the participant list. With that I can point to the exact race or handler gap and suggest a minimal code fix.
, with interactive elementswonderful-airport-21213
05/06/2026, 10:10 AMtall-airline-16756
05/06/2026, 10:10 AMparticipantDisconnected / trackUnpublished events and remove UI entries immediately.
◦ Add a short guard delay (50–200 ms) before reading participant list after leave events to avoid race conditions.
◦ Serialize access to your local participant cache to avoid concurrent read/write races.
If you want, I can:
• Provide a small code snippet for reconnect logic (your platform), or
• Show how to call and reconcile with listParticipants() (server API) and apply the diff in the client.
Which would you prefer, and what platform/SDK are you using for the client?
Sources: How we built a globally distributed mesh network to scale WebRTC | LiveKit, with interactive elementswonderful-airport-21213
05/06/2026, 10:12 AMtall-airline-16756
05/06/2026, 10:12 AM// assumes RoomServiceClient or RoomService initialized with server credentials
const participants = await roomService.listParticipants(roomName);
participants.forEach(p => {
console.log(p.sid, p.identity, p.state, p.publishedTracks?.length);
});
Next step
• Tell me which server SDK/language you’re using and I’ll provide a copy-paste example showing auth, calling listParticipants(), pagination (if applicable), and a simple diff routine to reconcile client lists., with interactive elementswonderful-airport-21213
05/06/2026, 10:13 AMtall-airline-16756
05/06/2026, 10:13 AMRoomServiceClient.listParticipants() with Flutter in mind.
Quick summary
• listParticipants() is a server‑side API (part of LiveKit server SDKs). You must call it from a trusted backend using your LiveKit API key/secret. The Flutter client cannot and should not call it directly.
• It returns authoritative ParticipantInfo objects: sid, identity, state (JOINED/DISCONNECTED), metadata, published tracks/trackSids, timestamps, etc.
• Use it to reconcile ghost/stale participants shown in the Flutter client.
Recommended approaches
• Backend reconciliation:
a. Implement an endpoint on your server that calls RoomServiceClient.listParticipants(roomName).
b. Return the participant list (or a diff) to the Flutter client.
c. Flutter compares server list vs local SDK list and removes any participants that server reports as DISCONNECTED or absent.
• Client reconnect:
◦ As a simpler alternative, have the Flutter client do a disconnect() then connect() to refresh its local state from the server.
Practical notes
• Authentication: call from server with LiveKit API credentials; never embed secrets in the Flutter app.
• Pagination: some server SDKs support pagination for large rooms—handle page tokens if needed.
• Use state and publishedTracks from ParticipantInfo to decide if a participant is truly present.
If you want, I can:
• Provide a ready‑to‑use server example in Node/Go/Python/.NET showing auth + listParticipants(roomName) and a simple diff routine.
• Provide a short Flutter snippet showing how to call your backend endpoint and reconcile the local participant list.
Which backend language do you plan to use?
, with interactive elementswonderful-airport-21213
05/06/2026, 10:18 AMtall-airline-16756
05/06/2026, 10:18 AMparticipantDisconnected (or equivalent) event and:
▪︎ Remove the participant from your local participant list/UI.
▪︎ Call participant.dispose() (or SDK equivalent) to stop tracks and free resources.
◦ Add a short guard delay (50–200 ms) before reading the participant list after leave events to avoid race conditions.
1. Defensive checks where you query the list
◦ When reading the SDK participant list, verify each participant’s `state`/`connectionState` or publishedTracks before showing them. If state is DISCONNECTED or publishedTracks is empty, remove them from the UI.
1. Force a fresh client state
◦ If stale references persist, call room.disconnect() then room.connect() to re-sync full server state for that client.
1. Server-side reconciliation (authoritative)
◦ Implement a backend endpoint that calls RoomServiceClient.listParticipants(roomName) and returns the canonical list.
◦ From Flutter, fetch that list and reconcile (remove any participants not present or marked DISCONNECTED on the server).
1. Preventive measures
◦ Serialize updates to your local participant cache to avoid concurrent read/write races.
◦ Enable verbose SDK logging when reproducing the issue to capture the leave event and subsequent state transitions.
If you want, I can:
• Provide a small Flutter code snippet showing how to handle the disconnect event and call participant.dispose(), or
• Provide a simple server snippet (your preferred language) that calls listParticipants() and a client-side reconcile example.
Which snippet would help most?
, with interactive elementswonderful-airport-21213
05/06/2026, 10:21 AMtall-airline-16756
05/06/2026, 10:21 AMparticipant.dispose() (or the SDK equivalent) to stop tracks and free resources.
• Ensure your UI checks `state`/`publishedTracks` before rendering a participant (hide if DISCONNECTED or zero tracks).
• Optionally keep a short grace window (50–200 ms) before final removal to avoid races.
Minimal Flutter sketch
// on participant disconnect / when you confirm left:
setState(() {
participants.removeWhere((p) => p.sid == leftSid);
});
participant.dispose(); // stop tracks, free resources
Why this is safe
• The server is authoritative; if it confirmed the leave and there are no active tracks, removing the client-side reference only cleans local state and does not affect the meeting.
• This avoids forcing a disconnect/reconnect and works without server APIs.
If you want, I can provide a precise Flutter snippet showing event handlers for participantDisconnected and a defensive renderer that skips disconnected participants. Which would you prefer?
, with interactive elementswonderful-airport-21213
05/07/2026, 8:47 AMtall-airline-16756
05/07/2026, 8:48 AMdisable_sync toggled).
Immediate checklist to troubleshoot
• Verify deployment topology: single node or cluster, and whether a LB sits in front of nodes.
• Ensure WebSocket passthrough and sticky sessions are enabled on your load balancer (so signaling reaches the same node).
• Check Redis and NATS health and latency; ensure they’re reachable by all LiveKit nodes.
• Confirm all LiveKit components run the same version and config (especially room/state related flags).
• Enable verbose server logs and search for missing or delayed participant_left / participant_disconnected events.
• Reproduce with logging: capture the sequence when a participant leaves and confirm that the server emitted the leave event and broadcasted it to other nodes.
• If single‑node, confirm room_event_broadcast / sync settings are correct and no flags prevent state propagation.
Short mitigation you can apply client‑side
• Continue removing/disposing stale participants locally when you confirm the server reports them gone (safe fix).
• Optionally implement a server endpoint that calls RoomServiceClient.listParticipants() to reconcile clients instead of forcing reconnects.
If you want, share these deployment details and I’ll give targeted steps:
• single node or cluster?
• load balancer type/config (sticky sessions, WebSocket passthrough)?
• Redis/NATS setup (single/clustered, versions)?
• LiveKit server version and config flags., with interactive elementswonderful-airport-21213
05/07/2026, 8:50 AMtall-airline-16756
05/07/2026, 8:50 AMRoomServiceClient.listParticipants() to reconcile clients, or implement a small backend endpoint returning authoritative state for your Flutter app.
1. Consider upgrade
◦ If feasible, test on the latest LiveKit release (post‑1.9.3) — there have been fixes related to state propagation.
If you want targeted steps, tell me:
• Single node or cluster?
• Do you have an LB in front (type/config: nginx/traefik/ALB)?
• NATS/Redis: single or clustered, and any recent errors in logs?
• A representative debug log snippet around a participant leaving (server-side) — I can point to the exact missed event.
If you prefer, I can provide exact commands/config checks for nginx/ALB sticky sessions, Redis/NATS health checks, or a server log filtering command to find participant leave events. Which would help most?
, with interactive elementswonderful-airport-21213
05/07/2026, 8:51 AMtall-airline-16756
05/07/2026, 8:51 AMwonderful-airport-21213
05/07/2026, 8:56 AM