fix: use exact expected filename instead of newest-file heuristic

Parallel downloads to the same album dir (e.g. two tracks from same
album) both resolved to the last-written file, causing wrong metadata
to be embedded. Now each download targets its known output path
(trackPrefix + safeTitle + audioFmt) directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-02 18:25:51 +02:00
1 parent 3962a90b0d
commit f831e1fd8f
1 file changed
+6 -13
+6 -13
View File
@@ -289,14 +289,10 @@ async function downloadTrack({ jobId, artist, albumArtist, title, album, year, t
// Without it yt-dlp gets a mixed feed of videos, channels, and playlists as well.
const YTM_SONGS_PARAM = 'EgWKAQIIAWoKEAkQBRAKEAMQBA%3D%3D';
const ytmUrl = `https://music.youtube.com/search?q=${encodeURIComponent(query)}&params=${YTM_SONGS_PARAM}`;
// Snapshot files already in dir before we start — so hasAudio() only detects NEW files
// from the current download attempt, not pre-existing files from parallel jobs.
let snapBefore = new Set(fs.readdirSync(dir));
const resetSnap = () => { snapBefore = new Set(fs.readdirSync(dir)); };
const hasAudio = () => fs.readdirSync(dir).some(
f => !snapBefore.has(f) && AUDIO_EXTS.some(e => f.endsWith(`.${e}`))
);
const tryYtdlp = async (args) => { resetSnap(); await spawnYtdlp(args); };
// We know the exact output filename before yt-dlp runs — no snapshot heuristic needed.
const expectedAudio = path.join(dir, `${trackPrefix}${safeTitle}.${CONFIG.audioFmt}`);
const hasAudio = () => fs.existsSync(expectedAudio);
const tryYtdlp = async (args) => { await spawnYtdlp(args); };
const variantFilter = buildVariantFilter(title);
const titleKws = buildTitleKeywords(title);
@@ -387,11 +383,8 @@ async function downloadTrack({ jobId, artist, albumArtist, title, album, year, t
}
}
// Step 2: find the audio file yt-dlp wrote (newest audio file in dir)
const audioFile = fs.readdirSync(dir)
.filter(f => AUDIO_EXTS.some(e => f.endsWith(`.${e}`)))
.map(f => path.join(dir, f))
.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs)[0];
// Step 2: locate the audio file yt-dlp wrote (exact expected path)
const audioFile = hasAudio() ? expectedAudio : null;
if (!audioFile) {
log(jobId, '⚠️ Keine Audio-Datei gefunden');