Files

158 lines
6.6 KiB
Markdown
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.
# nodecg-venue-gfx
Broadcast graphics for a venue screen, as a [NodeCG](https://nodecg.dev) 2
bundle: an always-on scrolling ticker with operator-added TTL messages,
corner-alternating ads that shrink the live program into a corner, a break
announcement slide, and automated + manual OBS scene choreography over
obs-websocket. Built for festivals and concerts; generic enough for any
single-screen show.
- All on-screen text is edited live from the dashboard
- Support for multiple locales
- OBS setup is generated. One script emits an importable scene collection, and a
dashboard panel verifies a live OBS against the exact geometry the graphics
render from.
- If OBS dies mid-show, the scheduler keeps running and re-applies the right
scene the moment OBS comes back. If NodeCG dies, restart it and it comes back
in live mode with all content intact.
## Quick start
**Fresh venue machine** (installs NodeCG + this bundle + config + OBS scene
collection in one go):
```sh
curl -fsSLO https://git.dvdrw.dev/kckljajicevo/nodecg-venue-gfx/raw/branch/master/scripts/install.sh
bash install.sh
```
**Into an existing NodeCG install:**
```sh
cd <nodecg>/bundles
git clone https://git.dvdrw.dev/kckljajicevo/nodecg-venue-gfx.git
cd nodecg-venue-gfx
npm ci && npm run build
```
Then:
1. Write `cfg/nodecg-venue-gfx.json` (see
[docs/examples/cfg.example.json](docs/examples/cfg.example.json)).
2. Set up OBS: `npm run obs:scenes` -> import -> done. Details in
[docs/OBS-SETUP.md](docs/OBS-SETUP.md).
3. Start NodeCG (`node index.js` from the install root) and open the
dashboard at <http://localhost:9090>.
To run as a service that survives reboots: `scripts/install-service.sh`
(systemd user unit). To update later: `scripts/update.sh`.
## Configuration
`cfg/nodecg-venue-gfx.json` in the NodeCG install, validated against
[configschema.json](configschema.json). Everything is optional:
| Key | Default | Purpose |
| --- | --- | --- |
| `locale` | `"en"` | Dashboard language (`"en"` or `"sr"`) |
| `branding.tickerBlurb` | `"Welcome ♪"` | First-run seed for the recurring ticker blurb |
| `branding.breakHeading` | `"Stay tuned — there's more!"` | First-run seed for the break-slide heading |
| `branding.sampleQrUrl` | `"https://example.com"` | First-run seed for the sample ad's QR URL |
| `obs.enabled` | `false` | Connect to OBS and drive scenes |
| `obs.url` | `"ws://127.0.0.1:4455"` | obs-websocket URL |
| `obs.password` | `""` | obs-websocket password |
| `obs.scenes.*` | `MAIN`, `MAIN_AD_TR`, … | Names of the six driven scenes |
| `obs.transitions.*` | `Move`, `Stinger` | Names of the two transitions |
| `obs.sources.*` | `TickerOverlay`, … | Names of the shared sources/nested scenes (for the generator + verifier) |
`branding.*` values only seed the very first run — after that, everything is
edited from the dashboard and persists in NodeCG's database. Set
`obs.enabled: false` to develop without OBS; everything else keeps working.
## Dashboard panels
- **Ticker messages** — ticker settings (loop blurb, separator, default TTL,
speed) and message management; each active message shows a depleting fill
for its remaining time, with renew/remove/inline-edit.
- **Ads** — CRUD for ads (strip text, column text, column image from the
Assets dialog, QR URL, enabled), with a live QR preview per row. Each row
has a "Trigger now" button to force that specific ad onto air immediately
(enabled or not), bypassing the round-robin — disabled while an ad slot is
already showing.
- **Choreography / OBS** — connection status, mode/phase badges, countdown to
the next automatic transition, break-slide content, and manual controls:
show ad now (round-robin), skip ad, break toggle.
- **Timing** — the choreography timing settings: ad interval, ad duration,
break gap, break ad duration, ads per burst.
- **OBS setup check** — read-only verification of the live OBS against the
expected scenes/sources/transforms/transitions, with concrete fixes.
Images (ad backgrounds, column images, break background, act logos) are
uploaded through NodeCG's standard **Assets** dialog.
## Graphics (1920×1080)
| URL | Default OBS source | Purpose |
| --- | --- | --- |
| `graphics/ticker.html` | `TickerOverlay` | Bottom 96 px scrolling ticker |
| `graphics/ad.html` | `AdOverlay` | QR + headline in the gamma-shaped cutout |
| `graphics/break.html` | `BreakSlide` | Break announcement slide (ambient motion) |
The ticker uses a segment-queue marquee: loop content is snapshotted per
revolution, so adding/removing messages mid-scroll never causes visual jumps.
## Theming
- **Colors**: edit the `THEME LAB` block in
[`src/graphics/index.css`](src/graphics/index.css) — every brand color the
graphics use is a token there.
- **Fonts**: the `FONT LAB` block right above it (Margarine is bundled as the
default; drop a `.ttf`/`.woff2` into `src/graphics/fonts/` to swap).
- **Geometry** (canvas size, the 70% shrink, ad cutout, OBS transforms):
[`src/shared/obs-geometry.mjs`](src/shared/obs-geometry.mjs) — one module
shared by the graphics, the scene-collection generator, and the verify
panel, so they can never disagree. v1 is fixed at 1920×1080.
## Adding a language
1. Copy `src/i18n/en.ts` to `src/i18n/<code>.ts` and translate (the `Strings`
type keeps you honest).
2. Register it in `src/i18n/index.ts` (`locales`).
3. Add the code to the `locale` enum in `configschema.json`.
## Development
```sh
npm run dev # parcel watch + nodemon restarting NodeCG
npm run build # one-shot production build
npm run obs:scenes # regenerate the OBS scene collection
```
Dev mode assumes the bundle lives inside a NodeCG install
(`bundles/nodecg-venue-gfx`); `nodemon` runs `node ../../index.js`.
Rules of thumb:
- **Graphics/dashboard** changes: rebuild (or let the watcher do it), then
refresh the page / OBS browser source. No server restart.
- **Extension** (`src/extension/`), **types**, or **package.json** changes:
rebuild **and restart NodeCG** — plain `node index.js` never rebuilds
anything.
- Graphics are fixed 1920×1080 canvases — judge them in OBS or a fullscreen
1080p tab; smaller windows show a crop.
## Architecture notes
- The scheduler is a state machine over `(mode: normal|break, phase: live|ad)`
with exactly one pending timer; OBS calls are fire-and-forget, so an
unreachable OBS never stalls the choreography.
- Corner alternation and ad round-robin persist across restarts
(`schedulerState` replicant). On startup the bundle always returns to
(normal, live) + the main scene.
- Replicant defaults are only applied when nothing is persisted, so operator
edits survive restarts.
## License
[AGPL-3.0](LICENSE)