fix: correct artist names and prevent wrong song downloads for Japanese tracks
- spotify.js: stop overwriting trackName with iTunes English title — yt-dlp must search with original Japanese title to find the right song (was downloading English covers e.g. Ghost In A Flower instead of 幽霊花) - metadata.js: add title-only fallback in lookupItunesTrackMeta so tracks are found even when kuromoji gives wrong artist romanization (e.g. Terui Jun Sei vs iTunes Yoshimasa Terui); also return itunesArtistName - novasonic-server.js: use itunesArtistName from iTunes lookup as the stored artist when available (single-track and playlist download paths) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
392da7e021
commit
c7bebd5691
3 files changed
+22
-18
No files matched your search
+15
-11
@@ -103,21 +103,25 @@ async function lookupItunesTrackMeta(artist, title) {
|
|||||||
const normA = (artist || '').toLowerCase().trim();
|
const normA = (artist || '').toLowerCase().trim();
|
||||||
// Split by space OR comma/semicolon/slash so "VXLLAIN, iGRES" → "vxllain" not "vxllain,"
|
// Split by space OR comma/semicolon/slash so "VXLLAIN, iGRES" → "vxllain" not "vxllain,"
|
||||||
const firstWord = s => (s || '').toLowerCase().split(/[\s,;/]/)[0];
|
const firstWord = s => (s || '').toLowerCase().split(/[\s,;/]/)[0];
|
||||||
const match = results.find(t =>
|
// Prefer strict match (title + first-word artist), fall back to title-only.
|
||||||
|
// Title-only fallback handles cases where kuromoji gave a wrong artist romanization
|
||||||
|
// (e.g. "Terui Jun Sei" vs iTunes "Yoshimasa Terui" — different first word).
|
||||||
|
const match = results.find(t =>
|
||||||
normalizeTitle(t.trackName) === normT &&
|
normalizeTitle(t.trackName) === normT &&
|
||||||
firstWord(t.artistName) === firstWord(normA)
|
firstWord(t.artistName) === firstWord(normA)
|
||||||
);
|
) || results.find(t => normalizeTitle(t.trackName) === normT);
|
||||||
if (!match) return {};
|
if (!match) return {};
|
||||||
return {
|
return {
|
||||||
album: match.collectionName || '',
|
album: match.collectionName || '',
|
||||||
year: match.releaseDate ? new Date(match.releaseDate).getFullYear() : undefined,
|
year: match.releaseDate ? new Date(match.releaseDate).getFullYear() : undefined,
|
||||||
trackNum: match.trackNumber || undefined,
|
trackNum: match.trackNumber || undefined,
|
||||||
totalTracks: match.trackCount || undefined,
|
totalTracks: match.trackCount || undefined,
|
||||||
discNum: match.discNumber || undefined,
|
discNum: match.discNumber || undefined,
|
||||||
discTotal: match.discCount || undefined,
|
discTotal: match.discCount || undefined,
|
||||||
genre: match.primaryGenreName || undefined,
|
genre: match.primaryGenreName || undefined,
|
||||||
artworkUrl: (match.artworkUrl100 || '').replace('100x100bb', '1000x1000bb'),
|
artworkUrl: (match.artworkUrl100 || '').replace('100x100bb', '1000x1000bb'),
|
||||||
durationMs: match.trackTimeMillis || undefined,
|
durationMs: match.trackTimeMillis || undefined,
|
||||||
|
itunesArtistName: match.artistName || undefined,
|
||||||
};
|
};
|
||||||
} catch { return {}; }
|
} catch { return {}; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -364,7 +364,8 @@ app.post('/api/download', async (req, res) => {
|
|||||||
} else {
|
} else {
|
||||||
log(jobId, `📋 Album aus Spotify: "${meta.album}"`);
|
log(jobId, `📋 Album aus Spotify: "${meta.album}"`);
|
||||||
}
|
}
|
||||||
const result = await downloadTrack({ jobId, artist, title, ...meta, sourceUrl: sourceUrl || sp.sourceUrl || undefined });
|
const finalArtist = meta.itunesArtistName || artist;
|
||||||
|
const result = await downloadTrack({ jobId, artist: finalArtist, title, ...meta, sourceUrl: sourceUrl || sp.sourceUrl || undefined });
|
||||||
if (result?.skipped) {
|
if (result?.skipped) {
|
||||||
updateJob(jobId, { status: 'done', progress: 100, message: 'Bereits vorhanden – übersprungen', skipped: true });
|
updateJob(jobId, { status: 'done', progress: 100, message: 'Bereits vorhanden – übersprungen', skipped: true });
|
||||||
} else {
|
} else {
|
||||||
@@ -438,10 +439,11 @@ app.post('/api/download', async (req, res) => {
|
|||||||
log(jobId, `📋 iTunes: "${trackArtist} – ${trackTitle}"`);
|
log(jobId, `📋 iTunes: "${trackArtist} – ${trackTitle}"`);
|
||||||
itunes = await lookupItunesTrackMeta(searchArtist, trackTitle);
|
itunes = await lookupItunesTrackMeta(searchArtist, trackTitle);
|
||||||
}
|
}
|
||||||
|
const resolvedArtist = itunes.itunesArtistName || trackArtist;
|
||||||
return downloadTrack({
|
return downloadTrack({
|
||||||
jobId,
|
jobId,
|
||||||
artist: trackArtist,
|
artist: resolvedArtist,
|
||||||
albumArtist: trackArtist,
|
albumArtist: resolvedArtist,
|
||||||
title: trackTitle,
|
title: trackTitle,
|
||||||
album: itunes.album || track.collectionName || track.album || '',
|
album: itunes.album || track.collectionName || track.album || '',
|
||||||
year: itunes.year || (track.releaseDate ? new Date(track.releaseDate).getFullYear() : undefined) || track.year,
|
year: itunes.year || (track.releaseDate ? new Date(track.releaseDate).getFullYear() : undefined) || track.year,
|
||||||
|
|||||||
+2
-4
@@ -295,10 +295,8 @@ async function _loadSpotifyTrackArtwork(tracks, listEl) {
|
|||||||
if (match.trackExplicitness) t.trackExplicitness = match.trackExplicitness;
|
if (match.trackExplicitness) t.trackExplicitness = match.trackExplicitness;
|
||||||
if (match.previewUrl) t.previewUrl = match.previewUrl;
|
if (match.previewUrl) t.previewUrl = match.previewUrl;
|
||||||
if (match.trackTimeMillis) t.durationMs = match.trackTimeMillis;
|
if (match.trackTimeMillis) t.durationMs = match.trackTimeMillis;
|
||||||
// Use iTunes canonical English/romaji names — more accurate than Spotify (which may use Japanese)
|
// Use iTunes canonical English/romaji artist name (Spotify may have Japanese or wrong order)
|
||||||
if (match.artistName) t.artistName = match.artistName;
|
if (match.artistName) t.artistName = match.artistName;
|
||||||
const JP_RE = /[-ヿ一-鿿]/;
|
|
||||||
if (JP_RE.test(t.trackName) && match.trackName) t.trackName = match.trackName;
|
|
||||||
if (window._spotifyResolved?.tracks?.[idx]) Object.assign(window._spotifyResolved.tracks[idx], t);
|
if (window._spotifyResolved?.tracks?.[idx]) Object.assign(window._spotifyResolved.tracks[idx], t);
|
||||||
const url = match.artworkUrl100 || match.artworkUrl60 || '';
|
const url = match.artworkUrl100 || match.artworkUrl60 || '';
|
||||||
if (url) _setArt(artEls[idx], url);
|
if (url) _setArt(artEls[idx], url);
|
||||||
|
|||||||
Reference in new issue
Block a user