How to detect microphone usage on OS X?
Asked Answered
S

5

11

Is there a way to detect when the microphone of my Mac is in use? Similar to what Mikro Snitch does? Can this be done in Cocoa?

Scotland answered 19/9, 2016 at 13:37 Comment(0)
E
7

This isn't really an Objective-C or Cocoa solution, but if you're willing to do a subprocess call, try this:

ioreg -c AppleHDAEngineInput | grep IOAudioEngineState

You will see "IOAudioEngineState" = 1 when audio input is active.

Also, try searching for IOAudioEngineNumActiveUserClients which increases by one for each app taking in audio.

Eck answered 18/5, 2017 at 20:50 Comment(3)
I just discovered this may only apply for the internal/built-in microphone... the IOAudioEngineState remains zero when using a bluetooth audio device.Eck
I know this is old question, what about latest 2019-2020 mic?Instruction
I think this is related to CoreAudio as well. kaudiodevicepropertydeviceisrunningsomewhere is not working for external device like bluetooth audio device. it always return 0 even though it's in use and the weird thing is that if you do listenerBlock on kaudiodevicepropertydeviceisrunningsomewhere, it gets triggered when being used or not used with the bluetooth devices but you just don't get the correct data I guessHedgehog
S
5

Is there a way to detect when the microphone of my Mac is in use?

Simple answer - Yes, but it's not going to be easy!

Can this be done in Cocoa?

As the documentation states: -

The Cocoa application layer is primarily responsible for the appearance of apps and their responsiveness to user actions

So this doesn't cover the microphone and if it did, it would be too high level for what you want.

A detailed answer on how to do this is complex and too broad for Stack Overflow. However, to set you off in the right direction, you need to create an IOKit kernel extension driver (KEXT) and have a good understanding of the I/O Registry

Shayneshays answered 20/9, 2016 at 12:58 Comment(0)
E
5

My previous answer no longer works and was rather brittle (it only applied to the internal device). This is a quick solution for PyObjC, which can be translated to Objective-C or Swift reasonably easily.

import AVFoundation
import CoreAudio
import struct

mic_ids = {
    mic.connectionID(): mic
    for mic in AVFoundation.AVCaptureDevice.devicesWithMediaType_(
        AVFoundation.AVMediaTypeAudio
    )
}

opa = CoreAudio.AudioObjectPropertyAddress(
    CoreAudio.kAudioDevicePropertyDeviceIsRunningSomewhere,
    CoreAudio.kAudioObjectPropertyScopeGlobal,
    CoreAudio.kAudioObjectPropertyElementMaster
)

for mic_id in mic_ids:
    response = CoreAudio.AudioObjectGetPropertyData(mic_id, opa, 0, [], 4, None)
    print('Mic', mic_ids[mic_id], 'active:', bool(struct.unpack('I', response[2])[0]))

Note that this script will work once through, but if your app does not have a run loop, as observed in this question, repeated calls to AudioObjectGetPropertyData will always return the same result.

Eck answered 23/10, 2020 at 19:37 Comment(4)
Just started a new Swift project and seem to get a lot of deprecated features when tryin get at the mic from AVCaptureDevice. I think devicesWithMeidaType was replaced with devices which is now deprecated in favor of AVCaptureDevice.DiscoverySession. Seen this answered two days ago and was curious if you were targeting old frameworks? Trying to just write some fun code to know when the mic is on but seems strangely difficult on macOS.Fyke
@Fyke I was using old code samples - it works for me on Catalina, and while I saw that deprecation warning, I ignored it because I just wanted to get it working... if you get it working with AVCaptureDevice.DiscoverySession, can you post your code?Eck
Is there a way to determine which application is using the microphone, like the menu bar widget in macOS?Protactinium
@Protactinium have you found a way? I'm trying to see if there's a way to do what you wrote.Hedgehog
C
2

I'm working on go module that detects camera/microphone state (using cgo) and here is my crafted Objective-C implementation for IsMicrophoneOn(): https://github.com/antonfisher/go-media-devices-state/blob/main/pkg/microphone/microphone_darwin.mm

I used kAudioHardwarePropertyDevices to get all audio devices (microphones + speakers) and then [AVCaptureDevice deviceWithUniqueID:uid] to filter out only microphones by device UID.

Condenser answered 13/1, 2021 at 7:52 Comment(0)
S
2

Based on the solution of @kgutwin I was able to find a way to get the active state of the mic on MacOS Big Sur. Actually only exchanged the -c with an -l. So all kudos to @kgutwin.

ioreg -l |grep IOAudioEngineState

Spitz answered 5/2, 2021 at 21:8 Comment(2)
This was helpful thanks. If you run this it will just output the boolean value: ioreg -l | grep -o "\"IOAudioEngineState\" = 1" | wc -lEger
This works on Mojave using the built-in mic, but not using Bluetooth headphones unfortunately.Boutis

© 2022 - 2024 — McMap. All rights reserved.