Built for music lovers who were abandoned by every player Microsoft shipped.
Prefer a portable build? Grab
NovaTune-Setup-1.1.6.exefrom the Releases page β no installer, just double-click and play. Ensure You download the latest version it has some critical fixez ... oh b the way this will ook nice with a 14 incher and above i dont know how its gonna look like in smaller screens (i mean in the full screen aspect).
I never really set out to code up a music player. I just wanted to listen to music on my laptop the way I do on my phone.
On Android, an app called Oto Music quietly became the gold standard. Built largely by one person β Piyush Mamidwar β it crossed 2 million downloads and held a steady 4.6-star rating for years. It was Material You to the core: accent colors that flowed from your wallpaper, a beautiful full-screen lyrics view, gapless playback, a built-in tag editor, a folder blacklist so your ringtones never polluted your library, and synced lyrics pulled from four different sources. It was free. It was ad-free. It was feature-complete. It proved that a local music player could be beautiful and powerful at the same time. (Android Police called it "the only one I kept.")
Then I looked at my Windows laptop. And Windows has a music player problem it has never solved.
- Groove Music was killed in 2017. Microsoft pulled its streaming service on October 2, 2017, pushed everyone to Spotify, and along the way dropped the visualizations instead of re-licensing them. Gapless playback took "years of crying and begging." Even now, years after it was replaced, users on Microsoft Q&A are still asking "Is there any way to get back the old Groove Music player? The interface was way much better."
- The new Windows 11 Media Player looks pretty, and then it betrays you. Users on r/Windows11 report it locking up mid-song, repeating the last 5 seconds of audio in a loop until you kill it from Task Manager. It's slower to open than VLC and even the legacy WMP. It routinely can't detect music that's clearly on disk. It throws
0x80070005when you try to create a playlist β and the community answer is literally "switch to Foobar2000, it's free." Worse, songs silently disappear from your playlists β sometimes 50% of them β and the player tells you it "cannot find the file" for files that are still sitting right there on your hard drive. And synced lyrics? Forget it. The old WMP 11 karaoke-style lyrics pane was stripped. Anyone asking how to display lyrics in the modern player is told to go install Dopamine or foobar2000. - Windows Media Player Legacy is still there β as an Optional Feature you have to install manually. Microsoft's own Insider forum admits it "still looks like it's from the 2000s", its DRM services are officially deprecated, and on some installs it refuses to open at all.
In short: Windows users are stuck choosing between a buggy modern app that lost the plot, a dead 2017 streaming husk, and a player frozen in 2000s amber. Meanwhile Android users have had Oto Music for years.
So I built NovaTune.
Synced lyrics from the open LRCLIB database (better sync quality than Musixmatch, according to MusicBee users, with zero API keys and zero profit motive). A real 10-band parametric equalizer with 20 presets. Crossfade and gapless playback through a professional Web Audio API pipeline. A library scanner that doesn't choke. Themes that can pull their accent color straight from the album art of whatever's playing. A squiggly progress bar that animates on its own off-main-thread canvas. Playlists that actually keep their songs. A lyrics editor. A tag-aware metadata engine that reads anything music-metadata can parse β MP3, FLAC, WAV, OGG, M4A, AAC, WMA, and more.
This is the music player Windows should have shipped. Since it didn't, I did.
NovaTune is a native Windows desktop music player built with Electron 28, Node.js native modules (better-sqlite3, sharp, node-vibrant, music-metadata, electron-updater), and a custom Web Audio API mastering pipeline. It is single-instance, frameless, dark by default, and integrates with the Windows System Media Transport Controls (SMTC) so your media keys, lock screen, and taskbar flyout all work the way they should.
It is not a streaming client. It is not a cloud anything. Point it at a folder of your own music files, and it builds a fast, searchable, beautiful local library. Your data stays on your machine.
| App ID | com.novatune.player |
| Version | 1.1.6 |
| License | MIT |
| Platform | Windows x64 (NSIS installer + portable build) |
| Aesthetic | Spotify-dark, Material-You-aware accent system |
| Library backend | SQLite (WAL mode) with JSON-denormalized track rows |
| Audio backend | Web Audio API + (optional) WASAPI exclusive mode |
- Why I Built NovaTune β An Honest Story
- What is NovaTune
- Screenshots
- Feature Highlights
- The Squiggly Progress Bar
- Audio Engine
- Lyrics System
- Library & Metadata
- Playlists
- Theming & Accent Colors
- Windows Integration
- Settings Reference
- Keyboard Shortcuts
- Project Map
- Tech Stack
- Build From Source
- A Note About Screen Sizes (14β³ vs 13β³)
- Known Limitations & Quirks
- Roadmap
- Contact the Developer
- Credits
- License
Add each screenshot to a
screenshots/folder at the root of your repo, then keep these paths. Recommended sizes are noted under each placeholder.
Replace these three placeholders with screenshots of NovaTune running with different accent colors (Spotify Green, Sky Blue, Orange, Pink, etc.) β or with Dynamic Accent enabled, so the color follows the album art.
Replace these three placeholders with screenshots at different window widths (full desktop width, narrow window, and overlay/mobile-style layout) to show how the sidebar collapses and the layout adapts.
- Premium Spotify-dark aesthetic β 12 / 18 / 24 hex surface stack, custom titlebar overlay, frameless window.
- Synced lyrics from 5 sources β in-memory cache β SQLite β
.lrcsidecar β embedded tags (USLT/SYLT/Vorbis/iTunes/APEv2) β LRCLIB online. Auto-scroll with click-to-seek. - Real 10-band parametric EQ β 32 Hz to 16 kHz, 20 presets, master toggle, volume boost up to 2Γ.
- Equal-power crossfade + gapless playback β 1β12 s fade curves through a full mastering chain (compressor β analyser β boost β destination).
- Three visualizer styles β bars, wave, circle β running on a DPR-aware canvas with smoothed data and reflections.
- The squiggly progress bar β a signature AOSP-ported canvas animation that runs in an
OffscreenCanvasdriven by a Web Worker, so it never touches your main thread. Falls back gracefully to a SVG sine-wave overlay. - Dynamic accent from album art β toggle it on and the entire UI (including the squiggly bar) recolors itself based on the dominant palette of whatever's playing, extracted by
node-vibrant. - Album / artist / folder organization β automatic grouping, album detail view, artist detail view.
- Playlists done right β full CRUD, drag-and-drop reordering, Favorites, and import / export in M3U, M3U8, PLS, XSPF, and JSON.
- Exhaustive cover-art discovery β embedded tags β
.novaart.*sidecar β exact-name match β common names (cover,folder,album,front,artwork,art, β¦) β WMP cache files (AlbumArt_{GUID}_Large.jpg) β any image β₯5 KB in the same directory β subdirectories (1 level) β parent directories (up to 3 levels). - On-demand thumbnail generation via
sharpβ WebP, center-cropped, with in-flight deduplication so 100 simultaneous requests for the same thumbnail produce one Sharp job. - SQLite library backend with WAL journaling, indexed title / artist / album / dateAdded columns, and JSON-denormalized
datacolumn for schema flexibility. - Windows SMTC integration β your media keys, lock-screen controls, and taskbar media flyout all work. Falls back to simulation mode if the native module isn't installed.
- OTA updates via
electron-updaterβ auto-checks 60 s after launch, then every 4 hours, with manual "Check for Updates" in Help. User consent required for downloads. - Single-instance β second launch focuses the existing window.
- Window state persistence β your window position, size, and maximized state survive restarts, with multi-display bounds validation.
- Custom
nova-media://protocol β byte-range-accurate local file serving with correct MIME types, plus an LRU response cache (max 500 entries). - Frameless window with native Windows caption buttons β
titleBarOverlaywith transparent background, no Electron-caption-button hacks.
This deserves its own section because it's the soul of NovaTune's UI.
The squiggly progress bar is a direct port of the AOSP (Android Open Source Project) SquigglyProgress animation. The wave:
- Animates only while playing β it freezes when paused, like a held breath haha...
- Runs on an
OffscreenCanvasdriven by a dedicated Web Worker (created from a Blob URL) so animation never blocks the main thread. - Falls back gracefully β if
OffscreenCanvasis unavailable or CSP blocks the Worker, it drops to a main-threadrequestAnimationFrameloop. - Has an SVG sine-wave overlay as a secondary implementation inside the bottom now-playing bar (
PlayerControls._injectWaveSvg), with cosine/sine path tiles. - Color follows the active accent β when Dynamic Accent is on, the worker receives a
postMessagewith the new color and the wave recolors instantly, in lockstep with the rest of the UI. - Click anywhere on the canvas to seek β with a mouse-move preview showing where you'll land.
It is, frankly, the kind of detail Microsoft removed when they replaced Groove.
NovaTune runs audio through a fully wired Web Audio API graph β not just <audio> alone. The signal chain:
HTMLAudioElement
β MediaElementAudioSourceNode
β [EQEngine: preampGain β 10Γ BiquadFilter chain] (only when EQ enabled)
β GainNode (user volume, 0β1, 8 ms ramp)
β DynamicsCompressorNode (transparent mastering limiter)
β AnalyserNode (fftSize=8192, smoothing 0.8)
β GainNode (volume boost, 1.0Γβ2.0Γ)
β AudioContext.destination
- 10-band parametric EQ β bands at 32, 64, 125, 250, 500, 1k, 2k, 4k, 8k, 16 kHz; gain range β12 to +12 dB; lowshelf at 32 Hz, peaking through 64 Hzβ8 kHz, highshelf at 16 kHz. Per-band Q tuned for natural sound (0.707 for shelves, 1.0β2.0 for peaking). 5 ms time constant for click-free adjustments.
- 20 EQ presets grouped as Neutral (Flat), Genre (Rock, Pop, Hip-Hop, Jazz, Classical, Electronic, R&B, Country, Metal, Latin, Acoustic), and Use-case (Bass Boost, Treble Boost, Vocal, Loudness, Late Night, Headphones, Speakers).
- Dynamic headroom protection β preamp gain is automatically reduced as you boost bands, with
min(-4 dB, -maxBoost Γ 0.7)clipping protection. - Transparent mastering limiter β a
DynamicsCompressorNodewith -14 dB threshold, 8 dB knee, 4:1 ratio, 3 ms attack, 150 ms release. It catches transients without audibly squashing your music. - Equal-power crossfade β
sin(phase) Γ targetVolfor fade-in,cos(phase) Γ targetVolfor fade-out (preserves perceived loudness). 1β12 second duration, default 3 s. - Gapless playback β
endedevent advances to the next track with zero silence in between, ideal for classical, live albums, and Pink Floyd. - Volume boost up to 2Γ β post-analyser
GainNodefor quiet masters, with 8 ms ramp to avoid clicks. The visualizer sees the pre-boost signal so it stays musically meaningful. - WASAPI exclusive mode on Windows β
--enable-exclusive-audioChromium flag for bit-perfect output on supported devices. - Device-native sample rate β no forced resampling, no extra SRC artifacts.
- Pre-allocated analyser buffers β
Uint8ArrayforgetByteFrequencyData/getByteTimeDomainDataare allocated once, eliminating 120 allocations/sec at 60 fps.
| File | Purpose |
|---|---|
renderer/audio/AudioEngine.js |
Web Audio graph, play/pause/seek/volume/boost, analyser data |
renderer/audio/EQEngine.js |
10-band BiquadFilter chain + presets + headroom preamp |
renderer/audio/Crossfader.js |
Equal-power crossfade + gapless mode, full-graph secondary pipeline |
renderer/audio/Visualizer.js |
Canvas 2D bars / wave / circle visualizer |
Lyrics in NovaTune are a 5-tier cascade. Whichever tier returns first wins, and the panel upgrades in place when a better source arrives β no "no lyrics" flash before the network response.
- In-memory cache (
Map<trackId, lyrics>) β instant. - SQLite-stored lyrics β checks the
lyricsPathon disk first, then thesyncedLyrics/plainLyricscolumns. ~1 ms. - Local
.lrcsidecar β replaces the audio file's extension with.lrc(case-insensitive). ~2 ms. - Embedded tag lyrics β read by
music-metadatafrom ID3v2.3 / ID3v2.4 USLT (unsynced) and SYLT (synced) frames, Vorbis CommentsLYRICS(FLAC / OGG), iTunesΒ©lyr(M4A / MP4), and APEv2LYRICS(APE / Musepack). SYLT timestamps are converted from milliseconds to seconds when thetimeStampFormatis2; frame-number format (1) is gracefully skipped. - Online LRCLIB β
https://lrclib.net/api/getand/api/searchare raced in parallel, with duration-aware matching (Β±2 s tolerance) and a 12 s timeout.
The LRC parser supports [mm:ss.xx], [mm:ss:ms], [mm:ss], multi-timestamp lines, and skips [ti:], [ar:], [al:], [by:], [offset:] metadata headers. If plainLyrics happens to contain LRC timestamps, they're auto-promoted into synced lyrics and stripped from the plain version β so the panel never shows raw [00:15.04] tokens to the user.
- Synced lyrics β smooth lerp scroll (13% per frame) centering the active line at 35β40% of the container height.
- Manual scroll override β any user scroll cancels in-flight programmatic lerp and pauses auto-scroll for 1500 ms. Auto-scroll resumes on the next line change.
- Unsynced lyrics β full manual control at all times. The app never fights your scroll position.
- Click any synced line to seek to that timestamp.
- A "synced" badge is shown when lyrics are time-stamped.
A three-tab modal:
- Search LRCLIB β by title/artist; returns up to 20 results with synced/plain badges and a duration-match indicator. Retries 3Γ with 1.2 s backoff on failure.
- Paste / Type β a textarea accepting plain text or LRC format.
- Load File β drag-and-drop or browse for a
.lrcor.txtfile.
"Save to Track" writes a .lrc sidecar next to the audio file and patches the SQLite row. "Clear Lyrics" removes both the sidecar file and the DB entries.
When a track is queued for playback, prefetchLyrics() fires the LRCLIB online fetch in parallel with audio init. By the time audio starts (~300β800 ms later), online lyrics are usually already cached β so the lyrics panel is populated from the moment the first note plays.
- Recursive scan via
fs.readdirSync({ withFileTypes: true }). - Automatic skip list for system directories:
node_modules,.git,.svn,.hg,__pycache__,System Volume Information,$RECYCLE.BIN,Windows,Program Files,Program Files (x86),ProgramData,AppData. - Hidden files (
.prefix) are skipped. - Per-file modification-time caching means unchanged files are skipped on rescan.
- Filename-pattern fallback β if a track has no tags, NovaTune parses
Artist - Title.ext. - Auto self-healing β if a file is missing, NovaTune looks for another DB track with the same title + artist and updates the path.
- Scan progress overlay shows stages: scanning β reading metadata β saving β complete / error.
The scanner accepts 12 audio extensions: .mp3, .flac, .wav, .ogg, .m4a, .aac, .wma, .opus, .ape, .wv, .tta, .mpc. Seven of them (mp3, flac, wav, ogg, m4a, aac, wma) are registered as Windows file associations so double-clicking a file in Explorer launches NovaTune.
Powered by music-metadata v8+ (ESM-only, loaded via dynamic import()). Reads title, artists (joined with , ), album, albumArtist, genre, year, track number, disc number, duration, bitrate, sample rate, number of channels, and container format. If the library can't load, NovaTune falls back to filename-based metadata only.
NovaTune will try, in order:
- Embedded picture tag (from
music-metadata). .novaart.{jpg,jpeg,png,webp}sidecar (downloaded online art saved next to the audio file).- Exact-name match (
Song.jpgforSong.mp3). - Common names:
cover,folder,album,front,artwork,art,thumb,thumbnail,back,insert,booklet,jacket,label,sticker. - WMP hidden cache files:
AlbumArt_{GUID}_Large.jpg,AlbumArtSmall.jpg. - Any image β₯5 KB in the same directory.
- Subdirectories (1 level) β same priority tiers.
- Parent directories (up to 3 levels) β common names only.
Powered by sharp. Center-cropped square, resized to the target size (32β800 px, default 48 px), saved as WebP quality 75β80 (25β35% smaller than PNG, faster to decode) to cached_covers/thumbs/{trackId}_{size}.webp. Simultaneous requests for the same trackId+size share one Sharp job β in-flight deduplication prevents redundant CPU and disk I/O. An IndexedDB cache (NovaTuneThumbCache) persists thumbnail URLs across launches.
Database file: novatune.sqlite in WAL journal mode.
tracksβid(TEXT PK, first 16 chars ofsha256(filePath)), denormalized columns fortitle,artist,album,genre,year,duration,dateAdded,filePath(TEXT UNIQUE), plus adataTEXT column holding the full track JSON for schema flexibility.- Indexes on
title,artist,album(case-insensitive), anddateAdded DESC. playlistsβid,name,createdAt,updatedAt, indexed onupdatedAt DESC.playlist_tracksβplaylistId,trackId,position,addedAt, with composite indexes.- A legacy
library.jsonandplaylists/*.jsonare auto-migrated to SQLite on first run.
- Create β right-click the "Playlists" section header in the sidebar, or click the create button.
- Rename β double-click any playlist in the sidebar for an inline rename dialog, or right-click for the context menu.
- Delete β right-click β Delete. Cascades to
playlist_tracks. - Add track β drag-and-drop a song onto a playlist in the sidebar, or right-click a song and use "Add to Playlist" from the context menu. The context menu lists all playlists with "Added" / "Quickly Add" status; "+ New Playlist" creates and adds in one action.
- Reorder β drag-and-drop in the Play Queue view.
- Remove from queue β right-click in the queue.
Click the heart icon on any song to add it to your Favorites playlist. The Favorites playlist is auto-created on the first heart-click. The heart toggle appears in both the now-playing bar and the full-screen overlay. Click again to unfavorite.
Every playlist gets an auto-generated 4-track cover collage built from the first four tracks' art, rendered as a WebP with content-hash invalidation so the collage regenerates only when the underlying tracks change.
| Format | Encoding | Notes |
|---|---|---|
| M3U | latin1 | #EXTM3U header + #EXTINF:duration,Artist - Title lines. Latin1 for legacy Windows player compatibility. |
| M3U8 | UTF-8 | Same as M3U but UTF-8 β use this for non-ASCII filenames. |
| PLS | UTF-8 | [playlist] header + File{n}=, Title{n}=, Length{n}=. |
| XSPF | UTF-8 | XML with`` blocks, file:/// locations, escaped entities. |
| JSON | UTF-8 | {name, createdAt, updatedAt, tracks: [{filePath, title, artist, album, duration}]} β NovaTune's native portable format. |
Import uses cross-platform basename matching, so playlists exported from an Android player (e.g. /storage/emulated/0/Music/song.mp3) resolve correctly on Windows (C:\Users\...\Music\song.mp3). Import reports matched vs. unmatched counts with a details dialog.
| Token | Value |
|---|---|
--bg |
#121212 |
--sidebar-bg |
#181818 |
--surface |
#242424 |
--surface-hover |
#2a2a2a |
--surface-active |
#2e2e2a |
--green (default accent) |
#1ed760 |
--green-hover |
#1fdf64 |
--text-primary |
#ffffff |
--text-secondary |
#b3b3b3 |
--text-muted |
#6a6a6a |
--app-font |
"Outfit", sans-serif |
Eight preset swatches:
| Name | Hex |
|---|---|
| Spotify Green | #1ed760 |
| Sky Blue | #00bfff |
| Orange | #ff6b35 |
| Yellow | #f7c948 |
| Mint | #3de0c0 |
| Pink | #e040fb |
| Red | #ff4d6d |
| Ice | #a8edea |
Plus a custom color picker (any HTML color input) and Dynamic Accent β a toggle that uses node-vibrant to extract Vibrant β LightVibrant β Muted β DarkVibrant from the current track's cover art. The entire UI recolors instantly, including the squiggly progress bar (a postMessage to the OffscreenCanvas Worker).
For the full-screen Now Playing overlay, NovaTune extracts DarkVibrant β DarkMuted β Vibrant β Muted and darkens it if the luminance is above 0.4, so the background always reads as "moodily dark" rather than "loudly purple."
- Outfit (default) β preloaded 300 / 400 / 500 weights.
- Figtree (optional) β all 7 weights preinstalled; CSS loaded with
media="not all"then activated via JS once loaded (non-blocking).
- On Hover β swipe from the left edge or hover near the left edge to reveal a floating icon nav strip. Auto-hides after 2500 ms on touch.
- Always Visible β the icon strip persists.
- Edge detection (mouse + touch) with 100 ms show delay, 300 ms hide delay, 2500 ms touch hide delay.
- The real sidebar shows on wide screens (>950 px); a floating card shows on narrow screens.
- On Hover β slider appears when hovering the volume icon.
- Visible β slider always shown for quick adjustments.
Implemented in main/smtc.js using the optional windows-media-controls native module. If the module isn't installed, NovaTune falls back to a simulation mode and continues to function. SMTC forwards OS media button events to the renderer (smtc:play, smtc:pause, smtc:next, smtc:previous, smtc:stop, smtc:seek), and the renderer pushes state back via IPC (smtc:update-metadata, smtc:update-status, smtc:update-position). Cover art for SMTC is saved as a temp file (novatune-smtc-thumb.{jpg|png}) on the fly. SMTC is only initialized on Windows (process.platform === "win32").
This is what makes your media keys, lock-screen controls, and taskbar media flyout all work β they show the track title, artist, album art, and a seek bar.
titleBarStyle: "hidden" + Windows titleBarOverlay (transparent background, #b3b3b3 symbols, 32 px height). The native Windows caption buttons (minimize / maximize / close) are drawn by Windows itself, not by Electron, so they look and behave exactly as expected. A custom in-app titlebar shows the NovaTune logo and name.
WindowStateManager saves { x, y, width, height, isMaximized } to window-state.json. On restore, it validates that the position is within multi-display bounds and resets if the window would be off-screen. Default size: 1280Γ720. Minimum: 360Γ420.
Menu.setApplicationMenu(null) β no native menu bar. All menus are in-app custom HTML/CSS.
- Provider: GitHub (
github.com/AnonymousV73X/WINDOWS-MUSIC-PLAYER, release type:release). autoDownload = falseβ user consent required.autoInstallOnAppQuit = true.- Auto-check 60 s after launch, then every 4 hours.
- Renderer events:
update:available,update:not-available,update:download-progress,update:downloaded,update:error. - Manual "Check for Updates" button in the Help section.
- Dev-mode fallback: opens the GitHub Releases page in the system browser if
electron-updatercan't run (unpkg'd dev mode).
app.requestSingleInstanceLock() β second launch quits and focuses the existing window.
oneClick: false, allowToChangeInstallationDirectory: true, createDesktopShortcut: true, createStartMenuShortcut: true, shortcutName: "NovaTune", perMachine: false, differentialPackage: true, requestedExecutionLevel: "asInvoker". Separate icons for installer, uninstaller, and header. x64 only.
| Flag | Purpose |
|---|---|
--autoplay-policy=no-user-gesture-required |
UnblocksAudioContext.resume() on first track. |
--disable-features=AudioServiceOutOfProcess,BackgroundTracing,PaintHolding |
Stability / latency. |
--enable-features=PlatformHEVCEncoderSupport |
HEVC encoding for any future video features. |
--audio-buffer-size=2048 |
Lower audio latency. |
--enable-gpu-rasterization, --enable-zero-copy, --force-gpu-mem-available-mb=1024, --disk-cache-size=268435456 |
GPU / disk performance. |
--enable-exclusive-audio (Windows only) |
WASAPI exclusive mode for bit-perfect output. |
The Settings panel is grouped into four cards:
| Setting | Values | Description |
|---|---|---|
| Shuffle by default | checkbox | Start every queue in shuffle mode. |
| Show lyrics panel when available | checkbox | Auto-open the lyrics panel for tracks with lyrics. |
| Hardware acceleration | checkbox | Toggle Chromium GPU compositing. |
| Volume bar | On Hover / Visible | Whether the volume slider is always shown. |
| Side menu (compact view) | On Hover / Always Visible | Behavior of the collapsed sidebar on narrow screens. |
| Setting | Values | Description |
|---|---|---|
| Preset swatches | 8 colors | One-click accent presets. |
| Custom color picker | any hex | Use any color. |
| Dynamic (from album art) | toggle | Accent follows the current track's cover art. |
| Setting | Values | Description |
|---|---|---|
| Font | Outfit / Figtree | Switch the app's primary font. |
| Setting | Values | Description |
|---|---|---|
| Add Folder | button | Open a folder picker and add to scan folders. |
| Refresh All Folders | button | Rescan every added folder. |
| Per-folder Refresh / Remove | buttons | Manage individual scan folders. |
| Back to Music Library | link | Return to the library view. |
| Key | Default | Description |
|---|---|---|
theme |
"dark" |
Theme (only "dark" is implemented). |
accentColor |
"#1DB954" |
Accent color hex. |
volume |
0.5 (renderer default) |
0β1. |
crossfadeDuration |
0 |
Seconds (0 = disabled). |
equalizer |
[0,0,0,0,0,0,0,0,0,0] |
10-band dB values. |
equalizerEnabled |
true |
EQ master toggle. |
volumeBoost |
1.0 |
1.0β2.0. |
repeatMode |
"off" |
off / all / one. |
shuffle |
false |
|
showLyrics |
false |
|
visualizerStyle |
"bars" |
bars / wave / circle. |
scanFolders |
[] |
Array of folder paths. |
sortOrder |
"title" |
|
sortDirection |
"asc" |
|
hardwareAcceleration |
true |
|
dynamicAccentColor |
false |
Renderer-only. |
volumeBarMode |
"hover" |
hover / always. |
navMode |
"hover" |
hover / always. |
font |
"outfit" |
outfit / figtree. |
_queue |
β | Persisted queue{ids, index} for session restore. |
recentlyPlayed |
[] |
Array of track IDs. |
| Shortcut | Action |
|---|---|
Space |
Play / Pause |
N |
Next track |
P |
Previous track |
β / β |
Volume up / down (Β±5%) |
β / β |
Seek Β±5 s (or with Shift: Next / Previous track) |
M |
Mute / Unmute |
S |
Toggle shuffle mode |
1 / R |
Toggle repeat one track |
0 / O |
Toggle repeat all tracks |
L |
Like / Favorite currently playing track |
T |
Open Tag Editor for currently playing track |
Ctrl+P / Cmd+P |
Add currently playing track to playlist |
Ctrl+L / Cmd+L |
Switch to Light Mode |
Ctrl+D / Cmd+D |
Switch to Dark Mode |
Ctrl+F or / |
Focus search |
PageUp / PageDown (or Shift+β / Shift+β) |
Scroll library view |
Esc |
Close overlay / dialog / clear search |
F11 |
Close Now Playing overlay |
Enter |
Confirm playlist rename / confirm dialog / search LRCLIB in lyrics editor |
MediaPlayPause |
Play / Pause (media key) |
MediaNextTrack |
Next track (media key) |
MediaPrevTrack |
Previous track (media key) |
Renderer-level shortcuts are skipped when typing in
INPUT/TEXTAREA/SELECTfields.
NovaTune/
βββ package.json # App metadata, scripts, build config
βββ package-lock.json # Lockfile (committed)
βββ electron.config.js # electron-builder: NSIS, file associations, extraResources
βββ make_icons.js # Sharp script: generates icon.ico + icon.png + tray.png from SVG
βββ download-fonts.js # Helper: fetches Outfit font weights from Google Fonts (dev-only)
βββ test-date-sort.js # Standalone debug script for dateAdded SQLite sort
βββ .gitignore # Ignores node_modules, dist, data/library.json, data/settings.json, data/playlists/
β
βββ assets/ # Static app assets
β βββ speaker-cone-bg.png # Background image for Home hero
β βββ fonts/ # Figtree TTFs (300/400/500/600/700) + figtree.css
β βββ icons/
β βββ icon.ico # Multi-size Windows icon (16β256 px)
β βββ icon.png # 512Γ512 app icon
β βββ tray.png # 32Γ32 tray icon (packaged as extraResource)
β
βββ main/ # Electron main process
β βββ main.js (736 lines) # App bootstrap, Chromium flags, nova-media:// protocol, autoUpdater, SMTC init
β βββ ipc.js (3007 lines) # All IPC handlers: library, playlists, settings, lyrics, cover art, SMTC, OTA, window controls, SQLite schema
β βββ fileScanner.js (173 lines) # Recursive fs.readdirSync scanner + fs.watch watcher with debounce
β βββ metadataReader.js (616 lines) # music-metadata wrapper, cover-art extraction + exhaustive sidecar search
β βββ smtc.js (194 lines) # Windows SMTC bridge (windows-media-controls native module + simulation fallback)
β βββ windowManager.js (134 lines) # WindowStateManager β persists position/size/maximized across sessions
β βββ preload.js (16 lines) # Exposes window.novaAPI = { invoke, on, send }
β
βββ renderer/ # Electron renderer process (the actual UI)
β βββ index.html (725 lines) # App shell: splash, titlebar, sidebar, content, lyrics panel, now-playing bar + overlay, lyrics editor modal
β βββ renderer.js (9503 lines) # All app logic: state, views, audio wiring, search, lyrics, playlists, EQ, settings, help
β β
β βββ audio/ # Web Audio engine
β β βββ AudioEngine.js (509 lines) # Web Audio graph, play/pause/seek/volume/boost, analyser data
β β βββ EQEngine.js (296 lines) # 10-band BiquadFilter chain + presets + headroom preamp
β β βββ Crossfader.js (262 lines) # Equal-power crossfade + gapless mode, full-graph secondary pipeline
β β βββ Visualizer.js (402 lines) # Canvas 2D bars / wave / circle visualizer
β β
β βββ services/ # Renderer-side services
β β βββ LyricsService.js (239 lines) # 5-tier lyrics fetcher with in-memory cache
β β βββ PlaylistManager.js (500 lines) # CRUD + M3U/PLS/XSPF/JSON encode/decode
β β βββ LibraryIndex.js (332 lines) # In-memory track index, search, albums/artists grouping
β β βββ MetadataService.js (119 lines) # Renderer-side metadata IPC wrapper
β β βββ SettingsService.js (181 lines) # Settings load/set with theme application
β β
β βββ ui/ # UI component classes (alternate scaffold β see Quirks below)
β β βββ Sidebar.js (332 lines) # Nav, search, playlist list, create/rename/delete dialogs, mobile menu
β β βββ LibraryView.js (394 lines) # Track-row rendering + scan-progress overlay
β β βββ LyricsPanel.js (276 lines) # Synced/plain lyrics display + auto-scroll
β β βββ NowPlayingOverlay.js(336 lines) # Full-screen overlay with blurred bg + particle animation
β β βββ PlayerControls.js (397 lines) # Bottom now-playing bar wiring + seek/volume/shuffle/repeat + keyboard shortcuts
β β
β βββ fonts/ # Outfit (300/400/500/600/700) + Figtree (300/400/500/600/700) TTFs
β β
β βββ styles/
β βββ main.css (5447 lines) # Primary stylesheet β dark Spotify-like theme, all components
β βββ outfit.css (40 lines) # @font-face for Outfit
β βββ figtree.css (40 lines) # @font-face for Figtree (loaded lazily via media="not all" trick)
β βββ components.css (empty) # Reserved for future component splits
β βββ overlay.css (empty) # Reserved for future overlay-only styles
β
βββ (generated at runtime)
βββ data/ (dev) or userData/ (prod)
βββ novatune.sqlite # SQLite DB (tracks, playlists, playlist_tracks)
βββ settings.json # Persisted settings
βββ window-state.json # Window position / size / maximized
βββ library.json # Legacy JSON library (auto-migrated to SQLite on first run)
βββ playlists/ # Legacy JSON playlists dir (auto-migrated)
βββ cached_covers/
βββ cover_<hash>.jpg # Large embedded cover art (>200 KB) extracted from tags
βββ thumbs/ # WebP thumbnails (per trackId and per path hash)
βββ collages/ # Playlist cover collages + .hash files for invalidation
| Module | Lines |
|---|---|
renderer/renderer.js |
9,503 |
renderer/styles/main.css |
5,447 |
main/ipc.js |
3,007 |
main/metadataReader.js |
616 |
renderer/audio/AudioEngine.js |
509 |
renderer/services/PlaylistManager.js |
500 |
renderer/audio/Visualizer.js |
402 |
renderer/ui/PlayerControls.js |
397 |
renderer/ui/LibraryView.js |
394 |
renderer/ui/NowPlayingOverlay.js |
336 |
renderer/ui/Sidebar.js |
332 |
renderer/services/LibraryIndex.js |
332 |
renderer/audio/EQEngine.js |
296 |
renderer/ui/LyricsPanel.js |
276 |
renderer/audio/Crossfader.js |
262 |
renderer/services/LyricsService.js |
239 |
main/smtc.js |
194 |
renderer/services/SettingsService.js |
181 |
main/fileScanner.js |
173 |
main/windowManager.js |
134 |
renderer/services/MetadataService.js |
119 |
main/main.js |
736 |
renderer/index.html |
725 |
main/preload.js |
16 |
| Total source | ~24,500 |
| Layer | Technology |
|---|---|
| Shell | Electron 28 |
| UI | Vanilla JS + custom HTML/CSS (no framework) |
| Audio | Web Audio API +MediaElementAudioSourceNode graph |
| Library | SQLite (better-sqlite3, WAL mode) |
| Metadata | music-metadata v8+ (ESM-only, dynamic import) |
| Cover art | sharp (WebP thumbnails), node-vibrant (palette extraction) |
| Lyrics | LRCLIB online API + embedded tags +.lrc sidecars |
| File watching | Nativefs.watch with debounce |
| Updates | electron-updater (GitHub Releases) |
| Windows integration | SMTC viawindows-media-controls (optional native module) |
| Tool | Purpose |
|---|---|
electron-builder |
NSIS Windows installer + portable build |
sharp (dev) |
Icon generation (make_icons.js) |
jest |
Test runner (referencedNovaTune.Tests/ directory) |
nodeIntegration: true(renderer canrequire())contextIsolation: falsesandbox: falsewebSecurity: true- Strict CSP in
index.html:default-src 'self', scripts'self' 'unsafe-inline', images allownova-media:,data:,blob:, plus iTunes / Deezer CDN hosts,connect-srcallowslrclib.net,itunes.apple.com,api.deezer.com. - All external links opened in system browser via
shell.openExternal. will-navigateblocks non-file://navigations.
- Node.js 18+ (LTS recommended)
- npm 9+
- Windows 10 or 11 (the app is Windows-only by design β
titleBarOverlay, SMTC, and WASAPI exclusive mode are Windows-specific)
git clone https://github.com/AnonymousV73X/WINDOWS-MUSIC-PLAYER.git NovaTune
cd NovaTune
npm install
npmRebuild: falseis set inelectron.config.js. The native modules (better-sqlite3,sharp) ship prebuilt binaries for Electron's Node ABI. If you switch Electron versions in dev, you may need to runnpx electron-rebuildmanually.
npm startDev mode:
- Uses
./data/for user data (production usesapp.getPath('userData')). - Opens DevTools in detached mode.
electron-updateris disabled (only runs inapp.isPackaged).- OTA update checks fall back to opening the GitHub Releases page in your browser.
npm run buildProduces dist/NovaTune-Setup-1.0.0.exe (NSIS installer).
npm run build:portableProduces dist/NovaTune-1.0.0-portable.exe β no installer, just double-click and play.
If you change the icon SVG, regenerate all icon formats:
node make_icons.jsThis produces assets/icons/icon.ico (multi-size 16β256 px), icon.png (512Γ512), and tray.png (32Γ32).
β οΈ Honest disclaimer from the developer.
NovaTune has only been tested on a 14-inch laptop. I have no idea how it'll look on a 13-inch screen at full screen. The responsive breakpoints are tuned around a 14β³ / 15β³ target.
My hope is that on a 13β³ screen at full-screen the layout holds together β the sidebar is wide enough, the album grid is dense enough, the squiggly bar is long enough β but I genuinely don't know. If you're on a 13β³ laptop and the app collapses into the compact (mobile-style) layout even when maximized, please tell me (see Contact the Developer) and I'll tune the breakpoints. The sidebar collapses to the hover-revealed icon strip below 950 px window width, so anything above that should keep the full sidebar visible.
If you'd like to help test on 13β³, 11β³, 16β³, 4K external monitors, or anything in between, screenshots and feedback are very welcome.
This is v1.0.0 β a few honest caveats:
- Crossfade is implemented but disabled by default. The
Crossfader.jsengine exists and works, but the renderer currently advances tracks viaplayNext()directly on theendedevent. ThecrossfadeDurationsetting defaults to0and there's no UI toggle to enable it yet. Gapless playback works fully. - Tray icon assets exist but no
Trayinstance is created.assets/icons/tray.pngis generated and packaged viaextraResources, but theTrayAPI is never called inmain/. This is a planned feature. chokidaris listed as a dependency but unused.FileScanneruses nativefs.watchwith debounce instead.thumbhashandwindows-media-controlsarerequire()d at runtime but not declared inpackage.json. They fall back gracefully if missing (ThumbHash generation is skipped; SMTC runs in simulation mode). If you want full functionality, install them:npm install thumbhash windows-media-controls.- Some settings are declared but unused:
miniPlayer,alwaysOnTop,outputDevice,languageare inDEFAULT_SETTINGSbut never read or surfaced in the UI. - The
renderer/ui/*.jsmodules exist as classes but the live app uses inline implementations inrenderer.js. These files are earlier refactors that were never wired in. They're kept for future componentization. renderer/styles/components.cssandrenderer/styles/overlay.cssare empty files. Reserved for future splits.npm testrunsjest NovaTune.Tests/but theNovaTune.Tests/directory doesn't exist in the repo yet.- M3U is written as
latin1for legacy Windows player compatibility. Non-ASCII filenames may corrupt. Use M3U8 (UTF-8) for non-ASCII libraries. - A zero-byte file named
s.includes(x)).join('sits in the project root β a broken shell redirect from early development. Safe to delete. download-fonts.jshas a hardcoded Windows path. It's a dev-only utility script, not used in the build.
The codebase is heavily annotated with REVFIX v1, REVFIX v2, CHANGES v1, CHANGES v2, BUGFIX v3 comments documenting multiple rounds of performance and correctness fixes (in-flight thumbnail dedup, protocol-cache LRU, thumbhash placeholders, crossfade graph fix, etc.). Read the header comments in main/main.js, main/ipc.js, and renderer/renderer.js for the full history.
Roughly in priority order:
- Wire up the crossfade UI toggle and connect
Crossfader.jsto the live renderer path. - Implement the system tray icon (assets are already in place).
- Move
renderer/ui/*.jsfrom scaffold to live (componentize the 9,500-linerenderer.js). - Add a
NovaTune.Tests/directory and write the first Jest tests. - Test and tune breakpoints for 13β³ laptops.
- Test and tune breakpoints for 4K external monitors (DPR > 1).
- Clean up unused settings (
miniPlayer,alwaysOnTop,outputDevice,language). - Add a tag editor (the metadata layer is already there β
MetadataService.js). - Add a folder blacklist (Oto Music's most-requested feature).
- macOS port (would require replacing SMTC with
nowPlayingInfoandtitleBarOverlaywith a custom traffic-light implementation).
If you have questions, feedback, feature requests, or run into any issues, the fastest way to reach me is WhatsApp. I typically respond within a few hours during business hours (East Africa Time). For bug reports, please include your NovaTune version and steps to reproduce the issue.
NovaTune stands on the shoulders of giants:
- Oto Music by Piyush Mamidwar β the inspiration. The proof that a local music player can be beautiful, free, ad-free, and feature-complete at the same time. Two million downloads and a 4.6-star rating, earned by one developer who cared. Thank you.
- LRCLIB β the open, free, no-API-key, no-profit synced-lyrics database that powers NovaTune's online lyrics. "Better than Musixmatch," per MusicBee forum users. If you find good lyrics, consider publishing back to LRCLIB so the next listener benefits.
- music-metadata by Borewit β the library that reads every tag format NovaTune encounters.
- better-sqlite3 β synchronous, fast, no-callback SQLite for Node.js. The library backend wouldn't be this fast without it.
- sharp β the image processing library that generates every thumbnail, collage, and icon in NovaTune.
- node-vibrant β the palette extractor behind Dynamic Accent.
- Electron β the framework that lets a web developer ship a native Windows app without learning Win32.
- Android Open Source Project β the
SquigglyProgressanimation that became NovaTune's signature UI element was originally ported from AOSP. - Every forum thread, Reddit post, and BleepingComputer user who documented a Windows Media Player bug β you proved this needed to exist.
License β see LICENSE for the full text.
Β© 2026 NovaTune. All rights reserved.
NovaTune v1.1.6 β’ Made with love for music lovers
If NovaTune brings you joy, star the repo and tell a friend.