UNPKG

taglib-wasm

Version:

TagLib for TypeScript platforms: Deno, Node.js, Bun, Electron, browsers, and Cloudflare Workers

222 lines (221 loc) 7.26 kB
import { PICTURE_TYPE_VALUES } from "./types.js"; import { applyPictures, getCoverArt, readPictures, replacePictureByType, setCoverArt } from "./simple.js"; import { readFileData } from "./utils/file.js"; import { writeFileData } from "./utils/write.js"; async function exportCoverArt(audioPath, imagePath) { const coverData = await getCoverArt(audioPath); if (!coverData) { throw new Error(`No cover art found in: ${audioPath}`); } await writeFileData(imagePath, coverData); } async function exportPictureByType(audioPath, imagePath, type) { const pictures = await readPictures(audioPath); const typeValue = typeof type === "string" ? PICTURE_TYPE_VALUES[type] : type; const picture = pictures.find((pic) => pic.type === typeValue); if (!picture) { throw new Error(`No picture of type ${type} found in: ${audioPath}`); } await writeFileData(imagePath, picture.data); } async function exportAllPictures(audioPath, outputDir, options = {}) { const pictures = await readPictures(audioPath); const exportedPaths = []; const dir = outputDir.endsWith("/") ? outputDir : outputDir + "/"; for (let i = 0; i < pictures.length; i++) { const picture = pictures[i]; let filename; if (options.nameFormat) { filename = options.nameFormat(picture, i); } else { const typeNames = { [PICTURE_TYPE_VALUES.FrontCover]: "front-cover", [PICTURE_TYPE_VALUES.BackCover]: "back-cover", [PICTURE_TYPE_VALUES.LeafletPage]: "leaflet", [PICTURE_TYPE_VALUES.Media]: "media", [PICTURE_TYPE_VALUES.LeadArtist]: "lead-artist", [PICTURE_TYPE_VALUES.Artist]: "artist", [PICTURE_TYPE_VALUES.Conductor]: "conductor", [PICTURE_TYPE_VALUES.Band]: "band", [PICTURE_TYPE_VALUES.Composer]: "composer", [PICTURE_TYPE_VALUES.Lyricist]: "lyricist", [PICTURE_TYPE_VALUES.RecordingLocation]: "recording-location", [PICTURE_TYPE_VALUES.DuringRecording]: "during-recording", [PICTURE_TYPE_VALUES.DuringPerformance]: "during-performance", [PICTURE_TYPE_VALUES.MovieScreenCapture]: "screen-capture", [PICTURE_TYPE_VALUES.ColouredFish]: "fish", [PICTURE_TYPE_VALUES.Illustration]: "illustration", [PICTURE_TYPE_VALUES.BandLogo]: "band-logo", [PICTURE_TYPE_VALUES.PublisherLogo]: "publisher-logo" }; const typeName = typeNames[picture.type] || "other"; const ext = picture.mimeType.split("/")[1] || "jpg"; filename = `${typeName}-${i + 1}.${ext}`; } const fullPath = dir + filename; await writeFileData(fullPath, picture.data); exportedPaths.push(fullPath); } return exportedPaths; } async function importCoverArt(audioPath, imagePath, options = {}) { const imageData = await readFileData(imagePath); let mimeType = options.mimeType; if (!mimeType) { const ext = imagePath.split(".").pop()?.toLowerCase(); const mimeTypes = { "jpg": "image/jpeg", "jpeg": "image/jpeg", "png": "image/png", "gif": "image/gif", "webp": "image/webp", "bmp": "image/bmp" }; mimeType = mimeTypes[ext || ""] || "image/jpeg"; } const modifiedBuffer = await setCoverArt(audioPath, imageData, mimeType); await writeFileData(audioPath, modifiedBuffer); } async function importPictureWithType(audioPath, imagePath, type, options = {}) { const imageData = await readFileData(imagePath); let mimeType = options.mimeType; if (!mimeType) { const ext = imagePath.split(".").pop()?.toLowerCase(); const mimeTypes = { "jpg": "image/jpeg", "jpeg": "image/jpeg", "png": "image/png", "gif": "image/gif", "webp": "image/webp", "bmp": "image/bmp" }; mimeType = mimeTypes[ext || ""] || "image/jpeg"; } const picture = { mimeType, data: imageData, type: typeof type === "string" ? PICTURE_TYPE_VALUES[type] : type, description: options.description }; const modifiedBuffer = await replacePictureByType(audioPath, picture); await writeFileData(audioPath, modifiedBuffer); } async function loadPictureFromFile(imagePath, type = "FrontCover", options = {}) { const data = await readFileData(imagePath); let mimeType = options.mimeType; if (!mimeType) { const ext = imagePath.split(".").pop()?.toLowerCase(); const mimeTypes = { "jpg": "image/jpeg", "jpeg": "image/jpeg", "png": "image/png", "gif": "image/gif", "webp": "image/webp", "bmp": "image/bmp" }; mimeType = mimeTypes[ext || ""] || "image/jpeg"; } return { mimeType, data, type: typeof type === "string" ? PICTURE_TYPE_VALUES[type] : type, description: options.description || imagePath.split("/").pop() }; } async function savePictureToFile(picture, imagePath) { await writeFileData(imagePath, picture.data); } async function copyCoverArt(sourcePath, targetPath, options = {}) { if (options.copyAll) { const pictures = await readPictures(sourcePath); if (pictures.length === 0) { throw new Error(`No pictures found in: ${sourcePath}`); } const modifiedBuffer = await applyPictures(targetPath, pictures); await writeFileData(targetPath, modifiedBuffer); } else { const coverData = await getCoverArt(sourcePath); if (!coverData) { throw new Error(`No cover art found in: ${sourcePath}`); } const pictures = await readPictures(sourcePath); const coverPicture = pictures.find( (p) => p.type === PICTURE_TYPE_VALUES.FrontCover ) || pictures[0]; const modifiedBuffer = await setCoverArt( targetPath, coverData, coverPicture.mimeType ); await writeFileData(targetPath, modifiedBuffer); } } async function findCoverArtFiles(audioPath) { const dir = audioPath.substring(0, audioPath.lastIndexOf("/") + 1); const commonNames = [ "cover", "front", "folder", "album", "artwork", "Cover", "Front", "Folder", "Album", "Artwork" ]; const extensions = ["jpg", "jpeg", "png", "gif", "webp"]; const found = {}; for (const name of commonNames) { for (const ext of extensions) { const path = `${dir}${name}.${ext}`; try { const data = await readFileData(path); if (data.length > 0) { if (!found.front && ["cover", "front", "Cover", "Front"].includes(name)) { found.front = path; } else if (!found.folder && ["folder", "Folder"].includes(name)) { found.folder = path; } else { found[name.toLowerCase()] = path; } break; } } catch { } } } const backNames = ["back", "Back", "back-cover", "Back-Cover"]; for (const name of backNames) { for (const ext of extensions) { const path = `${dir}${name}.${ext}`; try { const data = await readFileData(path); if (data.length > 0) { found.back = path; break; } } catch { } } if (found.back) break; } return found; } export { copyCoverArt, exportAllPictures, exportCoverArt, exportPictureByType, findCoverArtFiles, importCoverArt, importPictureWithType, loadPictureFromFile, savePictureToFile };