music-metadata 10.6.5 → 10.7.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.
@@ -17,7 +17,6 @@ import { musepackParserLoader } from './musepack/MusepackLoader.js';
17
17
  import { oggParserLoader } from './ogg/OggLoader.js';
18
18
  import { wavpackParserLoader } from './wavpack/WavPackLoader.js';
19
19
  import { riffParserLoader } from './wav/WaveLoader.js';
20
- import { amrParserLoader } from './amr/AmrLoader.js';
21
20
  import { scanAppendingHeaders } from './core.js';
22
21
  const debug = initDebug('music-metadata:parser:factory');
23
22
  export function parseHttpContentType(contentType) {
@@ -46,8 +45,7 @@ export class ParserFactory {
46
45
  wavpackParserLoader,
47
46
  musepackParserLoader,
48
47
  dsfParserLoader,
49
- dsdiffParserLoader,
50
- amrParserLoader
48
+ dsdiffParserLoader
51
49
  ].forEach(parser => this.registerParser(parser));
52
50
  }
53
51
  registerParser(parser) {
@@ -10,13 +10,7 @@ declare const AsfContentParseError_base: {
10
10
  stack?: string;
11
11
  };
12
12
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
13
- prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite /**
14
- * Specifies the amount of time to buffer data before starting to play the file, in millisecond units.
15
- * If this value is nonzero, the Play Duration field and all of the payload Presentation Time fields have been offset
16
- * by this amount. Therefore, player software must subtract the value in the preroll field from the play duration and
17
- * presentation times to calculate their actual values. It follows that all payload Presentation Time fields need to
18
- * be at least this value.
19
- */[]) => any) | undefined;
13
+ prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined;
20
14
  stackTraceLimit: number;
21
15
  };
22
16
  export declare class AsfContentParseError extends AsfContentParseError_base {
@@ -119,7 +119,7 @@ export class AsfParser extends BasicParser {
119
119
  await this.tokenizer.ignore(remaining);
120
120
  break;
121
121
  case GUID.CompatibilityObject.str:
122
- this.tokenizer.ignore(remaining);
122
+ await this.tokenizer.ignore(remaining);
123
123
  break;
124
124
  case GUID.ASF_Index_Placeholder_Object.str:
125
125
  await this.tokenizer.ignore(remaining);
package/lib/default.cjs CHANGED
@@ -1,5 +1,5 @@
1
- // CommonJS core (default) entry point
2
- "use strict";
3
- module.exports = {
4
- loadMusicMetadata: () => import('./core.js'),
5
- };
1
+ // CommonJS core (default) entry point
2
+ "use strict";
3
+ module.exports = {
4
+ loadMusicMetadata: () => import('./core.js'),
5
+ };
@@ -291,7 +291,7 @@ interface IAtomStsdHeader extends IVersionAndFlags {
291
291
  export interface ISampleDescription {
292
292
  dataFormat: string;
293
293
  dataReferenceIndex: number;
294
- description: Uint8Array;
294
+ description: Uint8Array | undefined;
295
295
  }
296
296
  export interface IAtomStsd {
297
297
  header: IAtomStsdHeader;
@@ -214,17 +214,18 @@ const stsdHeader = {
214
214
  };
215
215
  /**
216
216
  * Atom: Sample Description Atom ('stsd')
217
- * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25691
217
+ * Ref: https://developer.apple.com/documentation/quicktime-file-format/sample_description_atom
218
218
  */
219
219
  class SampleDescriptionTable {
220
220
  constructor(len) {
221
221
  this.len = len;
222
222
  }
223
223
  get(buf, off) {
224
+ const descrLen = this.len - 12;
224
225
  return {
225
226
  dataFormat: FourCcToken.get(buf, off),
226
227
  dataReferenceIndex: Token.UINT16_BE.get(buf, off + 10),
227
- description: new Token.Uint8ArrayType(this.len - 12).get(buf, off + 12)
228
+ description: descrLen > 0 ? new Token.Uint8ArrayType(descrLen).get(buf, off + 12) : undefined
228
229
  };
229
230
  }
230
231
  }
@@ -243,7 +244,7 @@ export class StsdAtom {
243
244
  for (let n = 0; n < header.numberOfEntries; ++n) {
244
245
  const size = Token.UINT32_BE.get(buf, off); // Sample description size
245
246
  off += Token.UINT32_BE.len;
246
- table.push(new SampleDescriptionTable(size).get(buf, off));
247
+ table.push(new SampleDescriptionTable(size - Token.UINT32_BE.len).get(buf, off));
247
248
  off += size;
248
249
  }
249
250
  return {
@@ -4,9 +4,9 @@ import { BasicParser } from '../common/BasicParser.js';
4
4
  import { Genres } from '../id3v1/ID3v1Parser.js';
5
5
  import { Atom } from './Atom.js';
6
6
  import * as AtomToken from './AtomToken.js';
7
+ import { Mp4ContentError } from './AtomToken.js';
7
8
  import { TrackType } from '../type.js';
8
9
  import { uint8ArrayToHex, uint8ArrayToString } from 'uint8array-extras';
9
- import { Mp4ContentError } from './AtomToken.js';
10
10
  const debug = initDebug('music-metadata:parser:MP4');
11
11
  const tagFormat = 'iTunes';
12
12
  const encoderDict = {
@@ -442,14 +442,16 @@ export class MP4Parser extends BasicParser {
442
442
  dataReferenceIndex: sampleDescription.dataReferenceIndex
443
443
  };
444
444
  let offset = 0;
445
- const version = AtomToken.SoundSampleDescriptionVersion.get(sampleDescription.description, offset);
446
- offset += AtomToken.SoundSampleDescriptionVersion.len;
447
- if (version.version === 0 || version.version === 1) {
448
- // Sound Sample Description (Version 0)
449
- ssd.description = AtomToken.SoundSampleDescriptionV0.get(sampleDescription.description, offset);
450
- }
451
- else {
452
- debug(`Warning: sound-sample-description ${version} not implemented`);
445
+ if (sampleDescription.description) {
446
+ const version = AtomToken.SoundSampleDescriptionVersion.get(sampleDescription.description, offset);
447
+ offset += AtomToken.SoundSampleDescriptionVersion.len;
448
+ if (version.version === 0 || version.version === 1) {
449
+ // Sound Sample Description (Version 0)
450
+ ssd.description = AtomToken.SoundSampleDescriptionV0.get(sampleDescription.description, offset);
451
+ }
452
+ else {
453
+ debug(`Warning: sound-sample-description ${version} not implemented`);
454
+ }
453
455
  }
454
456
  return ssd;
455
457
  }
package/lib/node.cjs CHANGED
@@ -1,5 +1,5 @@
1
- // CommonJS Node entry point
2
- "use strict";
3
- module.exports = {
4
- loadMusicMetadata: () => import('./index.js'),
5
- };
1
+ // CommonJS Node entry point
2
+ "use strict";
3
+ module.exports = {
4
+ loadMusicMetadata: () => import('./index.js'),
5
+ };
package/package.json CHANGED
@@ -1,150 +1,150 @@
1
- {
2
- "name": "music-metadata",
3
- "description": "Music metadata parser for Node.js, supporting virtual any audio and tag format.",
4
- "version": "10.6.5",
5
- "author": {
6
- "name": "Borewit",
7
- "url": "https://github.com/Borewit"
8
- },
9
- "funding": [
10
- {
11
- "type": "github",
12
- "url": "https://github.com/sponsors/Borewit"
13
- },
14
- {
15
- "type": "buymeacoffee",
16
- "url": "https://buymeacoffee.com/borewit"
17
- }
18
- ],
19
- "type": "module",
20
- "exports": {
21
- ".": {
22
- "node": {
23
- "import": "./lib/index.js",
24
- "require": "./lib/node.cjs",
25
- "types": "./lib/index.d.ts"
26
- },
27
- "default": {
28
- "import": "./lib/core.js",
29
- "require": "./lib/default.cjs",
30
- "types": "./lib/core.d.ts"
31
- }
32
- }
33
- },
34
- "types": "lib/index.d.ts",
35
- "files": [
36
- "lib/**/*.js",
37
- "lib/**/*.d.ts",
38
- "lib/*.cjs"
39
- ],
40
- "keywords": [
41
- "music",
42
- "metadata",
43
- "meta",
44
- "audio",
45
- "tag",
46
- "tags",
47
- "duration",
48
- "MusicBrainz",
49
- "Discogs",
50
- "Picard",
51
- "ID3",
52
- "ID3v1",
53
- "ID3v2",
54
- "m4a",
55
- "m4b",
56
- "mp3",
57
- "mp4",
58
- "Vorbis",
59
- "ogg",
60
- "flac",
61
- "Matroska",
62
- "WebM",
63
- "EBML",
64
- "asf",
65
- "wma",
66
- "wmv",
67
- "ape",
68
- "MonkeyAudio",
69
- "aiff",
70
- "wav",
71
- "WavPack",
72
- "Opus",
73
- "speex",
74
- "musepack",
75
- "mpc",
76
- "dsd",
77
- "dsf",
78
- "mpc",
79
- "dff",
80
- "dsdiff",
81
- "aac",
82
- "adts",
83
- "length",
84
- "chapter",
85
- "info",
86
- "parse",
87
- "parser",
88
- "bwf",
89
- "slt",
90
- "lyrics"
91
- ],
92
- "scripts": {
93
- "clean": "del-cli 'lib/**/*.js' 'lib/**/*.js.map' 'lib/**/*.d.ts' 'src/**/*.d.ts' 'test/**/*.js' 'test/**/*.js.map' 'test/**/*.js' 'test/**/*.js.map' 'doc-gen/**/*.js' 'doc-gen/**/*.js.map'",
94
- "compile-src": "tsc -p lib",
95
- "compile-test": "tsc -p test",
96
- "compile-doc": "tsc -p doc-gen",
97
- "compile": "yarn run compile-src && yarn compile-test && yarn compile-doc",
98
- "lint-ts": "biome check",
99
- "lint-md": "yarn run remark -u remark-preset-lint-consistent .",
100
- "lint": "yarn run lint-ts && yarn run lint-md",
101
- "test": "mocha",
102
- "build": "yarn run clean && yarn compile && yarn run doc-gen",
103
- "test-coverage": "c8 yarn run test",
104
- "send-codacy": "c8 report --reporter=text-lcov | codacy-coverage",
105
- "doc-gen": "yarn node doc-gen/gen.js"
106
- },
107
- "dependencies": {
108
- "@tokenizer/token": "^0.3.0",
109
- "content-type": "^1.0.5",
110
- "debug": "^4.4.0",
111
- "file-type": "^19.6.0",
112
- "link": "^2.1.1",
113
- "media-typer": "^1.1.0",
114
- "strtok3": "^10.0.1",
115
- "token-types": "^6.0.0",
116
- "uint8array-extras": "^1.4.0"
117
- },
118
- "devDependencies": {
119
- "@biomejs/biome": "1.9.4",
120
- "@types/chai": "^5.0.1",
121
- "@types/chai-as-promised": "^8.0.1",
122
- "@types/content-type": "^1.1.8",
123
- "@types/debug": "^4.1.12",
124
- "@types/media-typer": "^1.1.3",
125
- "@types/mocha": "^10.0.10",
126
- "@types/node": "^22.10.1",
127
- "c8": "^10.1.3",
128
- "chai": "^5.1.2",
129
- "chai-as-promised": "^8.0.1",
130
- "del-cli": "^6.0.0",
131
- "mime": "^4.0.6",
132
- "mocha": "^11.0.1",
133
- "remark-cli": "^12.0.1",
134
- "remark-preset-lint-consistent": "^6.0.0",
135
- "ts-node": "^10.9.2",
136
- "typescript": "^5.7.2"
137
- },
138
- "engines": {
139
- "node": ">=16.0.0"
140
- },
141
- "repository": {
142
- "type": "git",
143
- "url": "git+https://github.com/borewit/music-metadata.git"
144
- },
145
- "license": "MIT",
146
- "bugs": {
147
- "url": "https://github.com/Borewit/music-metadata/issues"
148
- },
149
- "packageManager": "yarn@4.3.1"
150
- }
1
+ {
2
+ "name": "music-metadata",
3
+ "description": "Music metadata parser for Node.js, supporting virtual any audio and tag format.",
4
+ "version": "10.7.1",
5
+ "author": {
6
+ "name": "Borewit",
7
+ "url": "https://github.com/Borewit"
8
+ },
9
+ "funding": [
10
+ {
11
+ "type": "github",
12
+ "url": "https://github.com/sponsors/Borewit"
13
+ },
14
+ {
15
+ "type": "buymeacoffee",
16
+ "url": "https://buymeacoffee.com/borewit"
17
+ }
18
+ ],
19
+ "type": "module",
20
+ "exports": {
21
+ ".": {
22
+ "node": {
23
+ "import": "./lib/index.js",
24
+ "require": "./lib/node.cjs",
25
+ "types": "./lib/index.d.ts"
26
+ },
27
+ "default": {
28
+ "import": "./lib/core.js",
29
+ "require": "./lib/default.cjs",
30
+ "types": "./lib/core.d.ts"
31
+ }
32
+ }
33
+ },
34
+ "types": "lib/index.d.ts",
35
+ "files": [
36
+ "lib/**/*.js",
37
+ "lib/**/*.d.ts",
38
+ "lib/*.cjs"
39
+ ],
40
+ "keywords": [
41
+ "music",
42
+ "metadata",
43
+ "meta",
44
+ "audio",
45
+ "tag",
46
+ "tags",
47
+ "duration",
48
+ "MusicBrainz",
49
+ "Discogs",
50
+ "Picard",
51
+ "ID3",
52
+ "ID3v1",
53
+ "ID3v2",
54
+ "m4a",
55
+ "m4b",
56
+ "mp3",
57
+ "mp4",
58
+ "Vorbis",
59
+ "ogg",
60
+ "flac",
61
+ "Matroska",
62
+ "WebM",
63
+ "EBML",
64
+ "asf",
65
+ "wma",
66
+ "wmv",
67
+ "ape",
68
+ "MonkeyAudio",
69
+ "aiff",
70
+ "wav",
71
+ "WavPack",
72
+ "Opus",
73
+ "speex",
74
+ "musepack",
75
+ "mpc",
76
+ "dsd",
77
+ "dsf",
78
+ "mpc",
79
+ "dff",
80
+ "dsdiff",
81
+ "aac",
82
+ "adts",
83
+ "length",
84
+ "chapter",
85
+ "info",
86
+ "parse",
87
+ "parser",
88
+ "bwf",
89
+ "slt",
90
+ "lyrics"
91
+ ],
92
+ "scripts": {
93
+ "clean": "del-cli 'lib/**/*.js' 'lib/**/*.js.map' 'lib/**/*.d.ts' 'test/**/*.js' 'test/**/*.js.map' 'test/**/*.js' 'test/**/*.js.map' 'doc-gen/**/*.js' 'doc-gen/**/*.js.map'",
94
+ "compile-src": "tsc -p lib",
95
+ "compile-test": "tsc -p test",
96
+ "compile-doc": "tsc -p doc-gen",
97
+ "compile": "yarn run compile-src && yarn compile-test && yarn compile-doc",
98
+ "lint-ts": "biome check",
99
+ "lint-md": "yarn run remark -u remark-preset-lint-consistent .",
100
+ "lint": "yarn run lint-ts && yarn run lint-md",
101
+ "test": "mocha",
102
+ "build": "yarn run clean && yarn compile && yarn run doc-gen",
103
+ "test-coverage": "c8 yarn run test",
104
+ "send-codacy": "c8 report --reporter=text-lcov | codacy-coverage",
105
+ "doc-gen": "yarn node doc-gen/gen.js"
106
+ },
107
+ "dependencies": {
108
+ "@tokenizer/token": "^0.3.0",
109
+ "content-type": "^1.0.5",
110
+ "debug": "^4.4.0",
111
+ "file-type": "^19.6.0",
112
+ "link": "^2.1.1",
113
+ "media-typer": "^1.1.0",
114
+ "strtok3": "^10.0.1",
115
+ "token-types": "^6.0.0",
116
+ "uint8array-extras": "^1.4.0"
117
+ },
118
+ "devDependencies": {
119
+ "@biomejs/biome": "1.9.4",
120
+ "@types/chai": "^5.0.1",
121
+ "@types/chai-as-promised": "^8.0.1",
122
+ "@types/content-type": "^1.1.8",
123
+ "@types/debug": "^4.1.12",
124
+ "@types/media-typer": "^1.1.3",
125
+ "@types/mocha": "^10.0.10",
126
+ "@types/node": "^22.10.7",
127
+ "c8": "^10.1.3",
128
+ "chai": "^5.1.2",
129
+ "chai-as-promised": "^8.0.1",
130
+ "del-cli": "^6.0.0",
131
+ "mime": "^4.0.6",
132
+ "mocha": "^11.0.1",
133
+ "remark-cli": "^12.0.1",
134
+ "remark-preset-lint-consistent": "^6.0.0",
135
+ "ts-node": "^10.9.2",
136
+ "typescript": "^5.7.3"
137
+ },
138
+ "engines": {
139
+ "node": ">=16.0.0"
140
+ },
141
+ "repository": {
142
+ "type": "git",
143
+ "url": "git+https://github.com/borewit/music-metadata.git"
144
+ },
145
+ "license": "MIT",
146
+ "bugs": {
147
+ "url": "https://github.com/Borewit/music-metadata/issues"
148
+ },
149
+ "packageManager": "yarn@4.6.0"
150
+ }
@@ -1,2 +0,0 @@
1
- import type { IParserLoader } from '../ParserFactory.js';
2
- export declare const amrParserLoader: IParserLoader;
@@ -1,8 +0,0 @@
1
- export const amrParserLoader = {
2
- parserType: 'amr',
3
- extensions: ['.amr'],
4
- async load(metadata, tokenizer, options) {
5
- return new (await import('./AmrParser.js')).AmrParser(metadata, tokenizer, options);
6
- }
7
- };
8
- //# sourceMappingURL=AmrLoader.js.map
@@ -1,7 +0,0 @@
1
- import { BasicParser } from '../common/BasicParser.js';
2
- /**
3
- * Adaptive Multi-Rate audio codec
4
- */
5
- export declare class AmrParser extends BasicParser {
6
- parse(): Promise<void>;
7
- }
@@ -1,58 +0,0 @@
1
- import { BasicParser } from '../common/BasicParser.js';
2
- import { AnsiStringType } from 'token-types';
3
- import initDebug from 'debug';
4
- import { FrameHeader } from './AmrToken.js';
5
- import { EndOfStreamError } from 'strtok3';
6
- const debug = initDebug('music-metadata:parser:AMR');
7
- /**
8
- * There are 8 varying levels of compression. First byte of the frame specifies CMR
9
- * (codec mode request), values 0-7 are valid for AMR. Each mode have different frame size.
10
- * This table reflects that fact.
11
- */
12
- const m_block_size = [12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0];
13
- /**
14
- * Adaptive Multi-Rate audio codec
15
- */
16
- export class AmrParser extends BasicParser {
17
- async parse() {
18
- const magicNr = await this.tokenizer.readToken(new AnsiStringType(5));
19
- if (magicNr !== '#!AMR') {
20
- throw new Error('Invalid AMR file: invalid MAGIC number');
21
- }
22
- this.metadata.setFormat('container', 'AMR');
23
- this.metadata.setFormat('codec', 'AMR');
24
- this.metadata.setFormat('sampleRate', 8000);
25
- this.metadata.setFormat('bitrate', 64000);
26
- this.metadata.setFormat('numberOfChannels', 1);
27
- let total_size = 0;
28
- let frames = 0;
29
- const assumedFileLength = this.tokenizer.fileInfo?.size ?? Number.MAX_SAFE_INTEGER;
30
- if (this.options.duration) {
31
- let header;
32
- while (this.tokenizer.position < assumedFileLength) {
33
- try {
34
- header = await this.tokenizer.readToken(FrameHeader);
35
- }
36
- catch (error) {
37
- if (error instanceof EndOfStreamError)
38
- break;
39
- throw error;
40
- }
41
- /* first byte is rate mode. each rate mode has frame of given length. look it up. */
42
- const size = m_block_size[header.frameType];
43
- if (size > 0) {
44
- total_size += size + 1;
45
- if (total_size > assumedFileLength)
46
- break;
47
- await this.tokenizer.ignore(size);
48
- ++frames;
49
- }
50
- else {
51
- debug(`Found no-data frame, frame-type: ${header.frameType}. Skipping`);
52
- }
53
- }
54
- this.metadata.setFormat('duration', frames * 0.02);
55
- }
56
- }
57
- }
58
- //# sourceMappingURL=AmrParser.js.map
@@ -1,10 +0,0 @@
1
- import type { IGetToken } from 'strtok3';
2
- export interface IFrameHeader {
3
- frameType: number;
4
- }
5
- /**
6
- * ID3v2 header
7
- * Ref: http://id3.org/id3v2.3.0#ID3v2_header
8
- * ToDo
9
- */
10
- export declare const FrameHeader: IGetToken<IFrameHeader>;
@@ -1,15 +0,0 @@
1
- import { getBitAllignedNumber } from '../common/Util.js';
2
- /**
3
- * ID3v2 header
4
- * Ref: http://id3.org/id3v2.3.0#ID3v2_header
5
- * ToDo
6
- */
7
- export const FrameHeader = {
8
- len: 1,
9
- get: (buf, off) => {
10
- return {
11
- frameType: getBitAllignedNumber(buf, off, 1, 4)
12
- };
13
- }
14
- };
15
- //# sourceMappingURL=AmrToken.js.map
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};