Add slskd provider, Navidrome playlist sync, library paths, and queue UX#182
Add slskd provider, Navidrome playlist sync, library paths, and queue UX#182dx616b wants to merge 59 commits into
Conversation
Route video-id resolution through the configured audio_providers order and add robust YouTube/YouTube Music fallback matching so UI provider selection is applied consistently at runtime. Co-authored-by: Cursor <cursoragent@cursor.com>
Add slskd provider with leave-in-place, track dedupe, and timeouts; fix library/M3U path resolution for /slskd mounts; sync Navidrome playlists in place after incremental scan; improve matching and YouTube fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
Add slskd/Navidrome configuration guide, docker-compose.example.yml for dx616b/spoti-to-navidrome:2.7.7, and compose quick-start in the README. Co-authored-by: Cursor <cursoragent@cursor.com>
Add status filters and per-track or bulk retry on the queue page, clear completed jobs, and drop finished tracks when a new Spotify playlist starts while keeping failures and in-progress work. Co-authored-by: Cursor <cursoragent@cursor.com>
Bump version and refresh production dist for Docker image publish. Co-authored-by: Cursor <cursoragent@cursor.com>
Use downloadSaveName() so queue and library saves use real filenames instead of URL-encoded path segments from /media/ URLs. Co-authored-by: Cursor <cursoragent@cursor.com>
Point docker-compose.example and README quick-start at ghcr.io instead of fork-specific publish tags. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep jobs queued until a parallel slot is acquired; simplify queue filters and audio-source hint copy. Co-authored-by: Cursor <cursoragent@cursor.com>
In progress covers active work (provider search and download); Waiting is only tracks not started yet. Show search progress in the UI. Co-authored-by: Cursor <cursoragent@cursor.com>
Allow up to max_parallel_downloads concurrent slskd search/enqueue operations and wait for transfers outside the lock so playlist jobs are not serialized on Soulseek. Co-authored-by: Cursor <cursoragent@cursor.com>
Refresh slskd semaphore and downloader slskd_settings on max_parallel save so the UI limit applies without a separate slskd settings save. Co-authored-by: Cursor <cursoragent@cursor.com>
slskd caps concurrent Soulseek searches; high Downtify parallel mostly queues or fails without faster transfers. Co-authored-by: Cursor <cursoragent@cursor.com>
Settings path and cookies.txt upload fix age-restricted and sign-in errors; env DOWNTIFY_COOKIES_* remains as fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
FastAPI multipart routes require this package at import time. Co-authored-by: Cursor <cursoragent@cursor.com>
When cookies are configured, prefer the main YouTube URL and web player client; fall back from music.youtube.com on age-restriction errors. Co-authored-by: Cursor <cursoragent@cursor.com>
Broadcast provider over WebSocket, keep progress text when work starts, and label YouTube Music / YouTube steps like slskd. Co-authored-by: Cursor <cursoragent@cursor.com>
Wire PO tokens into extractor args and fall back through broader audio format chains before failing a YouTube download. Co-authored-by: Cursor <cursoragent@cursor.com>
…dio. Cookies force web clients that often return SABR-only/image formats; fall back to ios/android without cookies. Use web_safari for cookie profile only. Co-authored-by: Cursor <cursoragent@cursor.com>
When multiple matching files exist for one query, enqueue and wait on each in order until one completes or download_attempts is exhausted. Co-authored-by: Cursor <cursoragent@cursor.com>
Validate login cookies on upload/settings, drop web_creator for cookie clients, retry up to five ytsearch results when age-gate or format fails, and surface weak-cookie warnings in Settings. Co-authored-by: Cursor <cursoragent@cursor.com>
Refresh M3U and Navidrome when deleting from Library; fix invalidate_library_paths_cache imports; prune stale rows and always invalidate path cache on reconcile. Co-authored-by: Cursor <cursoragent@cursor.com>
Drop docker-hub-fork workflow, docker-compose.dockerhub.yml, and docker-push script; keep fork image publishing local/manual only. Co-authored-by: Cursor <cursoragent@cursor.com>
Library UI supports multi-select track delete and full playlist delete with shared backend cleanup. Skip Navidrome library scan after deletes and reconcile; sync playlists via API only. Validate Navidrome rows by comparing Spotify playlist metadata to mutagen file tags instead of filename parsing. Fix queue polling stuck state and rebuild frontend dist. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Hi — quick note on the size of this PR. I know there are a lot of changes here. I built and tested everything freehand in my fork (dx616b/downtify) the way I actually use Downtify day to day, not as a chain of small theoretical PRs. The diff is large on purpose: slskd paths, library catalog, Navidrome sync, queue UX, batch delete, and related fixes grew together in real use. This branch is my working “how I would like it” snapshot. Happy to refactor or split follow-ups if you prefer a different shape for upstream. |
|
Hi @dx616b! I don't see a problem with the size of the PR, and thank you very much for your contribution. It's great that you're testing everything manually; I think that's very important. I'll also manually test the new features as soon as possible; I've already verified that the existing features in Downtify continue to work perfectly. Due to my other activities, I don't think I'll be able to test everything today, but I want to test it by Sunday. As for the changes, we can keep them in this single PR. |
Hi, it's my pleasure. It's such a great app. Ok then I will push one or two small fixes regarding logs and quality of slskd findings. |
- Add shared DownloadParallelLimiter so settings changes do not reset in-flight slots - Register batch tracks with playlist context; raise NoAudioMatchError when YouTube is exhausted - Add track_tag_match for mix-variant last resort, probe-based verify, and duration tolerance - Align strict duration caps; slskd holds semaphore through transfer and fixes mix import - Default download_attempts to 5 and ffmpeg threads to 4 - SQLite WAL helpers, library cache/index fixes, Navidrome and catalog updates - Player/Downloads UI: bulk delete, autoplay, queue progress, mobile layout and safe areas - Tests for download pool, track tag match, downloader, and slskd responses Co-authored-by: Cursor <cursoragent@cursor.com>
- Auto-fix import order and unused imports; noqa PLR0914 on heavy download paths - Add Path import and named discard helper in slskd test - Format Downloads.vue and Player.vue for prettier_action Co-authored-by: Cursor <cursoragent@cursor.com>
…nloads. Spotify playlist URLs open in search with correct Open on Spotify links; navbar search and a clean compact bar replace in-field action circles. Player queue and playlist filter persist across routes; M3U/Navidrome playlists refresh when retries succeed. Local make run builds and serves frontend/dist from the repo. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
In-progress tab now includes queued tracks so a new playlist batch is not hidden behind stale failures; retry Spotify embed fetches on transient HTTP errors with quieter reconcile logging. Co-authored-by: Cursor <cursoragent@cursor.com>
Share live/karaoke/spam checks via remote_text_unacceptable for YouTube, yt-dlp, and slskd; default duration tolerance to 15%; persist missing settings keys to settings.json on load; fix queue tab on new downloads. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Stop auto-switching to Failed after playlist prune leaves only old failures; switch to In progress when pending work is added instead. Co-authored-by: Cursor <cursoragent@cursor.com>
Make queue item updates reactive, re-queue existing failed tracks on batch submit, sync from server after batch POST, and show waiting tracks under In progress so the tab populates immediately. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep reactive queue updates but switch to Waiting when a new batch queues tracks, and to In progress when downloads actually start. Co-authored-by: Cursor <cursoragent@cursor.com>
Stay on In progress when new work is queued; show a hint when that tab is empty but tracks are waiting on the Waiting tab. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Destructure downloadQueue for proper Vue reactivity, bump queueVersion on changes, poll while the queue view is open, and sync after batch queueing. Co-authored-by: Cursor <cursoragent@cursor.com>
Track playlist batches against cached Spotify metadata, surface incomplete playlists on Search with delete/download-missing actions, allow Extended Mix YouTube matches when duration fits, and poll in-progress rows every 5s so counts update during queue runs. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Hey, I think i have done whatever i had in mind as addition to this app (which fulfills what I thought would make this more complete). Hopefully i have not drifted much from your initial idea. |
|
I freaking love u guys. As a broke college student lol, Downtify has been so amazing for me. Everything's been great, truly. Only things I wish I could enable is deleteing songs that also get dropped from the Spotify album. I discovered and used an open source de-duplicator website (spotify-dedup) earlier today and found around 700-1000 duplicate songs between all my playlists that I track😭😭. Even with 8 parallel downloads, took several days of downloading to get all my songs done but after I discovered the deduplicator and removed sooo many duplicate songs that got abandonded (not in playlist but file still exists downloaded on the drive) I will most likely have to delete everything and redownload the playlists since there were so many duplicates spread out across so many different albums. I understand that is on me though to not have checked my albums before adding them to downtify to be watched. Additionally, soulseek network does seem to have better quality going up and well above 320kbs and better artwork resolution (current downloads are all 300*300px which does look blurry on a lot of phones nowadays with big screens (aka typical pro/plus/ultra model iphones/androids). Occasionally ytmusic does download the wrong song files for certain songs so even with the correct spotify name and artists for a song, the song file itself will be off.
Unfortunately I'm still very new to self-hosting, linux, dockers, github and all that so it takes me a long time between troubleshooting, online guides, forums, etc. to figure out how to get stuff up and running even with ZimaOS (Downtify being in the app store was an absolute godsend, thank you so much for that!) But I do not want to give up. Frankly I have spent half a month of all nighters/days of my summer break now messing around with my "server" and should've given up a long time ago but I refuse to and will continue and will keep trying to figure out the problems. Also I apologize if this comes off as rude or demanding in any way possible😭 I truly have no intention of that, I'm just fairly bad at wording out the thoughts in my head. I also am still unfamiliar with all the github terminology and how to use and navigate this website so I'm not fully sure if this is the correct forum/channel to post this in. I truly love this project and love u guys and the team for putting in the work that has gone into Downtify to make it as awesome as it is and helping us newbies get away from spotify and learn about selfhosting. I also want to help in anyway possible if I can. I'm not a cs major unfortunately so don't know much about coding and software outside of chatgpt. But I do have a chat gpt plus plan split between a couple other friends if you need help with iterating and stuff with chat but the daily limits get in the way please let me know and I can help. I am a Mechanical engineering major so can do 3d modelling, CAD, 3d printing, matlab, and similar stuff, which is probably not so helpful when it comes to making software, but if there is anything like that I can help with in that aspect, please let me know and I'll gladly help! I also have decent experience and troubleshooting knowledge about windows and macOS, but I'm guessing everyone on the team probably already has that too lol, but if there are ways I can help, do testing, feedback, hunt for bugs, help with UI, mess around with how it behaves on zimaOS (still a version of linux I think), reacts to changes, etc. please let me know! I also tried to find a discord and couldn't on the downtify website or on the gitbuh here and was wondering if there was a way to connect with the downtify community to help one another get it up and going, help with file pathing, to answer q/a's, or provide feedback that way? Thank you again! |
on this PR you will not re-download the same tracks, but just point them to different playlists. Soulseek is supported with good filtering. give it a try using this image: dx616b/spoti-to-navidrome:latest which is the one from my fork (this PR) |
Auto-remove wrong on-disk audio during playlist refresh and Navidrome sync when embedded tags disagree with Spotify. Rebuild the full playlist catalog from library on partial batches so M3U/Navidrome stay complete. Co-authored-by: Cursor <cursoragent@cursor.com>
Document slskd/Navidrome catalog work, tag-mismatch cleanup, queue/player improvements, and dx616b/spoti-to-navidrome as the fork quick-start image. Co-authored-by: Cursor <cursoragent@cursor.com>

Summary
This PR adds optional Soulseek downloads via slskd, Navidrome playlist sync (Subsonic API), a global Spotify track index to skip re-downloads, improved library/M3U path handling for
/downloadsand/slskd, and a more usable download queue (filters, retry, playlist pruning).Developed and tested in a fork (dx616b/downtify); happy to split into smaller PRs if preferred.
Note from contributor
I know this PR touches a lot of files. I built and tested it freehand in my own fork the way I actually run Downtify day to day—not as a stack of tiny theoretical PRs. The diff is large on purpose because the features (slskd paths, library catalog, Navidrome sync, queue UX, batch delete) grew together in real use. I am happy to refactor or split follow-ups if you prefer a different shape for upstream; this branch is my working “how I want it” snapshot.
Audio providers
/slskd(no copy into/downloads)Navidrome
Library & playlists
library_pathsresolvesslskd/…stored paths for player, M3U, and Navidrome matching/downloads/…,/slskd/…)/media/slskd/…Download queue (UI)
downloadSaveName()decodes URL-encoded filenames)Docs & compose
docker-compose.example.ymlwith/downloads,/slskd, and/datavolumesTest plan
/slskdand M3U paths%20)pytest(new tests for slskd, navidrome, library_paths, queue API, track index)Made with Cursor