Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

How it works

lightmime is a pipeline of three stages, run every frame.

1. Capture

The XDG ScreenCast portal asks you which screen to share and hands lightmime a PipeWire stream of it, with a restore token so it can skip the question next time. GStreamer receives the stream and scales it down to 64 × 36 pixels of RGB:

pipewiresrc ! videoconvert ! videoscale ! video/x-raw,format=RGB,width=64,height=36 ! appsink

The portal is the only way to capture the screen on Wayland, and it works the same in a Flatpak, so lightmime needs no special permissions.

2. Mapping

Each light in the entertainment area has a position. Its left-right coordinate becomes a horizontal position on the screen and its height a vertical one. lightmime averages the pixels in a square around that point (region_size of the screen), in linear light so that bright and dark parts mix the way light does. Then it applies saturation, smoothing and brightness.

3. Streaming

The bridge’s Entertainment API takes colours over an encrypted UDP stream:

  1. lightmime starts the area with a PUT on /clip/v2/resource/entertainment_configuration/<id>.
  2. It opens a DTLS 1.2 connection to UDP port 2100, authenticated with the client key from pairing (PSK-AES128-GCM-SHA256).
  3. Every frame goes out as one HueStream v2 message: a header, the area’s id and, per light, its channel and a 16-bit red, green and blue value.
  4. On stop, it ends the connection and stops the area, so the lights return to normal.

Code

The repository is a Cargo workspace:

Crate
lightmime-coreCapture, colour mapping, the Hue API and streaming, and the Engine that runs them. No user interface.
lightmime-guiThe window and tray icon, built with gpui.
lightmimeThe binary: the CLI, the headless daemon and the Home Assistant bridge.

Your own frontend

lightmime-core can drive a frontend you write yourself. Create an Engine inside a tokio runtime, then call start, stop, update_settings and set_bridge and watch subscribe() for its state. Pairing and area listing are in lightmime_core::hue. The crate README covers the details, and examples/minimal.rs is a complete frontend in one file.

See AGENTS.md for the architecture and protocol details.