#!/usr/bin/env bash # Captures the screen and writes a JPEG to standard output. # # scripts/capture-screen.sh [width] [output] # # width Width to scale the capture down to. Defaults to 1280, the # measured minimum for the model to read UI text without making # it up (see docs/RENDIMIENTO.md). # output A specific monitor. Empty = everything there is. # # It lives outside the binary so supporting a new graphical environment means # editing this script, not recompiling. Detection goes from most specific to # most general. set -euo pipefail WIDTH="${1:-1280}" OUTPUT="${2:-}" missing() { echo "nothing to capture the screen with: $1" >&2; exit 1; } # Scaling happens here and not in the binary: shrinking before sending the # image to the model is what brings the cost from 23 s down to 7 s, and ffmpeg # is already needed for the camera. shrink() { if command -v ffmpeg >/dev/null 2>&1; then ffmpeg -hide_banner -loglevel error -i - \ -vf "scale=${WIDTH}:-2:flags=lanczos" -q:v 3 -f image2 -c:v mjpeg - else cat # without ffmpeg it goes full size: slow, but it works fi } if [ -n "${WAYLAND_DISPLAY:-}" ] && command -v grim >/dev/null 2>&1; then # wlroots: Hyprland, Sway, river… grim writes to stdout with «-». if [ -n "$OUTPUT" ]; then grim -t png -o "$OUTPUT" - | shrink else grim -t png - | shrink fi elif [ -n "${WAYLAND_DISPLAY:-}" ] && command -v spectacle >/dev/null 2>&1; then TMP=$(mktemp --suffix=.png); trap 'rm -f "$TMP"' EXIT spectacle -b -n -f -o "$TMP" >/dev/null 2>&1 shrink < "$TMP" elif [ -n "${DISPLAY:-}" ] && command -v maim >/dev/null 2>&1; then maim --format=png /dev/stdout | shrink elif [ -n "${DISPLAY:-}" ] && command -v import >/dev/null 2>&1; then # ImageMagick, present on almost any X11. import -silent -window root png:- | shrink elif [ -n "${DISPLAY:-}" ] && command -v scrot >/dev/null 2>&1; then scrot -o /dev/stdout | shrink else missing "install grim (Wayland) or maim/imagemagick (X11)" fi