How to Control Backstage via OSC
How to Control Backstage via OSC
Backstage can send and receive OSC (Open Sound Control) messages through its Node Editor. Use OSC to integrate with QLab, Watchout, MA lighting desks, or any custom show controller that speaks OSC over UDP.
Before you start
- You have a working Backstage project with at least one Sequence set up
- The Node Editor is open (main area tab)
- You know the IP address and port your external controller sends OSC on
- Windows Firewall allows inbound UDP on the port you plan to use (default:
13579)
How OSC works in Backstage
Backstage does not have a built-in OSC server. Instead, OSC is handled as a two-node chain in the Node Editor:
-
Receiving: A Network:UDPReceiver node listens for raw UDP packets, then an Network:OSCDecode (or Network:UnpackOSC) node parses the OSC content.
-
Sending: A Network:OSCEncodeMessage (or Network:PackOSC) node builds the OSC packet, then a Network:UDPSender node transmits it.
This separation gives you full control over port binding, NIC selection, and message routing without locking you into a single OSC configuration.
Steps
1. Receive OSC messages
Right-click the Node Editor canvas and add Network:UDPReceiver and Network:OSCDecode.
Configure the UDPReceiver:
-
Set the NIC dropdown to
localhostto listen on all interfaces, or pick a specific network adapter. -
Set the Port to match what your controller sends to (e.g.
8000). -
Check the connected checkbox. It turns green when the socket is bound and listening.
Configure the OSCDecode:
-
Set the Domain field to the OSC address pattern you want to filter for (e.g.
/Backstage/p1). Only messages matching this domain prefix are passed through. The default domain is/Backstage/p1.
Connect the Message output of the UDPReceiver to the OSC message input of the OSCDecode node.
The OSCDecode node outputs a Pack containing the parsed OSC arguments (integers, floats, and strings). The sub-address after the domain prefix becomes the Pack label, so you can route different commands from the same domain.
Alternative: Network:UnpackOSC is a simpler node that matches one exact address and outputs each argument to a separate typed pin (no Pack). Set the Domain to the full OSC address and the Tags to the argument types you expect (e.g. f for one float, ifs for int + float + string). Use UnpackOSC when you know the exact message format and want direct typed outputs.
2. Send OSC messages
Right-click the Node Editor canvas and add Network:OSCEncodeMessage and Network:UDPSender.
Configure the OSCEncodeMessage:
-
Set the Domain to the OSC address pattern your target expects (e.g.
/cue/1/gofor QLab). -
Set the Tags field to define argument types. Use
ifor integer,ffor float,sfor string. For example,fscreates two input pins: one Float and one String. -
Wire your data into the dynamically created input pins. Send a Bang to the Emit input to build and output the OSC packet.
Configure the UDPSender:
-
Set the IP address to the target device (e.g.
192.168.1.50). -
Set the Port to match the receiver (e.g.
53000for QLab). -
Check the connected checkbox to activate the sender.
Connect the OSC message output of the OSCEncodeMessage to the Message input of the UDPSender.
Alternative: Network:PackOSC works like OSCEncodeMessage but uses typed tag inputs. Network:OSCEncodePack accepts a Pack input directly and can produce OSC bundles from nested Packs. Use OSCEncodePack when building complex multi-message bundles.
3. Example: trigger sequence playback from an OSC message
Goal: an external controller sends /Backstage/p1/Play over OSC, and Backstage starts a sequence.
-
Add a UDPReceiver node. Set the port (e.g.
8000) and enable listening. -
Add an OSCDecode node. Set Domain to
/Backstage/p1. -
Connect UDPReceiver Message output to OSCDecode OSC message input.
-
Add a Sequence:Sequence node and select your target sequence.
-
Add a Datatype:String node and set its value to
Play. -
Connect the OSCDecode Output (Pack) to the Datatype:String node's trigger input. This fires the string
Playevery time a matching OSC message arrives. -
Connect the Datatype:String output to the Action input of the Sequence:Sequence node.
When the controller sends /Backstage/p1/Play, OSCDecode matches the domain prefix, the Pack output fires, the String node emits Play, and the sequence starts.
4. Example: control a parameter from an OSC fader
Goal: an OSC fader sends a float value on /Backstage/p1/opacity and that value controls a sequence's opacity.
-
Add a UDPReceiver and an UnpackOSC node (the simpler decode node for known formats).
-
On the UDPReceiver, set the port and enable listening.
-
On the UnpackOSC node, set Domain to
/Backstage/p1/opacityand Tags tof(one float argument). An F output pin appears on the node. -
Connect UDPReceiver Message output to UnpackOSC OSC message input.
-
Add a Sequence:Properties node. Select your target sequence.
-
Connect the F output from UnpackOSC to the Opacity input of the Sequence:Properties node.
Now the fader controls sequence opacity in real time. The same approach works for volume, tempo, or any float-accepting Sequence property.
Most OSC faders send values between 0.0 and 1.0. If the target parameter uses a different range, add a Math:Map node between the UnpackOSC output and the target input to remap the range.
Options explained
OSC address pattern format
OSC messages in Backstage follow the standard OSC address pattern: a forward-slash-delimited path like /Backstage/p1/opacity. The Domain field on OSCDecode and UnpackOSC acts as a prefix filter. OSCDecode strips the matched prefix and uses the remaining path as a Pack label. UnpackOSC requires an exact full-address match.
OSC type tags
The Tags field on encode and decode nodes defines the argument types in the message. Each character maps to one argument:
|
Tag |
Type |
Example |
|---|---|---|
|
|
32-bit integer |
Cue number, step index |
|
|
32-bit float |
Fader value, opacity, volume |
|
|
String |
Sequence name, command label |
For example, a tags value of ifs means the message carries one integer, one float, and one string argument in that order.
Node reference
|
Node |
Purpose |
Key settings |
|---|---|---|
|
Network:UDPReceiver |
Listens for incoming UDP packets on a port |
NIC (dropdown), Port (integer 0–65535), Connected (checkbox) |
|
Network:OSCDecode |
Parses OSC messages/bundles, filters by domain prefix, outputs a Pack |
Domain (string, default |
|
Network:UnpackOSC |
Decodes one specific OSC address to individual typed output pins |
Domain (full address), Tags ( |
|
Network:OSCEncodeMessage |
Builds an OSC message from individual typed inputs, sends on Bang |
Domain (string), Tags ( |
|
Network:OSCEncodePack |
Converts a Pack to an OSC message or bundle |
Domain (string, default |
|
Network:PackOSC |
Builds an OSC message from tag-typed inputs (like OSCEncodeMessage with separate tag config) |
Domain (string), Tags ( |
|
Network:UDPSender |
Sends UDP packets to a target IP and port |
IP address (string), Port (integer 0–65535), Connected (checkbox) |
Port configuration and firewall
The default UDP port for new UDPReceiver and UDPSender nodes is 13579. Change it to match your show controller's configuration.
-
Valid port range:
0to65535. Avoid ports below 1024 (reserved by Windows) and ports already in use by other services. -
Multiple UDPReceiver nodes can share the same port. Backstage pools socket listeners internally — all nodes bound to the same address/port receive every packet.
-
If the UDPReceiver checkbox stays red after enabling, the port is likely blocked. Open Windows Firewall and add an inbound rule for UDP on that port.
-
The UDPReceiver ignores messages originating from the same bound address (self-sent packets are filtered).
Common Mistakes
-
OSCDecode output is empty even though UDPReceiver receives packets — the Domain on the OSCDecode node does not match the incoming OSC address prefix. Check the address your controller is sending (e.g.
/QLab/cuevs/Backstage/p1) and update the Domain field to match. -
UnpackOSC produces no output — UnpackOSC requires an exact domain match (not a prefix). The full OSC address in the incoming message must match the Domain field character for character. Also verify the Tags field matches the argument types being sent.
-
OSCEncodeMessage creates wrong argument count — changing the Tags field after wiring can disconnect pins. If you need to change Tags, rewire the dynamic input pins afterward.
-
UDPSender shows "Cannot connect" — the target IP address is unreachable or malformed. Verify the IP is correct and the target is on the same network or routable.
Tips
-
Use a Unspecified:FiFoLog node connected to the UDPReceiver's Message output to see raw incoming data during debugging. The FiFoLog displays the last 10 received strings directly on the graph canvas.
-
OSCDecode handles both single messages and OSC bundles. If your controller sends bundles (e.g. TouchOSC, QLab), OSCDecode unpacks them automatically into a nested Pack structure.
-
The Domain input on OSCDecode and OSCEncodeMessage can be set dynamically from another node. This lets you switch between OSC namespaces at runtime.
-
For bidirectional OSC (e.g. feedback to a TouchOSC layout), use one UDPReceiver for incoming and one UDPSender pointing at the controller's IP for outgoing — typically on different ports.
-
The Sender output on UDPReceiver gives you the source IP:port of each message. Use this with a String:Route node to filter messages by source device when multiple controllers share the same port.
Related
Trigger Playback via UDP — trigger sequences from plain-text UDP commands (non-OSC)
Your First Graph — build your first Node Editor graph from scratch
Build a Multi-Step Show — create a multi-step show using the Stepper node
Integrate with Conductor — connect Backstage to Conductor for DMX and show control
