A cinematic player that lives inside Spotify.
Cover, compact bar, and lyrics that stay in time — frosted glass, album color, and a look you can tune without guessing.
Spicetify extension · Desktop Spotify · MIT
Install · Open it · Layouts · Settings · Releases · For builders
Lumen is not a separate app, not a phone player, and not Spotify’s tiny PiP window. It is a Spicetify extension: it fills the Spotify window you already have. Snap it, tile it, drop it in a sidebar — Lumen follows the window.
If you only want to listen, read Install, Open it, and Layouts. Everything after that is optional.
You need the Spotify desktop app and Spicetify. Lumen does not run in the browser player or on phones.
- Install Spicetify Marketplace if you do not have it.
- In Spotify, open Marketplace → Extensions.
- Search Lumen and install.
- Fully quit Spotify (the tray icon too) and open it again.
Copy waveplayer.js into your Spicetify Extensions folder, then:
spicetify config extensions waveplayer.js
spicetify apply| Extensions folder | |
|---|---|
| Windows | %APPDATA%\spicetify\Extensions\ |
| macOS / Linux | ~/.config/spicetify/Extensions/ |
Quit Spotify completely and reopen it. Step-by-step, updates, and uninstall: docs/INSTALL.md.
Each GitHub Release also attaches the built waveplayer.js for that version.
Click Spotify’s miniplayer button. Lumen takes that button over. Close with ✕ in any layout.
If the button is missing, a Lumen control appears in the top bar after a few seconds.
Window size is yours. Lumen fills whatever size you give Spotify — including a tall sidebar.
All three fill the same window. Switching layout never resets the window size.
| Layout | What you see | When to use it |
|---|---|---|
| Expanded | Cover first, then title, optional lyric peek, next-up, glass controls | The default stage |
| Lyrics | Quiet header over full-height lines. Transport floats at the bottom | When you want the words |
| Compact | Art, title, progress, transport in a thin bar | Sidebars and short strips |
Expanded
- Double-tap the cover to open lyrics (can be turned off).
- Tap the cover to pause, if you enable that in Behavior.
- Tap the duration to switch remaining time.
- Tap Next · … (or Queue) to open the queue.
Lyrics
- Tap the art to go back to the cover.
- Tap a line to seek to it (can be turned off).
- Scroll freely; follow resumes after a short delay.
- Auto-hide fades the header and controls until you move.
- Queue icon in the header.
Queue
Up next and Played tabs. Now playing, tracks you added, the rest of the album or playlist, then songs that already played. Drag the grip to reorder (queued and up next). Filter, see time left, shuffle remaining, drop duplicates, save a playlist, like a row, play next, or stop after this track. In a wide window the queue sits in the stage next to art and lyrics — not a popup. If both lyrics and queue will not fit, opening one parks the other until you close it. All of that is under Settings → Queue.
New track: Lumen can show the cover first, then open lyrics if synced lines exist. Turn that off, or set how long the cover stays, under Behavior → Open lyrics automatically.
Keys: 1 compact · 2 expanded · 3 lyrics · L lyrics / cover · Q queue.
Plain language. No settings required to start.
| Stay with the song | Play, skip, seek, shuffle, repeat, like, volume, ±15 seconds |
| Read along | Synced lines: the current one is sharp, neighbors dim and blur |
| Peek | Current line under the title (expanded) or in the compact bar |
| Next up | What’s coming after this track — tap it to open the queue |
| Queue | Up next and Played. Grip to reorder, filter, remaining time, shuffle, duplicates, save, like, play next, stop after |
| Song menu | Right-click (or long-press) art, title, lyrics, or a queue row — play, queue, like, album, artist, radio, share |
| Play on | Switch speakers / devices from inside Lumen |
| Sleep | Pause after 15, 30, 45, or 60 minutes |
| Tune the look | Quality, cover shape, glass, grain, glow, lyric depth — with a live preview |
| One-tap cinema | Dream depth, auto-hide chrome, rich motion |
Lyrics come from Spotify when they exist. If a track has no timed lines, unsynced text can still show; follow and the karaoke bar need timed lines.
Gear in any layout, or press ,. Four tabs. Every tab has a live preview — change a control and watch the stage.
| Tab | For people who want to… |
|---|---|
| Player | Change quality, cover, dock, track info, and which buttons show |
| Lyrics | Change how lines look (presets first, then fine knobs) |
| Behavior | Change what happens on a new track, taps, follow, sleep, song menu |
| Queue | Change list chrome, tools, and glass |
Start with Soft lyrics and Balanced quality. If the player feels heavy, Player → Engine → Lite.
Player — every control
Performance
| Control | What it does |
|---|---|
| Engine | Lite is lightest on the GPU. Balanced is the default. Rich adds drift and heavier glass |
| Solid chrome | Skip blur glass — cheaper to draw |
Cover
| Control | What it does |
|---|---|
| Shape | Sharp corners, soft, or circle |
| Motion | Still, or a slow breathe while playing |
| Accent | Color from the album, or white |
| Background drift | Slow pan on the blurred art (Rich) |
| Big play button | Larger play control |
| Stage dim | How dark the overlay sits over the art |
Atmosphere — film grain, album-color glow, background brightness, glass opacity.
Dock — float over the stage or pin to the bottom. Push keeps art and lyrics clear of the dock.
Transport — show or hide volume (player / lyrics), skip ±15, shuffle & repeat, time labels, scrubber.
Track info — look (stack, center, on art, banner, quiet), size, like button, device name, lyric peek, next-up, compact peek, remaining time.
Lyrics — every control
Presets: Sharp, Soft, Dream. Use one, then tweak.
Type — left or center, size, line spacing, italic idle lines, uppercase, letter spacing.
Depth — how far-away lines blur, how fast neighbors fall off, how dim they go, fade at the top and bottom.
Active line — scale (“punch”), glow, karaoke fill, hover to unblur a line.
Behavior — every control
New track
| Control | What it does |
|---|---|
| Open lyrics automatically | After a change: show the cover, then switch if synced lyrics exist |
| Hold cover | How long to stay on the cover first — Now through 8 seconds |
Lyrics chrome — auto-hide header and controls, header art (tap to go back), header like.
Follow & sync — keep the active line in view, tap a line to seek, sync offset (negative = lyrics earlier) plus a fine slider.
Gestures — double-tap cover to open lyrics, tap cover to pause, how long until follow resumes after you scroll.
Song menu — right-click or long-press the cover, title, lyrics, or a queue row for play, queue, like, album, artist, radio, and share.
Sleep timer — off, or pause in 15–60 minutes.
Cinematic lyrics — one tap: dream depth, auto-hide, rich motion.
The full walkthrough, including tips: docs/GUIDE.md.
| Key | Action |
|---|---|
| Space | Play / pause |
| ← → | Seek 5 seconds |
| J K | Seek 15 seconds |
| ↑ ↓ | Volume |
| F | Like |
| S | Shuffle |
| R | Repeat |
| L | Lyrics / cover |
| Q | Queue |
| 1 2 3 | Compact / expanded / lyrics |
| , | Settings |
| Esc | Close a sheet, or leave lyrics |
Lumen grew from Wave Player by Ekko. That project is the reason this exists. They are not the same player.
| Spotify miniplayer | Wave Player | Lumen | |
|---|---|---|---|
| Where it lives | Tiny PiP window | Floating always-on-top window | Inside the Spotify window |
| Lyrics | Separate view | Synced, blurred neighbors | Synced, live look preview, full control |
| Layout | One size | Compact / expanded / lyrics | Same three, plus strip layouts for sidebars |
| Look | Spotify chrome | Liquid Glass | Liquid Glass, quality modes, per-control previews |
Want a small window glued on top of everything? Wave Player is still the right tool. Want a full-stage player you can snap, tile, or drop in a sidebar? Use Lumen.
Each GitHub Release attaches the built waveplayer.js for that version. CI builds on every push to main. Pull requests keep a draft of the next notes.
To publish a version:
git tag v2.1.0
git push origin v2.1.0Bump version in package.json and WP_VERSION in src/constants.js so the in-app notice matches the tag.
Spicetify still loads one file: waveplayer.js. Source is ES modules under src/, bundled to an IIFE with esbuild. No runtime npm dependencies.
npm install
npm run buildnpm run build and npm run watch also copy waveplayer.js into your local Spicetify Extensions folder. Then spicetify apply and a full Spotify restart.
flowchart LR
Spotify[Spotify desktop] --> Spicetify
Spicetify --> Bundle["waveplayer.js IIFE"]
Bundle --> Host[Shadow DOM overlay]
Host --> UI[Layouts + settings]
Bundle --> Lyrics[Lyrics pipeline]
Lyrics --> CL[Spotify color-lyrics]
Lyrics --> LB[LRCLIB fallback]
Bundle --> Theme[Album palette]
| Path | Owns |
|---|---|
src/index.js |
Boot: wait for Spicetify, load settings, bind the launcher |
src/config/ |
Settings schema (wp7-* keys) and lyric presets |
src/lyrics/ |
Fetch + parse |
src/player/ |
Theme, controls, lyrics view, settings panel, rAF tick |
src/host/ |
Overlay, Shadow DOM shell, open / close |
src/ui/ |
CSS and HTML |
src/spotify/ |
Connect devices, queue read / play / reorder / clear |
src/colors/ |
Palette from cover art |
src/utils/ |
DOM, format, icons, Spotify helpers |
| You want… | Touch |
|---|---|
| A new saved setting | src/config/settings.js schema, then a control in src/player/settings-panel.js / src/ui/settings-markup.js |
| A look that changes CSS | A class in src/player/theme.js |
| Another lyrics source | src/lyrics/fetch.js |
| New chrome | Markup + CSS in src/ui/, bind once in src/player/controls.js |
Keep settings keys stable. Existing installs already have wp7-* values in localStorage.
- Host — full-window overlay in a Shadow DOM. Spotify’s own chrome is hidden with
wp-litewhile Lumen is open. Toggle the miniplayer button again to close. - Tick —
requestAnimationFrameloop for progress, transport state, volume, and lyric follow. Pauses work when the page is hidden. - Layout —
ResizeObserverbreakpoints (xxs…lg) and a strip mode for narrow, tall windows. - Theme — k-means-style palette from the cover; CSS variables for blur, dim, glass, accent.
- Devices — Spotify Connect via
ConnectAPI, with a REST transfer fallback. - Queue —
Spicetify.QueueplusPlayerAPI/ Cosmos. Rows are recycled in place; the rAF loop only compares a revision string. Reorder uses the live queue client so both Next and Up next move.
- Spotify color-lyrics over
spclient.wg.spotify.com, including the/track/{id}/image/{cover}path, withApp-Platform: WebPlayer(desktop intercepts break the older route). - Cosmos /
wg://andPlatform.Lyricsfallbacks. - LRCLIB for timed LRC or plain text.
- In-memory cache per track URI.
Unsynced text still renders. Follow, karaoke fill, and tap-to-seek need timed lines.
src/config/settings.js is the schema: booleans, numbers, enums. Defaults vs “user turned it off” are distinguished (true unless "false", and the reverse for opt-in flags). Lyric blur still reads the older wp7-blur key if wp7-blur-px is missing.
| What you see | What to try |
|---|---|
| Miniplayer button does nothing | spicetify config extensions should list waveplayer.js. Fully quit Spotify |
| Old look after an update | Spotify was not fully quit. Close the tray icon too |
| “No lyrics” | That track has no timed lyrics from Spotify (or fallbacks). Unsynced text may still show |
| Feels heavy | Settings → Player → Engine → Lite |
| Lyrics late or early | Behavior → Sync offset. Negative is earlier |
| Spicetify broke after a Spotify update | spicetify restore backup apply, then confirm Lumen is still enabled |
More install notes: docs/INSTALL.md.
Original Wave Player by Ekko (@03x1).
This fork is maintained independently. Full thanks: CREDITS.md.
Also inspired by Beautiful Lyrics and Spictify Lyric Miniplayer.
MIT — same family of license as Wave Player. Ekko’s copyright stays in the license file.


