如何检测 OS X 上的麦克风使用情况?

问题描述 投票:0回答:6

有没有办法检测我的 Mac 麦克风何时在使用?类似于 Mikro Snitch 所做的事情吗?这可以在 Cocoa 中完成吗?

objective-c swift macos cocoa
6个回答
7
投票

这并不是真正的 Objective-C 或 Cocoa 解决方案,但如果您愿意进行子进程调用,请尝试以下操作:

ioreg -c AppleHDAEngineInput | grep IOAudioEngineState

当音频输入处于活动状态时,您将看到

"IOAudioEngineState" = 1

另外,尝试搜索

IOAudioEngineNumActiveUserClients
,每个应用程序接收音频,该值都会加一。


5
投票

有办法检测我的 Mac 麦克风何时在使用吗?

简单的答案 - 是的,但这并不容易!

这可以在 Cocoa 中完成吗?

如文档所述:-

Cocoa 应用程序层主要负责应用程序的外观及其对用户操作的响应

所以这不会覆盖麦克风,如果覆盖了,对于您想要的效果来说,它的级别太高了。

关于如何执行此操作的详细答案对于 Stack Overflow 来说非常复杂且过于宽泛。但是,为了让您朝着正确的方向前进,您需要创建一个 IOKit 内核扩展驱动程序 (KEXT) 并充分了解 I/O 注册表


5
投票

我之前的答案不再有效并且相当脆弱(它仅适用于内部设备)。这是 PyObjC 的快速解决方案,可以相当轻松地转换为 Objective-C 或 Swift。

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]))

请注意,此脚本将运行一次,但如果您的应用程序没有运行循环,如此问题中所示,重复调用

AudioObjectGetPropertyData
将始终返回相同的结果。


2
投票

我正在开发用于检测相机/麦克风状态的 go 模块(使用

cgo
),这是我为
IsMicrophoneOn()
精心设计的 Objective-C 实现:https://github.com/antonfisher/go-media-devices -state/blob/main/pkg/microphone/microphone_darwin.mm

我使用

kAudioHardwarePropertyDevices
获取所有音频设备(麦克风 + 扬声器),然后使用
[AVCaptureDevice deviceWithUniqueID:uid]
按设备 UID 仅过滤掉麦克风。


2
投票

基于@kgutwin的解决方案,我能够找到一种方法来获取MacOS Big Sur上麦克风的活动状态。 实际上只是将

-c
-l
交换。所以所有的荣誉都归功于@kgutwin。

ioreg -l |grep IOAudioEngineState


0
投票

我使用脚本和 HomeAssistant + hass-cli 做了类似的事情。 我的 LED 使用 ESPHome 被定义为开关,但如果你的是灯,请将开关替换为灯。

haToken="YOUR_TOKEN_HERE"
device_id="YOUR_LED_DEVICE_ID_HERE"
    

# Store a default status of 0 to initialize oldStatus
    micStatus=0
    
    
    #start a loop that should never end 
    while true ; do
        oldStatus=${micStatus}
        micStatus=$(ioreg -l | grep IOAudioEngineNumActiveUserClients | sed 's/.*\(.\)$/\1/')
    
        if [[ "${micStatus}" == "1" ]]; then
            #Recording in progress!
            if [[ "${oldStatus}" == "0" ]]; then
                #Recording switched on from being off
                #Turn on the LED
                /opt/homebrew/bin/hass-cli -x --token "${haToken}" service call switch.turn_on --arguments device_id=${device_id}
            fi
        else
            #No recording
            if [[ "${oldStatus}" == "1" ]]; then
                #Recording switched off from being on
                #Turn the LED off
                /opt/homebrew/bin/hass-cli -x --token "${haToken}" service call switch.turn_off --arguments device_id=${device_id}
            fi
        fi
    
        #Sleep 5 seconds to ensure we use as little CPU as possible
        sleep 5
    
    done

希望这对大家有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.