Skip to content

Instantly share code, notes, and snippets.

@jptoto
Last active February 14, 2025 15:25
Show Gist options
  • Save jptoto/3b2197dd652ef13bd7f3cab0f2152b19 to your computer and use it in GitHub Desktop.
Save jptoto/3b2197dd652ef13bd7f3cab0f2152b19 to your computer and use it in GitHub Desktop.
Catch camera event
#!/bin/bash
# Catch the system log events for when a camera turns on for conferencing. Should work on Zoom, Teams, etc. Your
# specific logging may vary. Also this sends API requests to the Elgato Key Light specifically.
# Begin looking at the system log via the steam sub-command. Using a --predicate and filtering by the correct
# subsystem first improves CPU performance DRASTICALLY. Then just pull out the camera event and shot a POST
# to the Elgato key light controller. It helps to create a static IP mapping in your DHCP setup so the IP of the light
# controller remains consistent.
log stream --predicate 'subsystem == "com.apple.cameracapture" && eventMessage CONTAINS[c] "posting notification"'| while read line; do
# If we catch a camera start event, turn the light on
if echo "$line" | grep -q "AVCaptureSessionDidStartRunningNotification"; then
echo "Camera has been activated, turn on the light."
curl --location --request PUT 'http://[IP ADDRESS]:9123/elgato/lights' --header 'Accept: application/json' --data-raw '{"numberOfLights": 1, "lights": [{ "on": 1, "brightness": 20, "temperature": 315 }]}'
fi
# If we catch a camera stop event, turn the light off.
if echo "$line" | grep -q "AVCaptureSessionDidStopRunningNotification"; then
echo "Camera shut down, turn off the light."
curl --location --request PUT 'http://[IP ADDRESS]:9123/elgato/lights' --header 'Accept: application/json' --data-raw '{"numberOfLights": 1, "lights": [{ "on": 0, "brightness": 20, "temperature": 315 }]}'
fi
done
@henrik242
Copy link

henrik242 commented Oct 27, 2021

This doesn't work in macOS Monterey. You'll have to use a slightly different predicate:

$ log stream --predicate 'subsystem == "com.apple.UVCExtension" and composedMessage contains "Post PowerLog"'
Filtering the log data using "subsystem == "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;
}

@ptstevens
Copy link

Is there a way to read the output for macOS Monterey - I tried to merge these 2 together but get nothing but the out put text - it doesnt appear to read the state of on or off - any help appreciated.

@henrik242
Copy link

henrik242 commented Apr 12, 2022

If you add --style ndjson to the command, every message is on one line. Then you can grep for e.g.'"VDCAssistant_Power_State" = On'.

@ptstevens
Copy link

henrik242 thanks fella got there in the end 👌

@jptoto
Copy link
Author

jptoto commented Aug 31, 2022

Thanks for the comments! I hadn't even tried this on Monterey yet but good to know it works with some predicate changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment