From 2df5a54985442a6bed070a503ff4421cba468531 Mon Sep 17 00:00:00 2001 From: Honey Date: Thu, 28 May 2026 00:06:33 +0200 Subject: [PATCH] fix: prevent 9-second downloads caused by short iTunes duration match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When iTunes enrichment returns a jingle/preview as the first result (e.g. trackTimeMillis=9000), the yt-dlp duration filter becomes impossible (duration > 30 & duration < 24), all filtered steps fail, and the final unfiltered fallback downloads whatever YouTube returns first — often a short clip. Fix 1: spotify.js — only copy iTunes trackTimeMillis to durationMs when it is > 30 seconds (genuine song, not a jingle or preview). Fix 2: ytdlp.js — only enter the duration-filtered search branch when durationMs > 30 000ms, so a corrupted short value silently falls back to the unfiltered search path which still finds the correct full song. Co-Authored-By: Claude Sonnet 4.6 --- backend/lib/ytdlp.js | 2 +- src/spotify.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/lib/ytdlp.js b/backend/lib/ytdlp.js index dd0001f..056a337 100644 --- a/backend/lib/ytdlp.js +++ b/backend/lib/ytdlp.js @@ -215,7 +215,7 @@ async function downloadTrack({ jobId, artist, rawArtist, albumArtist, title, alb await spawnYtdlp([...urls, '--max-downloads', '1', ...mfArgs, ...baseArgs]); }; - if (durationMs) { + if (durationMs && durationMs > 30000) { const durationSec = Math.round(durationMs / 1000); const margin = Math.max(15, Math.round(durationSec * 0.15)); const dur = { min: Math.max(30, durationSec - margin), max: durationSec + margin }; diff --git a/src/spotify.js b/src/spotify.js index 1c36a50..f723781 100644 --- a/src/spotify.js +++ b/src/spotify.js @@ -305,7 +305,9 @@ async function _loadSpotifyTrackArtwork(tracks, listEl) { if (match.collectionName) t.collectionName = match.collectionName; if (match.releaseDate) t.releaseDate = match.releaseDate; if (match.trackNumber) t.trackNumber = match.trackNumber; - if (match.trackTimeMillis) t.durationMs = match.trackTimeMillis; + // Only use iTunes duration if it looks like a full song (> 30s) — jingles/previews + // returning a small trackTimeMillis would corrupt the yt-dlp duration filter. + if (match.trackTimeMillis > 30000) t.durationMs = match.trackTimeMillis; } if (window._spotifyResolved?.tracks?.[idx]) Object.assign(window._spotifyResolved.tracks[idx], t); const url = match.artworkUrl100 || match.artworkUrl60 || '';