#!/bin/sh # Camera gesture control (open hand moves the pointer, fist clicks) — OPT-IN, and for # the specific rooms that are getting a webcam only. # # Two independent gates, on purpose. This one is per-image and decides whether the # software is on the disk at all: MediaPipe plus its OpenCV/numpy/matplotlib tail is a # few hundred MB, which has no business being in the image of a room that has no camera. # The second gate is the "enabled" flag in gesture-config.json and decides whether the # camera is ever OPENED — it defaults to false even on an image built with this hook, so # flashing a gesture-capable image is not the same act as switching a room's camera on. # # A venv rather than apt or `pip3 --break-system-packages`, same reasoning as # 0600-voice-satellite.hook.chroot: bookworm's system interpreter is PEP 668 # externally-managed, and mediapipe drags in its own opencv-contrib-python and numpy # which must not overwrite the apt-managed versions the rest of the image uses. # # No apt attempt first, unlike 0500/0800: mediapipe has never been packaged in Debian # (there is no python3-mediapipe in bookworm or trixie) and upstream ships only PyPI # wheels, so an `apt-get install mediapipe` here would be theatre rather than a real # fallback. The other half of that convention — fail to a documented placeholder rather # than to a broken image — does apply, and is what every failure path below does. set -eu . /etc/thinclient-agent/config.env if [ "${ENABLE_GESTURE_CONTROL}" != "true" ]; then echo "1100-gesture-control: ENABLE_GESTURE_CONTROL is false, skipping (this is the" echo " default — only images destined for a room that is getting a webcam should" echo " enable it, exactly as with ENABLE_VOICE_SATELLITE and microphones)." exit 0 fi VENV=/opt/gesture-control/venv MODEL=/opt/gesture-control/hand_landmarker.task # The published MediaPipe Hand Landmarker bundle. This IS a hardcoded URL, which the # rest of this tree avoids — the justification is that the trailing path is Google's own # `/latest/` alias rather than a version tag, so it does not rot the way a pinned GitHub # release tag does, and since mediapipe 1.0.0 dropped the legacy mediapipe.solutions # package the model no longer ships inside the wheel. VERIFY it still resolves if the # download below starts failing: # https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker#models MODEL_URL="https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/latest/hand_landmarker.task" python3 -m venv "$VENV" "$VENV/bin/pip" install --upgrade pip wheel setuptools # mediapipe pulls opencv-contrib-python itself, so there is nothing to install for the # capture side. Debian's own python3-opencv is deliberately NOT used: it does not satisfy # mediapipe's opencv-contrib-python requirement, so listing it would only put a second # copy of OpenCV on the image. The apt packages this needs are the shared libraries those # wheels dlopen at runtime, and they are in thin-client.list.chroot. if ! "$VENV/bin/pip" install mediapipe; then echo "1100-gesture-control: WARNING — 'pip install mediapipe' failed. Gesture control" echo " will not work on this image; nothing else is affected (the sway wrapper detects" echo " the missing venv and no-ops)." echo " Most likely causes: no network during the build, or upstream stopped publishing" echo " a manylinux wheel for this interpreter. bookworm is Python 3.11 and glibc 2.36;" echo " mediapipe 1.0.0 ships py3-none-manylinux_2_28_x86_64, which fits. Check" echo " https://pypi.org/project/mediapipe/#files if that changes." exit 0 fi if ! curl -fsSL -o "$MODEL" "$MODEL_URL"; then echo "1100-gesture-control: WARNING — could not download the hand-landmarker model." echo " Fetch it by hand onto the booted machine and gesture control starts working:" echo " sudo curl -fsSL -o ${MODEL} \\" echo " '${MODEL_URL}'" echo " gesture_pointer.py exits cleanly while the file is missing." exit 0 fi chown -R root:root /opt/gesture-control chmod 0644 "$MODEL" echo "1100-gesture-control: installed. The camera stays OFF until \"enabled\" is set to" echo " true in /var/lib/thinclient-agent/gesture-config.json on the booted machine."