feat(downloads): use taglib-wasm to set tags

taglib supports multiple media formats beyond what was previously supported, this would enable transcoding to other formats without needing to write additional metadata libraries.
This commit is contained in:
Daniel 2026-03-03 19:42:54 +00:00 committed by GitHub
parent c7a4ba194d
commit 50a5b79d70
9 changed files with 391 additions and 1301 deletions

453
bun.lock

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,7 @@ import { addMetadataToAudio } from './metadata.js';
import { DashDownloader } from './dash-downloader.js';
import { encodeToMp3, MP3EncodingError } from './mp3-encoder.js';
import { ffmpeg } from './ffmpeg.js';
import { initTagLib } from './taglib.js';
export const DASH_MANIFEST_UNAVAILABLE_CODE = 'DASH_MANIFEST_UNAVAILABLE';
const TIDAL_V2_TOKEN = 'txNoH4kkV41MfH25';
@ -1109,6 +1110,8 @@ export class LosslessAPI {
}
async downloadTrack(id, quality = 'HI_RES_LOSSLESS', filename, options = {}) {
// Initialize taglib in the background.
initTagLib().catch(console.error);
const { onProgress, track } = options;
try {

View file

@ -98,6 +98,8 @@ let settingsModule = null;
let downloadsModule = null;
let metadataModule = null;
export const managers = {};
async function loadSettingsModule() {
if (!settingsModule) {
settingsModule = await import('./settings.js');
@ -496,6 +498,7 @@ document.addEventListener('DOMContentLoaded', async () => {
window.monochromeScrobbler = scrobbler;
const lyricsManager = new LyricsManager(api);
ui.lyricsManager = lyricsManager;
managers.lyricsManager = lyricsManager;
// Check browser support for local files
const selectLocalBtn = document.getElementById('select-local-folder-btn');

View file

@ -17,6 +17,7 @@ import { DashDownloader } from './dash-downloader.js';
import { generateM3U, generateM3U8, generateCUE, generateNFO, generateJSON } from './playlist-generator.js';
import { encodeToMp3 } from './mp3-encoder.js';
import { ffmpeg } from './ffmpeg.js';
import { initTagLib } from './taglib.js';
const downloadTasks = new Map();
const bulkDownloadTasks = new Map();
@ -269,6 +270,9 @@ function removeBulkDownloadTask(notifEl) {
}
async function downloadTrackBlob(track, quality, api, lyricsManager = null, signal = null) {
// Initialize taglib in the background.
initTagLib().catch(console.error);
let enrichedTrack = {
...track,
artist: track.artist || (track.artists && track.artists.length > 0 ? track.artists[0] : null),

File diff suppressed because it is too large Load diff

29
js/taglib.js Normal file
View file

@ -0,0 +1,29 @@
import { TagLib as _TagLib } from 'taglib-wasm';
/**
* @type {typeof import('taglib-wasm').TagLib}
*/
export const TagLib = _TagLib;
import TagLibWasm from '!/taglib-wasm/dist/taglib-web.wasm?url';
export { TagLibWasm };
let tagLib = null;
const wasmBinary = fetch(TagLibWasm).then((r) => r.arrayBuffer());
/**
*
* @returns {ReturnType<typeof TagLib.initialize>}
*/
export async function initTagLib() {
if (tagLib) return await tagLib;
tagLib = TagLib.initialize({
wasmBinary: await wasmBinary,
legacyMode: true,
});
console.log('TagLib initialized', { tagLib: await tagLib, TagLibWasm });
return await tagLib;
}

View file

@ -398,6 +398,9 @@ function resizeImageBlob(blob, size) {
/**
* Fetches and caches cover art as a Blob
* @param {Object} api - API instance with getCoverUrl method
* @param {string} coverId - ID of the cover art to fetch
* @returns {Promise<Blob|null>} - Cover art blob or null if not available
*/
export async function getCoverBlob(api, coverId) {
if (!coverId) return null;

View file

@ -30,6 +30,7 @@
"homepage": "https://github.com/SamidyFR/monochrome#readme",
"devDependencies": {
"@neutralinojs/neu": "^11.7.0",
"@types/node": "^25.3.3",
"eslint": "^9.39.3",
"eslint-config-prettier": "^10.1.8",
"globals": "^17.4.0",
@ -39,6 +40,7 @@
"stylelint": "^16.26.1",
"stylelint-config-standard": "^39.0.1",
"stylelint-config-standard-scss": "^16.0.0",
"typescript": "^5.9.3",
"vite": "^7.3.1",
"vite-plugin-neutralino": "^1.0.3",
"vite-plugin-pwa": "^1.2.0"
@ -60,6 +62,7 @@
"fuse.js": "^7.1.0",
"jose": "^6.1.3",
"npm": "^11.11.0",
"pocketbase": "^0.26.8"
"pocketbase": "^0.26.8",
"taglib-wasm": "^0.9.0"
}
}

View file

@ -10,6 +10,7 @@ export default defineConfig(({ mode }) => {
base: './',
resolve: {
alias: {
'!': '/node_modules',
pocketbase: '/node_modules/pocketbase/dist/pocketbase.es.js',
},
},