A throwback open-source music player for macOS written in Swift, supporting Plex, Sonos, Navidrome, Jellyfin, Emby, Chromecast, ProjectM, local media, internet radio and more.
This is a 100% clean room hobby project is not affiliated with Winamp, Nullsoft, Sonos, Plex, Radionomy Group or anyone else.
- Library browser window for Plex, Jellyfin, Emby, Navidrome/Subsonic, and local library files
- Plex Media Server integration with PIN-based authentication
- Jellyfin media server integration with music and video streaming, scrobbling, and library browsing
- Emby media server integration with music and video streaming, scrobbling, and library browsing
- Inteligent radio mix generation for all sources
- Navidrome/Subsonic server integration with scrobbling support
- Local media library with metadata parsing, editing, library management
- ProjectM visualizations with 100 included. Users can download more
- Sonic similarity radio stations populated by Plex API's (Library, Genre, Decade, Hits, Deep Cuts)
- Plex radio track history with configurable exclusion rules. Stop the same songs from being added to your Plex radio stations
- Sonos content filtering for unsupported lossless formats. Keeps the music playing by not sending unsupported encodings to Sonos.
- Much better Sonos playlist support than the current PlexAmp (Jan 2026)
- Classic V1 UI has full support for classic Winamp skin skins (.wsz files)
- Modern V2 UI skin system, many v2 skins included. Open format, users can easily make new v2 skins via json
- Original Spenctrum analysis visualization system
- Album art visualization system with user selected effects
- Main player, Playlist editor, and 10-band Equalizer windows
- Classic window snapping and docking behavior
- Audio playback: MP3, FLAC, AAC, WAV, AIFF, ALAC, OGG
- Video playback: MKV, MP4, MOV, AVI, WebM, HEVC (KSPlayer/FFmpeg)
- Gapless playback for seamless track transitions
- Sweet Fades (crossfade) with configurable fade duration
- Media Drag and drop support
- Album/Cover/Movie art browser with visualizations
- Internet radio (Shoutcast/Icecast) with live metadata and auto-reconnect
- AirPlay and Casting to Chromecast, Sonos (multi-room), and DLNA devices
- Cast local files, Jellyfin/Emby/Navidrome/Subsonic streams, and internet radio to Sonos
- macOS Now Playing integration (Control Center, Touch Bar, AirPods controls)
- Discord Music Presence support
- Headless CLI mode for terminal-based browsing and playback (no GUI, no Dock icon)
Download the latest DMG from Releases.
Follow r/NullPlayer for release notifications. Report bugs on GitHub Issues or the subreddit.
Since the app is in beta testing and not code-signed (it costs $99 a year to sign the app and I am not sure yet I want to pay that yet) macOS Gatekeeper will block it. To fix this:
Option 1: Terminal (Recommended)
xattr -cr /Applications/NullPlayer.appOption 2: System Settings
- Try to open NullPlayer (it will be blocked)
- Go to System Settings → Privacy & Security
- Scroll down and click Open Anyway next to the NullPlayer message
- Click Open in the confirmation dialog
After either option, NullPlayer will open normally.
- macOS 14.0 (Sonoma) or later
Requires Xcode 15.0+ with Command Line Tools and Swift 5.9+.
# Clone the repository
git clone https://github.com/ad-repo/nullplayer.git
cd nullplayer
# Download required frameworks
./scripts/bootstrap.sh
# Build and run
./scripts/kill_build_run.shThe bootstrap script downloads VLCKit and libprojectM from GitHub Releases with checksum verification.
To open in Xcode:
open Package.swift| Library | Purpose |
|---|---|
| ZIPFoundation | .wsz skin file extraction |
| SQLite.swift | Media library storage |
| KSPlayer | Video playback with FFmpeg backend |
| AudioStreaming | HTTP audio streaming for Plex |
| FlyingFox | Embedded HTTP server for local file casting |
| libprojectM | ProjectM visualizations |
Library data is stored as a SQLite database at ~/Library/Application Support/NullPlayer/library.db.
Backup & Restore API (MediaLibrary.swift):
| Function | Description |
|---|---|
backupLibrary(customName:) |
Creates timestamped .db backup, returns URL |
restoreLibrary(from:) |
Restores from backup (auto-backs up current first) |
listBackups() |
Returns backup URLs sorted newest first |
deleteBackup(at:) |
Deletes a backup file |
Backups are stored in ~/Library/Application Support/NullPlayer/Backups/.
NullPlayer includes a headless CLI mode for browsing and playing music entirely from the terminal — no GUI, no Dock icon.
NullPlayer --cli [OPTIONS]NullPlayer --cli --list-sources # show configured sources
NullPlayer --cli --list-artists --source plex # list artists
NullPlayer --cli --list-albums --source local # list albums
NullPlayer --cli --list-tracks --source subsonic # list tracks
NullPlayer --cli --list-genres --source local # list genres
NullPlayer --cli --list-playlists --source jellyfin # list playlists
NullPlayer --cli --list-stations # list internet radio stations
NullPlayer --cli --list-eq # list EQ presets
NullPlayer --cli --list-outputs # list audio output devices
NullPlayer --cli --search "radiohead" --source local # search library
NullPlayer --cli --list-artists --source plex --json # JSON outputNullPlayer --cli --source local --artist "Pink Floyd"
NullPlayer --cli --source plex --album "OK Computer" --shuffle
NullPlayer --cli --source local --genre "Jazz" --repeat-all
NullPlayer --cli --station "KEXP" --source radio
NullPlayer --cli --source local --radio artist --artist "Björk"
NullPlayer --cli --source local --volume 80 --eq "Rock"| Key | Action |
|---|---|
Space |
Pause/Resume |
q |
Quit |
> / < |
Next / Previous track |
→ / ← |
Seek forward / backward 10s |
↑ / ↓ |
Volume up / down |
s |
Toggle shuffle |
r |
Cycle repeat (off → all → one) |
m |
Toggle mute |
i |
Show track info |
See --help for the full flag reference.
See AGENTS.md for documentation links and key source files.
Note: This project will never support Spotify, Youtube, Apple or Amazon. Please do not submit PRs for this type of integration.
NullPlayer has two UI modes, selectable from the right-click context menu under Skins. Switching between modes triggers an automatic restart prompt:
Classic .wsz skin support. No skins are bundled -- the app starts with a native macOS appearance. To apply a skin, use Skins > Load Skin... to open a .wsz file, or place skin files in ~/Library/Application Support/NullPlayer/Skins/ and select them from the Skins menu. Official NullPlayer skin packages are available in the dist/Skins/ directory or from Releases. Thousands of community-created skins can be downloaded from the Skins > Get More Skins... menu link.
A custom skin engine built from scratch with a neon cyberpunk aesthetic. Modern skins are JSON-configured and support:
- Color palette theming -- define 12 named colors and the entire UI adapts
- Custom PNG image assets -- optionally replace any UI element with your own artwork
- Procedural grid backgrounds -- configurable Tron-style perspective grids
- Bloom/glow post-processing -- Metal-based glow effects on bright UI elements
- Custom fonts -- bundle TTF/OTF fonts or use any system font
- Animations -- sprite frame cycling and parametric effects (pulse, glow, rotate, color cycle)
The bundled default skin ("NeonWave") is fully programmatic -- zero image assets, pure palette-driven rendering.
Creating a skin is as simple as writing a single JSON file. See SKINNING.md for the complete guide.
Skin installation: Place skin folders or .nps bundles in ~/Library/Application Support/NullPlayer/ModernSkins/, then right-click the player and select your skin from Modern UI > Select Skin.
This project is open source and uses the following licensed components:
- KSPlayer (GPL-3.0) - Video playback with FFmpeg backend
- libprojectM (LGPL-2.1) - ProjectM visualizations






