#!/usr/bin/env bash # Start and stop the Moonlight streaming stack on demand. # # It is not left running because it costs ~220 MiB of VRAM on the 3060 (sway # ~112, Sunshine ~108) and that card also holds the local LLM. With an 11.3 GB # model resident on a 12 GB card, 220 MiB is roughly a fifth of the remaining # headroom — enough to matter for KV cache growth. set -euo pipefail UNIT=sway-headless.service IDLE_MINUTES="${STREAM_IDLE_MINUTES:-15}" STAMP="${XDG_RUNTIME_DIR:-/tmp}/stream.lastseen" # A Moonlight client holds connections to the control and RTSP ports. clients_connected() { ss -Htn state established '( sport = :47984 or sport = :47989 or sport = :48010 )' 2>/dev/null | grep -q . } vram() { local used total read -r used total < <(nvidia-smi --query-gpu=memory.used,memory.total \ --format=csv,noheader,nounits 2>/dev/null | tr -d ',') printf '%s MiB used of %s, %s free' "$used" "$total" "$((total - used))" } case "${1:-status}" in on|start) systemctl --user start "$UNIT" sleep 6 date +%s > "$STAMP" printf 'streaming up — pair or connect at https://%s:47990\n' "$(uname -n)" printf 'GPU: %s\n' "$(vram)" ;; off|stop) systemctl --user stop "$UNIT" sleep 3 rm -f "$STAMP" printf 'streaming down\nGPU: %s\n' "$(vram)" ;; status) printf 'compositor: %s\nsunshine: %s\nclients: %s\nGPU: %s\n' \ "$(systemctl --user is-active "$UNIT")" \ "$(systemctl --user is-active sunshine.service)" \ "$(clients_connected && echo connected || echo none)" \ "$(vram)" ;; --idle-check) # Called from sunshine-idle-stop.timer. Releases the GPU when nobody has # been connected for IDLE_MINUTES, so a forgotten session does not sit on # VRAM the inference stack wants. systemctl --user is-active --quiet "$UNIT" || exit 0 if clients_connected; then date +%s > "$STAMP"; exit 0; fi last=$(cat "$STAMP" 2>/dev/null || echo 0) if (( last == 0 )); then date +%s > "$STAMP"; exit 0; fi if (( ($(date +%s) - last) >= IDLE_MINUTES * 60 )); then echo "no Moonlight client for ${IDLE_MINUTES}m; stopping to free the GPU" systemctl --user stop "$UNIT" rm -f "$STAMP" fi ;; *) echo "usage: stream [on|off|status]" >&2; exit 2 ;; esac