Skip to content

UDP Command API

Exaplay 3 exposes a UDP command interface that carries the same command set as the TCP Command API. It is aimed at show control systems, touch panels, and embedded controllers that prefer the simplicity of fire-and-forget datagrams over a persistent TCP connection.

Naming note: The Exaplay UI calls this composition type a Playlist. The wire protocol still uses the original cuelist identifier (returned by get:type, used in get:cuelist, etc.). This is intentional so existing integrations continue to work — treat cuelist and CueList in the protocol as synonyms for Playlist in the UI.

Connection

ParameterValue
ProtocolUDP (datagram)
Default Port8200
ConfigurationConfig → Network → UDP Listen
Line terminator\r\n (CRLF) recommended; bare \r or \n are also accepted
EncodingASCII / UTF-8

Each datagram contains exactly one command. The engine sends the complete response — which may span multiple logical lines — back to the sender's IP and port as a single reply datagram. There is no persistent session; each command/response exchange is independent.

Note: Because UDP does not guarantee delivery or ordering, avoid sending commands faster than you can process the responses. For reliable bidirectional communication (status polling, multi-step workflows) the TCP Command API is preferable.

Changing the Listen Address/Port

The UDP Listen config field accepts one or more entries (one per line), each in ADDRESS:PORT format. Use * as the address to listen on all network interfaces:

*:8200

To listen on a specific interface only:

192.168.1.5:8200

Leave the field empty to disable UDP control.

Command Format

COMMAND,COMPOSITION_ID[,ARGUMENT]
  • Fields are separated by commas.
  • The first field is always the command name.
  • Commands that target a composition require the composition's variable name (e.g. comp_1) as the second field.
  • Retrieve variable names with get:complist.
  • The response is returned as a single UDP datagram. Multi-line responses (list commands) have each line delimited by \r\n within that datagram and are terminated by a final END\r\n line.

Global Commands

These commands do not require a composition ID.

CommandResponseDescription
hellohalloConnection test / keep-alive
get:verExaplay,<version>Get engine version string
get:complistOne line per composition, then ENDList all compositions
get:projname<project name>Get the loaded project name

get:complist response format

<varname>,<display name>\r\n
<varname>,<display name>\r\n
...
END\r\n

Example:

→ get:complist
← comp_main,Main Show\r\ncomp_lobby,Lobby Loop\r\nEND\r\n

Composition Commands

All composition commands use the format COMMAND,COMPID[,ARGUMENT].

Transport

CommandArgumentsResponseDescription
play,COMPIDOKStart playback
pause,COMPIDOKPause playback
stop,COMPIDOKStop playback
set:cuetime,COMPID,SECONDSSECONDS — floatOKSeek to position (seconds)

Audio

CommandArgumentsResponseDescription
get:vol,COMPID<0–100>Get volume (integer %)
set:vol,COMPID,VALUEVALUE — integer 0–100OKSet volume

Display

CommandArgumentsResponseDescription
get:alpha,COMPID<0–100>Get master alpha (integer %)
set:alpha,COMPID,VALUEVALUE — integer 0–100OKSet master alpha

Playback Options

CommandArgumentsResponseDescription
get:loop,COMPID0 or 1Get loop state
set:loop,COMPID,VALUEVALUE0 or 1OKEnable/disable looping

Status and Info

CommandResponse formatDescription
get:name,COMPID<name>Get display name
get:type,COMPIDtimeline, cuelist, or compositionGet composition type
get:itemcount,COMPID<count>Number of media items
get:status,COMPIDSTATUS,TIME,FRAME,CUEINDEX,TOTALFull playback status (see below)
get:duration,COMPIDDepends on type (see below)Total duration
get:playingitem,COMPIDDepends on type (see below)Currently playing item
get:cuename,COMPID<name>Name of the currently active cue

get:status response fields:

FieldValuesDescription
STATUS0 stopped, 1 playing, 2 pausedPlayback state
TIMEfloat (seconds)Current playback position
FRAMEintegerCurrent frame number (TIME × 60)
CUEINDEXintegerActive cue index (timeline) or current item position (cuelist)
TOTALfloat (seconds)Total duration of current item (cuelist only)

get:duration response:

  • Timeline: DURATION — total timeline length in seconds (float)
  • CueList: COUNT,TOTAL — number of items and sum of all clip lengths (float seconds)

get:playingitem response:

  • CueList: INDEX,NAME,FILE — 1-based item index, friendly name, source file path
  • Timeline: INDEX,CUENAME,TIME — cue variable index, cue name, current time (float seconds)

Timeline Commands

These commands are only valid when the composition is a Timeline.

CommandArgumentsResponseDescription
set:cue,COMPID,INDEXINDEX — cue variable indexOKJump to cue by index and trigger it
get:cuelist,COMPIDOne line per cue, then ENDList all cues
get:cueinfo,COMPID,INDEXINDEX — cue variable indexINDEX,NAME,OFFSET,ACTIVEDetails about a specific cue

get:cuelist (Timeline) response format:

<index>,<name>,<time-offset seconds>\r\n
...
END\r\n

get:cueinfo (Timeline) response fields: INDEX,NAME,OFFSET_SECONDS,IS_ACTIVE


CueList Commands

These commands are only valid when the composition is a CueList.

CommandArgumentsResponseDescription
set:cue,COMPID,INDEXINDEX — 1-based item numberOKPlay item at the given position
next,COMPIDOKAdvance to the next item
prev,COMPIDOKGo back to the previous item
get:cuelist,COMPIDOne line per item, then ENDList all items
get:cueinfo,COMPID,INDEXINDEX — 1-based item numberINDEX,NAME,FILE,DURATIONDetails about a specific item

get:cuelist (CueList) response format:

<1-based index>,<name>,<file path>\r\n
...
END\r\n

Note: Timeline cue indices match the cue's variable index (arbitrary integer). CueList item indices are always 1-based sequential numbers.


Error Responses

All error responses begin with ERR,:

ErrorMeaning
ERR,unknown_commandCommand string not recognised
ERR,composition_not_foundNo composition with the given variable name exists
ERR,missing_argumentRequired argument was not supplied
ERR,cue_not_foundThe cue/item index does not exist
ERR,none_playingRequested info about a playing item, but nothing is playing
ERR,no_next_itemnext reached the end of the cue list
ERR,already_at_firstprev called when the first item is already playing
ERR,cuelist_emptynext/prev called on an empty cue list
ERR,unsupported_typeCommand is not applicable to this composition type
ERR,no_projectNo project is currently loaded
ERR,exceptionAn internal error occurred

Example Sessions

Connection test

→ hello
← hallo\r\n

Discover and play a composition

→ get:complist
← comp_main,Main Show\r\ncomp_lobby,Lobby Loop\r\nEND\r\n

→ play,comp_main
← OK\r\n

→ get:status,comp_main
← 1,12.3456,740,0,0.0000\r\n

Work with a CueList

→ set:cue,comp_lobby,2
← OK\r\n

→ next,comp_lobby
← OK\r\n

Work with a Timeline

→ set:cue,comp_main,2
← OK\r\n

Sending Commands from Common Environments

Python (testing / scripting)

python
import socket

HOST = "192.168.1.5"
PORT = 8200

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(2.0)

def send(cmd):
    sock.sendto((cmd + "\r\n").encode(), (HOST, PORT))
    try:
        data, _ = sock.recvfrom(65536)
        return data.decode().strip()
    except socket.timeout:
        return "(no response)"

print(send("hello"))             # hallo
print(send("get:complist"))      # comp_main,Main Show\r\nEND
print(send("play,comp_main"))    # OK

Node.js

js
const dgram = require('dgram');
const client = dgram.createSocket('udp4');

const HOST = '192.168.1.5';
const PORT = 8200;

function send(cmd) {
  return new Promise((resolve) => {
    client.once('message', (msg) => resolve(msg.toString().trim()));
    client.send(cmd + '\r\n', PORT, HOST);
  });
}

(async () => {
  console.log(await send('hello'));           // hallo
  console.log(await send('play,comp_main'));  // OK
  client.close();
})();

netcat / socat (quick diagnostics)

bash
# Send a single command and print the response
echo -ne "hello\r\n" | socat - UDP:192.168.1.5:8200

# Interactive session (socat keeps the socket open)
socat - UDP:192.168.1.5:8200

TCP vs UDP — When to Use Which

ScenarioRecommended
Show control system with persistent connectionTCP
Embedded controller / microcontroller with UDP onlyUDP
Single fire-and-forget trigger commandsUDP
Polling status at high frequencyTCP
Multi-step workflows requiring ordered responsesTCP

Firewall

Ensure UDP port 8200 is open on the Exaplay machine:

batch
netsh advfirewall firewall add rule name="Exaplay UDP Control" ^
  dir=in action=allow protocol=UDP localport=8200

See Also

  • HTTP REST API — JSON-based HTTP API (port 8123) with equivalent seeking and transport commands
  • TCP Command API — persistent connection variant of this API

Exaplay 3 User Documentation