music-metadata 8.3.0 → 9.0.1

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.
Files changed (96) hide show
  1. package/LICENSE.txt +9 -9
  2. package/README.md +519 -488
  3. package/lib/ParserFactory.d.ts +1 -1
  4. package/lib/ParserFactory.js +1 -2
  5. package/lib/aiff/AiffParser.js +3 -4
  6. package/lib/aiff/AiffToken.d.ts +2 -4
  7. package/lib/aiff/AiffToken.js +7 -7
  8. package/lib/apev2/APEv2Parser.d.ts +1 -1
  9. package/lib/apev2/APEv2Parser.js +10 -12
  10. package/lib/apev2/APEv2Token.d.ts +1 -1
  11. package/lib/asf/AsfObject.d.ts +15 -17
  12. package/lib/asf/AsfObject.js +51 -45
  13. package/lib/asf/AsfParser.js +6 -8
  14. package/lib/asf/AsfUtil.d.ts +1 -3
  15. package/lib/asf/AsfUtil.js +4 -5
  16. package/lib/asf/GUID.d.ts +4 -5
  17. package/lib/asf/GUID.js +14 -11
  18. package/lib/common/BasicParser.d.ts +1 -1
  19. package/lib/common/FourCC.d.ts +1 -1
  20. package/lib/common/FourCC.js +5 -3
  21. package/lib/common/MetadataCollector.d.ts +3 -3
  22. package/lib/common/MetadataCollector.js +7 -8
  23. package/lib/common/RandomFileReader.d.ts +2 -3
  24. package/lib/common/RandomFileReader.js +1 -1
  25. package/lib/common/Util.d.ts +1 -1
  26. package/lib/common/Util.js +4 -3
  27. package/lib/core.d.ts +16 -8
  28. package/lib/core.js +19 -5
  29. package/lib/dsdiff/DsdiffParser.js +1 -1
  30. package/lib/dsdiff/DsdiffToken.d.ts +1 -1
  31. package/lib/dsf/DsfChunk.d.ts +1 -1
  32. package/lib/flac/FlacParser.d.ts +1 -1
  33. package/lib/flac/FlacParser.js +6 -4
  34. package/lib/id3v1/ID3v1Parser.js +7 -7
  35. package/lib/id3v2/AbstractID3Parser.d.ts +1 -1
  36. package/lib/id3v2/AbstractID3Parser.js +1 -1
  37. package/lib/id3v2/FrameParser.js +3 -3
  38. package/lib/id3v2/ID3v24TagMapper.d.ts +2 -3
  39. package/lib/id3v2/ID3v24TagMapper.js +4 -4
  40. package/lib/id3v2/ID3v2Parser.d.ts +1 -1
  41. package/lib/id3v2/ID3v2Parser.js +10 -17
  42. package/lib/id3v2/ID3v2Token.d.ts +1 -1
  43. package/lib/id3v2/ID3v2Token.js +2 -2
  44. package/lib/iff/index.d.ts +1 -1
  45. package/lib/index.d.ts +1 -2
  46. package/lib/index.js +1 -1
  47. package/lib/lyrics3/Lyrics3.js +4 -4
  48. package/lib/matroska/MatroskaParser.d.ts +9 -2
  49. package/lib/matroska/MatroskaParser.js +44 -39
  50. package/lib/matroska/types.d.ts +13 -14
  51. package/lib/mp4/Atom.d.ts +1 -1
  52. package/lib/mp4/AtomToken.d.ts +11 -11
  53. package/lib/mp4/AtomToken.js +3 -2
  54. package/lib/mp4/MP4Parser.js +20 -19
  55. package/lib/mpeg/ExtendedLameHeader.d.ts +1 -1
  56. package/lib/mpeg/MpegParser.js +4 -4
  57. package/lib/mpeg/ReplayGainDataFormat.d.ts +1 -1
  58. package/lib/mpeg/XingTag.d.ts +2 -3
  59. package/lib/mpeg/XingTag.js +1 -1
  60. package/lib/musepack/index.js +1 -1
  61. package/lib/musepack/sv7/BitReader.d.ts +1 -1
  62. package/lib/musepack/sv7/StreamVersion7.d.ts +1 -1
  63. package/lib/musepack/sv7/StreamVersion7.js +1 -1
  64. package/lib/musepack/sv8/StreamVersion8.d.ts +1 -1
  65. package/lib/musepack/sv8/StreamVersion8.js +1 -1
  66. package/lib/ogg/Ogg.d.ts +2 -2
  67. package/lib/ogg/OggParser.d.ts +1 -1
  68. package/lib/ogg/OggParser.js +5 -5
  69. package/lib/ogg/opus/Opus.d.ts +1 -1
  70. package/lib/ogg/opus/Opus.js +6 -6
  71. package/lib/ogg/opus/OpusParser.d.ts +4 -5
  72. package/lib/ogg/opus/OpusParser.js +3 -3
  73. package/lib/ogg/speex/Speex.d.ts +1 -1
  74. package/lib/ogg/speex/Speex.js +13 -13
  75. package/lib/ogg/speex/SpeexParser.d.ts +3 -4
  76. package/lib/ogg/speex/SpeexParser.js +1 -1
  77. package/lib/ogg/theora/Theora.d.ts +1 -1
  78. package/lib/ogg/theora/Theora.js +6 -6
  79. package/lib/ogg/theora/TheoraParser.d.ts +4 -5
  80. package/lib/ogg/theora/TheoraParser.js +4 -4
  81. package/lib/ogg/vorbis/Vorbis.d.ts +3 -4
  82. package/lib/ogg/vorbis/Vorbis.js +11 -12
  83. package/lib/ogg/vorbis/VorbisDecoder.js +1 -1
  84. package/lib/ogg/vorbis/VorbisParser.d.ts +8 -8
  85. package/lib/ogg/vorbis/VorbisParser.js +21 -12
  86. package/lib/riff/RiffChunk.d.ts +1 -1
  87. package/lib/riff/RiffChunk.js +2 -2
  88. package/lib/type.d.ts +9 -11
  89. package/lib/wav/BwfChunk.d.ts +1 -1
  90. package/lib/wav/WaveChunk.d.ts +3 -4
  91. package/lib/wav/WaveChunk.js +8 -7
  92. package/lib/wav/WaveParser.js +2 -2
  93. package/lib/wavpack/WavPackParser.d.ts +1 -0
  94. package/lib/wavpack/WavPackParser.js +5 -3
  95. package/lib/wavpack/WavPackToken.d.ts +1 -1
  96. package/package.json +141 -140
@@ -1,6 +1,6 @@
1
1
  import { INativeMetadataCollector } from './common/MetadataCollector.js';
2
2
  import { IOptions, IAudioMetadata, ParserType } from './type.js';
3
- import { ITokenizer } from 'strtok3/core';
3
+ import type { ITokenizer } from 'strtok3';
4
4
  export interface ITokenParser {
5
5
  /**
6
6
  * Initialize parser with output (metadata), input (tokenizer) & parsing options (options).
@@ -2,7 +2,6 @@ import { fileTypeFromBuffer } from 'file-type';
2
2
  import ContentType from 'content-type';
3
3
  import MimeType from 'media-typer';
4
4
  import initDebug from 'debug';
5
- import { Buffer } from 'node:buffer';
6
5
  import { MetadataCollector } from './common/MetadataCollector.js';
7
6
  import { AIFFParser } from './aiff/AiffParser.js';
8
7
  import { APEv2Parser } from './apev2/APEv2Parser.js';
@@ -55,7 +54,7 @@ export class ParserFactory {
55
54
  if (!parserId) {
56
55
  // Parser could not be determined on MIME-type or extension
57
56
  debug('Guess parser on content...');
58
- const buf = Buffer.alloc(4100);
57
+ const buf = new Uint8Array(4100);
59
58
  await tokenizer.peekBuffer(buf, { mayBeLess: true });
60
59
  if (tokenizer.fileInfo.path) {
61
60
  parserId = this.getParserIdForExtension(tokenizer.fileInfo.path);
@@ -1,6 +1,6 @@
1
1
  import * as Token from 'token-types';
2
2
  import initDebug from 'debug';
3
- import * as strtok3 from 'strtok3/core';
3
+ import * as strtok3 from 'strtok3';
4
4
  import { ID3v2Parser } from '../id3v2/ID3v2Parser.js';
5
5
  import { FourCcToken } from '../common/FourCC.js';
6
6
  import { BasicParser } from '../common/BasicParser.js';
@@ -96,9 +96,8 @@ export class AIFFParser extends BasicParser {
96
96
  }
97
97
  async readTextChunk(header) {
98
98
  const value = await this.tokenizer.readToken(new Token.StringType(header.chunkSize, 'ascii'));
99
- value.split('\0').map(v => v.trim()).filter(v => v && v.length > 0).forEach(v => {
100
- this.metadata.addTag('AIFF', header.chunkID, v.trim());
101
- });
99
+ const values = value.split('\0').map(v => v.trim()).filter(v => v && v.length);
100
+ await Promise.all(values.map(v => this.metadata.addTag('AIFF', header.chunkID, v)));
102
101
  return header.chunkSize;
103
102
  }
104
103
  }
@@ -1,7 +1,5 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { Buffer } from 'node:buffer';
3
1
  import * as iff from '../iff/index.js';
4
- import { IGetToken } from 'strtok3';
2
+ import type { IGetToken } from 'strtok3';
5
3
  /**
6
4
  * The Common Chunk.
7
5
  * Describes fundamental parameters of the waveform data such as sample rate, bit resolution, and how many channels of
@@ -19,5 +17,5 @@ export declare class Common implements IGetToken<ICommon> {
19
17
  private isAifc;
20
18
  len: number;
21
19
  constructor(header: iff.IChunkHeader, isAifc: boolean);
22
- get(buf: Buffer, off: number): ICommon;
20
+ get(buf: Uint8Array, off: number): ICommon;
23
21
  }
@@ -10,22 +10,22 @@ export class Common {
10
10
  }
11
11
  get(buf, off) {
12
12
  // see: https://cycling74.com/forums/aiffs-80-bit-sample-rate-value
13
- const shift = buf.readUInt16BE(off + 8) - 16398;
14
- const baseSampleRate = buf.readUInt16BE(off + 8 + 2);
13
+ const shift = Token.UINT16_BE.get(buf, off + 8) - 16398;
14
+ const baseSampleRate = Token.UINT16_BE.get(buf, off + 8 + 2);
15
15
  const res = {
16
- numChannels: buf.readUInt16BE(off),
17
- numSampleFrames: buf.readUInt32BE(off + 2),
18
- sampleSize: buf.readUInt16BE(off + 6),
16
+ numChannels: Token.UINT16_BE.get(buf, off),
17
+ numSampleFrames: Token.UINT32_BE.get(buf, off + 2),
18
+ sampleSize: Token.UINT16_BE.get(buf, off + 6),
19
19
  sampleRate: shift < 0 ? baseSampleRate >> Math.abs(shift) : baseSampleRate << shift
20
20
  };
21
21
  if (this.isAifc) {
22
22
  res.compressionType = FourCcToken.get(buf, off + 18);
23
23
  if (this.len > 22) {
24
- const strLen = buf.readInt8(off + 22);
24
+ const strLen = Token.UINT8.get(buf, off + 22);
25
25
  if (strLen > 0) {
26
26
  const padding = (strLen + 1) % 2;
27
27
  if (23 + strLen + padding === this.len) {
28
- res.compressionName = new Token.StringType(strLen, 'binary').get(buf, off + 23);
28
+ res.compressionName = new Token.StringType(strLen, 'latin1').get(buf, off + 23);
29
29
  }
30
30
  else {
31
31
  throw new Error('Illegal pstring length');
@@ -1,4 +1,4 @@
1
- import * as strtok3 from 'strtok3/core';
1
+ import * as strtok3 from 'strtok3';
2
2
  import { IOptions, IRandomReader, IApeHeader } from '../type.js';
3
3
  import { INativeMetadataCollector } from '../common/MetadataCollector.js';
4
4
  import { BasicParser } from '../common/BasicParser.js';
@@ -1,7 +1,7 @@
1
1
  import initDebug from 'debug';
2
- import * as strtok3 from 'strtok3/core';
2
+ import * as strtok3 from 'strtok3';
3
3
  import { StringType } from 'token-types';
4
- import { Buffer } from 'node:buffer';
4
+ import { uint8ArrayToString } from 'uint8array-extras';
5
5
  import * as util from '../common/Util.js';
6
6
  import { BasicParser } from '../common/BasicParser.js';
7
7
  import { DataType, DescriptorParser, Header, TagFooter, TagItemHeader } from './APEv2Token.js';
@@ -35,7 +35,7 @@ export class APEv2Parser extends BasicParser {
35
35
  */
36
36
  static async findApeFooterOffset(reader, offset) {
37
37
  // Search for APE footer header at the end of the file
38
- const apeBuf = Buffer.alloc(TagFooter.len);
38
+ const apeBuf = new Uint8Array(TagFooter.len);
39
39
  await reader.randomRead(apeBuf, 0, TagFooter.len, offset - TagFooter.len);
40
40
  const tagFooter = TagFooter.get(apeBuf, 0);
41
41
  if (tagFooter.ID === 'APETAGEX') {
@@ -70,7 +70,7 @@ export class APEv2Parser extends BasicParser {
70
70
  if (this.tokenizer.fileInfo.size) {
71
71
  // Try to read the APEv2 header using just the footer-header
72
72
  const remaining = this.tokenizer.fileInfo.size - this.tokenizer.position; // ToDo: take ID3v1 into account
73
- const buffer = Buffer.alloc(remaining);
73
+ const buffer = new Uint8Array(remaining);
74
74
  await this.tokenizer.readBuffer(buffer);
75
75
  return APEv2Parser.parseTagFooter(this.metadata, buffer, this.options);
76
76
  }
@@ -87,7 +87,7 @@ export class APEv2Parser extends BasicParser {
87
87
  return this.tryParseApeHeader();
88
88
  }
89
89
  async parseTags(footer) {
90
- const keyBuffer = Buffer.alloc(256); // maximum tag key length
90
+ const keyBuffer = new Uint8Array(256); // maximum tag key length
91
91
  let bytesRemaining = footer.size - TagFooter.len;
92
92
  debug(`Parse APE tags at offset=${this.tokenizer.position}, size=${bytesRemaining}`);
93
93
  for (let i = 0; i < footer.fields; i++) {
@@ -107,9 +107,7 @@ export class APEv2Parser extends BasicParser {
107
107
  case DataType.text_utf8: { // utf-8 text-string
108
108
  const value = await this.tokenizer.readToken(new StringType(tagItemHeader.size, 'utf8'));
109
109
  const values = value.split(/\x00/g);
110
- for (const val of values) {
111
- this.metadata.addTag(tagFormat, key, val);
112
- }
110
+ await Promise.all(values.map(val => this.metadata.addTag(tagFormat, key, val)));
113
111
  break;
114
112
  }
115
113
  case DataType.binary: // binary (probably artwork)
@@ -117,12 +115,12 @@ export class APEv2Parser extends BasicParser {
117
115
  await this.tokenizer.ignore(tagItemHeader.size);
118
116
  }
119
117
  else {
120
- const picData = Buffer.alloc(tagItemHeader.size);
118
+ const picData = new Uint8Array(tagItemHeader.size);
121
119
  await this.tokenizer.readBuffer(picData);
122
120
  zero = util.findZero(picData, 0, picData.length);
123
- const description = picData.toString('utf8', 0, zero);
124
- const data = Buffer.from(picData.slice(zero + 1));
125
- this.metadata.addTag(tagFormat, key, {
121
+ const description = uint8ArrayToString(picData.slice(0, zero));
122
+ const data = picData.slice(zero + 1);
123
+ await this.metadata.addTag(tagFormat, key, {
126
124
  description,
127
125
  data
128
126
  });
@@ -1,5 +1,5 @@
1
1
  import * as Token from 'token-types';
2
- import { IGetToken } from 'strtok3/core';
2
+ import type { IGetToken } from 'strtok3';
3
3
  /**
4
4
  * APETag versionIndex history / supported formats
5
5
  *
@@ -1,6 +1,4 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { IGetToken, ITokenizer } from 'strtok3/core';
3
- import { Buffer } from 'node:buffer';
1
+ import type { IGetToken, ITokenizer } from 'strtok3';
4
2
  import { IPicture, ITag } from '../type.js';
5
3
  import GUID from './GUID.js';
6
4
  /**
@@ -56,21 +54,21 @@ export interface IAsfTopLevelObjectHeader extends IAsfObjectHeader {
56
54
  * Token for: 3. ASF top-level Header Object
57
55
  * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3
58
56
  */
59
- export declare const TopLevelHeaderObjectToken: IGetToken<IAsfTopLevelObjectHeader, Buffer>;
57
+ export declare const TopLevelHeaderObjectToken: IGetToken<IAsfTopLevelObjectHeader, Uint8Array>;
60
58
  /**
61
59
  * Token for: 3.1 Header Object (mandatory, one only)
62
60
  * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_1
63
61
  */
64
- export declare const HeaderObjectToken: IGetToken<IAsfObjectHeader, Buffer>;
62
+ export declare const HeaderObjectToken: IGetToken<IAsfObjectHeader, Uint8Array>;
65
63
  export declare abstract class State<T> implements IGetToken<T> {
66
64
  len: number;
67
65
  constructor(header: IAsfObjectHeader);
68
- abstract get(buf: Buffer, off: number): T;
66
+ abstract get(buf: Uint8Array, off: number): T;
69
67
  protected postProcessTag(tags: ITag[], name: string, valueType: number, data: any): void;
70
68
  }
71
69
  export declare class IgnoreObjectState extends State<any> {
72
70
  constructor(header: IAsfObjectHeader);
73
- get(buf: Buffer, off: number): null;
71
+ get(buf: Uint8Array, off: number): null;
74
72
  }
75
73
  /**
76
74
  * Interface for: 3.2: File Properties Object (mandatory, one only)
@@ -176,7 +174,7 @@ export interface IFilePropertiesObject {
176
174
  export declare class FilePropertiesObject extends State<IFilePropertiesObject> {
177
175
  static guid: GUID;
178
176
  constructor(header: IAsfObjectHeader);
179
- get(buf: Buffer, off: number): IFilePropertiesObject;
177
+ get(buf: Uint8Array, off: number): IFilePropertiesObject;
180
178
  }
181
179
  /**
182
180
  * Interface for: 3.3 Stream Properties Object (mandatory, one per stream)
@@ -198,7 +196,7 @@ export interface IStreamPropertiesObject {
198
196
  export declare class StreamPropertiesObject extends State<IStreamPropertiesObject> {
199
197
  static guid: GUID;
200
198
  constructor(header: IAsfObjectHeader);
201
- get(buf: Buffer, off: number): IStreamPropertiesObject;
199
+ get(buf: Uint8Array, off: number): IStreamPropertiesObject;
202
200
  }
203
201
  export interface IHeaderExtensionObject {
204
202
  reserved1: GUID;
@@ -213,7 +211,7 @@ export declare class HeaderExtensionObject implements IGetToken<IHeaderExtension
213
211
  static guid: GUID;
214
212
  len: number;
215
213
  constructor();
216
- get(buf: Buffer, off: number): IHeaderExtensionObject;
214
+ get(buf: Uint8Array, off: number): IHeaderExtensionObject;
217
215
  }
218
216
  export interface ICodecEntry {
219
217
  type: {
@@ -222,7 +220,7 @@ export interface ICodecEntry {
222
220
  };
223
221
  codecName: string;
224
222
  description: string;
225
- information: Buffer;
223
+ information: Uint8Array;
226
224
  }
227
225
  /**
228
226
  * 3.5: Read the Codec-List-Object, which provides user-friendly information about the codecs and formats used to encode the content found in the ASF file.
@@ -237,7 +235,7 @@ export declare class ContentDescriptionObjectState extends State<ITag[]> {
237
235
  static guid: GUID;
238
236
  private static contentDescTags;
239
237
  constructor(header: IAsfObjectHeader);
240
- get(buf: Buffer, off: number): ITag[];
238
+ get(buf: Uint8Array, off: number): ITag[];
241
239
  }
242
240
  /**
243
241
  * 3.11 Extended Content Description Object (optional, one only)
@@ -246,7 +244,7 @@ export declare class ContentDescriptionObjectState extends State<ITag[]> {
246
244
  export declare class ExtendedContentDescriptionObjectState extends State<ITag[]> {
247
245
  static guid: GUID;
248
246
  constructor(header: IAsfObjectHeader);
249
- get(buf: Buffer, off: number): ITag[];
247
+ get(buf: Uint8Array, off: number): ITag[];
250
248
  }
251
249
  export interface IStreamName {
252
250
  streamLanguageId: number;
@@ -286,7 +284,7 @@ export interface IExtendedStreamPropertiesObject {
286
284
  export declare class ExtendedStreamPropertiesObjectState extends State<IExtendedStreamPropertiesObject> {
287
285
  static guid: GUID;
288
286
  constructor(header: IAsfObjectHeader);
289
- get(buf: Buffer, off: number): IExtendedStreamPropertiesObject;
287
+ get(buf: Uint8Array, off: number): IExtendedStreamPropertiesObject;
290
288
  }
291
289
  /**
292
290
  * 4.7 Metadata Object (optional, 0 or 1)
@@ -306,7 +304,7 @@ export interface IWmPicture extends IPicture {
306
304
  format: string;
307
305
  description: string;
308
306
  size: number;
309
- data: Buffer;
307
+ data: Uint8Array;
310
308
  }
311
309
  /**
312
310
  * Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd757977(v=vs.85).aspx
@@ -314,7 +312,7 @@ export interface IWmPicture extends IPicture {
314
312
  export declare class WmPictureToken implements IGetToken<IWmPicture> {
315
313
  len: any;
316
314
  static fromBase64(base64str: string): IPicture;
317
- static fromBuffer(buffer: Buffer): IWmPicture;
315
+ static fromBuffer(buffer: Uint8Array): IWmPicture;
318
316
  constructor(len: any);
319
- get(buffer: Buffer, offset: number): IWmPicture;
317
+ get(buffer: Uint8Array, offset: number): IWmPicture;
320
318
  }
@@ -1,10 +1,10 @@
1
1
  // ASF Objects
2
2
  import * as Token from 'token-types';
3
- import { Buffer } from 'node:buffer';
4
3
  import * as util from '../common/Util.js';
5
4
  import GUID from './GUID.js';
6
5
  import { AsfUtil } from './AsfUtil.js';
7
6
  import { AttachedPictureType } from '../id3v2/ID3v2Token.js';
7
+ import { base64ToUint8Array } from 'uint8array-extras';
8
8
  /**
9
9
  * Data Type: Specifies the type of information being stored. The following values are recognized.
10
10
  */
@@ -43,7 +43,7 @@ export const TopLevelHeaderObjectToken = {
43
43
  len: 30,
44
44
  get: (buf, off) => {
45
45
  return {
46
- objectId: GUID.fromBin(new Token.BufferType(16).get(buf, off)),
46
+ objectId: GUID.fromBin(buf, off),
47
47
  objectSize: Number(Token.UINT64_LE.get(buf, off + 16)),
48
48
  numberOfHeaderObjects: Token.UINT32_LE.get(buf, off + 24)
49
49
  // Reserved: 2 bytes
@@ -58,7 +58,7 @@ export const HeaderObjectToken = {
58
58
  len: 24,
59
59
  get: (buf, off) => {
60
60
  return {
61
- objectId: GUID.fromBin(new Token.BufferType(16).get(buf, off)),
61
+ objectId: GUID.fromBin(buf, off),
62
62
  objectSize: Number(Token.UINT64_LE.get(buf, off + 16))
63
63
  };
64
64
  }
@@ -144,10 +144,11 @@ export class HeaderExtensionObject {
144
144
  this.len = 22;
145
145
  }
146
146
  get(buf, off) {
147
+ const view = new DataView(buf.buffer, off);
147
148
  return {
148
149
  reserved1: GUID.fromBin(buf, off),
149
- reserved2: buf.readUInt16LE(off + 16),
150
- extensionDataSize: buf.readUInt32LE(off + 18)
150
+ reserved2: view.getUint16(16, true),
151
+ extensionDataSize: view.getUint16(18, true)
151
152
  };
152
153
  }
153
154
  }
@@ -159,14 +160,15 @@ HeaderExtensionObject.guid = GUID.HeaderExtensionObject;
159
160
  const CodecListObjectHeader = {
160
161
  len: 20,
161
162
  get: (buf, off) => {
163
+ const view = new DataView(buf.buffer, off);
162
164
  return {
163
- entryCount: buf.readUInt16LE(off + 16)
165
+ entryCount: view.getUint16(16, true)
164
166
  };
165
167
  }
166
168
  };
167
169
  async function readString(tokenizer) {
168
170
  const length = await tokenizer.readNumber(Token.UINT16_LE);
169
- return (await tokenizer.readToken(new Token.StringType(length * 2, 'utf16le'))).replace('\0', '');
171
+ return (await tokenizer.readToken(new Token.StringType(length * 2, 'utf-16le'))).replace('\0', '');
170
172
  }
171
173
  /**
172
174
  * 3.5: Read the Codec-List-Object, which provides user-friendly information about the codecs and formats used to encode the content found in the ASF file.
@@ -182,7 +184,7 @@ export async function readCodecEntries(tokenizer) {
182
184
  }
183
185
  async function readInformation(tokenizer) {
184
186
  const length = await tokenizer.readNumber(Token.UINT16_LE);
185
- const buf = Buffer.alloc(length);
187
+ const buf = new Uint8Array(length);
186
188
  await tokenizer.readBuffer(buf);
187
189
  return buf;
188
190
  }
@@ -212,13 +214,14 @@ export class ContentDescriptionObjectState extends State {
212
214
  }
213
215
  get(buf, off) {
214
216
  const tags = [];
215
- let pos = off + 10;
217
+ const view = new DataView(buf.buffer, off);
218
+ let pos = 10;
216
219
  for (let i = 0; i < ContentDescriptionObjectState.contentDescTags.length; ++i) {
217
- const length = buf.readUInt16LE(off + i * 2);
220
+ const length = view.getUint16(i * 2, true);
218
221
  if (length > 0) {
219
222
  const tagName = ContentDescriptionObjectState.contentDescTags[i];
220
223
  const end = pos + length;
221
- tags.push({ id: tagName, value: AsfUtil.parseUnicodeAttr(buf.slice(pos, end)) });
224
+ tags.push({ id: tagName, value: AsfUtil.parseUnicodeAttr(buf.slice(off + pos, off + end)) });
222
225
  pos = end;
223
226
  }
224
227
  }
@@ -237,18 +240,19 @@ export class ExtendedContentDescriptionObjectState extends State {
237
240
  }
238
241
  get(buf, off) {
239
242
  const tags = [];
240
- const attrCount = buf.readUInt16LE(off);
241
- let pos = off + 2;
243
+ const view = new DataView(buf.buffer, off);
244
+ const attrCount = view.getUint16(0, true);
245
+ let pos = 2;
242
246
  for (let i = 0; i < attrCount; i += 1) {
243
- const nameLen = buf.readUInt16LE(pos);
247
+ const nameLen = view.getUint16(pos, true);
244
248
  pos += 2;
245
- const name = AsfUtil.parseUnicodeAttr(buf.slice(pos, pos + nameLen));
249
+ const name = AsfUtil.parseUnicodeAttr(buf.slice(off + pos, off + pos + nameLen));
246
250
  pos += nameLen;
247
- const valueType = buf.readUInt16LE(pos);
251
+ const valueType = view.getUint16(pos, true);
248
252
  pos += 2;
249
- const valueLen = buf.readUInt16LE(pos);
253
+ const valueLen = view.getUint16(pos, true);
250
254
  pos += 2;
251
- const value = buf.slice(pos, pos + valueLen);
255
+ const value = buf.slice(off + pos, off + pos + valueLen);
252
256
  pos += valueLen;
253
257
  this.postProcessTag(tags, name, valueType, value);
254
258
  }
@@ -265,27 +269,28 @@ export class ExtendedStreamPropertiesObjectState extends State {
265
269
  super(header);
266
270
  }
267
271
  get(buf, off) {
272
+ const view = new DataView(buf.buffer, off);
268
273
  return {
269
274
  startTime: Token.UINT64_LE.get(buf, off),
270
275
  endTime: Token.UINT64_LE.get(buf, off + 8),
271
- dataBitrate: buf.readInt32LE(off + 12),
272
- bufferSize: buf.readInt32LE(off + 16),
273
- initialBufferFullness: buf.readInt32LE(off + 20),
274
- alternateDataBitrate: buf.readInt32LE(off + 24),
275
- alternateBufferSize: buf.readInt32LE(off + 28),
276
- alternateInitialBufferFullness: buf.readInt32LE(off + 32),
277
- maximumObjectSize: buf.readInt32LE(off + 36),
276
+ dataBitrate: view.getInt32(12, true),
277
+ bufferSize: view.getInt32(16, true),
278
+ initialBufferFullness: view.getInt32(20, true),
279
+ alternateDataBitrate: view.getInt32(24, true),
280
+ alternateBufferSize: view.getInt32(28, true),
281
+ alternateInitialBufferFullness: view.getInt32(32, true),
282
+ maximumObjectSize: view.getInt32(36, true),
278
283
  flags: {
279
284
  reliableFlag: util.getBit(buf, off + 40, 0),
280
285
  seekableFlag: util.getBit(buf, off + 40, 1),
281
286
  resendLiveCleanpointsFlag: util.getBit(buf, off + 40, 2)
282
287
  },
283
288
  // flagsNumeric: Token.UINT32_LE.get(buf, off + 64),
284
- streamNumber: buf.readInt16LE(off + 42),
285
- streamLanguageId: buf.readInt16LE(off + 44),
286
- averageTimePerFrame: buf.readInt32LE(off + 52),
287
- streamNameCount: buf.readInt32LE(off + 54),
288
- payloadExtensionSystems: buf.readInt32LE(off + 56),
289
+ streamNumber: view.getInt16(42, true),
290
+ streamLanguageId: view.getInt16(44, true),
291
+ averageTimePerFrame: view.getInt32(52, true),
292
+ streamNameCount: view.getInt32(54, true),
293
+ payloadExtensionSystems: view.getInt32(56, true),
289
294
  streamNames: [], // ToDo
290
295
  streamPropertiesObject: null
291
296
  };
@@ -302,20 +307,20 @@ export class MetadataObjectState extends State {
302
307
  }
303
308
  get(uint8Array, off) {
304
309
  const tags = [];
305
- const buf = Buffer.from(uint8Array);
306
- const descriptionRecordsCount = buf.readUInt16LE(off);
307
- let pos = off + 2;
310
+ const view = new DataView(uint8Array.buffer, off);
311
+ const descriptionRecordsCount = view.getUint16(0, true);
312
+ let pos = 2;
308
313
  for (let i = 0; i < descriptionRecordsCount; i += 1) {
309
314
  pos += 4;
310
- const nameLen = buf.readUInt16LE(pos);
315
+ const nameLen = view.getUint16(pos, true);
311
316
  pos += 2;
312
- const dataType = buf.readUInt16LE(pos);
317
+ const dataType = view.getUint16(pos, true);
313
318
  pos += 2;
314
- const dataLen = buf.readUInt32LE(pos);
319
+ const dataLen = view.getUint32(pos, true);
315
320
  pos += 4;
316
- const name = AsfUtil.parseUnicodeAttr(buf.slice(pos, pos + nameLen));
321
+ const name = AsfUtil.parseUnicodeAttr(uint8Array.slice(off + pos, off + pos + nameLen));
317
322
  pos += nameLen;
318
- const data = buf.slice(pos, pos + dataLen);
323
+ const data = uint8Array.slice(off + pos, off + pos + dataLen);
319
324
  pos += dataLen;
320
325
  this.postProcessTag(tags, name, dataType, data);
321
326
  }
@@ -335,7 +340,7 @@ MetadataLibraryObjectState.guid = GUID.MetadataLibraryObject;
335
340
  */
336
341
  export class WmPictureToken {
337
342
  static fromBase64(base64str) {
338
- return this.fromBuffer(Buffer.from(base64str, 'base64'));
343
+ return this.fromBuffer(base64ToUint8Array(base64str));
339
344
  }
340
345
  static fromBuffer(buffer) {
341
346
  const pic = new WmPictureToken(buffer.length);
@@ -345,17 +350,18 @@ export class WmPictureToken {
345
350
  this.len = len;
346
351
  }
347
352
  get(buffer, offset) {
348
- const typeId = buffer.readUInt8(offset++);
349
- const size = buffer.readInt32LE(offset);
353
+ const view = new DataView(buffer.buffer, offset);
354
+ const typeId = view.getUint8(0);
355
+ const size = view.getInt32(1, true);
350
356
  let index = 5;
351
- while (buffer.readUInt16BE(index) !== 0) {
357
+ while (view.getUint16(index) !== 0) {
352
358
  index += 2;
353
359
  }
354
- const format = buffer.slice(5, index).toString('utf16le');
355
- while (buffer.readUInt16BE(index) !== 0) {
360
+ const format = new Token.StringType(index - 5, 'utf-16le').get(buffer, 5);
361
+ while (view.getUint16(index) !== 0) {
356
362
  index += 2;
357
363
  }
358
- const description = buffer.slice(5, index).toString('utf16le');
364
+ const description = new Token.StringType(index - 5, 'utf-16le').get(buffer, 5);
359
365
  return {
360
366
  type: AttachedPictureType[typeId],
361
367
  format,
@@ -51,11 +51,11 @@ export class AsfParser extends BasicParser {
51
51
  break;
52
52
  case AsfObject.ContentDescriptionObjectState.guid.str: // 3.10
53
53
  tags = await this.tokenizer.readToken(new AsfObject.ContentDescriptionObjectState(header));
54
- this.addTags(tags);
54
+ await this.addTags(tags);
55
55
  break;
56
56
  case AsfObject.ExtendedContentDescriptionObjectState.guid.str: // 3.11
57
57
  tags = await this.tokenizer.readToken(new AsfObject.ExtendedContentDescriptionObjectState(header));
58
- this.addTags(tags);
58
+ await this.addTags(tags);
59
59
  break;
60
60
  case GUID.CodecListObject.str:
61
61
  const codecs = await AsfObject.readCodecEntries(this.tokenizer);
@@ -85,10 +85,8 @@ export class AsfParser extends BasicParser {
85
85
  } while (--numberOfObjectHeaders);
86
86
  // done
87
87
  }
88
- addTags(tags) {
89
- tags.forEach(tag => {
90
- this.metadata.addTag(headerType, tag.id, tag.value);
91
- });
88
+ async addTags(tags) {
89
+ await Promise.all(tags.map(({ id, value }) => this.metadata.addTag(headerType, id, value)));
92
90
  }
93
91
  async parseExtensionObject(extensionSize) {
94
92
  do {
@@ -103,11 +101,11 @@ export class AsfParser extends BasicParser {
103
101
  break;
104
102
  case AsfObject.MetadataObjectState.guid.str: // 4.7
105
103
  const moTags = await this.tokenizer.readToken(new AsfObject.MetadataObjectState(header));
106
- this.addTags(moTags);
104
+ await this.addTags(moTags);
107
105
  break;
108
106
  case AsfObject.MetadataLibraryObjectState.guid.str: // 4.8
109
107
  const mlTags = await this.tokenizer.readToken(new AsfObject.MetadataLibraryObjectState(header));
110
- this.addTags(mlTags);
108
+ await this.addTags(mlTags);
111
109
  break;
112
110
  case GUID.PaddingObject.str:
113
111
  // ToDo: register bytes pad
@@ -1,7 +1,5 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { Buffer } from 'node:buffer';
3
1
  import { DataType } from './AsfObject.js';
4
- export type AttributeParser = (buf: Buffer) => boolean | string | number | bigint | Buffer;
2
+ export type AttributeParser = (buf: Uint8Array) => boolean | string | number | bigint | Uint8Array;
5
3
  export declare class AsfUtil {
6
4
  static getParserForAttr(i: DataType): AttributeParser;
7
5
  static parseUnicodeAttr(uint8Array: Uint8Array): string;
@@ -1,27 +1,26 @@
1
1
  import * as Token from 'token-types';
2
- import { Buffer } from 'node:buffer';
3
2
  import * as util from '../common/Util.js';
4
3
  export class AsfUtil {
5
4
  static getParserForAttr(i) {
6
5
  return AsfUtil.attributeParsers[i];
7
6
  }
8
7
  static parseUnicodeAttr(uint8Array) {
9
- return util.stripNulls(util.decodeString(uint8Array, 'utf16le'));
8
+ return util.stripNulls(util.decodeString(uint8Array, 'utf-16le'));
10
9
  }
11
10
  static parseByteArrayAttr(buf) {
12
- return Buffer.from(buf);
11
+ return new Uint8Array(buf);
13
12
  }
14
13
  static parseBoolAttr(buf, offset = 0) {
15
14
  return AsfUtil.parseWordAttr(buf, offset) === 1;
16
15
  }
17
16
  static parseDWordAttr(buf, offset = 0) {
18
- return buf.readUInt32LE(offset);
17
+ return Token.UINT32_LE.get(buf, offset);
19
18
  }
20
19
  static parseQWordAttr(buf, offset = 0) {
21
20
  return Token.UINT64_LE.get(buf, offset);
22
21
  }
23
22
  static parseWordAttr(buf, offset = 0) {
24
- return buf.readUInt16LE(offset);
23
+ return Token.UINT16_LE.get(buf, offset);
25
24
  }
26
25
  }
27
26
  AsfUtil.attributeParsers = [
package/lib/asf/GUID.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  /**
3
2
  * Ref:
4
3
  * - https://tools.ietf.org/html/draft-fleischman-asf-01, Appendix A: ASF GUIDs
@@ -58,14 +57,14 @@ export default class GUID {
58
57
  static FileTransferMedia: GUID;
59
58
  static BinaryMedia: GUID;
60
59
  static ASF_Index_Placeholder_Object: GUID;
61
- static fromBin(bin: Buffer, offset?: number): GUID;
60
+ static fromBin(bin: Uint8Array, offset?: number): GUID;
62
61
  /**
63
62
  * Decode GUID in format like "B503BF5F-2EA9-CF11-8EE3-00C00C205365"
64
63
  * @param objectId Binary GUID
65
64
  * @param offset Read offset in bytes, default 0
66
65
  * @returns GUID as dashed hexadecimal representation
67
66
  */
68
- static decode(objectId: Buffer, offset?: number): string;
67
+ static decode(objectId: Uint8Array, offset?: number): string;
69
68
  /**
70
69
  * Decode stream type
71
70
  * @param mediaType Media type GUID
@@ -77,8 +76,8 @@ export default class GUID {
77
76
  * @param guid GUID like: "B503BF5F-2EA9-CF11-8EE3-00C00C205365"
78
77
  * @returns Encoded Binary GUID
79
78
  */
80
- static encode(str: string): Buffer;
79
+ static encode(str: string): Uint8Array;
81
80
  constructor(str: string);
82
81
  equals(guid: GUID): boolean;
83
- toBin(): Buffer;
82
+ toBin(): Uint8Array;
84
83
  }