Download tracks and albums (#35) - #254
Merged
Merged
Conversation
…album ZIP (refs #35) /rest/download is no longer a stream alias. Per Navidrome/Subsonic spec it returns original bytes (transcode params ignored) with Content-Disposition: attachment. Track id (t…) → single file named from metadata; album id (al…) → streaming ZIP (yazl, stored entries, sequential upstream fetches) of the best release's tracks. Peer-sourced tracks proxy raw via /federation/stream. SPA: album-header Download pill + per-track hover download link (#35). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Q3riZ78G26ohMgPDh8F7u
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements #35 — download buttons for tracks and whole albums, matching Navidrome's download semantics. Closes #35.
Backend
/rest/downloadis no longer an alias forstream(hub/src/routes/subsonic/download.ts). Per the Subsonic spec it now returns the original media bytes —format/maxBitRateare ignored — withContent-Disposition: attachment.t…) → single file, namedArtist - Title.ext(RFC 6266 ASCII fallback + UTF-8filename*; extension from the preferred source's format, content-type fallback).al…) → streaming ZIP namedArtist - Album.zipwithNN - Title.extentries (D-NNwhen multi-disc). Entries are stored, not deflated (audio doesn't compress; keeps the response streaming). Upstream fetches are sequential — one open connection to Navidrome/a peer at a time. Tracks whose source fails are skipped with a warning so the ZIP stays valid./federation/streamwith the same merge-time preferred-source selection as streaming. No federation contract change./rest/streamonly, Phase 4: eliminate stream-relay; Player hands devices Hub Subsonic stream URLs #218).yazl(+ types).Frontend
downloadUrl()helper inlib/subsonic.ts(authed URL, no transcode params).Tests
hub/test/download.test.ts: filename-helper units, 400/404 cases, track download (attachment header, raw upstream fetch asserted via capturing fake Navidrome), album ZIP (signatures, entry names, stored bytes).stream.test.ts.downloadUrlunit tests + ReleaseGroupPage button/link tests.pnpm verify✅,pnpm lint✅ (zero output),pnpm test:federation✅ (84 compat tests, all hubs).Docs
docs/opensubsonic.mddownload row updated.🤖 Generated with Claude Code
https://claude.ai/code/session_011Q3riZ78G26ohMgPDh8F7u