Pixel Streaming¶
Every PoleFX pole is a network pixel fixture. You can stream your own video or generative content to it from lighting and VJ software, exactly as you would to any other LED product, using standards the industry already speaks:
- DDP (Distributed Display Protocol)
- sACN (ANSI E1.31, also called Streaming ACN)
- Art-Net
This page tells you everything needed to drive a pole directly: the pixel layout, the universe math, the settings on each end, and how to check your work without guessing.
This is the opposite approach to the DMX page, and the two are easy to confuse. The difference is what you send and where it lands.
- What you send
- Nine channel values.
- How much data
- Nine numbers.
- What you control
- Brightness, which pattern, hue, text. The Player draws the picture.
- Where it goes
- Into the Player, which then drives the poles.
- Best for
- Running the pole from a lighting desk alongside a show.
- What you send
- The actual pixels.
- How much data
- 2,880 RGB pixels, every frame, up to 60 times a second.
- What you control
- Every LED. Nothing is drawn for you.
- Where it goes
- Straight to one pole. The Player is not in the path.
- Best for
- Your own video or generative content from VJ software.
Which generation is your pole?¶
There have been three generations of PoleFX pole, and they differ in ways that matter here. This page describes generation 3, the current product.
| Gen 1 | Gen 2 | Gen 3 (current) | |
|---|---|---|---|
| LED strips around the pole | 8 | 4 | 6 |
| Columns of pixels | 8 | 8 | 12 |
| Strip wiring | one column per strip, straight | two columns per strip, zigzag | two columns per strip, zigzag |
| Frame size | 255 x 8 | ask us | 240 x 12 |
| Streaming protocols | sACN multicast | sACN multicast | DDP, sACN, Art-Net |
Generation 3 raised the resolution around the pole from 8 columns to 12, which is where the current 12 pixel image height comes from.
One thing has always been true of every generation: you send a plain rectangular image and the pole deals with its own wiring. Gen 2 and gen 3 strips physically snake back and forth between their two columns, and gen 1 strips do not, but that is the pole's business. Your content never changes shape because of it.
If you have a gen 1 or gen 2 pole, the protocol options on this page may not be available to you and your frame is not 240 by 12. Read the frame size off the pole itself, as described under Frame size, or get in touch and we will tell you what your specific pole supports.
Before you start¶
You need three things. Check all three before you touch any software: two of the three account for most of the time people lose here.
A hard requirement. Check it in the Player web app under Settings > Devices, in the Firmware column. An older pole cannot report or change any of the settings on this page.
This is the question people get stuck on. See Finding your pole's IP address below.
Your computer must be on the same network as the pole. Wi-Fi technically works, then drops packets and stutters. Use a cable for anything you care about.
Everything on this page, including the settings and the diagnostics, arrived in the 2026.07 release. On a pole older than that the Player shows a note in place of the streaming panel, so update the firmware first.
Finding your pole¶
Try these in order. The first one that works is the one to use, and most people never get past the second.
-
First try You know the pole's nameDo Use
polefx-<name>.local, lowercase with hyphens for spaces. No IP address needed. Test it:curl http://polefx-top-support.local/json/cfg -
Or There is a PoleFX Player on the networkDo Open the web app, go to Settings > Devices, and read the IP address, name and firmware straight off the list.
-
Or You have the installation paperworkDo Poles ship with a static address, usually in
192.168.5.x. It is written down there. -
Or You have none of the aboveDo Scan the network:
nmap -sn 192.168.5.0/24, or a phone app like Fing. -
Then confirm You have a candidate addressDo Open
http://<address>/json/cfg. A pole answers with JSON starting with its name and profile. Anything else is not a pole. -
If A pole that used to work has vanishedDo Poles use static addresses, not DHCP, so one moved to a different network stays unreachable until its address is changed to match. That is usually the reason.
Poles answer to a name. A pole called "Top Support" is reachable at
polefx-top-support.local, so you can usually skip the IP address entirely:
curl http://polefx-top-support.local/json/cfg
The name is your pole's name in lowercase with spaces turned into hyphens, and
a polefx- prefix. This works out of the box on macOS, on Windows 10 and
newer, and on Linux with Avahi installed. It needs no setup, no server, and
no special switch or router: poles answer these lookups themselves. The one
limit is that it does not cross a router, so you must be on the same network
segment as the pole.
You can also list every pole at once. On macOS:
dns-sd -B _http._tcp local
Each pole also publishes its strip and pixel counts alongside its name, so a discovery tool can size a pole without connecting to it.
Finding your pole's IP address¶
If names are not working, or you need the address itself, poles also announce themselves on the network twice a second. The easiest path:
Open the PoleFX Player web app and go to Settings > Devices. Every pole the player can see is listed with its IP address, name, and firmware version. That list is built from the poles' own announcements, so it is current and needs no setup.
If you do not have a player on the network, a pole is still reachable, you just have to find it another way:
- Poles ship with a static IP address, usually in the
192.168.5.xrange, and each model has its own default. If you have the paperwork from your installation, the address is on it. - Any network scanner will find it.
nmap -sn 192.168.5.0/24from a terminal, or a phone app like Fing, will list the devices on the network. - Once you have a candidate address, confirm it is a pole by opening
http://<that-address>/json/cfgin a browser. A pole answers with a block of JSON that starts with its name and profile. Anything else is not a pole.
Because poles use static addresses rather than DHCP, a pole moved to a different network may not be reachable until its address is changed to match that network. If a pole has vanished, this is usually why.
Connecting a computer straight to a pole¶
You can plug a computer into a pole with a single Ethernet cable, with no switch and no router. One extra step is needed, and skipping it is the usual reason this appears not to work.
Give your computer an address on the pole's network. Poles use a fixed address and do not hand one out, so with a direct cable your computer will assign itself an unrelated address and the two will not be able to reach each other. Set your computer's Ethernet interface to a manual address on the same network as the pole, for example:
- IP address:
192.168.5.100(any free address on that network) - Subnet mask:
255.255.255.0 - Router: leave blank
On macOS that is System Settings > Network > Ethernet > Details > TCP/IP, Configure IPv4 set to Manually. On Windows it is the IPv4 properties of the adapter.
Once the addresses match, everything on this page works over that one cable,
including the .local name and streaming itself.
A pole displays whichever source is actively streaming to it. If the PoleFX Player is still sending to the same pole, the two will compete and one of them will simply be ignored. Before streaming from your own software, open the player's web app, go to Settings > Outputs, and set that pole's output to inactive.
The canvas¶
This is the part worth reading carefully. Get the canvas right and everything else is straightforward.
A pole is a rectangular image. Its width is the length of the pole and its height is the distance around the pole. For a standard pole that image is 240 pixels wide by 12 pixels tall.
Row 12 wraps back around to row 01. Send ordinary reading order, never serpentine.
Think of it as unwrapping the pole into a flat strip: 12 lines of pixels running the length of the pole, side by side. The first pixel of each line is at the top of the pole. The 12 lines wrap around the pole, so the top and bottom edges of your image are physically adjacent, and content that scrolls off the bottom edge should reappear at the top edge.
Pixel order is ordinary reading order. Start at the top-left, go left to right along the first line, then the next line down, and so on. Three bytes per pixel, red then green then blue.
pixel index = (line around the pole * pole length in pixels) + position along the pole
Do not add a zigzag or serpentine. This is the single most common mistake and it is worth stating plainly. Physically, each LED strip inside a gen 3 pole covers two of the 12 lines and the data path snakes back and forth between them. The pole undoes that for you. Your software should send a plain, straightforward image in normal reading order, and the pole rearranges the pixels internally to match its own wiring. If your software offers a "serpentine", "zigzag", "boustrophedon" or "snake" pixel order, leave it off.
This has been true of every generation, including the older poles whose strips are wired differently. The pole always adapts to the image, never the reverse.
Every line runs the same way, left to right. The pole rearranges the pixels internally to match its own wiring.
Alternate lines run backwards. The pole then undoes a snake that was never there, so every other line comes out mirrored.
Recognizable but torn into alternating bands along the pole. If that is what you have, turn serpentine off in your software.
Send linear RGB. Do not apply gamma twice. Each pole has its own gamma setting (default 1.0, meaning no correction). If your software also applies gamma, either turn one of them off or accept the combined result. When colors look crushed or washed out, this is almost always the cause.
Frame size¶
The frame size depends on the generation, not on the individual pole. There are only two:
| Generation | Image size | Pixels | Bytes per frame |
|---|---|---|---|
| Gen 3 (current) | 240 x 12 | 2,880 | 8,640 |
| Gen 1 | 255 x 8 | 2,040 | 6,120 |
| Gen 2 | Ask us |
Gen 2 poles are not one shape, so we do not print a number here that might not
be yours. Read led.strips and led.pixels from your own pole as described
below, or get in touch and we will tell you what that pole expects.
Send the frame size your pole reports. Poles come in different physical lengths, and a shorter pole can expect a smaller frame rather than a padded standard one.
Read it from the pole itself: open http://<pole-ip>/json/cfg and multiply
led.strips by led.pixels by 3 to get the bytes it expects. That reading is
always the authority for that pole, ahead of any table on this page. If it
disagrees with the table above, send what the pole says: a pole handed a frame
of the wrong size rejects the excess and may publish nothing at all.
Orientation¶
Pixel 0 is at the top of the pole. The left edge of your image is the top of the pole, and the right edge is the bottom.
This is the part that trips people up, so it is worth being explicit: the image is stored sideways relative to the pole. The pole stands vertically, but its length is the horizontal axis of your image. That means:
The horizontal axis of your image is the length of the pole.
The vertical axis wraps, so the top and bottom edges are physically next to each other.
This is the fix when your content comes out inverted.
A vertical video of a flame or a waterfall has to be turned on its side before it runs along the pole correctly.
If you are preparing footage, the practical consequence is that you usually want to rotate it 90 degrees. A tall video of a flame or a waterfall has to be turned on its side to run along the pole correctly.
If your content comes out upside down while you are streaming, flip the image horizontally in your own software. That reverses the length of the pole and leaves the way round it alone.
The Flipped toggle in a pole's output settings is not the same thing, so do not reach for it to fix a stream. It turns the whole canvas through 180 degrees: the length reverses and the way round the pole mirrors as well. That is the right behavior for a pole mounted the other way up, which is what it is for, and it only applies to content the Player is sending.
Choosing a protocol¶
| DDP | sACN (E1.31) | Art-Net | |
|---|---|---|---|
| UDP port | 4048 | 5568 | 6454 |
| Unicast to one pole | Yes | Yes | Yes |
| Multicast | Yes | No | No (broadcast works) |
| Addressed by | byte offset | universe | universe |
| Universes for a standard pole | not applicable | 17 | 17 |
| Best for | efficiency, many poles | consoles and media servers | Resolume and most VJ tools |
Use DDP if your software supports it. It carries a whole frame in six packets rather than seventeen, it has an explicit end-of-frame marker so frames never tear, and it is the only one of the three that can multicast a single stream to several poles at once. Software that speaks DDP includes xLights, LedFx, WLED based tools, and the DDP TouchDesigner plugin.
Use sACN or Art-Net if you are driving the pole from lighting or VJ software, which is far more likely to speak those. They are equivalent in practice here. Pick whichever your software supports; if it supports both, either is fine.
-
If It speaks DDPDo Use DDP. Six packets a frame instead of seventeen, an explicit end-of-frame marker so frames never tear, and no universe math at all.
-
If You are feeding several poles one identical streamDo Use DDP. It is the only one of the three that can multicast, so one stream reaches every pole.
-
If It is lighting or VJ softwareDo Use sACN or Art-Net; they are equivalent here. Pick whichever it supports, and if it supports both, either is fine.
-
If You picked sACNDo Switch it from multicast to unicast and type in the pole's IP address. A default sACN setup sends data that never arrives.
-
If You picked Art-NetDo Check which universe it starts at. Art-Net software usually counts from 0 and the pole starts at 1, which is the failure below.
Most sACN software defaults to multicast. Poles do not subscribe to sACN multicast groups, so a default setup will send data that never arrives. You must switch your software to unicast and give it the pole's IP address. A standard pole needs 17 universes, and subscribing to 17 multicast groups per pole is exactly the problem this avoids.
Universes¶
sACN and Art-Net both carry 512 channels per universe. Since a pixel takes 3 channels, a universe holds 170 pixels, using 510 channels. The last 2 channels of each universe go unused so that no pixel is split across two universes.
A standard pole is 2,880 pixels, so it needs 17 universes. The first 16 are full (510 channels each) and the 17th carries the remaining 480 channels.
| Generation | Universes | Last universe |
|---|---|---|
| Gen 3 (current), 240 x 12 | 17 | 480 channels |
| Gen 1, 255 x 8 | 12 | 510 channels (exactly full) |
Universes must be consecutive, starting at the pole's start universe.
Setting the start universe¶
Poles default to starting at universe 1, so a standard pole listens on universes 1 through 17.
There are two ways to change it, and they do exactly the same thing.
From the player web app (easiest). Go to Settings > Devices, click Details on the pole you want, and find Streaming protocols. You can turn each protocol on or off, set the start universe, and see live counts of what the pole is receiving. The panel shows how many universes that specific pole needs and which range it is listening on, so you do not have to work it out. Turning a protocol on or off needs a restart; the start universe applies immediately.
Over the pole's own API, which is useful for scripting or when there is no player on the network.
This is the single most common reason a correct-looking setup shows nothing at all, because Art-Net numbers universes from 0 and the pole starts at 1.
All 17 universes land where the pole is listening. Frames complete and
published climbs.
Universe 0 is thrown away and universe 17 never arrives. The pole gets 16 of the 17 it needs, so no frame ever completes and the pole shows nothing while looking perfectly healthy.
That pair of counters is the signature. Compare
last_bad_universe with want_uni_first and
want_uni_last to confirm.
Set your software to start at universe 1, or set the pole to start at 0 with the command below. Note that sACN cannot use universe 0, so a pole set to 0 is Art-Net only.
To read the current value:
curl http://192.168.5.12/json/cfg
To change the start universe (this example sets it to 0 for Art-Net software that counts from zero) and save it so it survives a reboot:
curl -X POST http://192.168.5.12/json/cfg -d '{"dmx":{"start_uni":0,"sacn_enable":0,"artnet_enable":1},"save":true}'
The start universe applies immediately, with no reboot. Note that sACN cannot use universe 0 (the standard reserves it), so a pole set to 0 is Art-Net only. That is why the example switches sACN off in the same request: leaving it on would advertise a receiver that can no longer be addressed.
You can also turn either receiver off entirely with "sacn_enable":0 or
"artnet_enable":0. Those take effect on the next reboot.
The rest of the configuration API¶
/json/cfg is not limited to these settings. A GET returns the pole's
entire configuration, and whatever it returns it will also accept back on a
POST, which is what makes it usable as a backup format rather than just an
API. It covers the device name and profile, network addresses, ports, LED
geometry and gamma, idle patterns, on-pole text, and the protocol settings
above.
Two rules the pole enforces, both worth relying on:
- A change is all or nothing. The pole validates the whole document before applying any of it. If one field is out of range it rejects the entire request with an error naming that field, and nothing on the pole changes. There is no half-applied state to clean up. Values are never quietly clamped to fit.
- Nothing persists until you ask. Add
"save":trueto write the change to the pole's permanent storage. Without it the change is live immediately but will be lost on the next power cycle.
A successful response looks like this:
{"ok":true,"applied":3,"saved":true,"save_error":0,"restart_required":false}
A rejected one is an HTTP 400 whose message names the field, for example
1 field(s) rejected, first: start_uni: out of range.
To back up a pole, save the output of a GET. To restore it, POST that file
back with "save":true. Because everything the pole reports is also something
it accepts, a backup taken from one pole can be pushed to another.
Setting up Resolume¶
Resolume is a good choice for streaming video content to poles. Some requirements to know before you start:
The rest of this section has not been run against a real pole. It is built from Resolume's own documentation and from what the pole is known to accept, so treat the field names and the numbers as a starting point rather than as a tested recipe. Everything above this heading, including the canvas, the universe math and the counters under Checking your work, is verified. If a step here does not work, read the counters: they are the authority, and please tell us what you found.
- Resolume Arena, not Avenue. Pixel output over Art-Net is an Arena-only feature. Avenue cannot do it.
- These steps use Art-Net. Recent versions of Arena also offer sACN output, but we have not tested that path against a pole. If you use it, remember the pole is unicast only, so give it the pole's IP address rather than leaving sACN on multicast.
- The free demo version does DMX output; it watermarks the video output.
Resolume's own reference for this is its DMX Output and Fixture Editor manual pages.
1. Build the fixture¶
Open Application > Fixture Editor and create a new fixture.
- Width 240, Height 12 for a standard pole. Use the sizes from the table above for other models.
- Distribution: choose plain reading order, going left to right and top to bottom. Do not choose a zigzag or serpentine option. The pole applies its own internal zigzag; adding one here scrambles the image.
- Color Space: RGB.
- Gamma: Resolume defaults this to 2.5. The pole's own gamma defaults to 1.0 (off), so leaving Resolume at 2.5 gives you a normal gamma curve overall. Change it only if the result looks wrong.
2. Create the output¶
Open Output > Advanced... to open the Advanced Output window.
- From the Presets dropdown choose New for a blank layout.
- Click the + icon and add a DMX Lumiverse. A Lumiverse is Resolume's virtual container for a set of universes.
- If you are only doing LED output, select Screen 1 and delete it.
- The Lumiverse creates a DMX Fixture automatically. Select it and choose your pole fixture from the Fixture dropdown at the bottom right.
- Position and scale the fixture in the Input Selection canvas. This decides which part of your composition the pole samples.
3. Point it at the pole¶
Select the Lumiverse and set, on the right-hand panel:
- TargetIP: choose IP Address and type the pole's address. Resolume can also auto-discover Art-Net nodes, but poles do not announce themselves, so enter the address manually.
- Subnet 0 and Universe 1, to match a pole using its default start universe. Type the universe number the pole is listening on: Resolume's field is the number that goes on the wire, so 1 here reaches a pole that starts at 1. The off-by-one warned about above is what happens when software starts its own count at 0 and you leave the field there; here you are setting it explicitly, so there is nothing to convert.
- Auto Span: on. This lets the Lumiverse grow past one universe automatically, which a 17 universe pole needs.
- Align Output: on. This stops a pixel from being split across two universes. Poles reject packets where pixels straddle a universe boundary, so this must stay on.
4. Settings worth changing¶
In Preferences > DMX:
- Network Adapter: pick the interface your poles are on. Sending to the wrong adapter is the most common reason nothing appears. Note that this switches Art-Net input and output together.
- Output Delay: defaults to 40 ms, which exists to line lights up with projectors. With no projector in the rig, set it to 0.
- Output Framerate: poles accept up to 60 frames per second.
The Output > Test Card has a moving diagonal line, which makes a flipped or misordered fixture obvious immediately.
Checking your work¶
Every pole reports what it is receiving. Open this in a browser:
http://<pole-ip>/json/cfg
Look at the info section for sacn, artnet or ddp. The useful fields:
| Field | Meaning |
|---|---|
packets |
Data packets accepted |
published |
Complete frames displayed. This is the number that matters. |
incomplete_frame |
The sender started a new frame before finishing the last |
wrong_universe |
Universes outside the pole's range |
last_bad_universe |
The most recent one it had to reject |
want_uni_first, want_uni_last |
The range the pole is actually listening on |
bad_stride |
A universe carried the wrong number of channels |
malformed |
Packets that did not parse |
stream_busy |
A different protocol already holds this pole |
foreign_source |
A second sender on the same protocol was ignored |
Test frames¶
Seven frames that each answer one question. They are 240 by 12 PNGs, the exact canvas a gen 3 pole expects, so you can send them straight through your software without resizing. Each preview below is magnified four times; the download is the real thing.
Black at the top of the pole, white at the bottom. If the bright end is at the top, flip your image horizontally.
Twelve flat colors, one per row. Count them on the pole. Fewer bands, or repeats, means the frame height is wrong.
Only rows 1 and 12 are lit. They are physically next to each other, so the two lines should appear side by side.
Four single pixels: white is pixel 0, red is pixel 239 which is the end of the first row and not the end of the pole, green starts the second row, blue is the last pixel.
The color changes every 170 pixels, once per universe. The bands do not line up with the rows, and the seventeenth is short. If your seams land elsewhere, your software packs a different number of pixels per universe.
Pure red, green and blue thirds. Wrong order means a channel swap. Washed out means gamma is being applied twice.
Alternating single pixels. Any smoothing or scaling in the chain turns it into flat gray.
These are generated by tools/make_test_patterns.py, so they always match the
canvas this page describes.
If nothing is displaying¶
The pole's own counters tell you which of these it is, so read them before changing anything. Each branch below ends in one thing to do.
/json/cfg and read the counters under info.-
If
packetsis 0Do Nothing is arriving at all. Check the pole's IP address, switch your software from multicast to unicast, and check it is sending on the right network adapter. -
If
packetsclimbs butpublishedstays 0Do Data arrives but no frame ever completes, which is nearly always the universe range. Comparelast_bad_universewithwant_uni_firstandwant_uni_last, then move your software or the pole's start universe so they agree. -
If
bad_strideis climbingDo Your software packs a different number of pixels per universe. Set it to 170 pixels, which is 510 channels. In Resolume this is the Align Output setting. -
If
stream_busyis climbingDo A different protocol already owns the pole, almost always the PoleFX Player. Switch that output off in Settings > Outputs. -
If
foreign_sourceis climbingDo Two senders are using the same protocol at this pole and one is being ignored. Find the second sender and stop it. This is the counter that moves when you have two copies of your own software running, andstream_busystays at 0. -
If
incomplete_frameis climbingDo Your sender starts a new frame before finishing the last. Lower the frame rate, or move off Wi-Fi onto wired Ethernet. -
If
publishedclimbs but the image is scrambledDo The stream is healthy, so this is the pixel order. Turn off serpentine or zigzag in your software. -
If
publishedclimbs but the colors look crushedDo Gamma is being applied twice. Turn it off in your software, or set the pole's gamma back to 1.0.
Limits and behavior¶
- 60 frames per second is what we test and recommend. Nothing in the pole rejects a faster stream, but frames that arrive before the previous one has been shown are simply superseded, so the extra work is wasted.
- A pole displays whichever source is actively streaming. A different protocol can take over once the current one has been quiet for half a second. A second sender on the same protocol is ignored until the first has been quiet for a quarter of a second.
- When streaming stops entirely, the pole returns to its built-in patterns after a few seconds.
- A frame is only displayed once all of it has arrived, so a dropped packet holds the previous frame rather than showing a torn one.