#!/usr/bin/env bash # run-stack.sh — Test-only launcher for the oko clip pipeline. # # Starts processes from the "backend" (coordinator) working toward runCam so # that each downstream consumer is listening before its upstream producer # connects. For testing, not production. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$ROOT" LOGDIR="$ROOT/logs" mkdir -p "$LOGDIR" # Shared pipeline auth token (override in the environment). : "${OKO_AUTH_TOKEN:=$(openssl rand -hex 16)}" # PBKDF2 iterations for clip encryption (lower = less CPU, weaker brute-force resistance). : "${OKO_PBKDF2_ITERS:=600000}" # runCam capture settings; 0 = keep the device default. : "${OKO_VIDEO_FPS:=5}" : "${OKO_VIDEO_WIDTH:=0}" : "${OKO_VIDEO_HEIGHT:=0}" # Matrix backend settings for coordinator (override in the environment). : "${OKO_MATRIX_HS:=https://ayrc.online}" : "${OKO_MATRIX_USER:=@okobot:ayrc.online}" : "${OKO_MATRIX_TOKEN_FILE:=$ROOT/matrix.token}" : "${OKO_CLIPS_ROOM:=!0hCGPJph-odzFEOScsnAOBlPHSolX8rwbh3mxQNNUrg}" : "${OKO_DETECTIONS_ROOM:=!XqatfFvJJT6xq8B0p7b5NL2RYRCBS2Fa3ItFu8xV2gQ}" : "${OKO_VIEW_ROOM:=!wyLfOhunJTOzeXHFfAc6CRCCII7KlA1Pm2MkkFf40tE}" PIDS=() cleanup() { echo "Shutting down pipeline..." for pid in "${PIDS[@]}"; do kill "$pid" 2>/dev/null || true done wait 2>/dev/null || true } trap cleanup INT TERM EXIT # build_if_missing — build the binary in its dir if absent. build_if_missing() { local name="$1" local binary="$name/$name" if [[ -x "$binary" ]]; then return fi echo "Building $name..." (cd "$name" && go build -o "$name" .) } # start [args...] — launch in background and record PID. start() { local name="$1" local log="$2" shift 2 echo "Starting $name (log: $log)" (cd "$ROOT/$name" && exec "$ROOT/$name/$name" "$@") >>"$log" 2>&1 & PIDS+=("$!") } # --- Build any missing binaries -------------------------------------------- build_if_missing coordinator build_if_missing terp build_if_missing mofin build_if_missing runCam # --- Start pipeline from backend toward runCam ----------------------------- # coordinator: Matrix-backed storage, listens :8082 start coordinator "$LOGDIR/coordinator.log" \ "--listen=:8082" \ "--auth-token=$OKO_AUTH_TOKEN" \ "--pbkdf2-iters=$OKO_PBKDF2_ITERS" \ "--matrix-homeserver=$OKO_MATRIX_HS" \ "--matrix-user=$OKO_MATRIX_USER" \ "--matrix-token-file=$OKO_MATRIX_TOKEN_FILE" \ "--clips-room=$OKO_CLIPS_ROOM" \ "--detections-room=$OKO_DETECTIONS_ROOM" \ "--view-room=$OKO_VIEW_ROOM" sleep 1 # terp: classifier, listens :8081, forwards to coordinator start terp "$LOGDIR/terp.log" \ "--listen=:8081" \ "--sendoff=localhost:8082" \ "--auth-token=$OKO_AUTH_TOKEN" \ "--classifiers=classifiers/*.xml" \ "--motion-percent=5" \ "--pbkdf2-iters=$OKO_PBKDF2_ITERS" sleep 1 # mofin: motion detection, listens :8083, drops no-motion clips, forwards to terp start mofin "$LOGDIR/mofin.log" \ "--listen=:8083" \ "--terp=localhost:8081" \ "--auth-token=$OKO_AUTH_TOKEN" \ "--threshold=30" \ "--pbkdf2-iters=$OKO_PBKDF2_ITERS" sleep 1 # runCam: camera source, connects to mofin — started last start runCam "$LOGDIR/runCam.log" \ "--mofin=localhost:8083" \ "--auth-token=$OKO_AUTH_TOKEN" \ "--min-cam=0" \ "--max-cam=10" \ "--clip-duration=10s" \ "--rescan-interval=10s" \ "--user=oko" \ "--camera-id=front" \ "--video-fps=$OKO_VIDEO_FPS" \ "--video-width=$OKO_VIDEO_WIDTH" \ "--video-height=$OKO_VIDEO_HEIGHT" \ "--pbkdf2-iters=$OKO_PBKDF2_ITERS" echo "Pipeline up. Press Ctrl-C to shut down." wait