A macOS Stream Deck plugin that captures screen region colours in real-time and displays them on Stream Deck keys. Built with Stream Deck SDK v2 and node-screenshots.
- Real-time screen colour sampling (100–2000 ms interval)
- Multiple capture regions: Full Screen, Left Half, Right Half, Center, Cursor
- HEX colour code displayed on the key
- Dynamic SVG background matching the captured colour
- Retina (2× pixel ratio) support via automatic
scaleFactorhandling - macOS Screen Recording permission detection with user-friendly warnings
- Press the key to pause / resume capture (when paused, screen analysis stops completely and does not load the system)
| Requirement | Version |
|---|---|
| macOS | 14+ (Sonoma) |
| Apple Silicon | M1 / M2 / M3 / M4 |
| Node.js | 20+ |
| Stream Deck app | 6.7+ |
| Stream Deck CLI | latest |
Windows 11? Stream Deck плагін — macOS-only, але сервер + Web UI + синхронізація зі Strip Pro повністю працюють на Windows. Див. WINDOWS.md та готові скрипти в теці
windows/.
FireLed/
├── com.fireblast.screen-color-sync.sdPlugin/ # Compiled plugin
│ ├── bin/ # Bundled JS output
│ ├── imgs/ # Icons (SVG)
│ ├── logs/ # Runtime logs
│ ├── node_modules/ # Native deps (auto-copied)
│ ├── ui/
│ │ └── screen-color.html # Property Inspector
│ └── manifest.json # Plugin metadata
├── src/
│ ├── actions/
│ │ └── screen-color-action.ts # Core capture logic
│ └── plugin.ts # Entry point
├── scripts/
│ └── copy-deps.mjs # Copies native modules to sdPlugin
├── package.json
├── rollup.config.mjs
├── tsconfig.json
└── README.md
npm installThis automatically runs postinstall which copies the native node-screenshots binary into the sdPlugin directory.
npm install -g @elgato/clinpm run buildnpm run linkThis creates a symlink so Stream Deck loads the plugin from this directory.
After the first npm run build and npm run link, Stream Deck loads the plugin from com.fireblast.screen-color-sync.sdPlugin/bin/plugin.js when the app starts. You do not need to compile again unless you change the code. Screen analysis runs only while the Screen Color key is visible on the profile and not paused; one key press pauses (stops capture), another press resumes.
npm run devOr use watch mode for auto-rebuild on file changes:
npm run watchOn first launch, macOS will prompt you to grant Screen Recording access. If the prompt doesn't appear or was dismissed:
- Open System Settings → Privacy & Security → Screen Recording
- Enable access for Stream Deck
- Restart Stream Deck
If permission is not granted, the plugin will display "Grant Screen Access" on the key.
Plugin settings (global): Debug mode — when enabled, starts a debug server at http://localhost:6789 for live capture/zone view. Disabled by default.
| Setting | Description | Range / Options |
|---|---|---|
| Update Interval | How often to capture (milliseconds) | 30–200 ms (default 50; lower = higher CPU load) |
| Screen Region | Which part of the screen to sample | Full Screen, Left Half, Right Half, Center, Cursor |
| Enable Strip Sync | Send color to Elgato Strip Pro | Checkbox (default: enabled) |
| Strip IP Address | IP address of your Strip Pro | e.g., 192.168.18.88 |
- Black pixels in a zone are ignored when averaging; if a zone is entirely black, its color is filled from the nearest non-black neighbor zone.
- Letterbox (horizontal bars) and pillarbox (vertical bars) are detected so sampling uses the actual picture area.
- Accent punch (0–1): saturated accent colors on dark backgrounds are weighted more strongly.
- Dark zone: LEDs off — if ~90% of samples in a zone are black, either turn those LEDs fully off (
RGB 0) or dim them to Dark zone min brightness (HSB %).
- Capture — Uses
node-screenshots(native NAPI-RS binding based on XCap) to take a screenshot of the primary monitor - Crop — Crops the image to the selected region (left, right, center, cursor area) before processing for better performance
- Sample — Reads up to ~1024 evenly-spaced pixels from the RGBA buffer and averages R, G, B channels
- Render — Generates an SVG rectangle filled with the average colour and sets it as the key image via
action.setImage() - Display — Shows the HEX colour code (e.g.
#A1B2C3) as the key title - Sync to LED — Sends the color to Elgato Strip Pro via HTTP API (port 9123) using HSL format
The plugin accounts for macOS Retina displays by multiplying logical dimensions with monitor.scaleFactor(). Cursor positions are also scaled to physical pixels before sampling.
The plugin sends RGB colors to your Strip Pro via HTTP API:
- Endpoint:
http://<IP>:9123/elgato/lights - Format: Converts RGB to HSL (Hue 0-360, Saturation 0-100, Lightness 0-100)
- Fallback: Tries RGB direct format if HSL fails
- IP Discovery: Find your Strip Pro IP in Control Center → Settings → Advanced → IP Address
The color updates happen every capture interval (100-2000ms), creating real-time ambient lighting that follows your screen content.
| Script | Description |
|---|---|
npm run build |
Compile TypeScript + copy native deps |
npm run watch |
Watch mode (auto-rebuild on changes) |
npm run link |
Symlink sdPlugin directory to Stream Deck |
npm run restart |
Restart the plugin in Stream Deck |
npm run dev |
Build + restart in one command |
- Ensure Stream Deck app is version 6.7+
- Run
npm run linkto register the plugin - Restart the Stream Deck app
- macOS Screen Recording permission is required
- System Settings → Privacy & Security → Screen Recording → enable Stream Deck
- Check logs in
com.fireblast.screen-color-sync.sdPlugin/logs/ - Ensure
node-screenshotsnative binary is present insdPlugin/node_modules/ - Re-run
npm run buildto re-copy native dependencies
- No monitors detected by
node-screenshots - This can happen on headless setups or certain VM configurations
- For Marketplace submission, replace SVG icons with proper PNG icons at the required sizes (see manifest docs)
- Download
sdpi-components.jslocally instead of using the CDN:curl -o com.fireblast.screen-color-sync.sdPlugin/ui/sdpi-components.js \ https://sdpi-components.dev/releases/v4/sdpi-components.js
- Update the HTML
<script src>to reference the local file
The local server (npm run server:build, then npm run server:start) serves the Web UI (default http://127.0.0.1:47891).
- Screen capture zone — width/height percentages for which part of each screen edge is sampled for colour (the same values as the draggable handles in Zone Editor).
- Reverse direction — reverses LED order along the left edge, bottom edge, or right edge relative to screen coordinates (also available as checkboxes under the Zone Editor preview).
- LED count per region — how many of the 120 strip LEDs are assigned to the left vertical run, bottom horizontal run, and right vertical run. Bottom is computed as
120 − left − right; each region is kept at least 10 LEDs when you move the sliders.
MIT