node-red-contrib-visibox 1.0.0
Node-RED nodes for controlling Visibox live visual performance software
Visibox Node-RED Nodes
Node-RED nodes for controlling Visibox, the live visual performance software from Spaceage.
Node-RED is a flow-based programming tool for wiring together hardware devices, APIs, and services. These nodes allow Node-RED flows to control Visibox playback and react to state changes in real time — ideal for theatre show control, event automation, and complex triggering logic.
What It Does
- 5 Node Types: Config, Action, Playback shortcut, Control (Real-Time Control bus), State output
- Full Action Coverage: Every Visibox action (30+) via the generic action node — the dropdown is generated from the API client, so it never goes stale
- Action Results: Action and control nodes emit Visibox's real accept/reject verdict and raise errors
catchnodes can handle - Playback Shortcuts: Dedicated node for play/pause/stop/resume/panic/mute/fullscreen
- Real-Time Control: Set or nudge Controls by letter, or write Target params, in percent with polarity-aware clamping
- Real-time State: State node emits
msg.payloadon every playback or output change, and on demand - Shared Connection: Config node manages a single authenticated WebSocket, shared by all nodes
- Status Indicators: Green/yellow/red connection status on every node
- Runtime Override: Override action, parameters, control and value via
msg.payloadat runtime
Prerequisites
- Visibox 6.0 or later on a pro plan (the Remote Control API is a pro feature; there is no setting to enable it)
- Node-RED 3.0 or higher
- Node.js 20 or later
Install
In the Node-RED editor, open Manage palette → Install, search for node-red-contrib-visibox, and install it. Or, from your Node-RED user directory:
cd ~/.node-red
npm install node-red-contrib-visibox
Restart Node-RED. The Visibox nodes appear in the palette under "Visibox".
Nodes
visibox-config
Configuration node that holds connection settings and pairing credentials, and manages a shared VisiboxApiClient instance. All other Visibox nodes reference this config node.
| Setting | Default | Description |
|---|---|---|
| Host | 127.0.0.1 |
IP address of the Visibox computer |
| WS Port | 17734 |
Visibox WebSocket API port |
| HTTP Port | 17736 |
Visibox HTTP API port |
| Pairing Code | — | One-time code from Visibox: choose Pair with Remote… (Visibox menu on macOS, File menu on Windows). Consumed on first connect. |
| Auth Token | — | Token issued after pairing. Saved automatically; paste one to reuse it. |
Pairing. Visibox 6.0 requires authentication on every API connection, including
from the same machine. On the first deploy either enter a Pairing Code, or leave both
credential fields empty and approve the "Node-RED" device in the dialog Visibox shows.
The token Visibox issues is written to the config node's credentials (encrypted by
Node-RED) and reused on every later deploy and restart. If authentication fails, every
node using the config shows auth failed: … in its status.
visibox-action
Generic action node with a dropdown for every Visibox action. The list is generated
from VisiboxActions in @visibox/api-client (exposed to the editor as
RED.settings.visiboxActionNames), so new actions appear without a package update.
Parameters can be set in the node editor or overridden at runtime.
Commonly used actions:
| Action | Description | Parameters |
|---|---|---|
PLAY_IN / STOP_IN / PAUSE_IN / RESUME_IN |
Transport | — |
PLAY_TOGGLE_IN / PAUSE_TOGGLE_IN |
Toggles | — |
PLAY_CLIP_BY_INDEX_IN |
Play clip by index | clipIndex, songID? |
RELEASE_CLIP_BY_INDEX_IN |
Release a held (Gate) clip | clipIndex, songID? |
NEXT_CLIP_IN / PREV_CLIP_IN |
Step clips | anySong? |
SONG_SELECT_IN / SONG_SELECT_BY_ID |
Select song | index or songID, stopPlaying? |
NEXT_SONG_IN / PREV_SONG_IN |
Step songs | noStop? |
OUTPUT_LEVEL_IN / OUTPUT_HUE_IN / OUTPUT_INTENSITY_IN |
Master output | 0.0-1.0 |
MUTE_TOGGLE / FULLSCREEN_TOGGLE / RECORD_TOGGLE |
Output toggles | — |
PANIC |
Emergency stop all | — |
SET_CONTROL / SET_PARAM |
Real-Time Control (see the control node) | id, value |
Runtime override via msg.payload:
{
"action": "PLAY_CLIP_BY_INDEX_IN",
"params": [2, "song-uuid"]
}
Parameters can also be passed as a comma-separated string: "2, song-uuid".
Output msg.payload — the server's verdict, not just "sent":
{ "action": "PLAY_CLIP_BY_INDEX_IN", "params": [2], "success": false, "error": "Clip index out of range" }
A rejected action also raises a node error, so a catch node receives it.
visibox-playback
Shortcut node for common playback commands. Wire an inject node to trigger it.
| Control | Visibox Action |
|---|---|
| Play | PLAY_IN |
| Stop | STOP_IN |
| Pause | PAUSE_IN |
| Resume | RESUME_IN |
| Play/Stop Toggle | PLAY_TOGGLE_IN |
| Pause/Resume Toggle | PAUSE_TOGGLE_IN |
| Panic | PANIC |
| Mute Toggle | MUTE_TOGGLE |
| Fullscreen Toggle | FULLSCREEN_TOGGLE |
msg.payload.control (or msg.control) overrides the configured control with one of
play, stop, pause, resume, playToggle, pauseToggle, panic, mute,
fullscreen. A rejection raises a node error for catch nodes.
visibox-control
Drives the Real-Time Control bus (a separately entitled Visibox feature).
| Setting | Description |
|---|---|
| Mode | Set Control, Adjust Control by, or Set Target Param |
| Control | Display letter (A…) or ctl_… id |
| Target ID | e.g. clip:abc123/opacity (Set Target Param only) |
| Value | Percent: 0–100, or -100–100 for a bipolar Control |
msg.payload (a number) overrides the value; msg.payload.control and
msg.payload.targetId override the address. The node reads the Control's polarity
from the active project and clamps to its range. Adjust steps from the value this
node last sent — Visibox does not report Control positions back.
Output msg.payload:
{ "action": "SET_CONTROL", "id": "A", "value": 0.5, "success": true }
visibox-state
Emits a message on every Visibox state change (playback, project, output level/mute/fullscreen), and immediately when any message arrives on its input. Wire to switch, change, or debug nodes for reactive logic.
Output msg.payload:
{
"connected": true,
"playbackStatus": "playing",
"projectTitle": "Tour 2026",
"activeSongName": "Opening Number",
"activeSongIndex": 0,
"activeClipName": "Intro Video",
"activeClipIndex": 2,
"activeClipProgress": 0.42,
"outputLevel": 0.8,
"outputMuted": false,
"outputFullscreen": true,
"projectId": "project-uuid",
"playstate": { }
}
playbackStatus ignores background clips and picks one foreground clip deterministically under polyphonic playback. playstate carries the raw playstate for advanced use cases. The raw project is not included, because its media metadata runs to thousands of lines per message.
Example Flows
Starter flow (ships with the package)
examples/Visibox starter.json appears in the editor under Import → Examples → node-red-contrib-visibox. It adds a "Visibox starter" tab with inject buttons for Play/Stop, Pause/Resume, Next Song, Next Clip, Mute, Control A to 0 and 100, and a state read, wired to debug nodes. Open its Local Visibox config node, enter a pairing code from Visibox (Pair with Remote…), and deploy.
Simple Playback Control
[inject: "Play"] → [visibox-playback: play]
[inject: "Stop"] → [visibox-playback: stop]
Trigger Clip by Index
[inject: payload 3] → [function: build params] → [visibox-action: PLAY_CLIP_BY_INDEX_IN]
Function node:
msg.payload = { params: [msg.payload] };
return msg;
Hold a Clip, Then Release It
Clips whose Launch Mode is Gate play only while held, like a note on a keyboard.
Send RELEASE_CLIP_BY_INDEX_IN with the same params to let go:
[inject: "press"] → [visibox-action: PLAY_CLIP_BY_INDEX_IN]
[inject: "release"] → [visibox-action: RELEASE_CLIP_BY_INDEX_IN]
Clips in Trigger or Toggle mode ignore the release, so it is safe to send
unconditionally. Address the release to the same song the press used — pass an
explicit songID as the second param if the active song may change while held.
React to State Changes
[visibox-state] → [switch: playbackStatus == "playing"] → [debug: "Now playing!"]
→ [switch: playbackStatus == "stopped"] → [debug: "Stopped"]
Show Active Song on Dashboard
[visibox-state] → [change: set msg.payload to msg.payload.activeSongName] → [text node]
How It Works
- The
visibox-confignode opens one connection to Visibox and authenticates it. - Every other Visibox node that uses that config node shares its connection.
- Action, playback and control nodes wait for Visibox's reply and pass on its verdict.
- The state node emits
msg.payloadwhenever Visibox reports a change. - Each node shows the connection's state in its status indicator.
API Connection
- HTTP:
http://<host>:17736— health checks, state fetch - WebSocket:
ws://<host>:17734— actions, real-time state updates - Authentication: token-based; the device appears in Visibox as "Node-RED". The token is saved in
visibox-tokens.jsonin your Node-RED user directory, readable only by your user account, so Node-RED reconnects after a restart without pairing again - Keepalive: 30-second ping interval
- Reconnect: 5-second fixed interval retry
Troubleshooting
| Problem | Solution |
|---|---|
| Nodes not in palette | Check the install in Manage palette → Nodes; restart Node-RED |
| Nodes show red status | Check config node host/port; verify Visibox running |
Status reads auth failed: … |
Pair again: enter a fresh Pairing Code in the config node, or clear the Auth Token and approve the device in Visibox |
| State node not emitting | Ensure config connected (green); verify project loaded in Visibox |
| Actions not working | Check node status indicator; verify action name and params |
License
MIT