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] : [];
}
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 lower = (title || '').toLowerCase();
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 variantFilter = buildVariantFilter(title);
const titleKws = buildTitleKeywords(title);
// Strip release-type suffixes Spotify sometimes appends to track/album names
// 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 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).
const albumQuerySuffix = hasJpTitle && albumWords ? ' ' + albumWords : '';
const query = `${ytmArtist} - ${title}${albumQuerySuffix}`;
const query = `${ytmArtist} - ${searchTitle}${albumQuerySuffix}`;
const baseArgs = [
'--extract-audio',