Jump to: 📦 Install · 🚀 First run · 🔧 How it works
Real-time ambilight that syncs your Nanoleaf panels to whatever's on your screen — games (like BF6) and your desktop. No capture card, no extra hardware: just a small Windows app watching the screen and streaming colors to the panels over your network.

Ambileaf mirroring Battlefield 6
Per-game profiles tune saturation, smoothing, and HUD-mask regions so the in-game UI doesn't pollute the ambient color. Built in Python; grab it, run it, and tweak it to taste.
Windows only — it uses the native Windows screen-capture API, so it will not run under WSL or Linux.
If Ambileaf brightens your setup, you can support its development:
Standalone .exe (easiest): download ambileaf.exe from the
latest release and
double-click it — no Python, no install. Or build it yourself by
double-clicking build.bat (needs Python on your PATH), which produces
dist\ambileaf.exe.
From source (Windows, Python 3.11+):
git clone https://github.com/denczo/ambileaf.git
cd ambileaf
python -m venv .venv
.venv\Scripts\activate
pip install -e ".[windows]"
Prerequisite: your Nanoleaf must already be set up and joined to your Wi-Fi network using the official Nanoleaf app. Ambileaf talks to the controller over your LAN — it does not do the initial Wi-Fi onboarding.
If you built or downloaded the standalone exe, just double-click
ambileaf.exe — no venv or scripts needed.
From source, activate the venv, then run ambileaf-tray:
.venv\Scripts\activate
ambileaf-tray
Or run .venv\Scripts\ambileaf-tray.exe directly. It runs in the system tray;
double-click the icon for Settings.
On first run the Settings window opens with a setup guide — three steps:
1. Pair the controller. In the Connection tab, auto-discover your Nanoleaf or type its IP address. Then hold the power button on the Nanoleaf controller for about 5–7 seconds until its LED starts flashing, and click Pair within 30 seconds.
The flashing LED means the controller is in pairing mode — it only hands out an API token during that window, so the physical button press is required. If pairing times out, hold the button again until it flashes and retry.
2. Calibrate the panel overlay so it lines up with your screen
(arrow keys nudge, +/- scale, x/y flip).
Note: calibration rendering has only been tested with triangle panels — other shapes (hexagons, squares, minis) should work but may need tweaks.

Aligning the panel layout in Settings
3. Run the test pattern to confirm every panel lights up.
Right-click the tray icon for brightness/saturation presets, pause/resume, and "Start with Windows" autostart. Double-click opens Settings.

Tray menu — brightness, saturation, pause
In Settings → Color, a swatch grid previews how your panels will render each reference color; sliders tune intensity, max brightness, and minimum glow, and Save to profile writes them into the active profile.
A dedicated profile (profiles/bf6.toml) activates automatically when
bf6.exe is detected. It applies HUD masks over the minimap/ammo bar
and squad list so those UI elements don't affect the panel colors, and
uses tuned brightness and smoothing values for fast-paced gameplay.
Only the profile is BF6-specific — the capture method is the same anti-cheat-safe path for every game and the desktop.
When BF6 is closed the app falls back to profiles/default.toml.
Each panel's physical position (mm, from the Nanoleaf API) maps to a pixel region on screen via calibration. Every frame:
- Screen captured via Windows.Graphics.Capture — the Xbox Game Bar API, so it is anti-cheat-safe (EAC, etc.) for every game, not just BF6
- 16× downsampled thumbnail computed once
- Each panel samples its region with a chroma-weighted mean
- Gamma → saturation boost (chroma-gated) → brightness → adaptive EMA
- Colors sent via Nanoleaf External Control v2 UDP
Downsampled thumbnail: the frame is shrunk 16× on each axis into a small thumbnail once per frame, so there are far fewer pixels to crunch — a panel covers a wide screen area anyway, so its average color is unchanged.
Chroma-weighted mean: when averaging a region, vivid pixels count for more than dull grey ones, so a small bright object (a health bar, a muzzle flash) still drives the color instead of being washed out by a grey backdrop.
Adaptive Exponential Moving Average is the frame-to-frame smoothing: colors ease gently between frames so the panels do not flicker, but when the screen changes a lot — a scene cut or an explosion — the smoothing automatically eases off so the lights keep up with the action.
On quit the previously active Nanoleaf scene (e.g. a Home Assistant effect) is automatically restored.
Pip installs two scripts into the venv folder .venv\Scripts\:
ambileaf-tray (GUI tray, no console — the usual way to run it) and ambileaf
(the CLI). Run ambileaf --help, or python -m ambileaf <command> if the venv
is not on your PATH.
| Command | Description |
|---|---|
tray |
System-tray app — primary way to run (calibration, color, and pairing live in its Settings window) |
run |
Foreground loop without tray |
test-pattern |
Sweep panels one-by-one to verify panel IDs |
pair --host <ip> |
Generate API token (button-press on controller) |
discover |
mDNS LAN discovery |
Drop a TOML into profiles/ — the process watcher picks it up
automatically without restarting:
[game]
name = "My Game"
executable = "mygame.exe"
[sampling]
fps = 25
panel_sample_radius_px = 360
[color]
gamma = 2.2
saturation_boost = 1.7
brightness_floor = 0.04
brightness_ceiling = 0.8
smoothing_alpha = 0.2
[[hud_mask]]
# normalized [0,1] — excluded from color sampling
x = 0.0
y = 0.82
w = 1.0
h = 0.18All config is stored in %APPDATA%\ambileaf\:
connection.json— controller host, port, tokencalibration.json— monitor size + cluster offset/scale/flip
Override with the AMBILEAF_CONFIG_DIR env var.
Ambileaf is released under the PolyForm Noncommercial License 1.0.0: free to use, modify, and share for noncommercial purposes — commercial use is not permitted.