MacOS - detect when camera is turned on/off
Asked Answered
L

7

21

I want to automate a personal workflow that is based on camera usage on my MBP.

Basically I want to know if any of the cameras (built-in or USB) has been turned on or off, so I can run a program or script I'll create.

I think it's OK if I need to poll for the cameras statuses but an event or callback based solution would be ideal

Labium answered 4/3, 2020 at 22:32 Comment(6)
I would like to do the same thing so I can connect it to an "On Air" indicator, letting my family know when I'm on a Zoom / Teams call.Douma
@PatrickMcElhaney Great idea!Wretched
@PatrickMcElhaney do you have larger snippets of sample code how you monitored the log steam? Your use case is identical to mine.Proudhon
@Proudhon I haven’t written any code yet. My answer is a command entered in Terminal and the output. The next challenge is finding a device that I can use for the “On Air” light and control with my computer. Doesn’t have to be anything fancy, I just don’t have experience with that kind of stuff. Once that’s solved, I’ll have no problem connecting the “glue” that connects the log output to the device.Douma
@PatrickMcElhaney I have that part setup with an LED strip connected to home-assistant. With the command below though, I'm not sure how multiple on/off states which produce multiple lines of output will work. Cheers. :)Proudhon
@Proudhon I created a chat room so we can discuss next steps.Douma
D
15

This seems to work.

❯  log stream | grep "Post event kCameraStream"
2020-12-01 14:58:53.137796-0500 0xXXXXXX   Default     0x0                  XXX    0    VDCAssistant: [com.apple.VDCAssistant:device] [guid:0xXXXXXXXXXXXXXXXX] Post event kCameraStreamStart
2020-12-01 14:58:56.431147-0500 0xXXXXXX   Default     0x0                  XXX    0    VDCAssistant: [com.apple.VDCAssistant:device] [guid:0xXXXXXXXXXXXXXXXX] Post event kCameraStreamStop
2020-12-01 14:58:56.668970-0500 0xXXXXXX   Default     0x0                  XXX    0    VDCAssistant: [com.apple.VDCAssistant:device] [guid:0xXXXXXXXXXXXXXXXX] Post event kCameraStreamStart

Some of the numbers in the output are redacted with Xs because I don't know what they mean. :)

Douma answered 1/12, 2020 at 21:0 Comment(3)
This works on my machine too. Good job! If you develop something cool with it let me know!Wretched
This works great! You can catch KCameraStreamStart and KCameraStreamStop. One hickup, on older hardware the log seems to be different. On my 2013 MBP, the proper log catch would be 'log stream | grep "AppleCameraAssistant: StartHardwareStream"' On my 2018 MBP, it's the KCameraStream* event like Patrick mentioned. This was tested on the exact same version of Catalina.Unfolded
This doesn't seem to work in Monterey, fwiw.Typehigh
M
12

Big Sur

log stream --predicate 'eventMessage contains "Post event kCameraStream"' only works up to macOS Big Sur

Monterey

On macOS Monterey you'll have to use a slightly different predicate:

$ log stream --predicate 'subsystem contains "com.apple.UVCExtension" and composedMessage contains "Post PowerLog"'

Timestamp                       Thread     Type        Activity             PID    TTL  
2021-10-27 12:21:13.366628+0200 0x147c5    Default     0x0                  353    0    UVCAssistant: (UVCExtension) [com.apple.UVCExtension:device] UVCExtensionDevice:0x1234005d7 [0x7fe3ce008ca0] Post PowerLog {
    "VDCAssistant_Device_GUID" = "00000000-1432-0000-1234-000022470000";
    "VDCAssistant_Power_State" = On;
}
2021-10-27 12:21:16.946379+0200 0x13dac    Default     0x0                  353    0    UVCAssistant: (UVCExtension) [com.apple.UVCExtension:device] UVCExtensionDevice:0x1234005d7 [0x7fe3ce008ca0] Post PowerLog {
    "VDCAssistant_Device_GUID" = "00000000-1432-0000-1234-000022470000";
    "VDCAssistant_Power_State" = Off;
}

Ventura

Here you can use log stream --predicate 'eventMessage contains "Cameras changed to"', which even gives you a list of active cameras:

Timestamp                       Thread     Type        Activity             PID    TTL  
2023-03-20 14:07:56.340362+0100 0x21ee     Default     0x0                  1144   0    ControlCenter: [com.apple.controlcenter:video-effects] Cameras changed to [ControlCenterApp.VideoCamera(id: "FOO-0176-46F7-B185-BAR", name: "FaceTime HD-kamera", utType: Optional(<UTType 0xFOO1c41BAR> com.apple.macbookpro-16-2023 (not dynamic, declared)), batteryInfo: nil, deskViewID: nil, supportedEffects: [portrait], appEffects: [ControlCenterApp.AppVideoEffects(bundleIDs: Set(["com.apple.PhotoBooth"]), bundleNames: ["com.apple.PhotoBooth": "Photo Booth"], enabledEffects: Set([]), unavailableEffects: Set([]))])]
2023-03-20 14:08:09.114873+0100 0x21ee     Default     0x0                  1144   0    ControlCenter: [com.apple.controlcenter:video-effects] Cameras changed to []
Malony answered 27/10, 2021 at 10:24 Comment(2)
This works great on Monterey, thanks! I'm using a USB camera and this immediately detected on/off changes.Typehigh
I have a 2019 (intel) macbook pro with Ventura installed, and the "Monterey" answer worked for me.Strategic
C
3

In macOS Ventura I find this incantation works:

log stream --predicate 'sender contains "appleh13camerad" and (composedMessage contains "PowerOnCamera" or composedMessage contains "PowerOffCamera")'
Cassicassia answered 21/12, 2022 at 2:24 Comment(1)
This works too, and gives you a list of active cameras: log stream --predicate 'eventMessage contains "Cameras changed to"'Malony
W
1

As far as I know, you can poll for the camera usage with:

$ lsof -n | grep "AppleCamera"

or change "AppleCamera" with the driver name of an external camera. Other relevant names to try are: "USBVDC" or "VDCAssistant" or "FaceTime" (or "iSight" in older Macs).

You should get one line with the name and pid of the process using the webcam or nothing, which means that it is not in use.

You could check for all of the keywords and decide that the camera is in use if any of these keywords give you something back.

The -n option is to skip resolving DNS names of IP connections and this speeds the command a lot.

As a side note, I use this app to know when any app is using the microphone and/or webcam: OverSight

Wretched answered 29/11, 2020 at 20:54 Comment(2)
When I run that command I get no results. It's a 2019 16-inch MBP. Photo Booth is using the camera and the LED is on. Even if that did work, it takes > 10 seconds for the command to run, which is too much lag for what I'm trying to do. I've tried watching the log file of OverSight as well. It seems to be hit and miss.Douma
@PatrickMcElhaney I admit I didn't test it thoroughly. I tried with Zoom on my computer and it worked. Further testing and google researches show that the camera usage could be detected also with "USBVDC" or "VDCAssistant" or "FaceTime" (or "iSight" in older Macs). You could have an OR condition with this names. The speed issue can be solved passing the -n parameter. I will update my answer.Wretched
B
1

MacOS Sonoma v. 14.2 solution (works on my 13-inch, M1, 2020 Macbook Pro)

log stream --predicate 'process == "kernel" && (eventMessage contains "AppleH13CamIn::power_off_hardware" || eventMessage contains "AppleH13CamIn::power_on_hardware")'
Butyraceous answered 1/2, 2024 at 13:25 Comment(0)
E
0

Unfortunately none of these seem to work any more in 14.2.x

I've tried

sender contains "appleh13camerad" and (composedMessage contains "PowerOnCamera" or composedMessage contains "PowerOffCamera")'
Cameras changed to"'

and lastly

subsystem contains "com.apple.UVCExtension" and composedMessage contains "Post PowerLog"'

UVCExtension seems to kinda work , in that it only triggers when using an external webcam, a Studio Display in my case. If am just using the laptop on its own the built in webcam does not appear to use this subsystem

Evalyn answered 2/1, 2024 at 20:37 Comment(0)
R
0

On MacOS Sonoma 14.5, you can use the following:

exec log stream --predicate '(eventMessage CONTAINS "AVCaptureSessionDidStartRunningNotification" || eventMessage CONTAINS "AVCaptureSessionDidStopRunningNotification")'

This is more elegant as it will trigger whenever a camera turns on/off, even an external one.

Rame answered 25/6, 2024 at 4:18 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.