Meeting mute toggle from anywhere on MacOS
Table of Contents
Problem #
On a virtual meeting. Have another app or window open. Heard my name called, and needed to respond. Quickly hunted for Teams window, and then for unmute button.
It happens every day, in almost every meeting.
Plus with IDEs and Docker open, and MS Teams running all day, many times the UI is unresponsive and I can’t get off mute.
I want a way to be able to toggle mute for MS Teams from anywhere.
Ideally menu bar icon + keyboard shortcut.
Solution #
Searched Google and the first response from Geeker’s Digest had a great solution: a tool called Hammerspoon.
Installation #
Install with brew:
brew install --cask hammerspoon
Download, unzip, and install the MicMute Spoon from here. Installation should just be double clicking on the MicMute.spoon
file.
Configure Hammerspoon #
Create a ~/.hammerspoon/init.lua
file which loads MicMute, and sets the appropriate keybinding. The keybinding I chose was 3 modifier keys (command, option, and shift) and then the m
key.
mkdir -p ~/.hammerspoon/Spoons
cat << EOF > ~/.hammerspoon/init.lua
local mm = hs.loadSpoon("MicMute")
local mmkeybind = {"toggle"}
mmkeybind.toggle = {[1]={"cmd", "option", "shift"}, [2]="m"}
local mmfunctionkeybind = {"toggle"}
mmfunctionkeybind.toggle = {[1]={}, [2]="f19"}
mm:bindHotkeys(mmkeybind, 1)
mm:bindHotkeys(mmfunctionkeybind, 1)
EOF
If you also want to add another button on the menu bar to automatically switch to the Teams window, add this:
cat << EOF >> ~/.hammerspoon/init.lua
-- Teams Show Button
local teamsShowButton = hs.menubar.new()
local logo = hs.image.imageFromAppBundle("com.microsoft.teams")
logo:size({w=16,h=16})
teamsShowButton:setIcon(logo)
function showTeams()
local teams = hs.application.find("com.microsoft.teams")
if not (teams == null) then
teams:activate()
end
end
teamsShowButton:setClickCallback(showTeams)
EOF
At this point, you should now have a .hammerspoon
folder with a Spoons subfolder and an init.lua
file. The Spoons subfolder should have MicMute.spoon
inside. The MicMute.spoon
is a folder with another init.lua and a docs.json file inside.
$ ls ~/.hammerspoon
Spoons init.lua
$ ls ~/.hammerspoon/Spoons
MicMute.spoon
$ ls ~/.hammerspoon/Spoons/MicMute.spoon
docs.json init.lua
Extend MicMute for Teams support #
Originally, MicMute only supported Zoom. I put in a Github Pull Request to extend MS Teams support to MicMute (v1.1). Depending on when you read this post, that might already be merged in (so no need to do the next step).
If you need to make that update, replace the toggleMicMute
function inside the MicMute.spoon/init.lua
file (using your editor of choice). You can see it here.
function obj:toggleMicMute()
local mic = hs.audiodevice.defaultInputDevice()
local zoom = hs.application'Zoom'
local teams = hs.application.find("com.microsoft.teams")
if mic:muted() then
mic:setInputMuted(false)
if zoom then
local ok = zoom:selectMenuItem'Unmute Audio'
if not ok then
hs.timer.doAfter(0.5, function()
zoom:selectMenuItem'Unmute Audio'
end)
end
end
if teams then
local ok = teams:selectMenuItem'Unmute'
if not ok then
hs.timer.doAfter(0.5, function()
hs.eventtap.keyStroke({"cmd","shift"}, "m", 0, teams)
end)
end
end
else
mic:setInputMuted(true)
if zoom then
local ok = zoom:selectMenuItem'Mute Audio'
if not ok then
hs.timer.doAfter(0.5, function()
zoom:selectMenuItem'Mute Audio'
end)
end
end
if teams then
local ok = teams:selectMenuItem'Mute'
if not ok then
hs.timer.doAfter(0.5, function()
hs.eventtap.keyStroke({"cmd","shift"}, "m", 0, teams)
end)
end
end
end
obj:updateMicMute(-1)
end
Run & Test it #
- Launch Hammerspoon (either from Applications, Spotlight, or Alfred)
- Click the menu bar Hammerspoon icon and reload the config
- Click the menu bar Hammerspoon icon and open the Console to verify that there are no errors. The last line should probably say
Done.
- Assuming everything before this step went correctly, you should now have another Microphone menu bar item that if you click on it toggles between
🎙 On
and📵 Muted
- Test the keyboard shortcut to validate that it toggles
- Launch a Zoom or Teams meeting, and validate that the menu bar and keybindings both toggle the meeting correctly
Troubleshooting #
- If there are any errors, you should see them on the Hammerspoon console
- If you make any changes to your
init.lua
or theMicMute.spoon/init.lua
files and you want to test them, choose the Reload config option in the Hammerspoon menu bar dropdown - If you want to add some log statements for debugging, add something like this to the top of the Lua files:
local log = hs.logger.new("mine", "debug")
log.d("HI")