fix: repair Japanese song download pipeline
Five separate root causes fixed: 1. buildTitleKeywords (ytdlp.js): For Japanese titles \w strips all kana/kanji leaving no keywords. Now uses the first whitespace- delimited segment as a literal regex keyword so --match-filter title ~= requires the YTM video to contain the Japanese text. 2. Tokenizer wait (ytdlp.js): If kuromoji hasn't finished loading when a Japanese download starts, romajiForStorage returns the original Japanese text unchanged — producing Japanese folder/filenames and skipping sort tags. Now waits up to 30 s for the tokenizer. 3. titleOnlyMatch guard (metadata.js): iTunes titleOnlyMatch (no artist check) was used as a fallback for all searches. For Japanese titles/artists this matched wrong US songs with identical titles (common in anime OSTs). Now titleOnlyMatch is skipped when the search title or artist contains Japanese characters. 4. squid.js rawArtist: rawArtist was not in squid's signature and never forwarded to embedMetadata, so Qobuz-downloaded J-Pop tracks stored the iTunes-resolved English name as artist instead of the Japanese original. Fixed by accepting and forwarding rawArtist. 5. squid.js romaji paths: Folder and filename used raw artist/title with no romaji conversion, creating Japanese-named paths inconsistent with the yt-dlp path. Now uses romajiForStorage same as ytdlp.js. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
52451f5086
commit
63ff8920bf
3 files changed
+45
-10
No files matched your search
+10
-5
@@ -11,6 +11,7 @@ const {
|
||||
downloadArtwork, fetchLyrics, findExistingTrack,
|
||||
} = require('./metadata');
|
||||
const { embedMetadata } = require('./ytdlp');
|
||||
const { romajiForStorage } = require('./romaji');
|
||||
|
||||
const SQUID_BASE = 'https://qobuz.squid.wtf';
|
||||
|
||||
@@ -222,14 +223,18 @@ async function downloadUrlToFile(url, destPath) {
|
||||
|
||||
// Download a single track via squid.wtf / Qobuz.
|
||||
// Returns { success: true, dir, skipped? } on success, null if track not found on Qobuz.
|
||||
async function downloadTrack({ jobId, artist, albumArtist, title, album, year, trackNum, totalTracks, discNum, discTotal, compilation, genre, artworkUrl, explicit, outputDir, durationMs }) {
|
||||
async function downloadTrack({ jobId, artist, rawArtist, albumArtist, title, album, year, trackNum, totalTracks, discNum, discTotal, compilation, genre, artworkUrl, explicit, outputDir, durationMs }) {
|
||||
const mainArtist = albumArtist || artist;
|
||||
const safeArtist = sanitize(mainArtist.split(',')[0].trim());
|
||||
const safeAlbum = sanitize(album || 'Singles');
|
||||
// Use romaji for folder/filename — same as ytdlp path so paths are consistent
|
||||
const mainArtistRomaji = romajiForStorage(mainArtist) || mainArtist;
|
||||
const titleRomaji = romajiForStorage(title) || title;
|
||||
const albumRomaji = album ? (romajiForStorage(album) || album) : null;
|
||||
const safeArtist = sanitize(mainArtistRomaji.split(/[,;&]/)[0].trim());
|
||||
const safeAlbum = sanitize(albumRomaji || 'Singles');
|
||||
const dir = path.join(outputDir || CONFIG.musicPath, safeArtist, safeAlbum);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
|
||||
const safeTitle = sanitize(title);
|
||||
const safeTitle = sanitize(titleRomaji);
|
||||
const trackPrefix = trackNum ? String(trackNum).padStart(2, '0') + ' - ' : '';
|
||||
const ext = squidExt();
|
||||
|
||||
@@ -278,7 +283,7 @@ async function downloadTrack({ jobId, artist, albumArtist, title, album, year, t
|
||||
|
||||
return embedMetadata({
|
||||
jobId, audioFile, dir, trackPrefix, safeTitle,
|
||||
artist, mainArtist, album, year, trackNum, totalTracks,
|
||||
rawArtist, artist, mainArtist, album, year, trackNum, totalTracks,
|
||||
discNum, discTotal, compilation, genre,
|
||||
artworkUrl: finalArtwork, explicit, title,
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user