music-metadata 7.13.0 → 7.13.2

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.
@@ -347,9 +347,6 @@ MetadataLibraryObjectState.guid = GUID_1.default.MetadataLibraryObject;
347
347
  * Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd757977(v=vs.85).aspx
348
348
  */
349
349
  class WmPictureToken {
350
- constructor(len) {
351
- this.len = len;
352
- }
353
350
  static fromBase64(base64str) {
354
351
  return this.fromBuffer(Buffer.from(base64str, 'base64'));
355
352
  }
@@ -357,6 +354,9 @@ class WmPictureToken {
357
354
  const pic = new WmPictureToken(buffer.length);
358
355
  return pic.get(buffer, 0);
359
356
  }
357
+ constructor(len) {
358
+ this.len = len;
359
+ }
360
360
  get(buffer, offset) {
361
361
  const typeId = buffer.readUInt8(offset++);
362
362
  const size = buffer.readInt32LE(offset);
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { DataType } from './AsfObject';
3
- export declare type AttributeParser = (buf: Buffer) => boolean | string | number | bigint | Buffer;
3
+ export type AttributeParser = (buf: Buffer) => boolean | string | number | bigint | Buffer;
4
4
  export declare class AsfUtil {
5
5
  static getParserForAttr(i: DataType): AttributeParser;
6
6
  static parseUnicodeAttr(uint8Array: Uint8Array): string;
package/lib/asf/GUID.js CHANGED
@@ -15,9 +15,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  * - https://github.com/dji-sdk/FFmpeg/blob/master/libavformat/asf.c
16
16
  */
17
17
  class GUID {
18
- constructor(str) {
19
- this.str = str;
20
- }
21
18
  static fromBin(bin, offset = 0) {
22
19
  return new GUID(this.decode(bin, offset));
23
20
  }
@@ -64,6 +61,9 @@ class GUID {
64
61
  Buffer.from(str.slice(24), "hex").copy(bin, 10);
65
62
  return bin;
66
63
  }
64
+ constructor(str) {
65
+ this.str = str;
66
+ }
67
67
  equals(guid) {
68
68
  return this.str === guid.str;
69
69
  }
@@ -2,10 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CommonTagMapper = void 0;
4
4
  class CommonTagMapper {
5
- constructor(tagTypes, tagMap) {
6
- this.tagTypes = tagTypes;
7
- this.tagMap = tagMap;
8
- }
9
5
  static toIntOrNull(str) {
10
6
  const cleaned = parseInt(str, 10);
11
7
  return isNaN(cleaned) ? null : cleaned;
@@ -20,6 +16,10 @@ class CommonTagMapper {
20
16
  of: parseInt(split[1], 10) || null
21
17
  };
22
18
  }
19
+ constructor(tagTypes, tagMap) {
20
+ this.tagTypes = tagTypes;
21
+ this.tagMap = tagMap;
22
+ }
23
23
  /**
24
24
  * Process and set common tags
25
25
  * write common tags to
@@ -1,9 +1,9 @@
1
- export declare type TagType = 'vorbis' | 'ID3v1' | 'ID3v2.2' | 'ID3v2.3' | 'ID3v2.4' | 'APEv2' | 'asf' | 'iTunes' | 'exif' | 'matroska' | 'AIFF';
1
+ export type TagType = 'vorbis' | 'ID3v1' | 'ID3v2.2' | 'ID3v2.3' | 'ID3v2.4' | 'APEv2' | 'asf' | 'iTunes' | 'exif' | 'matroska' | 'AIFF';
2
2
  export interface IGenericTag {
3
3
  id: GenericTagId;
4
4
  value: any;
5
5
  }
6
- export declare type GenericTagId = 'track' | 'disk' | 'year' | 'title' | 'artist' | 'artists' | 'albumartist' | 'album' | 'date' | 'originaldate' | 'originalyear' | 'comment' | 'genre' | 'picture' | 'composer' | 'lyrics' | 'albumsort' | 'titlesort' | 'work' | 'artistsort' | 'albumartistsort' | 'composersort' | 'lyricist' | 'writer' | 'conductor' | 'remixer' | 'arranger' | 'engineer' | 'technician' | 'producer' | 'djmixer' | 'mixer' | 'publisher' | 'label' | 'grouping' | 'subtitle' | 'discsubtitle' | 'totaltracks' | 'totaldiscs' | 'compilation' | 'rating' | 'bpm' | 'mood' | 'media' | 'catalognumber' | 'tvShow' | 'tvShowSort' | 'tvEpisode' | 'tvEpisodeId' | 'tvNetwork' | 'tvSeason' | 'podcast' | 'podcasturl' | 'releasestatus' | 'releasetype' | 'releasecountry' | 'script' | 'language' | 'copyright' | 'license' | 'encodedby' | 'encodersettings' | 'gapless' | 'barcode' | 'isrc' | 'asin' | 'musicbrainz_recordingid' | 'musicbrainz_trackid' | 'musicbrainz_albumid' | 'musicbrainz_artistid' | 'musicbrainz_albumartistid' | 'musicbrainz_releasegroupid' | 'musicbrainz_workid' | 'musicbrainz_trmid' | 'musicbrainz_discid' | 'acoustid_id' | 'acoustid_fingerprint' | 'musicip_puid' | 'musicip_fingerprint' | 'website' | 'performer:instrument' | 'peakLevel' | 'averageLevel' | 'notes' | 'key' | 'originalalbum' | 'originalartist' | 'discogs_artist_id' | 'discogs_label_id' | 'discogs_master_release_id' | 'discogs_rating' | 'discogs_release_id' | 'discogs_votes' | 'replaygain_track_gain' | 'replaygain_track_peak' | 'replaygain_album_gain' | 'replaygain_album_peak' | 'replaygain_track_minmax' | 'replaygain_album_minmax' | 'replaygain_undo' | 'description' | 'longDescription' | 'category' | 'hdVideo' | 'keywords' | 'movement' | 'movementIndex' | 'movementTotal' | 'podcastId' | 'showMovement' | 'stik';
6
+ export type GenericTagId = 'track' | 'disk' | 'year' | 'title' | 'artist' | 'artists' | 'albumartist' | 'album' | 'date' | 'originaldate' | 'originalyear' | 'comment' | 'genre' | 'picture' | 'composer' | 'lyrics' | 'albumsort' | 'titlesort' | 'work' | 'artistsort' | 'albumartistsort' | 'composersort' | 'lyricist' | 'writer' | 'conductor' | 'remixer' | 'arranger' | 'engineer' | 'technician' | 'producer' | 'djmixer' | 'mixer' | 'publisher' | 'label' | 'grouping' | 'subtitle' | 'discsubtitle' | 'totaltracks' | 'totaldiscs' | 'compilation' | 'rating' | 'bpm' | 'mood' | 'media' | 'catalognumber' | 'tvShow' | 'tvShowSort' | 'tvEpisode' | 'tvEpisodeId' | 'tvNetwork' | 'tvSeason' | 'podcast' | 'podcasturl' | 'releasestatus' | 'releasetype' | 'releasecountry' | 'script' | 'language' | 'copyright' | 'license' | 'encodedby' | 'encodersettings' | 'gapless' | 'barcode' | 'isrc' | 'asin' | 'musicbrainz_recordingid' | 'musicbrainz_trackid' | 'musicbrainz_albumid' | 'musicbrainz_artistid' | 'musicbrainz_albumartistid' | 'musicbrainz_releasegroupid' | 'musicbrainz_workid' | 'musicbrainz_trmid' | 'musicbrainz_discid' | 'acoustid_id' | 'acoustid_fingerprint' | 'musicip_puid' | 'musicip_fingerprint' | 'website' | 'performer:instrument' | 'peakLevel' | 'averageLevel' | 'notes' | 'key' | 'originalalbum' | 'originalartist' | 'discogs_artist_id' | 'discogs_label_id' | 'discogs_master_release_id' | 'discogs_rating' | 'discogs_release_id' | 'discogs_votes' | 'replaygain_track_gain' | 'replaygain_track_peak' | 'replaygain_album_gain' | 'replaygain_album_peak' | 'replaygain_track_minmax' | 'replaygain_album_minmax' | 'replaygain_undo' | 'description' | 'longDescription' | 'category' | 'hdVideo' | 'keywords' | 'movement' | 'movementIndex' | 'movementTotal' | 'podcastId' | 'showMovement' | 'stik';
7
7
  export interface INativeTagMap {
8
8
  [index: string]: GenericTagId;
9
9
  }
@@ -1,5 +1,5 @@
1
1
  import { IRatio } from '../type';
2
- export declare type StringEncoding = 'ascii' | 'utf8' | 'utf16le' | 'ucs2' | 'base64url' | 'latin1' | 'hex';
2
+ export type StringEncoding = 'ascii' | 'utf8' | 'utf16le' | 'ucs2' | 'base64url' | 'latin1' | 'hex';
3
3
  export interface ITextEncoding {
4
4
  encoding: StringEncoding;
5
5
  bom?: boolean;
@@ -27,7 +27,7 @@ export declare enum AttachedPictureType {
27
27
  'Band/artist logotype' = 19,
28
28
  'Publisher/Studio logotype' = 20
29
29
  }
30
- export declare type ID3v2MajorVersion = 2 | 3 | 4;
30
+ export type ID3v2MajorVersion = 2 | 3 | 4;
31
31
  export interface IExtendedHeader {
32
32
  size: number;
33
33
  extendedFlags: number;
@@ -45,9 +45,11 @@ class MatroskaParser extends BasicParser_1.BasicParser {
45
45
  const info = matroska.segment.info;
46
46
  if (info) {
47
47
  const timecodeScale = info.timecodeScale ? info.timecodeScale : 1000000;
48
- const duration = info.duration * timecodeScale / 1000000000;
49
- this.addTag('segment:title', info.title);
50
- this.metadata.setFormat('duration', duration);
48
+ if (typeof info.duration === 'number') {
49
+ const duration = info.duration * timecodeScale / 1000000000;
50
+ this.addTag('segment:title', info.title);
51
+ this.metadata.setFormat('duration', duration);
52
+ }
51
53
  }
52
54
  const audioTracks = matroska.segment.tracks;
53
55
  if (audioTracks && audioTracks.entries) {
package/lib/mp4/Atom.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ITokenizer } from 'strtok3/lib/core';
2
2
  import * as AtomToken from './AtomToken';
3
- export declare type AtomDataHandler = (atom: Atom, remaining: number) => Promise<void>;
3
+ export type AtomDataHandler = (atom: Atom, remaining: number) => Promise<void>;
4
4
  export declare class Atom {
5
5
  readonly header: AtomToken.IAtomHeader;
6
6
  extended: boolean;
package/lib/mp4/Atom.js CHANGED
@@ -5,13 +5,6 @@ const debug_1 = require("debug");
5
5
  const AtomToken = require("./AtomToken");
6
6
  const debug = (0, debug_1.default)('music-metadata:parser:MP4:Atom');
7
7
  class Atom {
8
- constructor(header, extended, parent) {
9
- this.header = header;
10
- this.extended = extended;
11
- this.parent = parent;
12
- this.children = [];
13
- this.atomPath = (this.parent ? this.parent.atomPath + '.' : '') + this.header.name;
14
- }
15
8
  static async readAtom(tokenizer, dataHandler, parent, remaining) {
16
9
  // Parse atom header
17
10
  const offset = tokenizer.position;
@@ -27,6 +20,13 @@ class Atom {
27
20
  await atomBean.readData(tokenizer, dataHandler, payloadLength);
28
21
  return atomBean;
29
22
  }
23
+ constructor(header, extended, parent) {
24
+ this.header = header;
25
+ this.extended = extended;
26
+ this.parent = parent;
27
+ this.children = [];
28
+ this.atomPath = (this.parent ? this.parent.atomPath + '.' : '') + this.header.name;
29
+ }
30
30
  getHeaderLength() {
31
31
  return this.extended ? 16 : 8;
32
32
  }
@@ -13,9 +13,6 @@ const SpeexParser_1 = require("./speex/SpeexParser");
13
13
  const TheoraParser_1 = require("./theora/TheoraParser");
14
14
  const debug = (0, debug_1.default)('music-metadata:parser:ogg');
15
15
  class SegmentTable {
16
- constructor(header) {
17
- this.len = header.page_segments;
18
- }
19
16
  static sum(buf, off, len) {
20
17
  let s = 0;
21
18
  for (let i = off; i < off + len; ++i) {
@@ -23,6 +20,9 @@ class SegmentTable {
23
20
  }
24
21
  return s;
25
22
  }
23
+ constructor(header) {
24
+ this.len = header.page_segments;
25
+ }
26
26
  get(buf, off) {
27
27
  return {
28
28
  totalPageSize: SegmentTable.sum(buf, off, this.len)
@@ -10,9 +10,6 @@ const ID3v2Token_1 = require("../../id3v2/ID3v2Token");
10
10
  * // ToDo: move to ID3 / APIC?
11
11
  */
12
12
  class VorbisPictureToken {
13
- constructor(len) {
14
- this.len = len;
15
- }
16
13
  static fromBase64(base64str) {
17
14
  return this.fromBuffer(Buffer.from(base64str, 'base64'));
18
15
  }
@@ -20,6 +17,9 @@ class VorbisPictureToken {
20
17
  const pic = new VorbisPictureToken(buffer.length);
21
18
  return pic.get(buffer, 0);
22
19
  }
20
+ constructor(len) {
21
+ this.len = len;
22
+ }
23
23
  get(buffer, offset) {
24
24
  const type = ID3v2Token_1.AttachedPictureType[Token.UINT32_BE.get(buffer, offset)];
25
25
  const mimeLen = Token.UINT32_BE.get(buffer, offset += 4);
package/lib/type.d.ts CHANGED
@@ -356,7 +356,7 @@ export interface IRatio {
356
356
  */
357
357
  dB: number;
358
358
  }
359
- export declare type FormatId = 'container' | 'duration' | 'bitrate' | 'sampleRate' | 'bitsPerSample' | 'codec' | 'tool' | 'codecProfile' | 'lossless' | 'numberOfChannels' | 'numberOfSamples' | 'audioMD5' | 'chapters' | 'modificationTime' | 'creationTime' | 'trackPeakLevel' | 'trackGain' | 'albumGain';
359
+ export type FormatId = 'container' | 'duration' | 'bitrate' | 'sampleRate' | 'bitsPerSample' | 'codec' | 'tool' | 'codecProfile' | 'lossless' | 'numberOfChannels' | 'numberOfSamples' | 'audioMD5' | 'chapters' | 'modificationTime' | 'creationTime' | 'trackPeakLevel' | 'trackGain' | 'albumGain';
360
360
  export interface IAudioTrack {
361
361
  samplingFrequency?: number;
362
362
  outputSamplingFrequency?: number;
@@ -507,7 +507,7 @@ export interface IAudioMetadata extends INativeAudioMetadata {
507
507
  /**
508
508
  * Corresponds with parser module name
509
509
  */
510
- export declare type ParserType = 'mpeg' | 'apev2' | 'mp4' | 'asf' | 'flac' | 'ogg' | 'aiff' | 'wavpack' | 'riff' | 'musepack' | 'dsf' | 'dsdiff' | 'adts' | 'matroska';
510
+ export type ParserType = 'mpeg' | 'apev2' | 'mp4' | 'asf' | 'flac' | 'ogg' | 'aiff' | 'wavpack' | 'riff' | 'musepack' | 'dsf' | 'dsdiff' | 'adts' | 'matroska';
511
511
  export interface IOptions {
512
512
  /**
513
513
  * default: `false`, if set to `true`, it will parse the whole media file if required to determine the duration.
@@ -570,7 +570,7 @@ export interface IMetadataEvent {
570
570
  */
571
571
  metadata: IAudioMetadata;
572
572
  }
573
- export declare type Observer = (update: IMetadataEvent) => void;
573
+ export type Observer = (update: IMetadataEvent) => void;
574
574
  /**
575
575
  * Provides random data read access
576
576
  * Used read operations on file of buffers
@@ -99,7 +99,12 @@ class WaveParser extends BasicParser_1.BasicParser {
99
99
  this.metadata.setFormat('numberOfSamples', numberOfSamples);
100
100
  this.metadata.setFormat('duration', numberOfSamples / this.metadata.format.sampleRate);
101
101
  }
102
- this.metadata.setFormat('bitrate', this.metadata.format.numberOfChannels * this.blockAlign * this.metadata.format.sampleRate); // ToDo: check me
102
+ if (this.metadata.format.codec === 'ADPCM') { // ADPCM is 4 bits lossy encoding resulting in 352kbps
103
+ this.metadata.setFormat('bitrate', 352000);
104
+ }
105
+ else {
106
+ this.metadata.setFormat('bitrate', this.blockAlign * this.metadata.format.sampleRate * 8);
107
+ }
103
108
  await this.tokenizer.ignore(header.chunkSize);
104
109
  break;
105
110
  case 'bext': // Broadcast Audio Extension chunk https://tech.ebu.ch/docs/tech/tech3285.pdf
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": "7.13.0",
4
+ "version": "7.13.2",
5
5
  "author": {
6
6
  "name": "Borewit",
7
7
  "url": "https://github.com/Borewit"
@@ -92,24 +92,24 @@
92
92
  "token-types": "^4.2.1"
93
93
  },
94
94
  "devDependencies": {
95
- "@types/chai": "^4.3.3",
95
+ "@types/chai": "^4.3.4",
96
96
  "@types/chai-as-promised": "^7.1.5",
97
97
  "@types/debug": "^4.1.7",
98
98
  "@types/file-type": "^10.9.1",
99
99
  "@types/mocha": "^9.1.0",
100
- "@types/node": "^18.7.14",
101
- "@typescript-eslint/eslint-plugin": "^5.37.0",
102
- "@typescript-eslint/parser": "^5.37.0",
103
- "chai": "^4.3.6",
100
+ "@types/node": "^18.11.9",
101
+ "@typescript-eslint/eslint-plugin": "^5.48.0",
102
+ "@typescript-eslint/parser": "^5.48.0",
103
+ "chai": "^4.3.7",
104
104
  "chai-as-promised": "^7.1.1",
105
105
  "del-cli": "5.0.0",
106
- "eslint": "^8.23.1",
107
- "eslint-config-prettier": "^8.5.0",
108
- "eslint-import-resolver-typescript": "^3.5.1",
106
+ "eslint": "^8.31.0",
107
+ "eslint-config-prettier": "^8.6.0",
108
+ "eslint-import-resolver-typescript": "^3.5.2",
109
109
  "eslint-plugin-import": "^2.26.0",
110
- "eslint-plugin-jsdoc": "^39.3.6",
110
+ "eslint-plugin-jsdoc": "^39.6.4",
111
111
  "eslint-plugin-node": "^11.1.0",
112
- "eslint-plugin-unicorn": "^43.0.2",
112
+ "eslint-plugin-unicorn": "^45.0.2",
113
113
  "mime": "^3.0.0",
114
114
  "mocha": "^9.2.2",
115
115
  "npm-run-all": "^4.1.5",
@@ -118,7 +118,7 @@
118
118
  "remark-preset-lint-recommended": "^6.1.2",
119
119
  "source-map-support": "^0.5.21",
120
120
  "ts-node": "^10.9.1",
121
- "typescript": "^4.8.3"
121
+ "typescript": "^4.9.4"
122
122
  },
123
123
  "engines": {
124
124
  "node": ">=10"