Can I trigger a HomeKit scene when my laptop's camera is turned on or off?

It doesn't seem possible to do this with HomeKit, but it is possible to make a script that communicates with IFTTT, and IFTTT will communicate with Hue directly. If you have a Hubitat hub or Home assistant that will also work as a webhook-in-the-middle.

I got through the first part easily: getting a push when camera is opened or closed. To detect camera on:

while true; do log stream | grep -o -m 1 "Post event kCameraStreamStop" > /dev/null && echo STOPPED; done

And camera off:

while true; do log stream | grep -o -m 1 "Post event kCameraStreamStart" > /dev/null && echo STARTED; done

These can be easily converted into a silent, single script that launches at startup. To communicate with the bulbs, we will replace "echo STARTED/STOPPED" with curl to an IFTTT webhook. So you need to make an IFTTT account (If you have used up more than one of your 3 free rules, create another account unless you're paying for premium already), and link up Hue with a webhook. Curl will call this webhook and set your hue bulb to whatever color, Kelvin, and brightness you want or turn it off. If you need more specific guidance then I can help you.


With the Shortcuts app and its shortcuts command line utility, it's now possible to trigger specific shortcuts that control your HomeKit scenes and accessories.

Overall steps

  1. Identify events for your triggers.
  2. Use the Shortcuts app to create shortcuts that trigger your desired HomeKit actions.
  3. Create a script that triggers shortcuts when the camera turns on/off.
  4. Run the script manually or automatically.

Identify events for your triggers

As of MacOS 12.1 Monterey, the Post event kCameraStreamStart and kCameraStreamStop events referenced in the answer by anonymous are no longer logged, but there are new equivalents. It's likely that the event logs may change over time, so first check that these are still correct.

In Terminal, run this to filter the logs to the expected messages as of Monterey:

log stream | /usr/bin/grep -E 'UVCAssistant:.*(stop|start) stream'

While that's running, open the Photo Booth app. You'll hopefully see lines like these output from the filtered log stream when the camera starts and stops (when you quit the app).

2022-01-04 14:56:58.628006-0500 0xb35b3    Default     0x18025b             266    0    UVCAssistant: (UVCFamily) [com.apple.UVCFamily:device] UVCUSBDeviceStreamingInterface: 0x1000005a6 [0x7fcd7bd08260] [start stream] format : UVCDeviceStreamFormat:[1280 * 720 (YUV420_420v)] [0x7fcd7bd08e90] [subtype 4] frameInterval : 333333
2022-01-04 14:57:31.179027-0500 0xb2227    Default     0x1803a4             266    0    UVCAssistant: (UVCFamily) [com.apple.UVCFamily:device] UVCUSBDeviceStreamingInterface: 0x1000005a6 [0x7fcd7bd08260] [stop stream] format : UVCDeviceStreamFormat:[1280 * 720 (YUV420_420v)] [0x7fcd7bd08e90] [subtype 4] frameInterval : 333333

If you get output, you're done with this step and can use the the regular expression matchers I provide in the next steps.

If you get no output, you'll need to broaden the filter to search for event logs that appear when the camera starts and stops. This might be a good starting place:

log stream | /usr/bin/grep -iE 'UVCAssistant|camera|stream|tccd'

Ensure the events you choose are emitted for any camera use (e.g. Zoom, Meet), not just PhotoBooth.

You'll need to come up with a regular expression for grep that matches only when your camera is toggled on or off. If you have multiple cameras, you may also want to test switching between cameras.

Create Shortcuts to trigger HomeKit actions

First, confirm that you're able to use the Home app on your Mac to trigger changes to whatever accessories or scenes you're interested in.

In the Shortcuts app, create a new shortcut (+ button). For toggling a light, you'll need a separate shortcut for each state (e.g. on/off). Give the shortcut a name such as Turn on lamp.

For each shortcut, select the Home app and add its Control <home name> action to your shortcut (drag or double-click). Select the specific scene or accessory you want to control, and select a state for you to set it to when the shortcut runs.

shortcut configuration

When complete, you should see your shortcuts in your shortcuts list and be able to run them and trigger your expected behavior.

both shortcuts

Last, confirm that you can trigger these successfully via the Terminal command line:

shortcuts run 'Turn on lamp'
shortcuts run 'Turn off lamp'

Trigger shortcuts on camera state

Create a script file (e.g. camera-lamp.sh) that, while running, will toggle your light based on whether the camera is running. A starter example:

#!/bin/bash
exec log stream |
  /usr/bin/grep -E --line-buffered 'UVCAssistant:.*(stop|start) stream' | # filter log events
  tee /dev/stderr |                           # output matching events for debugging
  /usr/bin/sed -Eu 's/.*(start|stop).*/\1/' | # reduce the log message down to a single word identifying the event/state
  while read -r event; do                     # store that word in the $event variable
    echo "Camera $event"
    if [ "$event" = "start" ]; then
      echo "Lamp on"
      shortcuts run 'Desk lamp on' &
    else
      echo "Lamp off"
      shortcuts run 'Desk lamp off' &
    fi
  done

Replace my shortcut names Desk lamp on and Desk lamp off with your own, if different. Feel free to alter messages like "Lamp on" to fit your scenario.

If you needed to choose a different filter in step 1:

  1. replace the grep regular expression with one that matches both your camera on and camera off event log messages,
  2. replace the sed substitution regular expression with one that matches the equivalent word that indicates the camera state, and
  3. if that word is not start when the camera turns on, update the if conditional that matches the start word.

Run the script

Run the script, and test it out. If you named it camera-lamp.sh, run

bash camera-lamp.sh

While the script is running, your HomeKit shortcuts should trigger whenever your camera turns on or off.

Optional steps:

  • Once the script is stable, run it in the background, and close the terminal.

    bash camera-lamp.sh &
    
  • Drop the extension, make the file executable, and relocate it to /usr/local/bin or elsewhere in your $PATH, so you can just run camera-lamp as a command.

  • Find a way to run the script in the background as a daemon on login. How to accomplish this is beyond the scope of this answer. Importantly though, this cannot run as a launchctl daemon, as these daemons cannot run shortcuts due to Error: Couldn’t communicate with a helper application. If you find a good approach, feel free to comment.