Files
dvdrw 4bb64a8ca3 init: initial commit
- ticker / QR ad overlay / break slide graphics (1920×1080) with all
  geometry derived from one shared module (src/shared/obs-geometry.mjs)
- OBS scene-collection generator (scripts/generate-obs-scenes.mjs) and a
  read-only in-dashboard setup verifier, both driven by the same module
- en/sr dashboard i18n selected via bundle config; configschema.json with
  neutral first-run defaults seeded from optional branding config
- install.sh / systemd user service / update.sh for venue deployment
- reference OBS scene collection + profile from a real venue as fixtures
2026-07-15 19:30:32 +02:00

167 lines
6.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Bootstrap a complete NodeCG + nodecg-venue-gfx install on a venue machine.
#
# Creates a standalone NodeCG installation (the nodecg npm package extracted
# as the install root — the layout NodeCG itself calls "standalone"; running
# it as a node_modules dependency is still flagged experimental upstream),
# clones this bundle into bundles/, builds it, writes the config files, and
# generates an importable OBS scene collection.
#
# Usage:
# ./install.sh [--dir ~/venue-gfx] [--port 9090] [--obs-password SECRET]
# [--repo <git-url>] [--local <path-to-checkout>] [--yes]
#
# --local uses an existing checkout (copied, not cloned) instead of --repo;
# when run from inside a checkout, --local defaults to that checkout.
# --yes accepts all defaults without prompting.
set -euo pipefail
BUNDLE=nodecg-venue-gfx
DEFAULT_REPO="https://git.dvdrw.dev/kckljajicevo/nodecg-venue-gfx.git"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
dir=""
port=""
obs_password=""
repo=""
local_src=""
assume_yes=0
while [[ $# -gt 0 ]]; do
case "$1" in
--dir) dir="$2"; shift 2 ;;
--port) port="$2"; shift 2 ;;
--obs-password) obs_password="$2"; shift 2 ;;
--repo) repo="$2"; shift 2 ;;
--local) local_src="$2"; shift 2 ;;
--yes|-y) assume_yes=1; shift ;;
--help|-h) sed -n '2,17p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
*) echo "unknown option: $1" >&2; exit 1 ;;
esac
done
# ── prerequisites ─────────────────────────────────────────────────────────
command -v node >/dev/null || { echo "node not found — install Node.js 20+" >&2; exit 1; }
command -v npm >/dev/null || { echo "npm not found" >&2; exit 1; }
node_major=$(node -p 'process.versions.node.split(".")[0]')
if (( node_major < 20 )); then
echo "Node.js $(node -v) is too old — need 20+" >&2
exit 1
fi
# When run from inside a checkout of the bundle, default to copying it.
if [[ -z $local_src && -z $repo && -f "$SCRIPT_DIR/../package.json" ]]; then
if node -p 'require(process.argv[1]).name' "$SCRIPT_DIR/../package.json" 2>/dev/null | grep -qx "$BUNDLE"; then
local_src="$(cd "$SCRIPT_DIR/.." && pwd)"
fi
fi
ask() { # ask <prompt> <default-var-name> <default-value>
local prompt="$1" var="$2" def="$3" answer
if [[ -n ${!var} ]]; then return; fi
if (( assume_yes )); then printf -v "$var" '%s' "$def"; return; fi
read -r -p "$prompt [$def]: " answer
printf -v "$var" '%s' "${answer:-$def}"
}
ask "Install directory" dir "$HOME/venue-gfx"
ask "NodeCG port" port "9090"
ask "OBS websocket password (empty = auth disabled)" obs_password ""
if [[ -z $local_src ]]; then
ask "Bundle git URL" repo "$DEFAULT_REPO"
fi
dir="${dir/#\~/$HOME}"
echo
echo "Installing into $dir (NodeCG on port $port)"
# ── NodeCG itself (standalone layout: install root = the nodecg package) ──
mkdir -p "$dir"
cd "$dir"
if [[ -f package.json ]] && node -p 'require("./package.json").name' | grep -qx nodecg; then
echo "NodeCG already present — skipping"
else
echo "Downloading NodeCG…"
tarball=$(npm pack nodecg@^2 --silent | tail -n1)
tar xzf "$tarball" --strip-components=1
rm -f "$tarball"
echo "Installing NodeCG dependencies…"
npm install --omit=dev --no-audit --no-fund
fi
mkdir -p bundles cfg obs
# ── the bundle ────────────────────────────────────────────────────────────
if [[ ! -d bundles/$BUNDLE ]]; then
if [[ -n $local_src ]]; then
echo "Copying bundle from $local_src"
mkdir -p "bundles/$BUNDLE"
(cd "$local_src" && git archive HEAD 2>/dev/null || tar cf - --exclude node_modules --exclude .git .) \
| tar xf - -C "bundles/$BUNDLE"
else
echo "Cloning $repo"
git clone "$repo" "bundles/$BUNDLE"
fi
fi
echo "Building the bundle…"
(cd "bundles/$BUNDLE" && npm ci --no-audit --no-fund && npm run build)
# ── config ────────────────────────────────────────────────────────────────
if [[ ! -f cfg/nodecg.json ]]; then
printf '{\n\t"port": %s\n}\n' "$port" > cfg/nodecg.json
echo "Wrote cfg/nodecg.json"
fi
if [[ ! -f cfg/$BUNDLE.json ]]; then
node - "$obs_password" > "cfg/$BUNDLE.json" <<'EOF'
const password = process.argv[2] ?? "";
process.stdout.write(JSON.stringify({
locale: "en",
obs: { enabled: true, url: "ws://127.0.0.1:4455", password },
}, null, "\t") + "\n");
EOF
echo "Wrote cfg/$BUNDLE.json"
fi
# ── OBS scene collection ──────────────────────────────────────────────────
node "bundles/$BUNDLE/scripts/generate-obs-scenes.mjs" \
--config "cfg/$BUNDLE.json" \
--nodecg-url "http://localhost:$port" \
--name VenueGfx \
--out obs/VenueGfx.json
# ── done ──────────────────────────────────────────────────────────────────
cat <<EOF
──────────────────────────────────────────────────────────────────────
Install complete. Start NodeCG with:
cd $dir && node index.js
Dashboard: http://localhost:$port
OBS setup (see bundles/$BUNDLE/docs/OBS-SETUP.md for details):
1. Install exeldro's Move plugin: https://obsproject.com/forum/resources/move.913/
2. Tools → WebSocket Server Settings: enable, port 4455$( [[ -n $obs_password ]] && echo ", set the password you chose" || echo ", disable authentication" )
3. Scene Collection → Import → $dir/obs/VenueGfx.json, then switch to it
4. Replace the "Program Placeholder" source with your real capture
5. Point the Stinger transition at a real video file
6. Settings → Video: 1920×1080 base + output, 60 FPS
7. Dashboard → "OBS setup check" panel → Run checks, fix anything red
To run NodeCG as a service that survives reboots:
bundles/$BUNDLE/scripts/install-service.sh $dir
──────────────────────────────────────────────────────────────────────
EOF