Pages Menu
TwitterRssFacebook

Posted by on Mar 10, 2021 in Azure Communication Services, Development

Learn Azure Communication Services Day 9 – Muting and Unmuting

Learn Azure Communication Services Day 9 – Muting and Unmuting

This blog post is part of a series called “Learn ACS“, all about Microsoft Azure Communication Services. The series covers a high-level overview of capabilities and considerations, then dives into the development detail of using ACS in your application. Find the rest of the posts in the series at learnACS.dev.

In this blog post, we’re going to explore the capabilities of the Azure Communication Services SDK a little bit by seeing how easy it is to add call functionality, using muting and un-muting as an example. We’re going to use our Day 5 sample of making a P2P call as an example, although this code will work with any of the other samples.

I’m going to assume that you have already followed all of the steps in Day 5 to get the sample code up and running. Replace the contents of index.html and client.js with these versions. We’ll talk about how they are different once everything is up and running. Don’t forget: on Line 18, replace the placeholder text with the full URL of your Azure Function created in Day 3, including the code parameter:

index.html

<!DOCTYPE html>
<html>
<head>
<title>Learn ASC Day 9 - Muting and Unmuting</title>
</head>
<body>
<h2>Learn ASC Day 9 - Muting and Unmuting</h2>
<p>Call state <span style="font-weight: bold" id="call-state">-</span></p>
<input id="destination-user-input" type="text" placeholder="ACS User ID to call" value="8:echo123"
style="margin-bottom:1em; width: 300px;" />
<div>
<button id="connect-button" type="button" disabled="false">
Connect
</button>
<button id="disconnect-button" type="button" disabled="true">
Disconnect
</button>
<button id="mute-button" type="button" disabled="true">
Mute
</button>
<button id="unmute-button" type="button" disabled="true">
Unmute
</button>
</div>
<hr/>
<p style="font-family: sans-serif">Hi, I'm Tom! I hope you found this code sample useful. This sample code comes from a series of blog posts about Azure Communication Services. Links for all blog posts can be found at <a href="https://learnacs.dev" target="_blank" rel="noopener">learnACS.dev</a>. I blog at <a href="https://blog.thoughtstuff.co.uk">thoughtstuff.co.uk</a>. You can also <a href="https://www.youtube.com/c/TomMorganTS?sub_confirmation=1" target="_blank" rel="noopener">subscribe to my YouTube channel</a> for videos about ACS (and much more!). </p>
<h4>Disclaimer: This is a sample. It’s not meant for you to take and use without fully understanding what it’s doing. It’s definitely not meant for production use. You should understand the risks of hosting your own ACS instance and associated web-based entry point on the public internet before proceeding. If you end up sharing your access tokens, or there’s a bug in the code and you end up with a huge hosting bill, or find yourself unwittingly hosting other people’s rooms, you’re on your own. This sample code is provided under the <a href="https://opensource.org/licenses/MIT">MIT license</a>, which you should read in full (it’s 21 LOC).</h4>
<script src="./bundle.js"></script>
</body>
</html>

client.js

import { CallClient, CallAgent } from "@azure/communication-calling";
import { AzureCommunicationTokenCredential } from '@azure/communication-common';
const connectButton = document.getElementById('connect-button');
const disconnectButton = document.getElementById('disconnect-button');
const callStateElement = document.getElementById('call-state');
const destinationUserElement = document.getElementById('destination-user-input');
const muteButton = document.getElementById('mute-button');
const unmuteButton = document.getElementById('unmute-button');
let call;
let callAgent;
let callClient;
async function init() {
callClient = new CallClient();
//get an access token to use
const response = await fetch('YOUR ACS TOKEN ISSUING WEB FUNCTION URL HERE (WITH THE CODE). SEE DAY 3');
const responseJson = await response.json();
const token = responseJson.value.item2.token;
const tokenCredential = new AzureCommunicationTokenCredential(token);
callAgent = await callClient.createCallAgent(tokenCredential);
connectButton.disabled = false;
}
init();
connectButton.addEventListener("click", () => {
const destinationToCall = { communicationUserId: destinationUserElement.value};
call = callAgent.startCall([destinationToCall]);
call.on('stateChanged', () => {
callStateElement.innerText = call.state;
})
// toggle button states
disconnectButton.disabled = false;
connectButton.disabled = true;
muteButton.disabled = false;
unmuteButton.disabled = false;
});
disconnectButton.addEventListener("click", async () => {
await call.hangUp();
// toggle button states
disconnectButton.disabled = true;
connectButton.disabled = false;
callStateElement.innerText = '-';
});
muteButton.addEventListener("click", async () => {
await call.mute();
});
unmuteButton.addEventListener("click", async () => {
await call.unmute();
});

Testing it out

To really test this out, you could implement the Day 6 sample to receive a call, or use the Day 8 sample to join a Teams Meeting and add this additional functionality in. Failing either of those options, you can examine the network traffic being sent to know that your mute/unmute calls are being correctly managed.

As before, use a command-line to run this command then browse to the sample application in your browser (usually http://localhost:8080):

npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map

Connect to either another ACS endpoint (or a Teams meeting if you’re using that code), or the test service:

Once the call has connected, play with the mute/unmute buttons to make sure they are working.

If you look at a network trace, you’ll also see that each time you press one of the buttons a new message is posted to the Azure Communication Services service, with a UpdateEndpointState call. In the body you’ll also see the new endpointState with the updated isMuted value:

What’s the code doing?

If you look at the code behind the two new buttons, you’ll see that it’s really minimal – just a simple call to mute and unmute, with no additional parameters needed. In some ways, this simplicity doesn’t justify a whole day to itself – but I wanted to highlight how easy the Azure Communication Services SDK makes dealing with call functions.

There is also a property on the Call object called isMicrophoneMuted which returns a boolean for the current mute state of the local participant. This can be useful in building up toggle buttons or displaying mute state. Be aware though, that the mute() and unmute() methods used above both return promises so make sure you wait for them before you read the property again, otherwise you’ll get an old value. There isn’t an event fired when the local isMicrophoneMuted property changes.


Today, we took our existing ACS code and quickly added mute/unmute buttons. Tomorrow we’re going to look at adding video. Links for all blog posts can be found at learnACS.dev. You can also subscribe to my YouTube channel for videos about ACS (and much more!).

Written by Tom Morgan

Tom is a Microsoft Teams Platform developer and Microsoft MVP who has been blogging for over a decade. Find out more.
Buy the book: Building and Developing Apps & Bots for Microsoft Teams. Now available to purchase online with free updates.

1 Comment

  1. Hi,
    How can I have a look insigde code client.js and html ? I dont see this option on this page ?

Post a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.