#809 review follow-up: crossfade preload also streams un-mounted Navidrome tracks

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.
This commit is contained in:
BoulderBadgeDad 2026-06-07 13:55:58 -07:00
parent df929dc022
commit 8b7b9d8f3f
2 changed files with 10 additions and 1 deletions

View file

@ -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:

View file

@ -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;