Keep the lyrics on your desktop and the music in sight.
A lightweight, transparent and customisable lyric overlay for Windows, with Spotify and YouTube Music support.
简体中文 · English
Download the latest release · Quick start · Spotify setup · Development
| 🎵 Immersive lyrics | ✨ Word-level sync | 🪶 Lightweight and native |
|---|---|---|
| Transparent, always on top and freely draggable, so you can sing along without switching windows. | Smooth sweep highlighting when a word-level timeline exists, with an automatic fall back to line lyrics when it does not. | Native .NET 8 + WPF. No Python service and no extra UI framework. |
| 🎧 Two playback sources | 🎨 Highly customisable | 🖱️ Unobtrusive interaction |
| Spotify and YouTube Music, switchable with one click. | Font size, colour, glow, opacity, width and position are all adjustable. | Locking makes it click-through; the tray menu brings it back, unlocks it or exits at any time. |
- Layered lyric experience: word-level sync → line sync → unsynced full text, degrading naturally with the available data quality.
- Smart lyric matching: combines title, artist, duration and version information to reduce the chance of a wrong version overwriting the right lyrics.
- Multi-source race with fault tolerance: basic sources show up first and enhanced sources upgrade asynchronously; a single failing service never interrupts playback.
- Per-song offset: every song keeps its own ±5 second calibration.
- Position presets: free drag, top/bottom centre, screen centre and the four corners.
- Single instance and tray: a second launch is reported, and a hidden overlay can be restored from the system tray.
Go to Releases and pick the package that fits your situation:
| Variant | When to use it | .NET 8 Desktop Runtime |
|---|---|---|
setup-online.exe |
Recommended; smallest download, fetches the runtime during setup | Detected automatically |
setup-offline.exe |
Offline installation or bulk deployment | Bundled |
portable.zip |
Portable, extract and run | Bundled |
framework.zip |
You already have .NET 8 and want the smallest download | Must be installed |
Important
Both ZIP variants must be fully extracted before you run FloatSpotify.Next.exe. Do not launch it from inside the archive.
- YouTube Music: no Google authorization required. The app reads the playback state of Chrome, Edge, Firefox, Brave, Opera, Vivaldi or the YouTube Music PWA through the Windows system media session.
- Spotify: uses the official Web API with PKCE authorization and requires your own Spotify Client ID.
| Action | Effect |
|---|---|
| Click the lyrics | Open or collapse the control bar |
| Click ↻ or tray “Refresh lyrics” | Cancel a stuck lookup and immediately fetch the current lyrics again |
| Drag the lyrics | Move the overlay |
| Adjust "Lyric width" | Set the overlay width between 160 and 1600 px |
| Click lock | Enable click-through so it never blocks anything |
| Right-click the tray icon | Show lyrics, refresh lyrics, open settings, unlock, re-authorize or exit |
FloatSpotify Next uses the official Spotify Web API. No developer Client ID ships with the app, and no Client Secret is needed.
-
Sign in to the Spotify Developer Dashboard.
-
Click Create app; if it asks which API you need, choose Web API.
-
Under the app's Settings → Redirect URIs, add:
http://127.0.0.1:8888/callback -
Save and copy the 32-character Client ID shown on the page.
-
Open the FloatSpotify Next settings and paste the Client ID into the field.
-
Click "Authorize Spotify with this Client ID" and finish signing in through your browser.
The Client ID is stored in the user environment variable FLOATSPOTIFY_SPOTIFY_CLIENT_ID and never written into the program directory. The authorization session is kept in the current user's local application data folder.
Tip
The ? button in the settings opens the in-app setup guide at any time. Using your own Spotify app also avoids the publisher account's allow-list limits.
Settings, the Spotify session and the lyric cache stay on your machine:
%LocalAppData%\FloatSpotify.Next\
├─ settings.json # Interface and behaviour settings
├─ spotify-session.json # Spotify authorization session
└─ lyrics\ # Lyric cache, split by source, artist, title and duration
Uninstalling the app does not delete that folder, so a reinstall usually needs no new authorization. Delete the folder by hand if you want it gone for good.
flowchart LR
A[Spotify Web API] --> C[PlaybackCoordinator]
B[Windows GSMTC<br/>YouTube Music] --> C
C --> D[LyricsCoordinator]
D --> E[Basic lyric sources]
D --> F[Enhanced lyric sources]
E --> G[Cache and version matching]
F --> G
G --> H[OverlayViewModel]
H --> I[WPF overlay]
How lyrics are fetched, matched and degraded
- Enabled basic sources (LRCLIB / optional NetEase) return usable lyrics first, then the Karalyr / Better Lyrics enhancement sources try to upgrade them to word-level results. Sources of the same class follow the user's ordering; nothing is requested when all of them are off.
- Spotify playback-state requests are serialized and polled every 5 seconds. Network failures back off exponentially up to 30 seconds; state older than 15 seconds is hidden and the current track is synchronized again after connectivity returns.
- Tracks explicitly marked English / Chinese / Japanese / Korean Ver. have both the returned title and the lyric script checked, so a wrong language cannot overwrite a correct result that merely has a lower sync level. The full version title takes part in the cache key.
- Each source has a 3 second timeout by default.
404,401, empty results, network failures and parse errors are isolated;429respectsRetry-Afterand enters a short cooldown. - When the current song has no lyrics it is rechecked every 30 seconds, subject to the rate-limit cooldown and a 5 minute miss cache.
- Word-level results are cached for 7 days, line-level results for 1 day. The cache is keyed by source, artist, title and duration.
- When Enhanced LRC is missing the end time of the last word, the next line or the end of the song is used as the boundary; if no boundary is available it falls back to line level rather than inventing an average word duration.
- TTML supports absolute clocks, grouped
begin/endand nested word-levelspan, and preserves whitespace. Background vocals and translations never leak into the lead line. - Multiline unsynced lyrics are split into an estimated line progression instead of one scrolling text block. Truly single-line text remains scrollable; with no text at all the app shows the song information and an automatic retry hint.
Lyric format and API references: Karalyr docs, Better Lyrics response format, Better Lyrics authentication. Actual word-level coverage depends on the upstream services.
- Windows 10 build 17763 (1809) or later
- .NET 8 SDK
- Visual Studio 2022 (optional, for XAML design and debugging)
git clone https://github.com/SISUBEN/FloatSpotifyNext.git
cd FloatSpotifyNext
dotnet build src/FloatSpotify/FloatSpotify.csproj -c ReleaseYou can also open FloatSpotify.Next.sln in Visual Studio.
FloatSpotifyNext/
├─ src/FloatSpotify/
│ ├─ Localization/ # Interface string table and runtime language switching
│ ├─ Playback/ # Playback engines, lyric sources, parsing, matching and caching
│ ├─ ViewModels/ # MVVM state and commands
│ ├─ Windows/ # Overlay, control bar, settings and custom rendering
│ ├─ Storage/ # Settings model and persistence
│ └─ Assets/ # Application icon and other static resources
├─ tests/ # Executable regression suite with no test framework dependency
├─ build/ # Release and packaging scripts
├─ installer/ # Inno Setup configuration
└─ artifacts/ # Locally generated test evidence and release artifacts
To add a playback source, implement IPlaybackEngine, extend PlaybackSource, and wire it into PlaybackCoordinator. To add a lyric source, implement ILyricsProvider and register it with LyricsCoordinator.
Interface text lives in src/FloatSpotify/Localization/Strings.cs as a single
key -> (Chinese, English) table. Use {loc:Tr Key} in XAML and Loc.T("Key") in code;
both follow the language the user picks in the settings, with no restart.
dotnet run --project tests/FloatSpotify.Lyrics.Tests -c Release -- artifacts/lyrics-word-syncThe suite covers simulated HTTP, lyric parsing, caching, settings migration, playback
timelines and WPF pixel verification. Add --i18n-probe to build the real windows and
verify that the interface actually switches language. The generated render evidence uses
synthetic test lyrics and does not represent real-song hit rates or player end-to-end
acceptance.
The project follows Conventional Commits:
feat(lyrics): add word-level timing
fix(playback): preserve position after source switch
docs: improve Spotify setup guide
Run the following script to enable the commit template and validation hook for this clone:
./tools/setup-git-hooks.ps1Full rules are in COMMIT_CONVENTION.md; project constraints aimed at coding agents are in AGENT.md.
Building the installers also needs Inno Setup 6:
winget install JRSoftware.InnoSetup
powershell -ExecutionPolicy Bypass -File build/build-release.ps1The script reads <Version> from src/FloatSpotify/FloatSpotify.csproj and produces the following in artifacts/:
FloatSpotifyNext-x86_64-v<version>-setup-online.exe
FloatSpotifyNext-x86_64-v<version>-setup-offline.exe
FloatSpotifyNext-x86_64-v<version>-portable.zip
FloatSpotifyNext-x86_64-v<version>-framework.zip
- Use
-Version 1.2.0to override the project version temporarily. - Use
-SkipInstallersto produce only the two ZIP packages. - When changing the product or architecture name you must update both
build/build-release.ps1andinstaller/FloatSpotify.Next.iss.
Note
WPF does not support PublishTrimmed. The self-contained build already shrinks its size by limiting framework satellite resources; most of the remaining space is the .NET runtime and the WinRT projections YouTube Music needs.
- Only a Windows x64 build is available today.
- There is no auto-update yet; upgrading means running the installer again or replacing the portable files.
- Obscure songs may have no usable lyrics, and word-level coverage depends on the upstream sources.
- YouTube Music relies on the Windows system media session; when several browser tabs play at once the wrong session may be selected.
- The project started as a fork of BitsJayMehta173/FloatSpotify. The original Python Flask backend has been removed and replaced with a native .NET rewrite.
- Lyric data and format support come from upstream services including LRCLIB, NetEase, Kugou, Karalyr and Better Lyrics.
- Thanks to everyone who reports issues, tests lyric matching and improves the desktop experience.
Released under the MIT License.