Light up a WS2812 LED strip mounted behind your piano when you play. MIDI from your computer is streamed over WiFi to a Raspberry Pi Zero that drives the strip.
Inspired by onlaj/Piano-LED-Visualizer.
Piano ──USB/MIDI──▶ Host computer ──WiFi (WebSocket)──▶ Raspberry Pi Zero ──▶ WS2812 strip
(Node + TS) (tiny Python driver)
• reads MIDI
• computes LED frames
• serves config web UI
• streams pixels to the Pi
Two pieces:
Runs on your computer (Linux/macOS/Windows). Responsibilities:
- Read MIDI from a selected input port (your piano, or a virtual DAW port).
- Own all the interesting logic: note → LED position mapping, invert, start/end range, velocity → color blending, background, brightness.
- Compute the final per-LED RGB frame and stream it to the Pi.
- Serve the Svelte config UI on
http://localhostand persist config to disk.
Runs on the Pi Zero. Deliberately dumb: it receives a finished pixel frame and
blits it to the strip via rpi_ws281x. No MIDI
logic, no color math — all of that lives on the host. This keeps the Pi side ~30 lines
and uses the Python that ships with Raspberry Pi OS.
By moving all LED logic to the host and streaming finished frames instead of raw MIDI, we get:
- One typed source of truth for all behavior (testable on the host).
- A trivially simple, robust Pi script.
- No duplicated color/position logic across two runtimes.
host/ Node + TypeScript + Svelte: MIDI, LED frames, config UI, Pi streaming
pi/ Python LED driver + systemd unit for autostart
Requires Node 20+.
cd host
npm install
npm start # builds the web UI, then runs the hostThen open http://localhost:3192, pick your MIDI input, set the Pi address, and play.
Config is saved to ~/.rgbpiano/config.json.
For development with hot-reloading UI on the same port:
cd host
npm run dev # host + UI on http://localhost:3192Clone this repo on the Pi, then:
cd RGBPiano/pi
./install.sh # idempotent: installs deps + a systemd service, starts on bootTo update after pulling new code, just run ./install.sh again. To remove
everything (service + virtualenv):
./uninstall.shUseful checks on the Pi:
systemctl status rgbpiano # is it running?
journalctl -u rgbpiano -f # live logsThe LED data pin defaults to GPIO 18 and the port to 3193. Override with the
RGBPIANO_GPIO / RGBPIANO_PORT environment variables in the service if needed.
| Port | Where | What |
|---|---|---|
| 3192 | Host | Config web UI + browser WebSocket |
| 3193 | Pi | LED frame stream (host → Pi) |
- Raspberry Pi Zero (W / 2 W) + microSD
- WS2812 addressable RGB LED strip (better strip = better color)
- 5V power supply sized for your LED count
- See onlaj/Piano-LED-Visualizer for detailed wiring.
