Remote Mute/Unmute

You're running a video call room and decide that someone who's currently talking shouldn't be talking.

You'd prefer they'd stay mute. Or perhaps you want their video turned off as well as their audio. You're looking for a remote mute.

Muting can apply to both audio and video.

Let's understand the steps:

Permissions

Can't let just anyone mute others. First, you need to create a role with the permissions to mute others and also to ask them to Unmute.

Permissions - Remote mute/unmute

The permission to mute others is within PermissionsParams mute and you should check for that within the HMSRole of the peer to see if they have it.

Similarly, the permission to Unmute other peers is within PermissionsParams unmute.

Here's how to check whether the local peer has permission to mute or Unmute others. You can do it like this:

Future<bool> isAllowedToMuteOthers() async{ return (await hmsSDK.getLocalPeer()).role.permission!.mute; } Future<bool> isAllowedToUnMuteOthers(){ return (await hmsSDK.getLocalPeer()).role.permission!.unMute; }

hmsSDK.getLocalPeer() will not return null as long as you're in a preview or in a meeting room. Since you likely won't need to check for permissions if you're not in one So, it would be ok.

Mute/Unmute other peers

HMSSDK provides dedicated methods to mute/unmute:

  • Individual peer
  • Specific role

These methods will only work if the peer has permission to mute/unmute another peer's audio/video. The permission can be checked as the steps mentioned above.

Let's look at each of them:

Individual peer

We can use the changeTrackState method to mute/unmute remote peer's audio/video

class Meeting implements HMSUpdateListener, HMSActionResultListener{ ... void changeTrackState(HMSTrack forRemoteTrack, bool mute, HMSActionResultListener hmsActionResultListener) { /// [forRemoteTrack] : track whose state needs to be changed(mute -> unmute or unmute -> mute) /// Set [mute] to true if the track needs to be muted, false otherwise. ///[hmsActionResultListener]: an instance of a class that implements HMSActionResultListener //Here this is an instance of a class that implements HMSActionResultListener, that is, Meeting if( //peer has permission to change track state localPeer?.role.permissions.mute ){ hmsSDK.changeTrackState( forRemoteTrack: forRemoteTrack, mute: mute, hmsActionResultListener: this); } else{ //Peer doesn't have permission to mute/unmute other peers } } void onSuccess( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments}) { switch (methodType) { ... case HMSActionResultListenerMethod.changeTrackState: //Track state successfully changed break; } } void onException( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments, required HMSException hmsException}) { switch (methodType) { ... case HMSActionResultListenerMethod.changeTrackState: // Check the HMSException object for details about the error break; } } }

If the changeTrackState method is successful we will get the onSuccess callback on HMSActionResultListener attached and track update in onTrackUpdate.

Specific role

We can use the changeTrackStateForRole method to mute/unmute peers under specific roles.

class Meeting implements HMSUpdateListener, HMSActionResultListener{ ... void changeTrackStateForRole(bool mute, HMSTrackKind? kind, String? source, List<HMSRole>? roles, HMSActionResultListener? hmsActionResultListener) { if(//peer has permission to change track state localPeer?.role.permissions.mute) { /// Set [mute] true if the track needs to be muted, false otherwise /// [kind] is the HMSTrackType that should be affected. If this and the source are specified, it is considered an AND operation. If not specified, all track sources are affected. /// [source] is the HMSTrackSource that should be affected. If this and type are specified, it is considered an AND operation. If not specified, all track types are affected. /// [roles] is a list of roles, that may have a single item in a list, whose tracks should be affected. //If not specified, all roles are affected. ///[hmsActionResultListener]: an instance of a class that implements HMSActionResultListener //Here this is an instance of a class that implements HMSActionResultListener, that is, Meeting HMSSDK.changeTrackStateForRole( mute: mute, kind: kind, source: source, roles: roles, hmsActionResultListener: this); } else{ //Peer doesn't have permission to mute/unmute other peers } } void onSuccess( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments}) { switch (methodType) { ... case HMSActionResultListenerMethod.changeTrackState: break; case HMSActionResultListenerMethod.changeTrackStateForRole: //Track state successfully changed break; } } void onException( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments, required HMSException hmsException}) { switch (methodType) { ... case HMSActionResultListenerMethod.changeTrackState: break; case HMSActionResultListenerMethod.changeTrackStateForRole: // Check the HMSException object for details about the error break; } } }

If the changeTrackStateForRole method is successful we will get the onSuccess callback and track update in onTrackUpdate similar to changeTrackState.

If roles is passed as an empty list then all the roles will get affected.

Handling a mute callback

Mute callbacks are automatically applied to the receiver. No action is required.

Handling an unmute callback

Let's turn the table now to what happens if a remote peer wishes to mute/unmute our audio/video.

  • In case when remote peer mutes our audio/video HMSSDK performs it automatically without asking permission In another case, we get the onChangeTrackStateRequest if we accept the request we need to call toggleCameraMuteState or toggleMicMuteState according to the request.

Let's understand this with a diagram:

accept-change-track-state

Now let's do it step-by-step:

PeerA calls changeTrackState on PeerB's track

hmsSDK.changeTrackState( forRemoteTrack: "PeerB's track", mute: mute, hmsActionResultListener: this);

PeerB receives onChangeTrackStateRequest

void onChangeTrackStateRequest( {required HMSTrackChangeRequest hmsTrackChangeRequest}){}

How this is implemented in the example app can be found here

Let's look at the HMSTrackChangeRequest structure :

class HMSTrackChangeRequest { bool mute; HMSPeer requestBy; HMSTrack track; }

This contains information on which track is requested for unmuting. Check the track type and call the unmute methods accordingly.

public void checkTrack(HMSTrack track) { if(track.kind == HMSTrackType.kHMSTrackKindAudio) { //Requested track is an audio track } else if (track.kind == HMSTrackType.kHMSTrackKindVideo) { //Requested track is a video track } }

So final implementation looks like this:

class Meeting implements HMSUpdateListener, HMSActionResultListener{ ... public void checkTrack(HMSTrack track) { if(track.kind == HMSTrackType.kHMSTrackKindAudio) { hmsSDK.toggleMicMuteState(); } else if (track.kind == HMSTrackType.kHMSTrackKindVideo) { hmsSDK.toggleCameraMuteState(); } } void onChangeTrackStateRequest( {required HMSTrackChangeRequest hmsTrackChangeRequest}){ checkTrack(hmsTrackChangeRequest.track) } }

PeerB calls toggleMicMuteState/toggleCameraMuteState depending on the track kind

If the track is an audio track then PeerB calls toggleMicMuteState

hmsSDK.toggleMicMuteState();

If the track is a video track then PeerB calls toggleCameraMuteState

hmsSDK.toggleCameraMuteState();

Now all the peers will receive an onTrackUpdate with the type as trackUnmuted


Have a suggestion? Recommend changes ->

Was this helpful?

1234