Skip to content

Using Code to Send OSC

This guide will walk you through some examples on how to use python or javascript to send OSC. We at sndwrks obviously like code a bit and we wanted to share some simple examples.

By then end of the guide, you’ll have two working scripts in python and node.js that will allow you to send osc via the terminal anywhere you want. We find scripts like this extremely helpful for testing devices when we don’t want to use a full tool like QLab or ETC EOS.

What will I be able to do: make Confetti with Python!

confetti.py
# pip3 install python-osc
from pythonosc import udp_client
server_ip = "10.0.10.100" # adjust to the server ip
server_udp_port = 52000 # adjust to the network server udp listen port
client = udp_client.SimpleUDPClient(server_ip, server_udp_port)
client.send_message("/sndwrks/server/v1/confetti", [])
# run it in terminal
# python3 confetti.py

To complete this guide, you’ll need python 3.12 and node.js 24. If you already know how to set those up, skip ahead. These instructions are for macOS with Terminal.

pyenv lets you install and switch between Python versions without touching the system Python.

  1. Install pyenv with Homebrew:

    Terminal window
    brew install pyenv
  2. Add pyenv to your shell. Add these lines to ~/.zshrc:

    Terminal window
    export PYENV_ROOT="$HOME/.pyenv"
    [[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
    eval "$(pyenv init -)"
  3. Restart your terminal, then install Python 3.12:

    Terminal window
    pyenv install 3.12
    pyenv global 3.12
  4. Verify it worked:

    Terminal window
    python --version
    # Python 3.12.x

nvm does the same thing as pyenv but for Node.js.

  1. Install nvm with Homebrew:

    Terminal window
    brew install nvm
  2. Add nvm to your shell. Add these lines to ~/.zshrc:

    Terminal window
    export NVM_DIR="$HOME/.nvm"
    [ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh"
  3. Restart your terminal, then install Node 24:

    Terminal window
    nvm install 24
    nvm use 24
  4. Verify it worked:

    Terminal window
    node --version
    # v24.x.x

This script lets you send any OSC message from the command line. You pass in the server IP, port, OSC address, and any arguments.

First, install the python-osc library:

Terminal window
pip install python-osc

Then create this script:

send_osc.py
# the sys package allows us to read values when the file is ran
import sys
# this is the library that will actually format and send our osc
from pythonosc import udp_client
# if the file is executed without the proper arguments we should
# let the user know and show them how to fix it.
if len(sys.argv) < 4:
print("Usage: python send_osc.py <ip> <port> <address> [args...]")
print("Example: python send_osc.py 10.0.10.100 52000 /sndwrks/server/v1/confetti")
sys.exit(1)
# read the arguments inputted at runtime
ip = sys.argv[1]
port = int(sys.argv[2])
address = sys.argv[3]
args = sys.argv[4:]
# initialize the client
client = udp_client.SimpleUDPClient(ip, port)
# now send our message
client.send_message(address, args)
# and lets show some feedback that we did that for the user
print(f"Sent {address} {' '.join(args)} -> {ip}:{port}")

Usage

Send confetti with no args:

Terminal window
python send_osc.py 10.0.10.100 52000 /sndwrks/server/v1/confetti

Log a custom event with args:

Terminal window
python send_osc.py 10.0.10.100 52000 /sndwrks/server/v1/event/custom "Pyro fired" "Stage left mortar"

Same idea, but in JavaScript using the osc.js library.

Set up a small project:

Terminal window
mkdir osc-sender && cd osc-sender
npm init -y
npm install osc

Then add "type": "module" to your package.json so you can use import syntax in .js files. It should look something like this:

package.json
{
"name": "osc-sender",
"type": "module",
"dependencies": {
"osc": "^2.4.5"
}
}

Now create the script:

sendOsc.js
// this is the library that will actually format and send our osc
import osc from "osc";
// process.argv contains the command line arguments
// the first two are the node path and script path, so we skip them
const args = process.argv.slice(2);
// if the script is executed without the proper arguments we should
// let the user know and show them how to fix it.
if (args.length < 3) {
console.log("Usage: node sendOsc.js <ip> <port> <address> [args...]");
console.log("Example: node sendOsc.js 10.0.10.100 52000 /sndwrks/server/v1/confetti");
process.exit(1);
}
// read the arguments inputted at runtime
const [ip, port, address, ...oscArgs] = args;
// initialize a udp port pointed at our target server
const udpPort = new osc.UDPPort({
localAddress: "0.0.0.0",
localPort: 0,
remoteAddress: ip,
remotePort: parseInt(port),
});
// once the port is ready, send our message and close it
udpPort.on("ready", () => {
udpPort.send({
address: address,
args: oscArgs.map((a) => ({ type: "s", value: a })),
});
// and lets show some feedback that we did that for the user
console.log(`Sent ${address} ${oscArgs.join(" ")} -> ${ip}:${port}`);
udpPort.close();
});
// open the port which will trigger the "ready" event above
udpPort.open();

Usage

Send confetti with no args:

Terminal window
node sendOsc.js 10.0.10.100 52000 /sndwrks/server/v1/confetti

Broadcast a chat message:

Terminal window
node sendOsc.js 10.0.10.100 52000 /sndwrks/server/v1/chat/broadcast/send "Stage Manager" "Places please" "info"

Let’s put one of these scripts to use. Say you want the sndwrks server to know when a Mac on your network has finished booting. We can create a .command file that runs on login and sends an OSC message automatically.

A .command file is just a bash script that macOS knows how execute. This is pretty neat because you can add it to your Login Items so it runs every time you log in.

Create a file called startup-completed.command wherever you like. We’ll use the Desktop for this example:

~/Desktop/startup-completed.command
#!/bin/bash
# wait a bit for the network to come up
sleep 10
# send a custom event to the sndwrks server
python ~/scripts/send_osc.py 10.0.10.100 52000 /sndwrks/server/v1/event/custom "Mac Online" "Booth Mac finished booting"

Adjust the IP, port, and message to match your setup. This assumes you saved send_osc.py to ~/scripts/. Update the path to wherever yours lives. You could use the Node.js script here too, just swap the command.

macOS won’t run it unless you mark it as executable:

Terminal window
chmod +x ~/Desktop/startup-completed.command

You can double-click it now to test. Terminal should open, wait 10 seconds, send the message.

  1. Open System SettingsGeneralLogin Items & Extensions.
  2. Under Open at Login, click the + button.
  3. Navigate to your startup-completed.command file and add it. You can also just drag and drop your .command file into the startup items window if you want.

Now every time this Mac logs in, it will send that OSC message to your server. Handy for knowing when all your machines are up and ready before a show.

~/Desktop/startup-completed.command
#!/bin/bash
# wait a bit for the network to come up
sleep 10
# send a custom event to the sndwrks server
python ~/scripts/send_osc.py 10.0.10.100 52000 /sndwrks/server/v1/event/custom "Mac Online" "Booth Mac finished booting"
osascript -e 'tell application "Terminal" to close front window' &