From 39206f41286fccb2cd641c145990732f3750fabd Mon Sep 17 00:00:00 2001 From: Eric D'Addario Date: Sat, 28 Feb 2026 15:39:50 -0500 Subject: [PATCH] feat(downloads): save replay gain tags to FLAC metadata --- js/api.js | 13 ++++++++++++- js/downloads.js | 9 +++++++++ js/metadata.js | 7 +++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/js/api.js b/js/api.js index 8fe0a35..e44f867 100644 --- a/js/api.js +++ b/js/api.js @@ -1254,7 +1254,18 @@ export class LosslessAPI { message: 'Adding metadata...', }); } - blob = await addMetadataToAudio(blob, track, this, quality); + + const enrichedTrack = { ...track }; + if (lookup.info) { + enrichedTrack.replayGain = { + trackReplayGain: lookup.info.trackReplayGain, + trackPeakAmplitude: lookup.info.trackPeakAmplitude, + albumReplayGain: lookup.info.albumReplayGain, + albumPeakAmplitude: lookup.info.albumPeakAmplitude, + }; + } + + blob = await addMetadataToAudio(blob, enrichedTrack, this, quality); } // Detect actual format and fix filename extension if needed diff --git a/js/downloads.js b/js/downloads.js index 74d6d23..f3c16ce 100644 --- a/js/downloads.js +++ b/js/downloads.js @@ -323,6 +323,15 @@ async function downloadTrackBlob(track, quality, api, lyricsManager = null, sign } } + if (lookup.info) { + enrichedTrack.replayGain = { + trackReplayGain: lookup.info.trackReplayGain, + trackPeakAmplitude: lookup.info.trackPeakAmplitude, + albumReplayGain: lookup.info.albumReplayGain, + albumPeakAmplitude: lookup.info.albumPeakAmplitude, + }; + } + // Handle DASH streams (blob URLs) let blob; if (streamUrl.startsWith('blob:')) { diff --git a/js/metadata.js b/js/metadata.js index 6d54dd6..82ad190 100644 --- a/js/metadata.js +++ b/js/metadata.js @@ -587,6 +587,13 @@ function createVorbisCommentBlock(track) { if (track.album?.numberOfTracks) { comments.push(['TRACKTOTAL', String(track.album.numberOfTracks)]); } + if (track.replayGain) { + const { albumReplayGain, albumPeakAmplitude, trackReplayGain, trackPeakAmplitude } = track.replayGain; + if (albumReplayGain) comments.push(['REPLAYGAIN_ALBUM_GAIN', String(albumReplayGain)]); + if (albumPeakAmplitude) comments.push(['REPLAYGAIN_ALBUM_PEAK', String(albumPeakAmplitude)]); + if (trackReplayGain) comments.push(['REPLAYGAIN_TRACK_GAIN', String(trackReplayGain)]); + if (trackPeakAmplitude) comments.push(['REPLAYGAIN_TRACK_PEAK', String(trackPeakAmplitude)]); + } const releaseDateStr = track.album?.releaseDate || (track.streamStartDate ? track.streamStartDate.split('T')[0] : '');