diff --git a/index.html b/index.html
index 91309b0..6883790 100644
--- a/index.html
+++ b/index.html
@@ -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);