Real-time bias lighting system for Linux Wayland using ESP32 + WS2812B LEDs. Captures screen edges via PipeWire (using XDG Desktop Portal) and sends RGB data to ESP32 over WiFi.
Uses libportal and PipeWire to capture screen borders, downsamples to an LED grid, and transmits color data to an ESP32 via UDP. Optimized for minimal CPU usage and low latency by accessing native PipeWire buffers.
Workflow:
- Request screencast via XDG Desktop Portal (
libportal). - Capture buffers directly from PipeWire (supports DMA-BUF and MemFd).
- Sample edges (Left, Top, Right) and average colors.
- Transmit RGB data to ESP32 over WiFi/UDP.
- ESP32 with WiFi
- WS2812B LED strip (connected to GPIO 14)
- USB-C power supply
- Recommended setup: ~62 LEDs for a standard monitor
Ensure you have the following development libraries installed:
libportalglib-2.0libpipewire-0.3pkg-configgccmake
Simply run:
makeThis builds the blight binary. The default configuration uses WiFi communication.
./blight [brightness] [saturation] [smoothing]Parameters:
brightness: 0-255 (default: 150)saturation: float (default: 1.0, determines color vibrancy. Try 1.5-2.0)smoothing: 0.1-1.0 (default: 1.0, lower values = smoother transitions)
Example:
./blight 200 1.8 0.7- Credentials: Create
esp32/main/creds.hwith your WiFi info:#define WIFI_SSID "YourSSID" #define WIFI_PASS "YourPassword"
- Configuration: Adjust
NUM_LEDSandDATA_PINinesp32/main/main.inoif necessary. - Flash: Use Arduino IDE or
arduino-clito flash the ESP32. - Network: The host app expects the ESP32 at
192.168.1.100(static IP) by default. You can change this insrc/main.c.
CPU usage is minimal (<2%) as it avoids heavy processing pipelines. Note that any PipeWire screencast may cause minor FPS drops in some Wayland compositors (like GNOME/Mutter) due to how they handle buffer synchronization.
- Daemon + Control Tool: Implement
blightddaemon withblightctlfor runtime control. - XDG Portal Token Restoration: Save authorization token to avoid permission dialogs on startup.
- Black Boundary Detection: Automatically skip black bars (letterboxing) for different aspect ratios.