LJ
A laser server for up to 4 ILDA lasers/etherdreams with WebUI manager (alignment, glitch parameters, etherdreams feedback display,...) LJ has MOVED : https://git.interhacker.space/teamlaser/LJ
Install / Use
/learn @tmpbci/LJREADME
LJ v0.8.2
By Sam Neurohack, Loloster, Cocoa
LICENCE : CC BY

A software laser framework with GUI, for up to 4 lasers live actions with ethedreams DACs. Think creative like Laser "battles", planetarium, sharing available lasers in demoparties for competition, ...
LJ has 5 main components :
- "Plugins" are points generators (to one or more lasers). Lot examples comes with LJ : planetarium, 3D anaglyph animations,... See plugins directory.
- A "tracer" per etherdream/laser that take its given point list, correct geometry, recompute in laser controller coordinates, send it to its controller and report its status to the "manager".
- A "manager" that talk to all tracers (which client number point lists to draw, new geometry correction,...), handle IOs (webui functions, OSC commands,...) and plugins.
- A web GUI in html, css, and vanilla js. This UI can be used in a tablet, computer, whatever. LJ does not come with an html server but absolutely can . This GUI has a (currently slow) simulator, but one can also use an etherdream/laser emulator (see nannou simulator below) to work without physical lasers !!
- A network available database (redis). "Plugins" can send directly their pointlists to redis. Each "tracer" is instructed to get one of the avalaible pointlist in redis.
Important : for best performance LJ is meant to run in a dedicated computer especially with multiple lasers and highly multitasked load : if you watch video, use live webcam face recognition, webui simulator,... and run LJ on the same computer, well you need a bunch of cores. If you don't, spread the load : you can use webui on a tablet, the livecam on a phone, run pointlists generators on another computer,...
Features among many others.
- Intensity and kpps live modification.
- Some Lasermapping ('alignment') like in videomapping.
- OSC and websocket commands. Very cool : LJ can script or be scripted.
- Python3
- Web User Interface in your browser : open www/index.html. Javascript is needed. By default it connect to localhost. If you want to control remotely, you need to change the uri line in LJ.js.
- Live WebUI extras : change debug level, restart plugin, rescan DACs,...
- Status update every 0.5 seconds : every etherdream DAC state, number of buffer points sent,...
- "Optimisation" points automatically added, can be changed live for glitch art. Search "resampler" commands.
- A compiled version for os x and linux of nannou.org etherdream+laser emulator is included. For more informations, like license see https://github.com/nannou-org/ether-dream
- Webcam live face display (trckr).
- Resolume OSC client.
- Artnet receiver plugin, another possibity to script LJ.
- Ableton link time synchro support.
- Maxwell laser synth emulation plugin. Work in progress
- Plugins list auto start, see line in LJ.conf : autostart = artnet
- user.py plugin code example
Scenes and pointlists.

LJ accept up to 4 groups = virtual "scenes" of 4 "pointlists" each (= one pointlist per laser), so up to 16 pointlists can be sent to redis at anytime from anywhere in the network. The idea behind this is to easily share actual lasers. Imagine in demo party :
Erica needs 4 lasers, that's the 4 pointlists of "scene" 0. Paula and Jennifer use only 2 lasers each, so they can share "scene" 1. And so on..
The server/network/webUI idea allows to spread cpu intensive tasks on different cpu cores and especially give tracers enough cpu to feed etherdreams DACs smoothly. Of course all this can happen in one computer if you have enough cpu/computers/network ressources.
It's obviously overkill for one laser in a garage, but for several laserS games events, laserS art, laserS competition, laserS planetarium,... LJ will handle the complexity. Content providers like artists, demomakers,... just need create plugin in whatever langage, send the points to redis.
To change current scene used by lasers/tracers use the command : /scene/scenenumber/start 1
Registering the plugin in LJ.conf is absolutely not mandatory.
Needs at least : an etherdream DAC connected to an ILDA laser, RJ 45 IP network (gigabits only !! wifi and wired 100 mpbs doesn't work well with several lasers). Seriously : if you experience frame drops you need to upgrade your network and use a dedicated computer to run seperately main program from plugins, youtube,...
LJ is tested with Firefox, supports Linux and OS X. Windows is unkown but welcome, if someone want to jump in.
LJ is in dev : versions in this repository will always be core functionnal : accept and draw pointlists. New features can be not fully implemented, wait for the next commit. Any feedback is welcome at any time.
Install
- Linux Buster : in LJ directory, type in a terminal window :
cd server ./install.sh
- OS X : you need brew already installed, then :
brew update brew upgrade brew install redis cd server type all install.sh commands beginning line 4. An OS X install script soon !!
-
KVM : an ISO is available here : https://www.tmplab.org/wp-content/lazer-iso.zip
-
Postinstall for all :
You probably want redis bound to all network interfaces : comment the bind line in /etc/redis/redis.conf and restart it.
The configure script to enter your etherdreams IPs,... is launched during install. You can use anytime, i.e if your network/etherdream setup change : python3 configure.py
- Webserver ?
A webserver is useful if you want to use the webUI remotely. Bring Your Own Webserver.
To run
Correct launch order is :
- Switch on Dacs/Lasers (emulator or IRL)
- Redis server, usually automatically started at boot (if redis is a service) or you launched manually : redis-server &
- LJ, see below.
- Load/reload webUI page from disk in a browser (www/index.html). Javascript must be enabled.
- Run a builtin plugin or your generator, to send pointlists in redis.
A typical LJ start is :
python3 main.py -L numberoflasers.
Use also -h to display all possible arguments, like -v 1 (or 2) for debug informations.
CASE 1 : the laser server computer, where LJ runs, is the same that the computer running a generator/plugin :
1/ Run LJ
python3 main.py -L 1
2/ Check in your client code if the laser server IP is the good one
Run your client
3/ to monitor redis server, there is an app for that (redis-manager/medis/...) or : redis-cli monitor redis-cli --stat redis-cli then ask for the key you want like : get /pl/0/0
CASE 2 : Server and Client computers are different :
1/ Say the laser server computer (running LJ) IP is 192.138.1.13, the client computer is 192.168.1.52, First remember to check on the server computer, if the redis server is listening to the right IP : edit /etc/redis/redis.conf
2/ Launch LJ with -r argument : python3 main.py -r 192.168.1.13 -L 1
3/ If the webUI is launched on "client" computer, use the configure.py
4/ run a client/plugin on client computer, like :
node nodeclient.js
5/ to monitor redis server use redis-manager/medis/... or :
redis-cli -h redisserverIP monitor
Plugin
A "plugin" is a software that send any number of pointlist(s) to redis and . LJ comes with different plugins in python 3 :
- artnet receiver : port 6454
- Aurora : Fill the input form and it's displayed. One word / laser.
- custom1 and square.py.
Client Side : Program your own "plugin"
The server approach is based on redis, so you can write and run your laser client software in any redis capable programming langage (50+ : https://redis.io/clients). An external program that just send pointlists to redis is a "client". If you want some interactions from the webUI, like text status area support, crash detection, autostart,... it's a "plugin" and some default code is needed. LJ and plugins signaling is over OSC.
- Read all this readme ;-)
- Generate at least one pointlist array (say a square) with enough points, one point is likely to fail for buffering reason.
- Feed your point list array in string format to redis server. i.e use "/pl/0/1" redis key to feed scene 0, laser 1. See /pl/ command in command reference below how to send your pointlist to i.e /pl/0/1 redis key.
- Tell LJ.conf your plugin configuration : OSC port and command line to start it.
- At least a plugin must reply /pong to OSC request /ping and must quit after an OSC command /quit.
Currently the WebUI (www/index.html) is static.
Client side dope mode for python 3 generators : How to use lj23
lj23 have many very useful functions to not reinvent the wheel for advanced points generation "client" side : layers, sprites, built in rotations,..
4 Great TRICKS with lj23 :
First open custom1.py and learn how to declare different objects. custom1.py is a 2D shape example in 3D rotation (red/green anaglyph rendering) that use 2 layers : one for left eye and one for right eye. custom1 is a copy of square.py
1/ How to have another laser drawing the same thing ?
That's a destination problem : just add another destination :
Dest1 = lj.DestObject('1', 1, True, 0 , 1, 1)
Dest1 will also send layer 0 points to scene 1, laser 1

2/ Different layers to different lasers ?
Say because of too much points you want Left element drawn by scene 0, laser 0 and right element by scene 0, laser 1
First define a different object/layer for each drawn element :
Leftsquare = lj.FixedObject('Leftsquare', True, 255, [], red, 255, 0, 0, 0 , True) # Left goes to layer 0
Rightsquare = lj.FixedObject('Rightsquare', True, 255, [], green, 0, 255, 0, 1 , True) # Right goes to layer 1
Define 2 destinations :
Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0) # Dest0 will send layer 0 points to scene 0, laser 0
Dest1 = lj.DestObject('1', 1, True, 1 , 0, 1) # Dest1 will send layer 1 points to scene 0, laser 1
3/ Different layers to one laser ?
You should consid
Related Skills
node-connect
344.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
99.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
344.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
344.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
