Generate album art URLs for audio files in the browser.
- Browser-only, ESM-only API
- Sidecar discovery (for example
folder.jpg,cover.jpg,song.jpg) - Embedded extraction:
- MP3 (
APIC/PIC) - M4A/MP4 (
covr) - MKA/MKV attachments and common cover-art patterns
- MP3 (
- Sidecar output returns direct URL candidates (no re-encode)
- Embedded output returns
blob:object URLs (default) ordata:URIs - Optional embedded resize/transcode (
output.size,output.mime) - Source strategies:
race(default),prefer-sidecar,all - Sidecar session cache (
sessionStorage) to avoid repeat validation
import audioThumbnail, { cleanupObjectURLs } from 'audio-thumbnail.js';
const results = await audioThumbnail('/audio/sidecar.mp3');
console.log(results.best?.URI, results.best?.source);
// Call when you no longer need blob: URLs created by this library
cleanupObjectURLs();const results = await audioThumbnail('/audio/track.mka', {
sources: ['sidecar', 'embedded'],
sourceStrategy: 'race',
sidecarExts: ['jpg', 'jpeg', 'png', 'webp'],
sidecarValidate: 'auto', // 'none' | 'head' | 'get-range' | 'img' | 'auto'
sidecarConcurrency: 6,
sidecarMaxResults: 1,
sidecarIncludeBasename: true,
embedded: {
maxBytes: 1_000_000,
preferPicture: 'front' // 'front' | 'any'
},
output: {
type: 'objectURL', // or 'dataURI'
mime: { type: 'image/webp', quality: 0.9 },
size: 512
}
});sources:['sidecar', 'embedded']sourceStrategy:'race'sidecarNames:['folder','cover','albumart','front','album','default','thumb','artwork','thumbnail']sidecarExts:['jpg', 'jpeg']sidecarIncludeBasename:truesidecarValidate:'auto'sidecarConcurrency:6sidecarMaxResults:1sidecarCache:truesidecarCacheKeyPrefix:'audio-thumbnail.js'embedded.maxBytes:1_000_000embedded.preferPicture:'front'output.type:'objectURL'timeoutMs:15000
Default export:
audioThumbnail(url: string, options?: Options): Promise<ArtworkResults>
Named exports:
cleanupObjectURLs(): numberclearCanvasPool(): booleangetMemoryUsage(): { canvasPoolEntries, activeObjectURLs }
ArtworkResults is an array of result objects with non-enumerable helpers:
results.best: best candidate ornullresults.timing:{ totalMs, fetchMsTotal, decodeMsTotal, encodeMsTotal }
Each result item includes:
URIsource('sidecar' | 'embedded')kind('front' | 'other')- optional metadata like
container,inputMime,outputMime,width,height
This repo includes sample media under audio/ and a demo harness at src/demo.html.
python -m http.server 8000Open http://localhost:8000/src/demo.html.