fix(backend): strip release-type suffixes from YTM search title + extend stopwords

- "recognize - Single" title → search uses "recognize" (strips "- Single/EP/Album/…")
- Adds Single/EP/Remaster/Deluxe/… to titleKws STOPWORDS so they never become
  mandatory title-match filters (no YouTube video title contains "Single")

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-06-19 09:42:07 +02:00
1 parent d1b107ae71
commit bff652a415
1 file changed
+8 -4
+8 -4
View File
@@ -22,7 +22,7 @@ function buildTitleKeywords(title) {
return escaped ? [escaped] : []; return escaped ? [escaped] : [];
} }
const VARIANT_WORDS = new Set(['sped','speedup','slowed','reverb','nightcore','karaoke','parody','remix','cover','acoustic','instrumental']); const VARIANT_WORDS = new Set(['sped','speedup','slowed','reverb','nightcore','karaoke','parody','remix','cover','acoustic','instrumental']);
const STOPWORDS = new Set(['the','a','an','and','or','of','in','on','at','to','for','feat','ft','with']); const STOPWORDS = new Set(['the','a','an','and','or','of','in','on','at','to','for','feat','ft','with','single','ep','album','remaster','remastered','deluxe','edition','version','live','bonus']);
const MIX_QUALIFIERS = ['radio', 'extended', 'club', 'vip', 'original', 'edit']; const MIX_QUALIFIERS = ['radio', 'extended', 'club', 'vip', 'original', 'edit'];
const lower = (title || '').toLowerCase(); const lower = (title || '').toLowerCase();
const strippedTitle = (title || '').replace(/\([^)]*\)/g, '').trim(); const strippedTitle = (title || '').replace(/\([^)]*\)/g, '').trim();
@@ -110,8 +110,12 @@ async function downloadTrack({ jobId, artist, rawArtist, albumArtist, title, alb
const escRe = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const escRe = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const variantFilter = buildVariantFilter(title); // Strip release-type suffixes Spotify sometimes appends to track/album names
const titleKws = buildTitleKeywords(title); // e.g. "recognize - Single" → "recognize", "Blue Moon - EP" → "Blue Moon"
const searchTitle = title.replace(/\s*[-–]\s*(single|ep|album|remaster(?:ed)?|deluxe(?:\s+edition)?|bonus\s+track)s?\s*$/i, '').trim() || title;
const variantFilter = buildVariantFilter(searchTitle);
const titleKws = buildTitleKeywords(searchTitle);
const variantPart = variantFilter ? ` & ${variantFilter}` : ''; const variantPart = variantFilter ? ` & ${variantFilter}` : '';
const titleKwPart = titleKws.length ? titleKws.map(k => ` & title ~= (?i)${k}`).join('') : ''; const titleKwPart = titleKws.length ? titleKws.map(k => ` & title ~= (?i)${k}`).join('') : '';
@@ -139,7 +143,7 @@ async function downloadTrack({ jobId, artist, rawArtist, albumArtist, title, alb
// For Western tracks, artist + title + duration matching is sufficient (matches spotdl behaviour). // For Western tracks, artist + title + duration matching is sufficient (matches spotdl behaviour).
const albumQuerySuffix = hasJpTitle && albumWords ? ' ' + albumWords : ''; const albumQuerySuffix = hasJpTitle && albumWords ? ' ' + albumWords : '';
const query = `${ytmArtist} - ${title}${albumQuerySuffix}`; const query = `${ytmArtist} - ${searchTitle}${albumQuerySuffix}`;
const baseArgs = [ const baseArgs = [
'--extract-audio', '--extract-audio',