A native tvOS (Apple TV) music visualizer. RoonVis renders Milkdrop presets with libprojectM — via ANGLE (OpenGL ES 3.0 → Metal) — reacting in real time to audio streamed from Roon over Snapcast. It works end-to-end on real hardware.
✅ Supported on all Apple TV models on tvOS 26 (v0.1.1). Reference device: Apple TV 4K 3rd gen (A15). The Apple TV HD is validated with reduced defaults (720p @ 30 fps) via a vendored ANGLE patch that unlocks ES 3.0 on its GPU; 4K 1st/2nd gen are expected to work but are untested on hardware. Older devices have real limitations — see Apple TV device support in the wiki.
Roon plays music → a Raspberry Pi captures it into a virtual audio cable and streams it with Snapcast → the Apple TV app receives the live audio and drives projectM, which renders reactive Milkdrop visuals to your TV.
Roon Core ──► Raspberry Pi ─────────────────────────► Apple TV 4K
(snd-aloop loopback (Snapcast client → live PCM ring
→ snapserver, 44.1k/16/2) → projectM → ANGLE GLES→Metal
→ CADisplayLink → your TV)
└──► your speakers (grouped Roon zone, delayed to match)
→ Full write-up in the wiki: How It Works · Apple TV Optimizations & Patch Catalog · Architecture.
🆕 v0.2.0 — the full Cream of the Crop pack (7,700+ presets, 26× more) with category browsing (sections, sub-category rows, chip filter) and a new Category rotation mode that keeps automatic preset changes within the playing preset's visual family; dramatically snappier menus; a black-screen recovery fix; and a major internals rework (tested rotation engine, event-driven preload planning, 825-check test suite, CI).
Full guide: Getting Started. The short version:
- Set up the Pi. On a Raspberry Pi (64-bit Raspberry Pi OS), run:
It installs RoonBridge + Snapcast and configures the snd-aloop loopback automatically. → Setup: Roon / Pi / Snapcast
sudo bash scripts/pi-setup.sh
- Finish in Roon (the script prints these): authorize RoonBridge; enable the loopback as an audio zone and group it with your speakers; set that zone's sample-rate conversion to 44.1 kHz in Roon's DSP engine (MUSE). → Setup details
- Install the app — sideload the release
.ipawith AltStore or Sideloadly (re-sign with your Apple ID), or build from source (see Build & Run). - Point it at your Pi — set
SnapcastServerHost(the Pi's IP) inInfo.plist/ build config.
Before building, set these for your environment:
| What | Where | Set to |
|---|---|---|
| Apple Developer Team ID | CMake -DROONVIS_DEVELOPMENT_TEAM=... |
your Team ID (free Personal Team is fine) |
| Snapcast server host | In-app: Settings → Connection (v0.1.2) | your Pi's IP or hostname |
Recommended in-app settings: run Settings → Audio → Calibrate sync for the A/V delay (v0.1.2 — sets it by ear in twenty seconds, including your TV's panel lag; keep 270 ms on the Roon audio output as the anchor). Rendering defaults: 1080p @ 60 (Apple TV HD: 720p @ 30), warp mesh 96×72 (HD: 64×48) — adjustable live in Settings → Rendering. → Recommended Settings · Delay Structure · Supported Resolutions
The wiki is the full manual — setup, architecture, the engineering deep-dives, troubleshooting, FAQ, and known issues. Start at the Home page.
RoonVis's own source is MIT (see LICENSE). It builds on libprojectM (LGPL-2.1,
patched — sources shipped as submodule + RoonVis/patches/), ANGLE (BSD-3-Clause), and
public-domain Milkdrop presets/textures. Full inventory: THIRD_PARTY.md.
RoonVis is sideload-only today. Note that any binary distribution also carries libprojectM's LGPL-2.1 terms — see
THIRD_PARTY.mdfor how we comply.