Overview
This guide will help you:- Understand why blocking a user does not automatically silence them in voice
- Populate a per-player mute list using Discord block relationships (client-side) or your game server (server-side)
- Apply that mute list using a shared implementation that works for both approaches
- Satisfy bi-directional mute requirements (if A blocks B, neither can hear the other)
Prerequisites
Before you begin, make sure you have:- Completed the Getting Started Guide
- A working lobby from the Managing Lobbies guide
- Familiarity with Managing Voice Chat
- Familiarity with Managing Relationships
Why Voice Muting Must Be Handled Explicitly
Discord Blocking Does Not Silence Voice
CallingClient::BlockUser prevents a user from sending friend requests or messages, but it does not mute them in a lobby voice call. If you want a blocked player to be inaudible, your game must explicitly call Call::SetLocalMute.
Block Signals May Come From Outside Discord
Your game may receive block information from sources other than Discord — for example, from a platform-level or game-level block list. In these cases, there is no Discord relationship to query on the client. Your server needs to supply this information to clients through another mechanism, such as lobby member metadata.Bi-Directional Muting
Call::SetLocalMute is one-directional: calling it on A’s client only stops A from hearing B — it has no effect on what B hears. To silence audio in both directions, both clients must independently call SetLocalMute on each other.
The challenge is that both players need to independently know to mute each other. A may know to mute B based on whatever block signal they have access to — but B may not have that same information, and vice versa. Each client can only act on what it knows.
The approaches in this guide address this through lobby member metadata: each player writes their mute_list to their own member metadata, which is visible to all lobby members. This lets players detect when someone else has listed them and mute that person in return, regardless of the original source of the block signal.
Step 1: Populate the Mute List
Both approaches in this guide work by writing amute_list key to each lobby member’s metadata. The value is a comma-separated list of Discord user IDs that player should mute in the voice call. How that list gets populated is what differs.
Client-Side
Use this approach when the block information your game needs is available directly on the client — for example, from Discord’s relationship system, your own in-game friend/block system, or any other client-accessible data source. When joining the lobby, build the mute list from whatever client-side data you have and write those IDs to your own member metadata usingClient::CreateOrJoinLobbyWithMetadata. This makes your mute list visible to other lobby members so they can mute you in return.
The example below uses Discord’s block relationships as the data source — substitute your own logic for building myMuteList if your game uses a different signal.
Member metadata has a maximum total length of 1,000 characters. At ~19 characters per Discord snowflake ID plus a comma separator, this comfortably fits around 50 blocked users.Look at Server Side integration if your needs exceed this limitation.
Server-Side
Use this approach when block information comes from an external source — such as a platform-level blocklist, when you want to guarantee bi-directional muting without relying on clients to populate their own metadata or when you need to filter lobby blocklists to only those in the lobby to support players who have very large potential blocklists. Your server code can filter each player’s block list down to only the other members in the session and writes it to their metadata when creating the lobby. Since you know exactly who is joining, you only need to consider block relationships between those specific players — not each player’s entire block list. The client-side code in Step 2 handles the reverse direction: each client also checks whether any other participant has listed them.Step 2: Apply the Mute List
Once themute_list metadata is populated — by either approach above — the client code that reads it and applies mutes is the same.
On Lobby Join
After joining the lobby and starting the voice call, runApplyMuteChecks against every other lobby member.
Handling Participants Who Join Later
RegisterCall::SetParticipantChangedCallback to apply mutes when new participants join the voice call mid-session.
This fires with added = true when someone joins and added = false when they leave.
Best Practices
- Consider filtering at matchmaking time. The cleanest experience is to avoid placing blocked players in the same lobby at all. Voice muting handles the audio side, but blocked players may still see each other in the game UI.
- Update mutes when relationships change. If a player blocks someone during an active session, call
Call::SetLocalMuteimmediately and update yourmute_listmember metadata by re-callingClient::CreateOrJoinLobbyWithMetadatawith the new list. For the server-side approach, update the member’s metadata viaPUT /lobbies/{lobby.id}/members/{user.id}. - Keep metadata compact. Lobby member metadata has a 1,000-character limit. Comma-separated ID strings are more efficient than JSON objects.
Next Steps
Managing Voice Chat
Add in-game voice communication to your lobbies.
Managing Lobbies
Create and manage game lobbies for matchmaking.
Managing Relationships
Manage Discord user relationships including friends and blocked users.
#social-sdk-dev-help channel for support from the community.
If you encounter a bug while working with the Social SDK, please report it here: https://dis.gd/social-sdk-bug-report
Change Log
| Date | Changes |
|---|---|
| April 22, 2026 | Initial release |