music-metadata 11.10.4 → 11.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,73 @@
1
+ // lib/id3v2/FrameHeader.ts
2
+ import * as Token from 'token-types';
3
+ import * as util from '../common/Util.js';
4
+ import { UINT32SYNCSAFE } from './ID3v2Token.js';
5
+ import { textDecode } from '@borewit/text-codec';
6
+ import { Id3v2ContentError } from './FrameParser.js';
7
+ /**
8
+ * Frame header length (bytes) depending on ID3v2 major version.
9
+ */
10
+ export function getFrameHeaderLength(majorVer) {
11
+ switch (majorVer) {
12
+ case 2: return 6;
13
+ case 3:
14
+ case 4: return 10;
15
+ default: throw makeUnexpectedMajorVersionError(majorVer);
16
+ }
17
+ }
18
+ function readFrameFlags(b) {
19
+ return {
20
+ status: {
21
+ tag_alter_preservation: util.getBit(b, 0, 6),
22
+ file_alter_preservation: util.getBit(b, 0, 5),
23
+ read_only: util.getBit(b, 0, 4)
24
+ },
25
+ format: {
26
+ grouping_identity: util.getBit(b, 1, 7),
27
+ compression: util.getBit(b, 1, 3),
28
+ encryption: util.getBit(b, 1, 2),
29
+ unsynchronisation: util.getBit(b, 1, 1),
30
+ data_length_indicator: util.getBit(b, 1, 0)
31
+ }
32
+ };
33
+ }
34
+ /**
35
+ * Factory: parse a frame header from its header bytes (6 for v2.2, 10 for v2.3/v2.4).
36
+ *
37
+ * Note: It only *parses* and does light validation. It does not read payload bytes.
38
+ */
39
+ export function readFrameHeader(uint8Array, majorVer, warningCollector) {
40
+ switch (majorVer) {
41
+ case 2:
42
+ return parseFrameHeaderV22(uint8Array, majorVer, warningCollector);
43
+ case 3:
44
+ case 4:
45
+ return parseFrameHeaderV23V24(uint8Array, majorVer, warningCollector);
46
+ default:
47
+ throw makeUnexpectedMajorVersionError(majorVer);
48
+ }
49
+ }
50
+ function parseFrameHeaderV22(uint8Array, majorVer, warningCollector) {
51
+ const header = {
52
+ id: textDecode(uint8Array.subarray(0, 3), 'ascii'),
53
+ length: Token.UINT24_BE.get(uint8Array, 3)
54
+ };
55
+ if (!header.id.match(/^[A-Z0-9]{3}$/)) {
56
+ warningCollector.addWarning(`Invalid ID3v2.${majorVer} frame-header-ID: ${header.id}`);
57
+ }
58
+ return header;
59
+ }
60
+ function parseFrameHeaderV23V24(uint8Array, majorVer, warningCollector) {
61
+ const header = {
62
+ id: textDecode(uint8Array.subarray(0, 4), 'ascii'),
63
+ length: (majorVer === 4 ? UINT32SYNCSAFE : Token.UINT32_BE).get(uint8Array, 4),
64
+ flags: readFrameFlags(uint8Array.subarray(8, 10))
65
+ };
66
+ if (!header.id.match(/^[A-Z0-9]{4}$/)) {
67
+ warningCollector.addWarning(`Invalid ID3v2.${majorVer} frame-header-ID: ${header.id}`);
68
+ }
69
+ return header;
70
+ }
71
+ function makeUnexpectedMajorVersionError(majorVer) {
72
+ throw new Id3v2ContentError(`Unexpected majorVer: ${majorVer}`);
73
+ }
@@ -54,6 +54,7 @@ export declare class FrameParser {
54
54
  */
55
55
  private splitValue;
56
56
  private static trimArray;
57
+ private static trimNullPadding;
57
58
  private static readIdentifierAndData;
58
59
  private static getNullTerminatorLength;
59
60
  }
@@ -7,6 +7,7 @@ import { makeUnexpectedFileContentError } from '../ParseError.js';
7
7
  import { decodeUintBE } from '../common/Util.js';
8
8
  const debug = initDebug('music-metadata:id3v2:frame-parser');
9
9
  const defaultEnc = 'latin1'; // latin1 == iso-8859-1;
10
+ const urlEnc = { encoding: defaultEnc, bom: false };
10
11
  export function parseGenre(origVal) {
11
12
  // match everything inside parentheses
12
13
  const genres = [];
@@ -90,7 +91,7 @@ export class FrameParser {
90
91
  case 'PCST': {
91
92
  let text;
92
93
  try {
93
- text = util.decodeString(uint8Array.subarray(1), encoding).replace(/\x00+$/, '');
94
+ text = FrameParser.trimNullPadding(util.decodeString(uint8Array.subarray(1), encoding));
94
95
  }
95
96
  catch (error) {
96
97
  if (error instanceof Error) {
@@ -135,7 +136,7 @@ export class FrameParser {
135
136
  break;
136
137
  }
137
138
  case 'TXXX': {
138
- const idAndData = FrameParser.readIdentifierAndData(uint8Array, offset + 1, length, encoding);
139
+ const idAndData = FrameParser.readIdentifierAndData(uint8Array.subarray(1), encoding);
139
140
  const textTag = {
140
141
  description: idAndData.id,
141
142
  text: this.splitValue(type, util.decodeString(idAndData.data, encoding).replace(/\x00+$/, ''))
@@ -147,28 +148,28 @@ export class FrameParser {
147
148
  case 'APIC':
148
149
  if (includeCovers) {
149
150
  const pic = {};
150
- offset += 1;
151
+ uint8Array = uint8Array.subarray(1);
151
152
  switch (this.major) {
152
153
  case 2:
153
- pic.format = util.decodeString(uint8Array.subarray(offset, offset + 3), 'latin1'); // 'latin1'; // latin1 == iso-8859-1;
154
- offset += 3;
154
+ pic.format = util.decodeString(uint8Array.subarray(0, 3), 'latin1'); // 'latin1'; // latin1 == iso-8859-1;
155
+ uint8Array = uint8Array.subarray(3);
155
156
  break;
156
157
  case 3:
157
158
  case 4:
158
- fzero = util.findZero(uint8Array, offset, length, defaultEnc);
159
- pic.format = util.decodeString(uint8Array.subarray(offset, fzero), defaultEnc);
160
- offset = fzero + 1;
159
+ fzero = util.findZero(uint8Array, defaultEnc);
160
+ pic.format = util.decodeString(uint8Array.subarray(0, fzero), defaultEnc);
161
+ uint8Array = uint8Array.subarray(fzero + 1);
161
162
  break;
162
163
  default:
163
164
  throw makeUnexpectedMajorVersionError(this.major);
164
165
  }
165
166
  pic.format = FrameParser.fixPictureMimeType(pic.format);
166
- pic.type = AttachedPictureType[uint8Array[offset]];
167
- offset += 1;
168
- fzero = util.findZero(uint8Array, offset, length, encoding);
169
- pic.description = util.decodeString(uint8Array.subarray(offset, fzero), encoding);
170
- offset = fzero + nullTerminatorLength;
171
- pic.data = uint8Array.subarray(offset, length);
167
+ pic.type = AttachedPictureType[uint8Array[0]];
168
+ uint8Array = uint8Array.subarray(1);
169
+ fzero = util.findZero(uint8Array, encoding);
170
+ pic.description = util.decodeString(uint8Array.subarray(0, fzero), encoding);
171
+ uint8Array = uint8Array.subarray(fzero + nullTerminatorLength);
172
+ pic.data = uint8Array;
172
173
  output = pic;
173
174
  }
174
175
  break;
@@ -178,7 +179,7 @@ export class FrameParser {
178
179
  break;
179
180
  case 'SYLT': {
180
181
  const syltHeader = SyncTextHeader.get(uint8Array, 0);
181
- offset += SyncTextHeader.len;
182
+ uint8Array = uint8Array.subarray(SyncTextHeader.len);
182
183
  const result = {
183
184
  descriptor: '',
184
185
  language: syltHeader.language,
@@ -187,12 +188,12 @@ export class FrameParser {
187
188
  syncText: []
188
189
  };
189
190
  let readSyllables = false;
190
- while (offset < length) {
191
- const nullStr = FrameParser.readNullTerminatedString(uint8Array.subarray(offset), syltHeader.encoding);
192
- offset += nullStr.len;
191
+ while (uint8Array.length > 0) {
192
+ const nullStr = FrameParser.readNullTerminatedString(uint8Array, syltHeader.encoding);
193
+ uint8Array = uint8Array.subarray(nullStr.len);
193
194
  if (readSyllables) {
194
- const timestamp = Token.UINT32_BE.get(uint8Array, offset);
195
- offset += Token.UINT32_BE.len;
195
+ const timestamp = Token.UINT32_BE.get(uint8Array, 0);
196
+ uint8Array = uint8Array.subarray(Token.UINT32_BE.len);
196
197
  result.syncText.push({
197
198
  text: nullStr.text,
198
199
  timestamp
@@ -224,42 +225,52 @@ export class FrameParser {
224
225
  break;
225
226
  }
226
227
  case 'UFID': {
227
- const ufid = FrameParser.readIdentifierAndData(uint8Array, offset, length, defaultEnc);
228
+ const ufid = FrameParser.readIdentifierAndData(uint8Array, defaultEnc);
228
229
  output = { owner_identifier: ufid.id, identifier: ufid.data };
229
230
  break;
230
231
  }
231
232
  case 'PRIV': { // private frame
232
- const priv = FrameParser.readIdentifierAndData(uint8Array, offset, length, defaultEnc);
233
+ const priv = FrameParser.readIdentifierAndData(uint8Array, defaultEnc);
233
234
  output = { owner_identifier: priv.id, data: priv.data };
234
235
  break;
235
236
  }
236
237
  case 'POPM': { // Popularimeter
237
- fzero = util.findZero(uint8Array, offset, length, defaultEnc);
238
- const email = util.decodeString(uint8Array.subarray(offset, fzero), defaultEnc);
239
- offset = fzero + 1;
240
- const valueLen = length - offset - 1;
238
+ uint8Array = uint8Array.subarray(offset);
239
+ const emailStr = FrameParser.readNullTerminatedString(uint8Array, urlEnc);
240
+ const email = emailStr.text;
241
+ uint8Array = uint8Array.subarray(emailStr.len);
242
+ if (uint8Array.length === 0) {
243
+ this.warningCollector.addWarning(`id3v2.${this.major} type=${type} POPM frame missing rating byte`);
244
+ output = { email, rating: 0, counter: undefined };
245
+ break;
246
+ }
247
+ const rating = Token.UINT8.get(uint8Array, 0);
248
+ const counterBytes = uint8Array.subarray(Token.UINT8.len);
241
249
  output = {
242
250
  email,
243
- rating: Token.UINT8.get(uint8Array, offset),
244
- counter: valueLen > 0 ? util.decodeUintBE(uint8Array.subarray(offset + 1)) : undefined
251
+ rating,
252
+ counter: counterBytes.length > 0 ? decodeUintBE(counterBytes) : undefined
245
253
  };
246
254
  break;
247
255
  }
248
256
  case 'GEOB': { // General encapsulated object
249
- fzero = util.findZero(uint8Array, offset + 1, length, encoding);
250
- const mimeType = util.decodeString(uint8Array.subarray(offset + 1, fzero), defaultEnc);
251
- offset = fzero + 1;
252
- fzero = util.findZero(uint8Array, offset, length, encoding);
253
- const filename = util.decodeString(uint8Array.subarray(offset, fzero), defaultEnc);
254
- offset = fzero + 1;
255
- fzero = util.findZero(uint8Array, offset, length, encoding);
256
- const description = util.decodeString(uint8Array.subarray(offset, fzero), defaultEnc);
257
- offset = fzero + 1;
257
+ // [encoding] <MIME> 0x00 <filename> 0x00/0x00 0x00 <description> 0x00/0x00 0x00 <data>
258
+ const encoding = TextEncodingToken.get(uint8Array, 0);
259
+ uint8Array = uint8Array.subarray(1);
260
+ const mimeTypeStr = FrameParser.readNullTerminatedString(uint8Array, urlEnc);
261
+ const mimeType = mimeTypeStr.text;
262
+ uint8Array = uint8Array.subarray(mimeTypeStr.len);
263
+ const filenameStr = FrameParser.readNullTerminatedString(uint8Array, encoding);
264
+ const filename = filenameStr.text;
265
+ uint8Array = uint8Array.subarray(filenameStr.len);
266
+ const descriptionStr = FrameParser.readNullTerminatedString(uint8Array, encoding);
267
+ const description = descriptionStr.text;
268
+ uint8Array = uint8Array.subarray(descriptionStr.len);
258
269
  const geob = {
259
270
  type: mimeType,
260
271
  filename,
261
272
  description,
262
- data: uint8Array.subarray(offset, length)
273
+ data: uint8Array
263
274
  };
264
275
  output = geob;
265
276
  break;
@@ -274,21 +285,26 @@ export class FrameParser {
274
285
  case 'WPAY':
275
286
  case 'WPUB':
276
287
  // Decode URL
277
- fzero = util.findZero(uint8Array, offset + 1, length, encoding);
278
- output = util.decodeString(uint8Array.subarray(offset, fzero), defaultEnc);
288
+ output = FrameParser.readNullTerminatedString(uint8Array, urlEnc).text;
279
289
  break;
280
290
  case 'WXXX': {
281
- // Decode URL
282
- fzero = util.findZero(uint8Array, offset + 1, length, encoding);
283
- const description = util.decodeString(uint8Array.subarray(offset + 1, fzero), encoding);
284
- offset = fzero + (encoding === 'utf-16le' ? 2 : 1);
285
- output = { description, url: util.decodeString(uint8Array.subarray(offset, length), defaultEnc) };
291
+ // [encoding] <description> 0x00/0x00 0x00 <url>
292
+ const encoding = TextEncodingToken.get(uint8Array, 0);
293
+ uint8Array = uint8Array.subarray(1);
294
+ const descriptionStr = FrameParser.readNullTerminatedString(uint8Array, encoding);
295
+ const description = descriptionStr.text;
296
+ uint8Array = uint8Array.subarray(descriptionStr.len);
297
+ // URL is always ISO-8859-1
298
+ output = { description, url: FrameParser.trimNullPadding(util.decodeString(uint8Array, defaultEnc)) };
286
299
  break;
287
300
  }
288
301
  case 'WFD':
289
- case 'WFED':
290
- output = util.decodeString(uint8Array.subarray(offset + 1, util.findZero(uint8Array, offset + 1, length, encoding)), encoding);
302
+ case 'WFED': {
303
+ const encoding = TextEncodingToken.get(uint8Array, 0);
304
+ uint8Array = uint8Array.subarray(1);
305
+ output = FrameParser.readNullTerminatedString(uint8Array, encoding).text;
291
306
  break;
307
+ }
292
308
  case 'MCDI': {
293
309
  // Music CD identifier
294
310
  output = uint8Array.subarray(0, length);
@@ -301,18 +317,21 @@ export class FrameParser {
301
317
  return output;
302
318
  }
303
319
  static readNullTerminatedString(uint8Array, encoding) {
304
- let offset = encoding.bom ? 2 : 0;
305
- const zeroIndex = util.findZero(uint8Array, offset, uint8Array.length, encoding.encoding);
306
- const txt = uint8Array.subarray(offset, zeroIndex);
307
- if (encoding.encoding === 'utf-16le') {
308
- offset = zeroIndex + 2;
309
- }
310
- else {
311
- offset = zeroIndex + 1;
320
+ const bomSize = encoding.bom ? 2 : 0;
321
+ const originalLen = uint8Array.length;
322
+ const valueArray = uint8Array.subarray(bomSize);
323
+ const zeroIndex = util.findZero(valueArray, encoding.encoding);
324
+ if (zeroIndex >= valueArray.length) {
325
+ // No terminator found, decode full buffer remainder
326
+ return {
327
+ text: util.decodeString(valueArray, encoding.encoding),
328
+ len: originalLen
329
+ };
312
330
  }
331
+ const txt = valueArray.subarray(0, zeroIndex);
313
332
  return {
314
333
  text: util.decodeString(txt, encoding.encoding),
315
- len: offset
334
+ len: bomSize + zeroIndex + FrameParser.getNullTerminatorLength(encoding.encoding)
316
335
  };
317
336
  }
318
337
  static fixPictureMimeType(pictureType) {
@@ -361,16 +380,21 @@ export class FrameParser {
361
380
  return FrameParser.trimArray(values);
362
381
  }
363
382
  static trimArray(values) {
364
- return values.map(value => value.replace(/\x00+$/, '').trim());
383
+ return values.map(value => FrameParser.trimNullPadding(value).trim());
384
+ }
385
+ static trimNullPadding(value) {
386
+ let end = value.length;
387
+ while (end > 0 && value.charCodeAt(end - 1) === 0) {
388
+ end--;
389
+ }
390
+ return end === value.length ? value : value.slice(0, end);
365
391
  }
366
- static readIdentifierAndData(uint8Array, offset, length, encoding) {
367
- const fzero = util.findZero(uint8Array, offset, length, encoding);
368
- const id = util.decodeString(uint8Array.subarray(offset, fzero), encoding);
369
- offset = fzero + FrameParser.getNullTerminatorLength(encoding);
370
- return { id, data: uint8Array.subarray(offset, length) };
392
+ static readIdentifierAndData(uint8Array, encoding) {
393
+ const idStr = FrameParser.readNullTerminatedString(uint8Array, { encoding, bom: false });
394
+ return { id: idStr.text, data: uint8Array.subarray(idStr.len) };
371
395
  }
372
396
  static getNullTerminatorLength(enc) {
373
- return enc === 'utf-16le' ? 2 : 1;
397
+ return enc.startsWith('utf-16') ? 2 : 1;
374
398
  }
375
399
  }
376
400
  export class Id3v2ContentError extends makeUnexpectedFileContentError('id3v2') {
@@ -3,8 +3,6 @@ import type { IOptions } from '../type.js';
3
3
  import type { INativeMetadataCollector } from '../common/MetadataCollector.js';
4
4
  export declare class ID3v2Parser {
5
5
  static removeUnsyncBytes(buffer: Uint8Array): Uint8Array;
6
- private static getFrameHeaderLength;
7
- private static readFrameFlags;
8
6
  private static readFrameData;
9
7
  /**
10
8
  * Create a combined tag key, of tag & description
@@ -25,5 +23,4 @@ export declare class ID3v2Parser {
25
23
  private handleTag;
26
24
  private addTag;
27
25
  private parseMetadata;
28
- private readFrameHeader;
29
26
  }
@@ -1,8 +1,7 @@
1
1
  import * as Token from 'token-types';
2
- import * as util from '../common/Util.js';
3
2
  import { FrameParser, Id3v2ContentError } from './FrameParser.js';
4
- import { ExtendedHeader, ID3v2Header, UINT32SYNCSAFE } from './ID3v2Token.js';
5
- import { textDecode } from '@borewit/text-codec';
3
+ import { ExtendedHeader, ID3v2Header } from './ID3v2Token.js';
4
+ import { getFrameHeaderLength, readFrameHeader } from './FrameHeader.js';
6
5
  export class ID3v2Parser {
7
6
  constructor() {
8
7
  this.tokenizer = undefined;
@@ -26,33 +25,6 @@ export class ID3v2Parser {
26
25
  }
27
26
  return buffer.subarray(0, writeI);
28
27
  }
29
- static getFrameHeaderLength(majorVer) {
30
- switch (majorVer) {
31
- case 2:
32
- return 6;
33
- case 3:
34
- case 4:
35
- return 10;
36
- default:
37
- throw makeUnexpectedMajorVersionError(majorVer);
38
- }
39
- }
40
- static readFrameFlags(b) {
41
- return {
42
- status: {
43
- tag_alter_preservation: util.getBit(b, 0, 6),
44
- file_alter_preservation: util.getBit(b, 0, 5),
45
- read_only: util.getBit(b, 0, 4)
46
- },
47
- format: {
48
- grouping_identity: util.getBit(b, 1, 7),
49
- compression: util.getBit(b, 1, 3),
50
- encryption: util.getBit(b, 1, 2),
51
- unsynchronisation: util.getBit(b, 1, 1),
52
- data_length_indicator: util.getBit(b, 1, 0)
53
- }
54
- };
55
- }
56
28
  static readFrameData(uint8Array, frameHeader, majorVer, includeCovers, warningCollector) {
57
29
  const frameParser = new FrameParser(majorVer, warningCollector);
58
30
  switch (majorVer) {
@@ -127,14 +99,14 @@ export class ID3v2Parser {
127
99
  while (true) {
128
100
  if (offset === data.length)
129
101
  break;
130
- const frameHeaderLength = ID3v2Parser.getFrameHeaderLength(this.id3Header.version.major);
102
+ const frameHeaderLength = getFrameHeaderLength(this.id3Header.version.major);
131
103
  if (offset + frameHeaderLength > data.length) {
132
104
  this.metadata.addWarning('Illegal ID3v2 tag length');
133
105
  break;
134
106
  }
135
107
  const frameHeaderBytes = data.subarray(offset, offset + frameHeaderLength);
136
108
  offset += frameHeaderLength;
137
- const frameHeader = this.readFrameHeader(frameHeaderBytes, this.id3Header.version.major);
109
+ const frameHeader = readFrameHeader(frameHeaderBytes, this.id3Header.version.major, this.metadata);
138
110
  const frameDataBytes = data.subarray(offset, offset + frameHeader.length);
139
111
  offset += frameHeader.length;
140
112
  const values = ID3v2Parser.readFrameData(frameDataBytes, frameHeader, this.id3Header.version.major, !this.options.skipCovers, this.metadata);
@@ -144,34 +116,6 @@ export class ID3v2Parser {
144
116
  }
145
117
  return tags;
146
118
  }
147
- readFrameHeader(uint8Array, majorVer) {
148
- let header;
149
- switch (majorVer) {
150
- case 2:
151
- header = {
152
- id: textDecode(uint8Array.subarray(0, 3), 'ascii'),
153
- length: Token.UINT24_BE.get(uint8Array, 3)
154
- };
155
- if (!header.id.match(/[A-Z0-9]{3}/g)) {
156
- this.metadata.addWarning(`Invalid ID3v2.${this.id3Header.version.major} frame-header-ID: ${header.id}`);
157
- }
158
- break;
159
- case 3:
160
- case 4:
161
- header = {
162
- id: textDecode(uint8Array.subarray(0, 4), 'ascii'),
163
- length: (majorVer === 4 ? UINT32SYNCSAFE : Token.UINT32_BE).get(uint8Array, 4),
164
- flags: ID3v2Parser.readFrameFlags(uint8Array.subarray(8, 10))
165
- };
166
- if (!header.id.match(/[A-Z0-9]{4}/g)) {
167
- this.metadata.addWarning(`Invalid ID3v2.${this.id3Header.version.major} frame-header-ID: ${header.id}`);
168
- }
169
- break;
170
- default:
171
- throw makeUnexpectedMajorVersionError(majorVer);
172
- }
173
- return header;
174
- }
175
119
  }
176
120
  function makeUnexpectedMajorVersionError(majorVer) {
177
121
  throw new Id3v2ContentError(`Unexpected majorVer: ${majorVer}`);
@@ -16,13 +16,11 @@ export declare class MpegContentError extends MpegContentError_base {
16
16
  export declare class MpegParser extends AbstractID3Parser {
17
17
  private frameCount;
18
18
  private syncFrameCount;
19
- private countSkipFrameData;
20
19
  private totalDataLength;
21
20
  private audioFrameHeader?;
22
21
  private bitrates;
23
22
  private offset;
24
23
  private frame_size;
25
- private crc;
26
24
  private calculateEofDuration;
27
25
  private samplesPerFrame;
28
26
  private buf_frame_header;
@@ -233,12 +233,10 @@ export class MpegParser extends AbstractID3Parser {
233
233
  super(...arguments);
234
234
  this.frameCount = 0;
235
235
  this.syncFrameCount = -1;
236
- this.countSkipFrameData = 0;
237
236
  this.totalDataLength = 0;
238
237
  this.bitrates = [];
239
238
  this.offset = 0;
240
239
  this.frame_size = 0;
241
- this.crc = null;
242
240
  this.calculateEofDuration = false;
243
241
  this.samplesPerFrame = null;
244
242
  this.buf_frame_header = new Uint8Array(4);
@@ -467,8 +465,8 @@ export class MpegParser extends AbstractID3Parser {
467
465
  return false;
468
466
  }
469
467
  async parseCrc() {
470
- this.crc = await this.tokenizer.readNumber(Token.INT16_BE);
471
- this.offset += 2;
468
+ await this.tokenizer.ignore(Token.INT16_BE.len); // Ignore CRC
469
+ this.offset += Token.INT16_BE.len;
472
470
  return this.skipSideInformation();
473
471
  }
474
472
  async skipSideInformation() {
@@ -561,7 +559,6 @@ export class MpegParser extends AbstractID3Parser {
561
559
  if (frameDataLeft < 0)
562
560
  throw new MpegContentError('frame-data-left cannot be negative');
563
561
  await this.tokenizer.ignore(frameDataLeft);
564
- this.countSkipFrameData += frameDataLeft;
565
562
  }
566
563
  areAllSame(array) {
567
564
  const first = array[0];
@@ -37,7 +37,7 @@ export declare class VorbisStream implements IPageConsumer {
37
37
  flush(): Promise<void>;
38
38
  parseUserComment(pageData: Uint8Array, offset: number): Promise<number>;
39
39
  addTag(id: string, value: string | IVorbisPicture): Promise<void>;
40
- calculateDuration(enfOfStream: boolean): void;
40
+ calculateDuration(_enfOfStream: boolean): void;
41
41
  /**
42
42
  * Parse first Ogg/Vorbis page
43
43
  * @param _header
@@ -77,7 +77,7 @@ export class VorbisStream {
77
77
  }
78
78
  await this.metadata.addTag('vorbis', id, value);
79
79
  }
80
- calculateDuration(enfOfStream) {
80
+ calculateDuration(_enfOfStream) {
81
81
  if (this.lastPageHeader && this.metadata.format.sampleRate && this.lastPageHeader.absoluteGranulePosition >= 0) {
82
82
  // Calculate duration
83
83
  this.metadata.setFormat('numberOfSamples', this.lastPageHeader.absoluteGranulePosition);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "music-metadata",
3
3
  "description": "Music metadata parser for Node.js, supporting virtual any audio and tag format.",
4
- "version": "11.10.4",
4
+ "version": "11.10.6",
5
5
  "author": {
6
6
  "name": "Borewit",
7
7
  "url": "https://github.com/Borewit"
@@ -110,14 +110,15 @@
110
110
  "@tokenizer/token": "^0.3.0",
111
111
  "content-type": "^1.0.5",
112
112
  "debug": "^4.4.3",
113
- "file-type": "^21.2.0",
113
+ "file-type": "^21.3.0",
114
114
  "media-typer": "^1.1.0",
115
115
  "strtok3": "^10.3.4",
116
116
  "token-types": "^6.1.2",
117
- "uint8array-extras": "^1.5.0"
117
+ "uint8array-extras": "^1.5.0",
118
+ "win-guid": "^0.1.3"
118
119
  },
119
120
  "devDependencies": {
120
- "@biomejs/biome": "2.3.10",
121
+ "@biomejs/biome": "2.3.11",
121
122
  "@types/chai": "^5.2.3",
122
123
  "@types/chai-as-promised": "^8.0.2",
123
124
  "@types/content-type": "^1.1.9",
package/lib/asf/GUID.d.ts DELETED
@@ -1,83 +0,0 @@
1
- /**
2
- * Ref:
3
- * - https://tools.ietf.org/html/draft-fleischman-asf-01, Appendix A: ASF GUIDs
4
- * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/10_asf_guids.html
5
- * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/index.html
6
- * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/10_asf_guids.html
7
- *
8
- * ASF File Structure:
9
- * - https://msdn.microsoft.com/en-us/library/windows/desktop/ee663575(v=vs.85).aspx
10
- *
11
- * ASF GUIDs:
12
- * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/10_asf_guids.html
13
- * - https://github.com/dji-sdk/FFmpeg/blob/master/libavformat/asf.c
14
- */
15
- export default class GUID {
16
- static HeaderObject: GUID;
17
- static DataObject: GUID;
18
- static SimpleIndexObject: GUID;
19
- static IndexObject: GUID;
20
- static MediaObjectIndexObject: GUID;
21
- static TimecodeIndexObject: GUID;
22
- static FilePropertiesObject: GUID;
23
- static StreamPropertiesObject: GUID;
24
- static HeaderExtensionObject: GUID;
25
- static CodecListObject: GUID;
26
- static ScriptCommandObject: GUID;
27
- static MarkerObject: GUID;
28
- static BitrateMutualExclusionObject: GUID;
29
- static ErrorCorrectionObject: GUID;
30
- static ContentDescriptionObject: GUID;
31
- static ExtendedContentDescriptionObject: GUID;
32
- static ContentBrandingObject: GUID;
33
- static StreamBitratePropertiesObject: GUID;
34
- static ContentEncryptionObject: GUID;
35
- static ExtendedContentEncryptionObject: GUID;
36
- static DigitalSignatureObject: GUID;
37
- static PaddingObject: GUID;
38
- static ExtendedStreamPropertiesObject: GUID;
39
- static AdvancedMutualExclusionObject: GUID;
40
- static GroupMutualExclusionObject: GUID;
41
- static StreamPrioritizationObject: GUID;
42
- static BandwidthSharingObject: GUID;
43
- static LanguageListObject: GUID;
44
- static MetadataObject: GUID;
45
- static MetadataLibraryObject: GUID;
46
- static IndexParametersObject: GUID;
47
- static MediaObjectIndexParametersObject: GUID;
48
- static TimecodeIndexParametersObject: GUID;
49
- static CompatibilityObject: GUID;
50
- static AdvancedContentEncryptionObject: GUID;
51
- static AudioMedia: GUID;
52
- static VideoMedia: GUID;
53
- static CommandMedia: GUID;
54
- static JFIF_Media: GUID;
55
- static Degradable_JPEG_Media: GUID;
56
- static FileTransferMedia: GUID;
57
- static BinaryMedia: GUID;
58
- static ASF_Index_Placeholder_Object: GUID;
59
- static fromBin(bin: Uint8Array, offset?: number): GUID;
60
- /**
61
- * Decode GUID in format like "B503BF5F-2EA9-CF11-8EE3-00C00C205365"
62
- * @param objectId Binary GUID
63
- * @param offset Read offset in bytes, default 0
64
- * @returns GUID as dashed hexadecimal representation
65
- */
66
- static decode(objectId: Uint8Array, offset?: number): string;
67
- /**
68
- * Decode stream type
69
- * @param mediaType Media type GUID
70
- * @returns Media type
71
- */
72
- static decodeMediaType(mediaType: GUID): 'audio' | 'video' | 'command' | 'degradable-jpeg' | 'file-transfer' | 'binary' | undefined;
73
- /**
74
- * Encode GUID
75
- * @param guid GUID like: "B503BF5F-2EA9-CF11-8EE3-00C00C205365"
76
- * @returns Encoded Binary GUID
77
- */
78
- static encode(str: string): Uint8Array;
79
- str: string;
80
- constructor(str: string);
81
- equals(guid: GUID): boolean;
82
- toBin(): Uint8Array;
83
- }