fix FLAC tag detection

This commit is contained in:
Armin 2026-07-08 00:50:53 +02:00
commit 6cb74abded

View file

@ -724,7 +724,62 @@ async function readId3v1(file) {
return tags;
} catch { return null; }
}
async function readVorbisComments(file) {
try {
const maxRead = Math.min(file.size, 256 * 1024);
const data = await readBytes(file, 0, maxRead);
if (data[0] !== 0x66 || data[1] !== 0x4C || data[2] !== 0x61 || data[3] !== 0x43) return null;
let pos = 4;
let commentData = null;
while (pos + 4 <= data.length) {
const isLast = data[pos] & 0x80;
const blockType = data[pos] & 0x7f;
const blockLen = (data[pos + 1] << 16) | (data[pos + 2] << 8) | data[pos + 3];
pos += 4;
if (pos + blockLen > data.length) break;
if (blockType === 4) { commentData = data.slice(pos, pos + blockLen); break; }
pos += blockLen;
if (isLast) break;
}
if (!commentData) return null;
let off = 0;
if (off + 4 > commentData.length) return null;
const vendorLen = commentData[off] | (commentData[off + 1] << 8) | (commentData[off + 2] << 16) | (commentData[off + 3] << 24);
off += 4 + vendorLen;
if (off + 4 > commentData.length) return null;
const numTags = commentData[off] | (commentData[off + 1] << 8) | (commentData[off + 2] << 16) | (commentData[off + 3] << 24);
off += 4;
const tags = {};
for (let i = 0; i < numTags; i++) {
if (off + 4 > commentData.length) break;
const tagLen = commentData[off] | (commentData[off + 1] << 8) | (commentData[off + 2] << 16) | (commentData[off + 3] << 24);
off += 4;
if (off + tagLen > commentData.length) break;
const tagStr = new TextDecoder('utf-8').decode(commentData.slice(off, off + tagLen));
off += tagLen;
const eqIdx = tagStr.indexOf('=');
if (eqIdx === -1) continue;
const key = tagStr.substring(0, eqIdx).toUpperCase();
const value = tagStr.substring(eqIdx + 1);
switch (key) {
case 'TITLE': tags.title = value; break;
case 'ARTIST': tags.artist = value; break;
case 'ALBUM': tags.album = value; break;
case 'GENRE': tags.genre = value; break;
case 'DATE':
case 'YEAR': tags.year = value; break;
case 'TRACKNUMBER': tags.track = value; break;
}
}
return Object.keys(tags).length > 0 ? tags : null;
} catch { return null; }
}
async function readTags(file) {
const ext = file.name.toLowerCase().slice(file.name.lastIndexOf('.'));
if (ext === '.flac') {
const v = await readVorbisComments(file);
if (v) return v;
}
let tags = await readId3v2(file);
if (tags && (tags.title || tags.artist)) return tags;
const v1 = await readId3v1(file);