fix(backend): remove album suffix from YTM search query
Album words ("KAGUYA Music", "OST" etc.) appended to the search query
caused wrong or no results — "Kei Haneoka 確信 KAGUYA Music" would miss
tracks the plain "Kei Haneoka 確信" query finds immediately.
Artist + cleanTitle is sufficient for both JP and Western tracks.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
fa4c954ab9
commit
d5b088a658
1 file changed
+2
-18
+2
-18
@@ -127,26 +127,10 @@ async function downloadTrack({ jobId, artist, rawArtist, albumArtist, title, alb
|
|||||||
const artistChannelPart = (artistFirstWord.length >= 3 && !JP_RE.test(artistFirstWord))
|
const artistChannelPart = (artistFirstWord.length >= 3 && !JP_RE.test(artistFirstWord))
|
||||||
? ` & channel ~= (?i)${escRe(artistFirstWord)}` : '';
|
? ` & channel ~= (?i)${escRe(artistFirstWord)}` : '';
|
||||||
|
|
||||||
// When the title is Japanese (keywords stripped to nothing) OR when we have an album that
|
|
||||||
// provides better search context, include the album's first two words in the search query.
|
|
||||||
// This helps YTM rank the official OST/album track above fan covers and romaji-subtitle uploads.
|
|
||||||
// Only use album words that are ASCII (romaji/English) — Japanese album words don't help YTM ranking.
|
|
||||||
const hasJpTitle = JP_RE.test(title);
|
|
||||||
const GENERIC_ALBUM_WORDS = new Set(['single', 'ep', 'album', 'soundtrack', 'ost', 'edition', 'remaster', 'remastered', 'deluxe', 'bonus', 'version', 'live']);
|
|
||||||
const titleWordSet = new Set(title.toLowerCase().split(/\s+/));
|
|
||||||
const albumWords = (album && album !== 'Singles' && album !== 'Unknown')
|
|
||||||
? album.split(/\s+/)
|
|
||||||
.filter(w => /^[A-Za-z0-9]/.test(w) && !titleWordSet.has(w.toLowerCase()) && !GENERIC_ALBUM_WORDS.has(w.toLowerCase()))
|
|
||||||
.slice(0, 2).join(' ')
|
|
||||||
: '';
|
|
||||||
// Only append album words for Japanese titles where title keywords are stripped to nothing.
|
|
||||||
// For Western tracks, artist + title + duration matching is sufficient (matches spotdl behaviour).
|
|
||||||
const albumQuerySuffix = hasJpTitle && albumWords ? ' ' + albumWords : '';
|
|
||||||
|
|
||||||
// Use a space (not " - ") between artist and title: this matches how users type
|
// Use a space (not " - ") between artist and title: this matches how users type
|
||||||
// in the YTM search box and ranks the exact official track first. A dash skews
|
// in the YTM search box and ranks the exact official track first. A dash skews
|
||||||
// YTM ranking toward a same-named artist's full discography.
|
// YTM ranking toward a same-named artist's full discography.
|
||||||
const query = `${ytmArtist} ${searchTitle}${albumQuerySuffix}`;
|
const query = `${ytmArtist} ${searchTitle}`;
|
||||||
|
|
||||||
const baseArgs = [
|
const baseArgs = [
|
||||||
'--extract-audio',
|
'--extract-audio',
|
||||||
@@ -195,7 +179,7 @@ async function downloadTrack({ jobId, artist, rawArtist, albumArtist, title, alb
|
|||||||
// for normal tracks; for ambiguous artist names yt-dlp's search may still not surface the
|
// for normal tracks; for ambiguous artist names yt-dlp's search may still not surface the
|
||||||
// exact official track (a known extractor limitation — use the direct link in that case).
|
// exact official track (a known extractor limitation — use the direct link in that case).
|
||||||
const YTM_SONGS_PARAM = 'EgWKAQIIAWoKEAkQBRAKEAMQBA%3D%3D';
|
const YTM_SONGS_PARAM = 'EgWKAQIIAWoKEAkQBRAKEAMQBA%3D%3D';
|
||||||
const ytmQuery = `${rawArtist || mainArtist} ${searchTitle}${albumQuerySuffix}`;
|
const ytmQuery = `${rawArtist || mainArtist} ${searchTitle}`;
|
||||||
const ytmUrl = `https://music.youtube.com/search?q=${encodeURIComponent(ytmQuery)}¶ms=${YTM_SONGS_PARAM}`;
|
const ytmUrl = `https://music.youtube.com/search?q=${encodeURIComponent(ytmQuery)}¶ms=${YTM_SONGS_PARAM}`;
|
||||||
const expectedAudio = path.join(dir, `${fileBase}.${CONFIG.audioFmt}`);
|
const expectedAudio = path.join(dir, `${fileBase}.${CONFIG.audioFmt}`);
|
||||||
const hasAudio = () => fs.existsSync(expectedAudio);
|
const hasAudio = () => fs.existsSync(expectedAudio);
|
||||||
|
|||||||
Reference in new issue
Block a user