id3-parser
Version:
A pure JavaScript id3 tag parser.
55 lines (48 loc) • 1.86 kB
text/typescript
import GENRES from '../constants/genres';
import { IBytes, IID3V1Tag } from '../interface';
import { readBytesToUTF8 } from '../bytesUtil';
const V1_MIN_LENGTH = 128;
/**
* Parse ID3v1 metadata from binary bytes.
* @description
* ID3v1 tag occupies 128 bytes, beginning with the string TAG 128 bytes
* from the end of the file.
*
* And the format is like: header(3) + title(30) + artist(30) +
* album(30) + year(4) + comment(30) + genre(1).
*
* And extended tag is only supported by few programs, so we ignore it.
* @param bytes binary bytes.
*/
export default function parseV1Data(bytes: IBytes): false | IID3V1Tag {
if (!bytes || bytes.length < V1_MIN_LENGTH) {
return false;
}
bytes = bytes.slice(bytes.length - V1_MIN_LENGTH);
const tags: IID3V1Tag = {
version: {
major: 1,
minor: 0,
},
};
const flag = readBytesToUTF8(bytes, 3);
if (flag !== 'TAG') {
return false;
}
// Strings are either space- or zero-padded. So remove them.
const reWhiteSpace = /(^[\s0]+|[\s0]+$)/;
tags.title = readBytesToUTF8(bytes.slice(3), 30).replace(reWhiteSpace, '');
tags.artist = readBytesToUTF8(bytes.slice(33), 30).replace(reWhiteSpace, '');
tags.album = readBytesToUTF8(bytes.slice(63), 30).replace(reWhiteSpace, '');
tags.year = readBytesToUTF8(bytes.slice(93), 4).replace(reWhiteSpace, '');
// If there is a zero byte at [125], the comment is 28 bytes and the remaining 2 are [0, trackno]
if (bytes[125] === 0) {
tags.comments = readBytesToUTF8(bytes.slice(97), 28).replace(reWhiteSpace, '');
tags.version.minor = 1;
tags.track = bytes[126];
} else {
tags.comments = readBytesToUTF8(bytes.slice(97), 30).replace(reWhiteSpace, '');
}
tags.genre = GENRES[bytes[127]] || '';
return tags;
}