music-metadata 11.16.1 → 12.1.0

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 (85) hide show
  1. package/README.md +78 -35
  2. package/lib/ParseError.d.ts +10 -3
  3. package/lib/ParseError.js +2 -0
  4. package/lib/ParserFactory.js +10 -4
  5. package/lib/aiff/AiffParser.js +1 -4
  6. package/lib/aiff/AiffToken.d.ts +4 -3
  7. package/lib/aiff/AiffToken.js +2 -0
  8. package/lib/apev2/APEv2Parser.d.ts +4 -3
  9. package/lib/apev2/APEv2Parser.js +2 -4
  10. package/lib/asf/AsfGuid.js +49 -49
  11. package/lib/asf/AsfObject.d.ts +11 -5
  12. package/lib/asf/AsfObject.js +117 -35
  13. package/lib/asf/AsfParser.d.ts +3 -0
  14. package/lib/asf/AsfParser.js +81 -12
  15. package/lib/common/BasicParser.js +3 -0
  16. package/lib/common/CombinedTagMapper.js +1 -1
  17. package/lib/common/GenericTagMapper.js +3 -1
  18. package/lib/common/MetadataCollector.d.ts +1 -0
  19. package/lib/common/MetadataCollector.js +35 -24
  20. package/lib/common/TrackInfo.d.ts +5 -0
  21. package/lib/common/TrackInfo.js +39 -0
  22. package/lib/common/Util.d.ts +1 -1
  23. package/lib/common/Util.js +6 -12
  24. package/lib/core.d.ts +1 -1
  25. package/lib/core.js +6 -11
  26. package/lib/dsdiff/DsdiffParser.d.ts +4 -3
  27. package/lib/dsf/DsfParser.d.ts +4 -3
  28. package/lib/ebml/EbmlIterator.d.ts +4 -3
  29. package/lib/ebml/EbmlIterator.js +4 -3
  30. package/lib/flac/FlacParser.js +1 -4
  31. package/lib/id3v1/ID3v1Parser.js +3 -0
  32. package/lib/id3v2/AbstractID3Parser.js +1 -4
  33. package/lib/id3v2/FrameParser.d.ts +4 -3
  34. package/lib/id3v2/FrameParser.js +2 -0
  35. package/lib/id3v2/ID3v2Parser.js +5 -7
  36. package/lib/matroska/MatroskaDtd.js +1 -0
  37. package/lib/matroska/MatroskaParser.js +38 -22
  38. package/lib/matroska/types.d.ts +8 -32
  39. package/lib/matroska/types.js +1 -18
  40. package/lib/mp4/Atom.js +6 -0
  41. package/lib/mp4/AtomToken.d.ts +15 -4
  42. package/lib/mp4/AtomToken.js +99 -13
  43. package/lib/mp4/MP4Parser.d.ts +6 -0
  44. package/lib/mp4/MP4Parser.js +350 -147
  45. package/lib/mpeg/AdtsFrameHeader.d.ts +17 -0
  46. package/lib/mpeg/AdtsFrameHeader.js +44 -0
  47. package/lib/mpeg/MpegFrameHeader.d.ts +41 -0
  48. package/lib/mpeg/MpegFrameHeader.js +84 -0
  49. package/lib/mpeg/MpegParser.d.ts +11 -24
  50. package/lib/mpeg/MpegParser.js +75 -335
  51. package/lib/musepack/MusepackConentError.d.ts +4 -3
  52. package/lib/musepack/sv7/BitReader.js +3 -2
  53. package/lib/musepack/sv7/MpcSv7Parser.js +3 -6
  54. package/lib/musepack/sv8/MpcSv8Parser.js +1 -4
  55. package/lib/musepack/sv8/StreamVersion8.js +1 -0
  56. package/lib/ogg/OggLoader.js +1 -1
  57. package/lib/ogg/OggParser.d.ts +4 -3
  58. package/lib/ogg/OggParser.js +49 -8
  59. package/lib/ogg/OggStreamMetadata.d.ts +14 -0
  60. package/lib/ogg/OggStreamMetadata.js +27 -0
  61. package/lib/ogg/OggToken.d.ts +1 -0
  62. package/lib/ogg/OggToken.js +3 -1
  63. package/lib/ogg/flac/FlacStream.d.ts +3 -1
  64. package/lib/ogg/flac/FlacStream.js +21 -3
  65. package/lib/ogg/opus/Opus.d.ts +4 -3
  66. package/lib/ogg/opus/Opus.js +1 -0
  67. package/lib/ogg/opus/OpusStream.js +4 -2
  68. package/lib/ogg/speex/SpeexStream.js +2 -1
  69. package/lib/ogg/theora/Theora.d.ts +4 -0
  70. package/lib/ogg/theora/Theora.js +5 -1
  71. package/lib/ogg/theora/TheoraStream.d.ts +1 -1
  72. package/lib/ogg/theora/TheoraStream.js +15 -1
  73. package/lib/ogg/vorbis/Vorbis.js +4 -3
  74. package/lib/ogg/vorbis/VorbisDecoder.js +2 -0
  75. package/lib/ogg/vorbis/VorbisStream.d.ts +4 -3
  76. package/lib/ogg/vorbis/VorbisStream.js +7 -3
  77. package/lib/riff/RiffChunk.js +3 -0
  78. package/lib/type.d.ts +34 -3
  79. package/lib/type.js +22 -1
  80. package/lib/wav/WaveChunk.d.ts +4 -3
  81. package/lib/wav/WaveChunk.js +2 -0
  82. package/lib/wav/WaveParser.js +7 -6
  83. package/lib/wavpack/WavPackParser.d.ts +4 -3
  84. package/lib/wavpack/WavPackParser.js +1 -4
  85. package/package.json +22 -17
package/README.md CHANGED
@@ -23,12 +23,12 @@ The [`music-metadata`](https://github.com/Borewit/music-metadata) module is idea
23
23
  ## Compatibility
24
24
 
25
25
  Module: version 8 migrated from [CommonJS](https://en.wikipedia.org/wiki/CommonJS) to [pure ECMAScript Module (ESM)](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
26
- The distributed JavaScript codebase is compliant with the [ECMAScript 2020 (11th Edition)](https://en.wikipedia.org/wiki/ECMAScript_version_history#11th_Edition_%E2%80%93_ECMAScript_2020) standard.
26
+ The distributed JavaScript codebase targets [ECMAScript 2023 (14th Edition)](https://262.ecma-international.org/14.0/).
27
27
 
28
28
  > [!NOTE]
29
29
  > See also [CommonJS backward Compatibility](#commonjs-backward-compatibility)
30
30
 
31
- This module requires a [Node.js ≥ 18](https://nodejs.org/en/about/previous-releases) engine.
31
+ This module requires a [Node.js ≥ 22](https://nodejs.org/en/about/previous-releases) engine.
32
32
  It can also be used in a browser environment when bundled with a module bundler.
33
33
 
34
34
  ## Support the Project
@@ -99,11 +99,12 @@ Support for encoding / format details:
99
99
 
100
100
 
101
101
  ## Online demo's
102
- - [<img src="https://raw.githubusercontent.com/Borewit/audio-tag-analyzer/master/src/assets/icon/audio-tag-analyzer.svg" width="40">Audio Tag Analyzer](https://audio-tag-analyzer.netlify.app/)
103
- - [<img src="https://cdn.sanity.io/images/3do82whm/next/ba8c847f13a5fa39d88f8bc9b7846b7886531b18-2500x2500.svg" width="40"> Webamp](https://webamp.org/)
102
+ - [<img src="https://raw.githubusercontent.com/Borewit/audio-tag-analyzer-vite/master/public/favicon.svg" width="40" alt="Audio Tag Analyzer logo"> Audio Tag Analyzer](https://audio-tag-analyzer.netlify.app/) ([source code](https://github.com/Borewit/audio-tag-analyzer-vite))
104
103
  - [ICY Radio Stream Player](https://icy-radio-stream-player.netlify.app/)
105
104
  - Expected to be released soon: [Overtone](https://overtone.pro/) by [Johannes Schickling](https://github.com/schickling)
106
105
 
106
+ Used by [around 50k+ GitHub projects](https://github.com/Borewit/music-metadata/network/dependents).
107
+
107
108
  ## Usage
108
109
 
109
110
  ### Installation
@@ -605,7 +606,10 @@ Returns a list of supported MIME-types. This may include some MIME-types which a
605
606
  only that the parser will attempt to calculate it when possible, even if it requires reading the full file.
606
607
 
607
608
  - `includeChapters`: `boolean` (default: `false`)
608
- When `true`, the MP4 parser scans the `mdat` atom for chapters.
609
+ When `true`, the MP4 parser reads QuickTime chapter tracks and Nero `chpl` chapter lists.
610
+ A usable QuickTime chapter track takes precedence over a Nero list.
611
+ Files, buffers, and Blobs support chapters whether `moov` appears before or after `mdat`.
612
+ For forward-only streams, `moov` must appear before the chapter data.
609
613
 
610
614
  - `mkvUseIndex`: `boolean` (default: `false`)
611
615
 
@@ -664,45 +668,84 @@ Audio format information. Defined in the TypeScript `IFormat` interface:
664
668
 
665
669
  #### `metadata.format.trackInfo`
666
670
 
667
- Containers such as Matroska and MPEG-4 can contain multiple audio and video tracks.
668
- The experimental `metadata.format.trackInfo` property describes these individual tracks.
671
+ `metadata.format.trackInfo` provides the same track abstraction for single-stream audio files and
672
+ multi-track containers (MPEG-4, Matroska, ASF, and Ogg). Tracks can carry audio, video, subtitles, or
673
+ metadata. Import `TrackType` from `music-metadata` to select tracks without knowing the container:
674
+
675
+ ```js
676
+ import { parseFile, TrackType } from 'music-metadata';
677
+
678
+ const { format } = await parseFile('movie.mp4');
679
+ const audioTracks = format.trackInfo.filter(track => track.type === TrackType.audio);
680
+ const videoTracks = format.trackInfo.filter(track => track.type === TrackType.video);
681
+ ```
682
+
683
+ Each entry describes one discovered track. The order follows container discovery and does not identify
684
+ a preferred track; use `type`, container flags, and language to choose one. In MPEG-4, the codec and
685
+ media properties describe the first sample description, even when the track has multiple sample descriptions. In Ogg, entries describe
686
+ logical media streams; Skeleton headers do not create media tracks. Single-stream audio parsers map
687
+ their format properties to one audio track after parsing.
688
+
689
+ Properties are optional when unavailable and are not copied between tracks. In particular, a container
690
+ or summary bitrate is not a per-track bitrate. MPEG-4 track timing comes from media headers (or parsed
691
+ audio fragments), and track bitrates from sample sizes and duration. ASF supplies audio/video stream
692
+ properties and stream bitrates from both standalone and nested Stream Properties Objects. Codec List
693
+ entries supply names for matching streams; unused codecs do not create tracks. Matroska applies
694
+ specified defaults for flags, language, channels, and sample rate, and prefers IETF language tags when present. Video duration/bitrate coverage and overall
695
+ video statistics remain incomplete. The existing `format` fields retain their summary semantics.
696
+
697
+ For Ogg/Opus, the per-track average bitrate uses the logical stream's payload bytes, including codec
698
+ headers and excluding Ogg framing and other streams. It requires the logical stream's end-of-stream
699
+ (EOS) page and a known duration; reaching input EOF alone is insufficient. Set `duration: true` to
700
+ allow scanning when needed. The summary `format.bitrate` retains
701
+ its existing file-size estimate and can differ from the per-track bitrate. Vorbis and Speex use nominal
702
+ bitrates when their headers provide them.
669
703
 
670
704
  `metadata.format.trackInfo` is an array of [trackInfo](#trackinfo) objects, empty when no track information is available.
671
705
 
672
706
  ##### trackInfo
673
707
 
674
708
  Individual track information. Defined in the TypeScript `ITrackInfo` interface:
675
- - `trackInfo.type?: TrackType` Track type
709
+ - `trackInfo.id?: number` Container track ID/number, or Ogg stream serial number; only meaningful within the file
710
+ - `trackInfo.type?: TrackType` Track type (`audio`, `video`, `subtitle`, `metadata`, or other known types)
711
+ - `trackInfo.codecId?: string` Container-specific codec identifier, such as `mp4a`, `A_AAC`, or ASF audio format tag `0x0161`
676
712
  - `trackInfo.codecName?: string` Codec name
713
+ - `trackInfo.codecProfile?: string` Codec profile
714
+ - `trackInfo.duration?: number` Track duration in seconds
715
+ - `trackInfo.bitrate?: number` Encoded track bitrate in bits per second
716
+ - `trackInfo.lossless?: boolean` Whether the track uses lossless compression
677
717
  - `trackInfo.codecSettings?: string` Codec settings
678
- - `trackInfo.flagEnabled?: boolean` Set if the track is usable, default: `true`
679
- - `trackInfo.flagDefault?: boolean` Set if that track (audio, video or subs) SHOULD be active if no language found matches the user preference.
680
- - `trackInfo.flagLacing?: boolean` Set if the track **may** contain blocks using lacing
718
+ - `trackInfo.flagEnabled?: boolean` Whether the track is enabled; Matroska defaults to `true`, MPEG-4 uses the track header flag
719
+ - `trackInfo.flagDefault?: boolean` Whether the container marks the track as a default selection; Matroska defaults to `true`
720
+ - `trackInfo.flagForced?: boolean` Whether a subtitle track should be displayed without explicit selection
721
+ - `trackInfo.flagLacing?: boolean` Whether a Matroska track may contain blocks using lacing; defaults to `true`
681
722
  - `trackInfo.name?: string` A human-readable track name.
682
723
  - `trackInfo.language?: string` Specifies the language of the track
683
- - `trackInfo.audio?: IAudioTrack`, see [`trackInfo.audioTrack`](#trackinfoaudiotrack)
684
- - `trackInfo.video?: IVideoTrack`, see [`trackInfo.videoTrack`](#trackinfovideotrack)
685
-
686
- ##### `trackInfo.audioTrack`
687
-
688
- - `audioTrack.samplingFrequency?: number`
689
- - `audioTrack.outputSamplingFrequency?: number`
690
- - `audioTrack.channels?: number`
691
- - `audioTrack.channelPositions?: Uint8Array`
692
- - `audioTrack.bitDepth?: number`
693
-
694
- ##### `trackInfo.videoTrack`
695
-
696
- - `videoTrack.flagInterlaced?: boolean`
697
- - `videoTrack.stereoMode?: number`
698
- - `videoTrack.pixelWidth?: number`
699
- - `videoTrack.pixelHeight?: number`
700
- - `videoTrack.displayWidth?: number`
701
- - `videoTrack.displayHeight?: number`
702
- - `videoTrack.displayUnit?: number`
703
- - `videoTrack.aspectRatioType?: number`
704
- - `videoTrack.colourSpace?: Uint8Array`
705
- - `videoTrack.gammaValue?: number`
724
+ - `trackInfo.audio?: IAudioTrack`, see [`trackInfo.audio`](#trackinfoaudio)
725
+ - `trackInfo.video?: IVideoTrack`, see [`trackInfo.video`](#trackinfovideo)
726
+
727
+ ##### `trackInfo.audio`
728
+
729
+ - `trackInfo.audio.numberOfSamples?: number` Number of decoded sample frames (one sample per channel), when known
730
+ - `trackInfo.audio.samplingFrequency?: number` Sample rate in hertz; for Opus, the informational original input rate
731
+ - `trackInfo.audio.outputSamplingFrequency?: number` Output sample rate in hertz; Opus granules and sample counts use 48000 Hz
732
+ - `trackInfo.audio.channels?: number`
733
+ - `trackInfo.audio.channelPositions?: Uint8Array`
734
+ - `trackInfo.audio.bitDepth?: number`
735
+
736
+ ##### `trackInfo.video`
737
+
738
+ - `trackInfo.video.frameRate?: number` Frames per second, when known
739
+ - `trackInfo.video.flagInterlaced?: boolean`
740
+ - `trackInfo.video.stereoMode?: number`
741
+ - `trackInfo.video.pixelWidth?: number`
742
+ - `trackInfo.video.pixelHeight?: number`
743
+ - `trackInfo.video.displayWidth?: number`
744
+ - `trackInfo.video.displayHeight?: number`
745
+ - `trackInfo.video.displayUnit?: number`
746
+ - `trackInfo.video.aspectRatioType?: number`
747
+ - `trackInfo.video.colourSpace?: Uint8Array`
748
+ - `trackInfo.video.gammaValue?: number`
706
749
 
707
750
  #### `metadata.common`
708
751
 
@@ -799,7 +842,7 @@ Using Node.js ≥ 22, which is support loading ESM module via require
799
842
  const mm = require('music-metadata');
800
843
  ```
801
844
 
802
- For older Node.js version < 22, you need to dynamically import **music-metadata**:
845
+ Alternatively, dynamically import **music-metadata**:
803
846
  ```js
804
847
  (async () => {
805
848
  // Dynamically loads the ESM module in a CommonJS project
@@ -4,6 +4,7 @@ export declare const makeParseError: <Name extends string>(name: Name) => {
4
4
  name: Name;
5
5
  message: string;
6
6
  stack?: string;
7
+ cause?: unknown;
7
8
  };
8
9
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
9
10
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
@@ -14,6 +15,7 @@ declare const CouldNotDetermineFileTypeError_base: {
14
15
  name: "CouldNotDetermineFileTypeError";
15
16
  message: string;
16
17
  stack?: string;
18
+ cause?: unknown;
17
19
  };
18
20
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
19
21
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
@@ -26,6 +28,7 @@ declare const UnsupportedFileTypeError_base: {
26
28
  name: "UnsupportedFileTypeError";
27
29
  message: string;
28
30
  stack?: string;
31
+ cause?: unknown;
29
32
  };
30
33
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
31
34
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
@@ -38,6 +41,7 @@ declare const UnexpectedFileContentError_base: {
38
41
  name: "UnexpectedFileContentError";
39
42
  message: string;
40
43
  stack?: string;
44
+ cause?: unknown;
41
45
  };
42
46
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
43
47
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
@@ -53,6 +57,7 @@ declare const FieldDecodingError_base: {
53
57
  name: "FieldDecodingError";
54
58
  message: string;
55
59
  stack?: string;
60
+ cause?: unknown;
56
61
  };
57
62
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
58
63
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
@@ -65,6 +70,7 @@ declare const InternalParserError_base: {
65
70
  name: "InternalParserError";
66
71
  message: string;
67
72
  stack?: string;
73
+ cause?: unknown;
68
74
  };
69
75
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
70
76
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
@@ -74,11 +80,12 @@ export declare class InternalParserError extends InternalParserError_base {
74
80
  }
75
81
  export declare const makeUnexpectedFileContentError: <FileType extends string>(fileType: FileType) => {
76
82
  new (message: string): {
77
- readonly fileType: string;
78
- toString(): string;
79
- name: "UnexpectedFileContentError";
80
83
  message: string;
81
84
  stack?: string;
85
+ cause?: unknown;
86
+ name: "UnexpectedFileContentError";
87
+ readonly fileType: string;
88
+ toString(): string;
82
89
  };
83
90
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
84
91
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
package/lib/ParseError.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export const makeParseError = (name) => {
2
2
  return class ParseError extends Error {
3
+ name;
3
4
  constructor(message) {
4
5
  super(message);
5
6
  this.name = name;
@@ -14,6 +15,7 @@ export class UnsupportedFileTypeError extends makeParseError('UnsupportedFileTyp
14
15
  }
15
16
  // Concrete error class representing unexpected file content.
16
17
  export class UnexpectedFileContentError extends makeParseError('UnexpectedFileContentError') {
18
+ fileType;
17
19
  constructor(fileType, message) {
18
20
  super(message);
19
21
  this.fileType = fileType;
@@ -1,4 +1,4 @@
1
- import ContentType from 'content-type';
1
+ import { parse as parseContentType } from 'content-type';
2
2
  import initDebug from 'debug';
3
3
  import { fileTypeFromBuffer } from 'file-type';
4
4
  import { parse as mimeTypeParse } from 'media-typer';
@@ -6,6 +6,7 @@ import { aiffParserLoader } from './aiff/AiffLoader.js';
6
6
  import { apeParserLoader } from './apev2/Apev2Loader.js';
7
7
  import { asfParserLoader } from './asf/AsfLoader.js';
8
8
  import { MetadataCollector } from './common/MetadataCollector.js';
9
+ import { createAudioTrackInfo } from './common/TrackInfo.js';
9
10
  import { scanAppendingHeaders } from './core.js';
10
11
  import { dsdiffParserLoader } from './dsdiff/DsdiffLoader.js';
11
12
  import { dsfParserLoader } from './dsf/DsfLoader.js';
@@ -21,7 +22,7 @@ import { riffParserLoader } from './wav/WaveLoader.js';
21
22
  import { wavpackParserLoader } from './wavpack/WavPackLoader.js';
22
23
  const debug = initDebug('music-metadata:parser:factory');
23
24
  export function parseHttpContentType(contentType) {
24
- const type = ContentType.parse(contentType);
25
+ const type = parseContentType(contentType);
25
26
  const mime = mimeTypeParse(type.type);
26
27
  return {
27
28
  type: mime.type,
@@ -31,8 +32,8 @@ export function parseHttpContentType(contentType) {
31
32
  };
32
33
  }
33
34
  export class ParserFactory {
35
+ parsers = [];
34
36
  constructor() {
35
- this.parsers = [];
36
37
  [
37
38
  flacParserLoader,
38
39
  mpegParserLoader,
@@ -54,7 +55,7 @@ export class ParserFactory {
54
55
  registerParser(parser) {
55
56
  this.parsers.push(parser);
56
57
  }
57
- async parse(tokenizer, parserLoader, opts) {
58
+ async parse(tokenizer, parserLoader, opts = {}) {
58
59
  if (tokenizer.supportsRandomAccess()) {
59
60
  debug('tokenizer supports random-access, scanning for appending headers');
60
61
  await scanAppendingHeaders(tokenizer, opts);
@@ -92,6 +93,11 @@ export class ParserFactory {
92
93
  const parser = new ParserImpl(metadata, tokenizer, opts ?? {});
93
94
  debug(`Parser ${parserLoader.parserType} loaded`);
94
95
  await parser.parse();
96
+ // Audio-only parsers describe their single stream through the format fields.
97
+ // Container parsers supply their own tracks; never copy aggregate fields to them.
98
+ if (metadata.format.trackInfo.length === 0 && metadata.format.hasAudio === true) {
99
+ metadata.addStreamInfo(createAudioTrackInfo(metadata.format));
100
+ }
95
101
  if (metadata.format.trackInfo) {
96
102
  if (metadata.format.hasAudio === undefined) {
97
103
  metadata.setFormat('hasAudio', !!metadata.format.trackInfo.find(track => track.type === TrackType.audio));
@@ -16,10 +16,7 @@ const debug = initDebug('music-metadata:parser:aiff');
16
16
  * - http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/Docs/AIFF-1.3.pdf
17
17
  */
18
18
  export class AIFFParser extends BasicParser {
19
- constructor() {
20
- super(...arguments);
21
- this.isCompressed = null;
22
- }
19
+ isCompressed = null;
23
20
  async parse() {
24
21
  const header = await this.tokenizer.readToken(iff.Header);
25
22
  if (header.chunkID !== 'FORM') {
@@ -14,11 +14,12 @@ export declare const compressionTypes: {
14
14
  export type CompressionTypeCode = keyof typeof compressionTypes;
15
15
  declare const AiffContentError_base: {
16
16
  new (message: string): {
17
- readonly fileType: string;
18
- toString(): string;
19
- name: "UnexpectedFileContentError";
20
17
  message: string;
21
18
  stack?: string;
19
+ cause?: unknown;
20
+ name: "UnexpectedFileContentError";
21
+ readonly fileType: string;
22
+ toString(): string;
22
23
  };
23
24
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
24
25
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
@@ -15,6 +15,8 @@ export const compressionTypes = {
15
15
  export class AiffContentError extends makeUnexpectedFileContentError('AIFF') {
16
16
  }
17
17
  export class Common {
18
+ len;
19
+ isAifc;
18
20
  constructor(header, isAifc) {
19
21
  this.isAifc = isAifc;
20
22
  const minimumChunkSize = isAifc ? 22 : 18;
@@ -6,11 +6,12 @@ import type { IApeHeader, IOptions } from '../type.js';
6
6
  import { type IFooter, type IHeader } from './APEv2Token.js';
7
7
  declare const ApeContentError_base: {
8
8
  new (message: string): {
9
- readonly fileType: string;
10
- toString(): string;
11
- name: "UnexpectedFileContentError";
12
9
  message: string;
13
10
  stack?: string;
11
+ cause?: unknown;
12
+ name: "UnexpectedFileContentError";
13
+ readonly fileType: string;
14
+ toString(): string;
14
15
  };
15
16
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
16
17
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
@@ -16,10 +16,6 @@ export function tryParseApeHeader(metadata, tokenizer, options) {
16
16
  return apeParser.tryParseApeHeader();
17
17
  }
18
18
  export class APEv2Parser extends BasicParser {
19
- constructor() {
20
- super(...arguments);
21
- this.ape = {};
22
- }
23
19
  /**
24
20
  * Calculate the media file duration
25
21
  * @param ah ApeHeader
@@ -68,6 +64,7 @@ export class APEv2Parser extends BasicParser {
68
64
  const apeParser = new APEv2Parser(metadata, strtok3.fromBuffer(buffer), options);
69
65
  return apeParser.parseTags(footer);
70
66
  }
67
+ ape = {};
71
68
  /**
72
69
  * Parse APEv1 / APEv2 header if header signature found
73
70
  */
@@ -202,6 +199,7 @@ export class APEv2Parser extends BasicParser {
202
199
  // ToDo before
203
200
  this.metadata.setFormat('lossless', true);
204
201
  this.metadata.setFormat('container', "Monkey's Audio");
202
+ this.metadata.setFormat('codec', "Monkey's Audio");
205
203
  this.metadata.setFormat('bitsPerSample', header.bitsPerSample);
206
204
  this.metadata.setFormat('sampleRate', header.sampleRate);
207
205
  this.metadata.setFormat('numberOfChannels', header.channel);
@@ -13,7 +13,54 @@ import { Guid, parseWindowsGuid } from 'win-guid';
13
13
  * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/10_asf_guids.html
14
14
  * - https://github.com/dji-sdk/FFmpeg/blob/master/libavformat/asf.c
15
15
  */
16
- class AsfGuid {
16
+ export default class AsfGuid {
17
+ // 10.1 Top-level ASF object GUIDs
18
+ static HeaderObject = new AsfGuid('75B22630-668E-11CF-A6D9-00AA0062CE6C');
19
+ static DataObject = new AsfGuid('75B22636-668E-11CF-A6D9-00AA0062CE6C');
20
+ static SimpleIndexObject = new AsfGuid('33000890-E5B1-11CF-89F4-00A0C90349CB');
21
+ static IndexObject = new AsfGuid('D6E229D3-35DA-11D1-9034-00A0C90349BE');
22
+ static MediaObjectIndexObject = new AsfGuid('FEB103F8-12AD-4C64-840F-2A1D2F7AD48C');
23
+ static TimecodeIndexObject = new AsfGuid('3CB73FD0-0C4A-4803-953D-EDF7B6228F0C');
24
+ // 10.2 Header Object GUIDs
25
+ static FilePropertiesObject = new AsfGuid('8CABDCA1-A947-11CF-8EE4-00C00C205365');
26
+ static StreamPropertiesObject = new AsfGuid('B7DC0791-A9B7-11CF-8EE6-00C00C205365');
27
+ static HeaderExtensionObject = new AsfGuid('5FBF03B5-A92E-11CF-8EE3-00C00C205365');
28
+ static CodecListObject = new AsfGuid('86D15240-311D-11D0-A3A4-00A0C90348F6');
29
+ static ScriptCommandObject = new AsfGuid('1EFB1A30-0B62-11D0-A39B-00A0C90348F6');
30
+ static MarkerObject = new AsfGuid('F487CD01-A951-11CF-8EE6-00C00C205365');
31
+ static BitrateMutualExclusionObject = new AsfGuid('D6E229DC-35DA-11D1-9034-00A0C90349BE');
32
+ static ErrorCorrectionObject = new AsfGuid('75B22635-668E-11CF-A6D9-00AA0062CE6C');
33
+ static ContentDescriptionObject = new AsfGuid('75B22633-668E-11CF-A6D9-00AA0062CE6C');
34
+ static ExtendedContentDescriptionObject = new AsfGuid('D2D0A440-E307-11D2-97F0-00A0C95EA850');
35
+ static ContentBrandingObject = new AsfGuid('2211B3FA-BD23-11D2-B4B7-00A0C955FC6E');
36
+ static StreamBitratePropertiesObject = new AsfGuid('7BF875CE-468D-11D1-8D82-006097C9A2B2');
37
+ static ContentEncryptionObject = new AsfGuid('2211B3FB-BD23-11D2-B4B7-00A0C955FC6E');
38
+ static ExtendedContentEncryptionObject = new AsfGuid('298AE614-2622-4C17-B935-DAE07EE9289C');
39
+ static DigitalSignatureObject = new AsfGuid('2211B3FC-BD23-11D2-B4B7-00A0C955FC6E');
40
+ static PaddingObject = new AsfGuid('1806D474-CADF-4509-A4BA-9AABCB96AAE8');
41
+ // 10.3 Header Extension Object GUIDs
42
+ static ExtendedStreamPropertiesObject = new AsfGuid('14E6A5CB-C672-4332-8399-A96952065B5A');
43
+ static AdvancedMutualExclusionObject = new AsfGuid('A08649CF-4775-4670-8A16-6E35357566CD');
44
+ static GroupMutualExclusionObject = new AsfGuid('D1465A40-5A79-4338-B71B-E36B8FD6C249');
45
+ static StreamPrioritizationObject = new AsfGuid('D4FED15B-88D3-454F-81F0-ED5C45999E24');
46
+ static BandwidthSharingObject = new AsfGuid('A69609E6-517B-11D2-B6AF-00C04FD908E9');
47
+ static LanguageListObject = new AsfGuid('7C4346A9-EFE0-4BFC-B229-393EDE415C85');
48
+ static MetadataObject = new AsfGuid('C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA');
49
+ static MetadataLibraryObject = new AsfGuid('44231C94-9498-49D1-A141-1D134E457054');
50
+ static IndexParametersObject = new AsfGuid('D6E229DF-35DA-11D1-9034-00A0C90349BE');
51
+ static MediaObjectIndexParametersObject = new AsfGuid('6B203BAD-3F11-48E4-ACA8-D7613DE2CFA7');
52
+ static TimecodeIndexParametersObject = new AsfGuid('F55E496D-9797-4B5D-8C8B-604DFE9BFB24');
53
+ static CompatibilityObject = new AsfGuid('26F18B5D-4584-47EC-9F5F-0E651F0452C9');
54
+ static AdvancedContentEncryptionObject = new AsfGuid('43058533-6981-49E6-9B74-AD12CB86D58C');
55
+ // 10.4 Stream Properties Object Stream Type GUIDs
56
+ static AudioMedia = new AsfGuid('F8699E40-5B4D-11CF-A8FD-00805F5C442B');
57
+ static VideoMedia = new AsfGuid('BC19EFC0-5B4D-11CF-A8FD-00805F5C442B');
58
+ static CommandMedia = new AsfGuid('59DACFC0-59E6-11D0-A3AC-00A0C90348F6');
59
+ static JFIF_Media = new AsfGuid('B61BE100-5B4E-11CF-A8FD-00805F5C442B');
60
+ static Degradable_JPEG_Media = new AsfGuid('35907DE0-E415-11CF-A917-00805F5C442B');
61
+ static FileTransferMedia = new AsfGuid('91BD222C-F21C-497A-8B6D-5AA86BFC0185');
62
+ static BinaryMedia = new AsfGuid('3AFB65E2-47EF-40F2-AC2C-70A90D71D343');
63
+ static ASF_Index_Placeholder_Object = new AsfGuid('D9AADE20-7C17-4F9C-BC28-8555DD98E2A2');
17
64
  static fromBin(bin, offset = 0) {
18
65
  return new AsfGuid(AsfGuid.decode(bin, offset));
19
66
  }
@@ -55,6 +102,7 @@ class AsfGuid {
55
102
  static encode(guid) {
56
103
  return parseWindowsGuid(guid);
57
104
  }
105
+ str;
58
106
  constructor(str) {
59
107
  this.str = str;
60
108
  }
@@ -65,51 +113,3 @@ class AsfGuid {
65
113
  return AsfGuid.encode(this.str);
66
114
  }
67
115
  }
68
- // 10.1 Top-level ASF object GUIDs
69
- AsfGuid.HeaderObject = new AsfGuid('75B22630-668E-11CF-A6D9-00AA0062CE6C');
70
- AsfGuid.DataObject = new AsfGuid('75B22636-668E-11CF-A6D9-00AA0062CE6C');
71
- AsfGuid.SimpleIndexObject = new AsfGuid('33000890-E5B1-11CF-89F4-00A0C90349CB');
72
- AsfGuid.IndexObject = new AsfGuid('D6E229D3-35DA-11D1-9034-00A0C90349BE');
73
- AsfGuid.MediaObjectIndexObject = new AsfGuid('FEB103F8-12AD-4C64-840F-2A1D2F7AD48C');
74
- AsfGuid.TimecodeIndexObject = new AsfGuid('3CB73FD0-0C4A-4803-953D-EDF7B6228F0C');
75
- // 10.2 Header Object GUIDs
76
- AsfGuid.FilePropertiesObject = new AsfGuid('8CABDCA1-A947-11CF-8EE4-00C00C205365');
77
- AsfGuid.StreamPropertiesObject = new AsfGuid('B7DC0791-A9B7-11CF-8EE6-00C00C205365');
78
- AsfGuid.HeaderExtensionObject = new AsfGuid('5FBF03B5-A92E-11CF-8EE3-00C00C205365');
79
- AsfGuid.CodecListObject = new AsfGuid('86D15240-311D-11D0-A3A4-00A0C90348F6');
80
- AsfGuid.ScriptCommandObject = new AsfGuid('1EFB1A30-0B62-11D0-A39B-00A0C90348F6');
81
- AsfGuid.MarkerObject = new AsfGuid('F487CD01-A951-11CF-8EE6-00C00C205365');
82
- AsfGuid.BitrateMutualExclusionObject = new AsfGuid('D6E229DC-35DA-11D1-9034-00A0C90349BE');
83
- AsfGuid.ErrorCorrectionObject = new AsfGuid('75B22635-668E-11CF-A6D9-00AA0062CE6C');
84
- AsfGuid.ContentDescriptionObject = new AsfGuid('75B22633-668E-11CF-A6D9-00AA0062CE6C');
85
- AsfGuid.ExtendedContentDescriptionObject = new AsfGuid('D2D0A440-E307-11D2-97F0-00A0C95EA850');
86
- AsfGuid.ContentBrandingObject = new AsfGuid('2211B3FA-BD23-11D2-B4B7-00A0C955FC6E');
87
- AsfGuid.StreamBitratePropertiesObject = new AsfGuid('7BF875CE-468D-11D1-8D82-006097C9A2B2');
88
- AsfGuid.ContentEncryptionObject = new AsfGuid('2211B3FB-BD23-11D2-B4B7-00A0C955FC6E');
89
- AsfGuid.ExtendedContentEncryptionObject = new AsfGuid('298AE614-2622-4C17-B935-DAE07EE9289C');
90
- AsfGuid.DigitalSignatureObject = new AsfGuid('2211B3FC-BD23-11D2-B4B7-00A0C955FC6E');
91
- AsfGuid.PaddingObject = new AsfGuid('1806D474-CADF-4509-A4BA-9AABCB96AAE8');
92
- // 10.3 Header Extension Object GUIDs
93
- AsfGuid.ExtendedStreamPropertiesObject = new AsfGuid('14E6A5CB-C672-4332-8399-A96952065B5A');
94
- AsfGuid.AdvancedMutualExclusionObject = new AsfGuid('A08649CF-4775-4670-8A16-6E35357566CD');
95
- AsfGuid.GroupMutualExclusionObject = new AsfGuid('D1465A40-5A79-4338-B71B-E36B8FD6C249');
96
- AsfGuid.StreamPrioritizationObject = new AsfGuid('D4FED15B-88D3-454F-81F0-ED5C45999E24');
97
- AsfGuid.BandwidthSharingObject = new AsfGuid('A69609E6-517B-11D2-B6AF-00C04FD908E9');
98
- AsfGuid.LanguageListObject = new AsfGuid('7C4346A9-EFE0-4BFC-B229-393EDE415C85');
99
- AsfGuid.MetadataObject = new AsfGuid('C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA');
100
- AsfGuid.MetadataLibraryObject = new AsfGuid('44231C94-9498-49D1-A141-1D134E457054');
101
- AsfGuid.IndexParametersObject = new AsfGuid('D6E229DF-35DA-11D1-9034-00A0C90349BE');
102
- AsfGuid.MediaObjectIndexParametersObject = new AsfGuid('6B203BAD-3F11-48E4-ACA8-D7613DE2CFA7');
103
- AsfGuid.TimecodeIndexParametersObject = new AsfGuid('F55E496D-9797-4B5D-8C8B-604DFE9BFB24');
104
- AsfGuid.CompatibilityObject = new AsfGuid('26F18B5D-4584-47EC-9F5F-0E651F0452C9');
105
- AsfGuid.AdvancedContentEncryptionObject = new AsfGuid('43058533-6981-49E6-9B74-AD12CB86D58C');
106
- // 10.4 Stream Properties Object Stream Type GUIDs
107
- AsfGuid.AudioMedia = new AsfGuid('F8699E40-5B4D-11CF-A8FD-00805F5C442B');
108
- AsfGuid.VideoMedia = new AsfGuid('BC19EFC0-5B4D-11CF-A8FD-00805F5C442B');
109
- AsfGuid.CommandMedia = new AsfGuid('59DACFC0-59E6-11D0-A3AC-00A0C90348F6');
110
- AsfGuid.JFIF_Media = new AsfGuid('B61BE100-5B4E-11CF-A8FD-00805F5C442B');
111
- AsfGuid.Degradable_JPEG_Media = new AsfGuid('35907DE0-E415-11CF-A917-00805F5C442B');
112
- AsfGuid.FileTransferMedia = new AsfGuid('91BD222C-F21C-497A-8B6D-5AA86BFC0185');
113
- AsfGuid.BinaryMedia = new AsfGuid('3AFB65E2-47EF-40F2-AC2C-70A90D71D343');
114
- AsfGuid.ASF_Index_Placeholder_Object = new AsfGuid('D9AADE20-7C17-4F9C-BC28-8555DD98E2A2');
115
- export default AsfGuid;
@@ -1,13 +1,14 @@
1
1
  import type { IGetToken, ITokenizer } from 'strtok3';
2
- import type { AnyTagValue, IPicture, ITag } from '../type.js';
2
+ import type { AnyTagValue, IAudioTrack, IPicture, ITag, IVideoTrack } from '../type.js';
3
3
  import AsfGuid from './AsfGuid.js';
4
4
  declare const AsfContentParseError_base: {
5
5
  new (message: string): {
6
- readonly fileType: string;
7
- toString(): string;
8
- name: "UnexpectedFileContentError";
9
6
  message: string;
10
7
  stack?: string;
8
+ cause?: unknown;
9
+ name: "UnexpectedFileContentError";
10
+ readonly fileType: string;
11
+ toString(): string;
11
12
  };
12
13
  captureStackTrace(targetObject: object, constructorOpt?: Function): void;
13
14
  prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
@@ -198,6 +199,11 @@ export interface IStreamPropertiesObject {
198
199
  * Error Correction Type
199
200
  */
200
201
  errorCorrectionType: AsfGuid;
202
+ streamNumber: number;
203
+ codecId?: string;
204
+ audio?: IAudioTrack;
205
+ video?: IVideoTrack;
206
+ bitrate?: number;
201
207
  }
202
208
  /**
203
209
  * Token for: 3.3 Stream Properties Object (mandatory, one per stream)
@@ -282,7 +288,7 @@ export interface IExtendedStreamPropertiesObject {
282
288
  streamNameCount: number;
283
289
  payloadExtensionSystems: number;
284
290
  streamNames: IStreamName[];
285
- streamPropertiesObject: number | null;
291
+ streamPropertiesObject: IStreamPropertiesObject | null;
286
292
  }
287
293
  /**
288
294
  * 4.1 Extended Stream Properties Object (optional, 1 per media stream)