Skip to content

Luniq v1.0.6

Latest

Choose a tag to compare

@saraansx saraansx released this 02 Jul 23:26

[1.0.6] - 2026-07-03

Added

  • Redesigned Create Playlist Modal: Overhauled the playlist creation and detail editing modal to adopt Spotify's side-by-side layout, positioning the artwork picker as a left column next to the stacked text input and description fields on the right. Simplified aesthetics by removing redundant input labels and changing the "ADD ARTWORK" label to a normal-cased "Choose photo" placeholder across all 21 translation files.
  • Weblate Translation Integration: Configured and integrated Weblate translation setup, registered translation instructions guidelines for translators, and unlocked automated pushing back to GitHub using authentication tokens.
  • Tamil Language Support: Added full Tamil translation (ta.json) and registered it in the i18n module and application settings language selection dropdown.
  • Discord Rich Presence Activity Button: Added an "🎧 Play on Luniq" button linking to the GitHub repository, allowing friends on Discord to see what you are listening to and download the Luniq app.
  • Command-Line Lyrics Test Suite: Added a dedicated CLI script scripts/test_lyrics.ts to test and verify all registered lyrics providers directly, including native Spotify credentials extraction.
  • YouLyPlus Lyrics Provider: Integrated the YouLyPlus engine, cascading requests across 5 mirror servers with support for XML-based TTML parsing and raw LRC fallback synchronization.
  • Multitasked Parallel Racing: Overhauled lyricshelper.ts to race lyric retrieval requests in parallel, returning single-line timed reports identifying the winning provider.
  • Paxsenix Cascading Fallbacks: Re-implemented the Paxsenix provider to cascade queries sequentially through Apple Music, NetEase, Spotify, Musixmatch, and YouTube mirror API endpoints.
  • KuGou Duration & Keyword Matching: Upgraded KuGou provider to filter candidates by duration tolerance and fall back to direct keyword metadata search queries.
  • LRCLib Similarity Matching: Implemented Levenshtein distance string similarity scoring and duration verification inside the LRCLib search handler.
  • Unison Database Search: Upgraded Unison provider to fall back to /lyrics/search to retrieve candidate summaries and resolve full entries by ID.
  • Programmatic Deprecation Suppression: Added an early interceptor in the Electron boot shim to silence the Node.js punycode deprecation warning before dependency load.
  • Local HTTP Stream Proxy: Implemented a local HTTP media streaming proxy in Electron that intercepts chunk requests, dynamically sets client-specific User-Agents, and routes stream data cleanly using Node's HTTP/1.1 fetch stack to bypass Chromium's HTTP/2 restriction.
  • Proxy connection auto-abort: Tied an AbortController to the proxy's client connection close events, preventing background fetch threads from hanging or wasting bandwidth when seeking or skipping tracks.
  • Spotify History Sync (GQL): The app now automatically syncs your remote Spotify "Recently Played" history into the Queue's History tab using GraphQL, intelligently parsing and mapping Context items into tracks without hitting strict REST API rate limits (HTTP 429).
  • Audio Engine Selector: Added a dropdown in Playback settings to switch between youtubei.js and yt-dlp audio backends. The selected engine is persisted and applied to streaming, downloads, and cache clearing.
  • Dual Engine Instantiation: Both youtubei.js and yt-dlp engines are created at startup. The active engine is resolved on each stream/download request, so switching does not require an app restart.
  • Engine Change Logs: Console logs now report audio engine changes in both the renderer ([Audio Engine] Switched to: ...) and main process ([Audio Engine] Active engine: ...).
  • Automatic Engine Fallback: If the selected audio engine fails to resolve a stream or download, the app automatically retries with the opposite engine before giving up.
  • Increased Prefetch Count: The stream prefetcher now fetches the next 2 upcoming tracks in the background instead of 1, improving gapless playback reliability.
  • New Audio Engine (youtubei.js): Replaced the previous stream resolver with a fully native youtubei.js-powered audio engine. No external binaries required for stream resolution — faster, cleaner, and more reliable.
  • YouTube + Spotify Integrated Universal Search: Search now queries both YouTube Music and Spotify simultaneously, merging results into a single unified view with deduplication.
  • Smarter Track Matching: The audio engine now selects the best YouTube video for a track using a multi-factor scoring system — tokenized title/artist coverage checks, strict duration filtering, and a weighted scoring system. No more accidental covers, karaoke, or wrong versions.
  • Extended Client Fallback Chain: Stream resolution now attempts multiple YouTube clients in order before giving up: TV → IOS → IOS_MUSIC → ANDROID → ANDROID_MUSIC → ANDROID_VR → TVHTML5 → WEB_REMIX → WEB → DEFAULT. Drastically reduces playback failures.
  • Explicit Opus Preference: The youtubei.js engine now selects the Opus codec first within WEBM audio formats, falling back to AAC only if Opus is unavailable. The yt-dlp engine also prefers Opus-bearing WEBM streams.
  • Last Successful Client Memory: The youtubei.js engine now remembers which YouTube client successfully resolved a video and tries that client first on the next fetch, speeding up repeat plays and skips.
  • Smarter Stream URL Caching: Stream URLs are now cached until their real expire= timestamp (minus a 60-second safety margin) instead of a fixed 30-minute TTL, preventing playback failures from stale URLs.
  • Playback Error Recovery: When a stream fails with MEDIA_ELEMENT_ERROR, the player now invalidates that track's cached URL, fetches a fresh URL, and automatically tries the fallback audio engine (yt-dlpyoutubei.js) before skipping.
  • One-Retry Guard: A per-track retry guard prevents infinite error loops — if recovery fails once, the track is skipped.
  • Stream URL HEAD Validation: Before returning a stream URL, the main process sends a HEAD request to verify it responds with 2xx. If it returns 403/404/410, the URL is rejected and the next engine/client is tried.
  • Per-Track Cache Invalidation: New invalidate-stream-cache IPC handler clears the cached stream URL for a specific track across both audio engines.
  • Autoplay Queue UI: Queue panel now shows a dedicated "Next in Autoplay" section below the regular queue (Spotify-style), with a live loading indicator while the radio pool is being filled.
  • Playlist Creation Options: Clicking the Add (+) icon in the Sidebar now reveals a dropdown menu to choose between "Create local playlist" and "Create spotify playlist".

Changed

  • App Rebranding: The entire application and all assets have been globally rebranded from Lune to Luniq.
  • Spotify Hash Registry Updates: Synced internal GraphQL hashes with the new Spotify version 2 registry and deprecated the legacy fetchSeedSuggestions radio fallback.
  • Splash Screen Polish: Tightened the letter spacing of the LUNIQ splash screen logo for a sleeker aesthetic.
  • Console Log Cleanup & Optimization: Consolidated multiple settings and lyrics helper messages into single-line summaries, silenced redundant WebRequest HTTP 404/401 error response logs from parallel fallback engines, and removed React's StrictMode wrapper from the main React bootstrapper to eliminate double-render log spams in development console.
  • Homepage Feed Optimization: Filtered out podcast episode sections ("Episodes you might like"), show recommendations, and audiobook items from the Spotify home feed to ensure a 100% music-focused layout.
  • Home Screen Cleanup: Hid the "Recently played" section from the main Home page browse grid, as it's now properly integrated into the Queue History tab.
  • Login UI Polish: Refined the "Connect with Spotify" button on the Login page. Replaced the older dark green icon with Spotify's modern lighter green (#1ed760) and added a subtle, soft drop-shadow for better contrast against dark backgrounds.
  • Login Localization: Updated the Spotify connection prompt from "Continue with Spotify" to "Connect with Spotify" across all 20 supported languages.
  • Reliable yt-dlp Updater: Completely rewrote the yt-dlp update mechanism. The app now directly queries the official GitHub API on every launch and downloads the newest binary release automatically, completely bypassing unreliable native updater commands.
  • Cleaner Error Logging: Silenced massive error stack traces in the console when yt-dlp is missing or when cache clears fail during a background download.
  • Cache Invalidation Alignment: youtubei.js and yt-dlp cache invalidation now targets the correct webm cache key, matching the engines' internal behavior.
  • Default Audio Quality: Increased the default audio streaming and download quality for new installations to 320 kbps (previously 256 kbps and 128 kbps).
  • Dynamic Home Greeting: The Home page greeting now dynamically adjusts based on the local time (Good Morning/Afternoon/Evening) and includes the connected user's Spotify display name.
  • Standardized Menus: Unified the design of all dropdown and context menus across the app (Equalizer, 3-dots, Sleep Timer, Sidebar context menus) to use a consistent solid dark #181818 background theme.

Fixed

  • Fixed Audio Output Device Selection: Fixed an issue where changing the playback device in Luniq settings did not route audio correctly and kept playing to the default system device. Since the audio is routed through a Web Audio API graph (for EQ, Mono, and Volume Normalization), the device must be applied to both the AudioContext destination node and the HTML <audio> node.

  • Fixed Paxsenix Duration Filtering: Added duration-string format support to the Paxsenix Spotify and YouTube search reducers to prevent duration-tolerance mismatches when parsing non-millisecond duration values.

  • Fixed Anonymous Google Video Range Block: Resolved the issue where Google Video Server rejected offset range requests past 1MB with a 403 Forbidden for anonymous clients. Prioritized the "ANDROID_VR" client, which natively supports offset range requests past 1MB without requiring cookies or active session verification.

  • Suppressed Chromium Media Encoder Errors: Appended the 'log-level' switch (set to '3') on Electron startup to fully suppress internal Chromium-native D3D device encoder error logs (0xC00D6D76) from the developer console.

  • Fixed console-message Deprecation Warning: Updated the 'console-message' webContents event listener structure to conform to Electron 30+, eliminating compiler type conflicts and console deprecation warnings.

  • Fixed Taskbar Controls Display: The Windows taskbar thumbnail controls (Play/Pause/Skip) are now properly hidden on the Login and Home pages, and will only appear when a track is actively loaded into the player.

  • Fixed 403 Forbidden Playback Skips: Completely resolved an issue where YouTube streams would skip with a 403 error during playback. youtubei.js and yt-dlp now embed their exact client type and precise User-Agent string into the stream URLs they generate, allowing the main process interceptor to accurately spoof the exact User-Agent YouTube's poToken anti-bot system expects for that specific client.

  • Fixed Radio Track Suggestions: Replaced the broken internal radio-apollo GraphQL implementation with a reliable REST API (api.spotify.com/v1/recommendations) fallback. Radio stations and infinite playback now fetch suggestions perfectly again.

  • Autoplay Queue Persistence: The "Next in Autoplay" pool is now saved to local storage and restored on app restart. Previously it was lost every time the app closed.

  • Lyrics Auto-Scroll Dragging Header: Fixed a bug where the lyrics auto-scroll would pull the album art, track name, and close button upward along with the lyrics. Replaced scrollIntoView (which could scroll the whole overlay) with a scoped scrollTo call on the lyrics content container only.

  • yt-dlp Binary Update Failure: Fixed a bug where yt-dlp.exe could not update in production builds because it was locked inside the read-only .asar package. The binary is now correctly migrated to the user's local AppData directory upon launch, granting it full permissions to overwrite itself.

  • Build Configuration Schema: Suppressed false-positive IDE schema warnings in electron-builder.json by removing the outdated schema URL.

  • Type Declaration Missing: Restored Vite's client typings (/// <reference types="vite/client" />) in vite-env.d.ts to fix missing module errors for image assets in the IDE.

  • Spotify Auth Popup Improvements: The Spotify sign-in popup now displays the correct Luniq app icon and title. The flow also bypasses the "Download Spotify" trap page by instantly detecting the auth cookie upon a successful login or signup and closing automatically.

  • Enabled Google Social Sign-In & Session Isolation: Configured the login window to spoof a standard Firefox User-Agent, bypassing Google's WebView security blocks. Also isolated the login session using dynamic, in-memory partitions, ensuring that failed or incorrect social logins (e.g. choosing a Google account not linked to Spotify) clear immediately, allowing users to try a different account without getting stuck on cached cookies.

  • Fixed yt-dlp PyInstaller Extraction Errors: Added a startup cleanup script that automatically deletes stale _MEI folders left behind by yt-dlp in the system's temporary directory. This prevents the return code -3 extraction failure caused by lingering files or corrupted temp caches.

  • Fixed Auto-Skip on Re-Play: Fixed a bug where clicking "Play" on a track that was already in the process of loading would mistakenly cancel the ongoing stream request, causing a stream error and forcing the player to auto-skip to the next song.

  • Log Simplification & Cleanup: Silenced verbose InnerTube decipher, resolution, and prefetch logs in favor of single-line timing summaries. Removed emojis from all system log entries to improve readability.

Security

  • yt-dlp Binary Integrity Verification: Added SHA256 verification for every yt-dlp.exe download. Before writing the binary to disk, the app fetches the official SHA2-256SUMS file from the yt-dlp GitHub release, computes the hash of the downloaded file, and rejects it if they don't match. This blocks supply chain attacks where the binary is tampered during download.
  • Postinstall Integrity Check: Added a postinstall script (scripts/verify-yt-dlp.mjs) that runs after npm install. It verifies the downloaded yt-dlp.exe against the official SHA256 checksums and automatically re-downloads the correct version if a mismatch is detected.