3.1.1 — macOS and Linux builds, OpenRGB, Spout and Syphon
⬇️ Download
| Get this one | Or | You should know | |
|---|---|---|---|
| 🪟 Windows | ⬇️ Installer | Portable no install |
Only the installer registers the Dynamic Lighting background identity. |
| 🍎 macOS | ⬇️ .dmg | .zip | Apple Silicon. Unsigned — one Terminal command is needed, see below. |
| 🐧 Linux | ⬇️ AppImage | .deb Debian / Ubuntu |
x64. Needs PulseAudio or PipeWire, which desktop installations already have. |
Important
🍎 macOS: the app will say it is damaged. It is not.
This build is not signed — the Apple Developer Program has not been bought. macOS puts a quarantine flag on anything unsigned that arrives from the internet and refuses to open it, reporting it as "damaged and can't be opened." Right-clicking and choosing Open does not clear this on macOS 15 and later.
Open the .dmg, drag the app into Applications, then run this once in Terminal:
xattr -dr com.apple.quarantine "/Applications/CAYADEV Visualizer.app"After that it opens normally, every time. The command removes the download flag; it does not change the application.
Then, for sound: macOS has no way to record its own output, so install BlackHole (free) and pick it as the audio source. Microphones and line inputs work with no extra setup — macOS will ask for microphone permission the first time.
The application leaves Windows. macOS and Linux packages, RGB lighting on all three platforms through OpenRGB, and the output handed to other applications over the GPU with Spout and Syphon.
macOS and Linux
Both are built by GitHub Actions on their own runners, because audify is a native module and cannot be cross-compiled — a macOS package produced on Windows shows the interface and captures no audio.
- macOS —
.dmgand.zip, Apple Silicon only. Intel is not in this release: Apple has finished the transition and GitHub's Intel runners queue for hours. - Linux —
.AppImageand.deb, x64. The.debdeclareslibpulse0among its dependencies, which is what the audio engine actually links against.
Windows is still packaged locally rather than in CI. The installer registers the Dynamic Lighting background identity from a certificate it generates itself, and the runner's PowerShell cannot open the Cert: drive — a CI-built installer would lack that identity, which makes it a different product.
System audio is not the same problem on all three. Windows opens an output device with WASAPI loopback. Linux has to open the PulseAudio or PipeWire monitor, which the system reports as an input — so the application recognises monitors, marks them as loopback and prefers them by default. macOS has no loopback at all and needs a virtual device such as BlackHole; there is no way around that, and the panel says so rather than presenting an empty list.
No Node.js next to the application
The audio helper is a separate process, and until now the Windows package carried a 93 MB node.exe so users would not have to install one. The other two platforms would have got nothing.
Electron is itself a Node runtime. Running the app's own binary with ELECTRON_RUN_AS_NODE=1 starts the helper, and audify loads under it because it is N-API. That removes the bundled node.exe from Windows and gives macOS and Linux a runtime that is guaranteed to be there. A system Node install is still tried as a fallback, and when neither works the error names which runtime was missing instead of saying the helper failed.
OpenRGB
Dynamic Lighting is a Windows service, so on macOS and Linux that card is replaced by a note saying as much. OpenRGB answers on those platforms — and is an additional option on Windows, not a replacement.
- Speaks the OpenRGB SDK protocol directly over TCP (port 6742 by default). No vendor software, no driver, and the server may sit on another machine.
- Drives every device the server exposes, per-LED where the hardware allows it.
- It shares one renderer with Windows Dynamic Lighting, so all ten dynamic modes and every static mode behave identically on either path. Extracting that renderer meant moving 580 lines of colour maths that had never been covered by a test; the behaviour was snapshotted first and compared after, and the snapshot immediately caught a real bug — the OpenRGB path was passing raw configuration where the renderer expected normalised, and every device came out flat grey.
- Devices that will not accept direct control say so instead of silently swallowing the colours.
Spout and Syphon
The output can be handed to another application on the same machine over the GPU: Resolume, OBS, TouchDesigner, MadMapper, anything that speaks either protocol. No window capture, no plugin, no CPU copy.
It renders into its own hidden window, so the feed continues even when no visualization window is open on any display. Audio capture is deliberately kept alive while this is the only consumer — otherwise the receiver would get a picture that never reacts, with no visible window to explain why.
Two documented facts turned out to be wrong, and both fail silently:
texture-bridgetypes the shared handle as anumber. Electron 43 gives{ ntHandle: Buffer }on Windows and{ ioSurface: Buffer }on macOS, and the two platforms need different calls. Getting this wrong raises no error at all — the receiver just shows a black frame. The conversion is therefore an isolated, pure module, which is also the only test coverage macOS has.- A handle beyond the safe-integer range would round silently and point at some other object, so it is rejected rather than sent.
Not available on Linux. Spout is a Windows technology and Syphon a macOS one, and Linux has no built-in equivalent. The card is not hidden there — it explains why and points at the OBS browser source, which works everywhere.
What is verified, and what is not
Everything above passes npm test (808 unit tests) and the GPU self-test. Spout was measured end to end on Windows: the sender registers with Spout, sends 30 frames a second with none dropped, and deregisters on stop.
Honestly, the following have never run on real hardware, and this is recorded in ROADMAP.md rather than left for you to discover:
- The macOS and Linux packages are built and structurally verified in CI, and the audio engine loads on both. Neither has been launched on an actual desktop.
- OpenRGB is tested against a protocol-level server, not against real devices.
- Syphon shares Spout's code path and has never run on a Mac.
macOS packages are unsigned — the Apple Developer Program has not been purchased. macOS quarantines unsigned downloads and reports them as damaged; right-clicking and choosing Open does not clear that on macOS 15 or later. Clearing the flag once with xattr -dr com.apple.quarantine is the whole workaround, and it is spelled out at the top of these notes.
Fixes found while building this
- The Windows icon test asserted on a generated build artifact that is not in version control, so CI could never pass on a clean checkout — all three runners failed in under a minute.
linux.desktophad a shape electron-builder rejects, and nothing on this machine could detect it because Linux packaging never ran here. It is now validated against electron-builder's own JSON schema, and the check was proven by feeding it the known-bad value.- An unescaped apostrophe in one English string broke the parse of
i18n.jsin the browser, leaving the entire interface untranslated. The self-test reported 698 untranslated strings; the cause was one character. Every source file is now parsed in a unit test. - Three shared modules declared top-level
constin classic scripts, which share one global scope with the preload bridge. One collided withwindow.apiand the file never loaded at all. - The documented test count was wrong in three places and had never broken a build. The runner now compares every count claimed in the documentation against the count the run actually produced, and fails if they disagree — including when it cannot read the total, since a check that can skip itself silently is not a check.