From 8b7b9d8f3f5d8f1159e3ad210e9200b4762c3945 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Sun, 7 Jun 2026 13:55:58 -0700 Subject: [PATCH] #809 review follow-up: crossfade preload also streams un-mounted Navidrome tracks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-review of df929dc0 found one gap: the crossfade preloader hits /stream/library-audio with the file PATH, which 404s for a streamed (not disk-mounted) Navidrome track — main playback worked, crossfade didn't. /stream/library-audio now uses the same _build_library_stream_url fallback on a disk-miss (resolving the song id from the new track_id param, or a DB lookup by path), and the preloader passes next.id. Crossfade now works for streamed libraries too. Review also confirmed (no change needed): /api/stream/status returns only status/progress/track_info/error_message — the Subsonic token in stream_url never reaches the browser; it stays server-side and the browser only hits /stream/audio. Proxy verified live: Range forwarded, 206 + Content-Range/ Accept-Ranges passthrough, body streamed in 64KB chunks, upstream closed. --- web_server.py | 6 ++++++ webui/static/media-player.js | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/web_server.py b/web_server.py index 8c9c18aa..f18175fb 100644 --- a/web_server.py +++ b/web_server.py @@ -12547,6 +12547,12 @@ def stream_library_audio(): return jsonify({"error": "path is required"}), 400 resolved = _resolve_library_file_path(raw_path) if not resolved or not os.path.exists(resolved): + # Not on disk — same Navidrome stream fallback as /api/library/play + # (#809), so crossfade preload of the NEXT track works for streamed + # libraries too. Resolves the song id by path (DB lookup). + stream_url = _build_library_stream_url(request.args.get('track_id'), raw_path) + if stream_url: + return _proxy_stream_url_with_range(stream_url) return jsonify({"error": _get_file_not_found_error(raw_path)}), 404 return _serve_audio_file_with_range(resolved) except Exception as e: diff --git a/webui/static/media-player.js b/webui/static/media-player.js index 4dff3642..4f155e92 100644 --- a/webui/static/media-player.js +++ b/webui/static/media-player.js @@ -1871,7 +1871,10 @@ function npStartCrossfade(nextIdx, next) { const targetVol = audioPlayer.volume; // fade the new track up to current level npXfadeMainVol = targetVol; // remember to restore on abort - xa.src = `/stream/library-audio?path=${encodeURIComponent(next.file_path)}&t=${Date.now()}`; + // Pass the server song id so a streamed (un-mounted) Navidrome track can + // crossfade-preload via the server stream API too (#809). + const _xfTid = next.id ? `&track_id=${encodeURIComponent(next.id)}` : ''; + xa.src = `/stream/library-audio?path=${encodeURIComponent(next.file_path)}${_xfTid}&t=${Date.now()}`; xa.volume = 0; xa.play().then(() => { const fadeMs = NP_CROSSFADE_SECONDS * 1000;