cucadmuh a63ba3c9cb fix(cover-backfill): kill idle CPU spin and offline-cache menu re-walks (#943)
* fix(cover-backfill): snapshot-diff worklist and live-tunable parallelism

Aggressive cover backfill pegged one tokio worker at ~100% on large,
fully-synced libraries while the download queues stayed empty.

- Take two snapshots once per pass — the DB catalog (single GROUP BY) and
  the on-disk cover bucket (one directory walk) — and download the
  set-difference. No per-row `stat` syscalls and no re-scan loop; the empty
  cache case (heavy backfill) costs zero per-item disk hits.
- Replace the front-loaded enumeration with a producer/consumer pipeline:
  the producer streams the catalog in chunks and feeds misses into a bounded
  channel; a fixed consumer pool keeps the download/encode pools saturated.
- Make cover backfill parallelism runtime-tunable from the Performance Probe
  (threads slider + "Run full pass now"); HTTP download and CPU encode
  semaphores resize live. Not surfaced in app settings.
- Add a "nothing changed" idle gate (catalog signature) so a settled pass is
  not re-run on every library:sync-idle, mirroring the analysis worker.
- Cancel promptly on switch to lazy: consumers bail on enabled/focus change
  and the producer feeds via try_send so a full channel cannot deadlock.
- Drop the per-item recursive disk walk from the ensure hot path.

* fix(cover-backfill): cheap idle gate, settle on 404s, transient retries

Follow-up to the snapshot-diff backfill: stop the periodic CPU spikes and the
89%-plateau wake storm on libraries whose covers can never reach 100%.

- Idle gate is now disk-free: compare only the catalog COUNT(DISTINCT) instead
  of walking ~all cover dirs on every sync-idle. "Did the server change?" never
  touches the filesystem. Clear-cache commands re-arm the gate (rearm_idle_gate)
  since a clear leaves the catalog total unchanged, and the settings UI wakes the
  active server after a clear.
- Settle the gate on any completed pass regardless of pending: remaining items
  are unfetchable-for-now (404), so the wake/sync-idle storm stops once the
  fetchable set is exhausted.
- Stop auto-clearing .fetch-failed markers every pass (it defeated the 30-min
  backoff and re-attempted 404s forever). The manual "Run full pass now" sends
  force=true to clear them and retry; wake/sync-idle/configure stay opportunistic.
- Rate-limit sync-idle passes (60s cooldown) as defence against chatty syncs.
- Retry cover downloads up to 3x with backoff on transient failures (5xx / 429 /
  network), but never on a real 4xx so missing covers don't hammer the server.

* fix(cover-cache): stop re-walking cover dirs from offline & cache menu

The settings cover-cache section polled disk usage + progress every 15s for
every server, each call doing a full recursive walk of the per-server cover
directory. On a fully populated cache this caused periodic CPU spikes whenever
that menu was open.

- mod.rs: add a 10s TTL memo around the per-server cover dir walk
  (cached_dir_usage_for_server), shared by cover_cache_stats_server and
  library_cover_progress; invalidate on clear (per-server and clear-all).
- CoverCacheStrategySection: recompute on entry only; rely on the
  cover:library-progress and cover:cache-cleared events for live updates;
  drop the per-cover cover:tier-ready refresh storm; turn the 15s loop into a
  5-minute safety net.

* fix(cover-backfill): keep emitting progress during the whole pass

The producer finishes enumerating the worklist long before the consumer pool
finishes downloading it, so progress was only emitted while feeding the channel
— the "offline & cache" menu and overlay then froze through the entire drain
phase. Replace the per-chunk emit with a 3s progress ticker that runs for the
lifetime of the pass and is aborted once the consumers drain (final accurate
emit still happens at settle).

* docs(changelog): record cover-backfill idle-CPU fix (PR #943)

Add [1.47.0] Fixed + Changed entries and a settingsCredits line for the
cover-backfill idle CPU / offline & cache menu work.
2026-06-02 04:56:34 +03:00
2026-05-07 13:11:22 +02:00

Psysonic Logo

A modern desktop client for self-hosted music libraries

Fast. Native. Beautiful. Built for people who actually care about their music collection.

Psysonic is built primarily for Navidrome and also works with Gonic, Airsonic, LMS and other Subsonic-compatible servers, depending on the features supported by your server.


Latest Release GitHub Stars License GPLv3 Tauri v2

Discord Community Telegram Community Support Psysonic on Ko-fi

AUR psysonic AUR psysonic-bin Cachix



Available languages: English, German, Spanish, French, Norwegian Bokmål, Dutch, Romanian, Russian and Chinese.

More translations are added over time.

No telemetry • Native performance • Navidrome-first • Community driven


Psysonic Screenshot


Warning

Psysonic is under active development. Bugs and rough edges can happen, and features may change as the project evolves.

What is Psysonic?

Psysonic is a desktop music client for self-hosted music libraries. It is designed for people who want the freedom of their own server without giving up the comfort, polish and speed of a modern music app.

It is built with Rust, Tauri v2 and React, with a strong focus on responsiveness, customization, practical music-library workflows and a user interface that does not require a manual before you can press play.

Psysonic is optimized first and foremost for Navidrome. Other Subsonic-compatible servers can work well too, but advanced features may depend on server-side support.


Highlights

Playback & Queue

  • Gapless playback
  • Crossfade
  • ReplayGain support
  • LUFS-based Smart Loudness Normalization
  • AudioMuse-AI support
  • Infinite Queue
  • Smart Radio sessions
  • Fast and responsive playback handling
  • Low memory usage compared to heavy web-first clients

Audio Tools

  • 10-band Equalizer
  • Equalizer presets
  • AutoEQ headphone correction
  • Per-device optimization
  • Loudness-aware playback options

Library Management

  • Fast search across large libraries
  • Albums, artists, tracks and genres
  • Ratings support
  • Multi-select bulk actions
  • Drag & drop playlist management
  • Smart Playlists
  • Built for large self-hosted collections

Lyrics & Discovery

  • Synced lyrics with seek support
  • Lyrics provider support: YouLy+, LRCLIB and NetEase
  • Auto-scrolling sidebar lyrics
  • Fullscreen lyric mode
  • Last.fm scrobbling
  • Similar artists
  • Loved tracks and listening stats

Sharing & Social Listening

  • Magic Strings sharing:

    • share albums, artists and queues
    • Navidrome user management helpers
    • fast account sharing
  • Orbit shared listening sessions:

    • host-controlled synchronized playback
    • session invites via link
    • guest song suggestions
    • real-time queue interaction

Personalization & Accessibility

  • Large theme collection
  • Catppuccin and Nord inspired styles
  • Glassmorphism effects
  • Font customization
  • Zoom controls
  • Keybind remapping
  • Theme Scheduler for automatic day/night switching
  • Colorblind-friendly theme options
  • Keyboard-friendly navigation

Power User Extras

  • CLI controls
  • USB / portable sync
  • Backup and restore settings
  • In-app auto updater
  • LAN / remote auto switching

Shared listening feature banner

Orbit brings synchronized shared listening sessions directly into Psysonic.

Start a session, invite others with a link and listen together with host-controlled playback, shared queue interaction and guest song suggestions. It is built for real-world music sharing without turning your self-hosted setup into a social-media circus.


Platforms

OS Support
Windows Native installer
macOS Signed DMG
Linux AppImage / DEB / RPM / AUR (psysonic, psysonic-bin) / NixOS

Install

Linux

curl -fsSL https://raw.githubusercontent.com/Psychotoxical/psysonic/main/scripts/install.sh | sudo bash

Linux builds are also available through GitHub Releases, AUR and Cachix/Nix.

AppImage runs under X11/XWayland — it pins GDK_BACKEND=x11 for a stable WebKitGTK stack. For a native-Wayland launch, use the .deb, .rpm, AUR, or Nix packages, which follow your session's display server.

Windows

Download the latest installer from the GitHub Releases.

macOS

Download the signed DMG from the GitHub Releases.


Development

Contributor expectations (PRs, CI, Tauri boundary, UI): CONTRIBUTING.md.

git clone https://github.com/Psychotoxical/psysonic.git
cd psysonic
npm install
npm run tauri:dev

Build release:

npm run tauri:build

Privacy

Psysonic is built for self-hosted music collections. Your library is yours.

  • No telemetry
  • No spyware nonsense
  • No analytics harvesting
  • No hidden tracking

See TELEMETRY.md for the telemetry stance and PRIVACY.md for how each opt-in integration handles data.


Community & Support

Join the community, report bugs, suggest features, share themes and help shape the future of Psysonic.


License

Psysonic is licensed under the GNU GPL v3.0.


Forks and Attribution

Psysonic is free and open-source software under the GPLv3. You are welcome to fork it, modify it and build upon it under the terms of the license.

If you publish a modified or rebranded version, please make it clear that your project is based on Psysonic and preserve proper attribution to the original project.

That is not about preventing forks. Forks are part of open source. It is about being honest with users and contributors about where the work comes from.

Features, design work and implementation ideas developed in Psysonic should not be presented as unrelated original work in downstream projects.


Own your music. Enjoy the client too.

Psysonic brings a modern desktop experience to self-hosted music libraries.

Languages
TypeScript 69.9%
Rust 24.9%
CSS 4.3%
JavaScript 0.5%
Shell 0.3%