diff --git a/js/api.js b/js/api.js index 70b9138..0964358 100644 --- a/js/api.js +++ b/js/api.js @@ -15,7 +15,7 @@ import { APICache } from './cache.js'; import { DashDownloader } from './dash-downloader.ts'; import { HlsDownloader } from './hls-downloader.js'; import { MP3EncodingError } from './mp3-encoder.js'; -import { loadFfmpeg, FfmpegError } from './ffmpeg.js'; +import { loadFfmpeg, FfmpegError, ffmpeg } from './ffmpeg.js'; import { triggerDownload, applyAudioPostProcessing } from './download-utils.ts'; import { isCustomFormat } from './ffmpegFormats.ts'; import { DownloadProgress } from './progressEvents.js'; @@ -1504,59 +1504,63 @@ export class LosslessAPI { if (!isVideo) { blob = await applyAudioPostProcessing(blob, quality, onProgress, options.signal); + } - // Add metadata if track information is provided - if (track) { - onProgress?.({ - stage: 'processing', - message: 'Adding metadata...', - }); + // Add metadata if track information is provided + if (track) { + onProgress?.({ + stage: 'processing', + message: 'Adding metadata...', + }); - const enrichedTrack = { ...track }; - if (lookup.info) { - enrichedTrack.replayGain = { - trackReplayGain: lookup.info.trackReplayGain, - trackPeakAmplitude: lookup.info.trackPeakAmplitude, - albumReplayGain: lookup.info.albumReplayGain, - albumPeakAmplitude: lookup.info.albumPeakAmplitude, - }; - } + const enrichedTrack = { ...track }; + if (lookup.info) { + enrichedTrack.replayGain = { + trackReplayGain: lookup.info.trackReplayGain, + trackPeakAmplitude: lookup.info.trackPeakAmplitude, + albumReplayGain: lookup.info.albumReplayGain, + albumPeakAmplitude: lookup.info.albumPeakAmplitude, + }; + } - if ( - track.album?.id && - (track.album?.totalDiscs == null || track.album?.numberOfTracksOnDisc == null) - ) { - try { - const albumData = await this.getAlbum(track.album.id); - if (albumData.tracks?.length > 0) { - const discTrackCounts = new Map(); - let maxDiscNumber = 0; - for (const t of albumData.tracks) { - const dn = getTrackDiscNumber(t); - discTrackCounts.set(dn, (discTrackCounts.get(dn) || 0) + 1); - if (dn > maxDiscNumber) maxDiscNumber = dn; - } - const totalDiscs = maxDiscNumber || 1; - const discNumber = getTrackDiscNumber(track); - enrichedTrack.album = { - ...(enrichedTrack.album || {}), - totalDiscs: track.album?.totalDiscs ?? totalDiscs, - numberOfTracksOnDisc: - track.album?.numberOfTracksOnDisc ?? discTrackCounts.get(discNumber), - }; - } - } catch (e) { - console.warn('Failed to fetch album for disc info:', e); - } - } - - onProgress?.(new DownloadProgress('Adding metadata')); + if (track.album?.id && (track.album?.totalDiscs == null || track.album?.numberOfTracksOnDisc == null)) { try { - blob = await addMetadataToAudio(blob, enrichedTrack, this, quality, prefetchPromises); - } catch (err) { - console.error(err); + const albumData = await this.getAlbum(track.album.id); + if (albumData.tracks?.length > 0) { + const discTrackCounts = new Map(); + let maxDiscNumber = 0; + for (const t of albumData.tracks) { + const dn = getTrackDiscNumber(t); + discTrackCounts.set(dn, (discTrackCounts.get(dn) || 0) + 1); + if (dn > maxDiscNumber) maxDiscNumber = dn; + } + const totalDiscs = maxDiscNumber || 1; + const discNumber = getTrackDiscNumber(track); + enrichedTrack.album = { + ...(enrichedTrack.album || {}), + totalDiscs: track.album?.totalDiscs ?? totalDiscs, + numberOfTracksOnDisc: + track.album?.numberOfTracksOnDisc ?? discTrackCounts.get(discNumber), + }; + } + } catch (e) { + console.warn('Failed to fetch album for disc info:', e); } } + + onProgress?.(new DownloadProgress('Adding metadata')); + try { + if (isVideo) { + blob = new File( + [await ffmpeg(blob, ['-c', 'copy'], 'output.mp4', 'video/mp4', onProgress, options.signal)], + 'output.mp4', + { type: 'video/mp4' } + ); + } + blob = await addMetadataToAudio(blob, enrichedTrack, this, quality, prefetchPromises); + } catch (err) { + console.error(err); + } } if (options.triggerDownload ?? true) { diff --git a/js/metadata.js b/js/metadata.js index c296c7c..336030c 100644 --- a/js/metadata.js +++ b/js/metadata.js @@ -34,12 +34,12 @@ export async function addMetadataToAudio(audioBlob, track, api, _quality, prefet try { data.title = getTrackTitle(track); data.artist = getFullArtistString(track); - data.albumTitle = track.album.title; + data.albumTitle = track.album?.title; data.albumArtist = track.album?.artist?.name || track.artist?.name; data.trackNumber = track.trackNumber; data.discNumber = track.volumeNumber ?? track.discNumber; - data.totalTracks = track.album.numberOfTracksOnDisc ?? track.album.numberOfTracks; - data.totalDiscs = track.album.totalDiscs; + data.totalTracks = track.album?.numberOfTracksOnDisc ?? track.album?.numberOfTracks; + data.totalDiscs = track.album?.totalDiscs; data.copyright = track.copyright; data.isrc = track.isrc; data.explicit = Boolean(track.explicit);