music-metadata 10.0.1 → 10.2.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.
- package/LICENSE.txt +9 -9
- package/README.md +535 -520
- package/lib/ParserFactory.d.ts +20 -28
- package/lib/ParserFactory.js +204 -207
- package/lib/aiff/AiffParser.js +20 -19
- package/lib/aiff/AiffToken.d.ts +14 -2
- package/lib/aiff/AiffToken.js +12 -0
- package/lib/apev2/APEv2Parser.d.ts +4 -4
- package/lib/apev2/APEv2Parser.js +12 -10
- package/lib/apev2/APEv2Token.d.ts +2 -4
- package/lib/apev2/APEv2Token.js +0 -3
- package/lib/asf/AsfObject.d.ts +7 -16
- package/lib/asf/AsfObject.js +8 -34
- package/lib/asf/AsfParser.js +17 -10
- package/lib/asf/AsfTagMapper.d.ts +1 -1
- package/lib/asf/AsfTagMapper.js +3 -2
- package/lib/asf/AsfUtil.d.ts +3 -11
- package/lib/asf/AsfUtil.js +29 -30
- package/lib/asf/GUID.js +6 -9
- package/lib/common/BasicParser.d.ts +4 -4
- package/lib/common/BasicParser.js +6 -0
- package/lib/common/CaseInsensitiveTagMap.d.ts +1 -1
- package/lib/common/CombinedTagMapper.d.ts +5 -5
- package/lib/common/CombinedTagMapper.js +1 -1
- package/lib/common/FourCC.d.ts +1 -1
- package/lib/common/GenericTagMapper.d.ts +8 -8
- package/lib/common/GenericTagMapper.js +4 -4
- package/lib/common/GenericTagTypes.d.ts +5 -4
- package/lib/common/GenericTagTypes.js +2 -2
- package/lib/common/MetadataCollector.d.ts +9 -9
- package/lib/common/MetadataCollector.js +22 -17
- package/lib/common/RandomFileReader.d.ts +1 -1
- package/lib/common/RandomFileReader.js +1 -1
- package/lib/common/RandomUint8ArrayReader.d.ts +1 -1
- package/lib/common/Util.d.ts +2 -6
- package/lib/common/Util.js +9 -11
- package/lib/core.d.ts +7 -9
- package/lib/core.js +10 -7
- package/lib/dsdiff/DsdiffParser.js +26 -14
- package/lib/dsdiff/DsdiffToken.d.ts +2 -2
- package/lib/dsdiff/DsdiffToken.js +1 -0
- package/lib/dsf/DsfChunk.js +1 -0
- package/lib/dsf/DsfParser.js +4 -2
- package/lib/ebml/EbmlIterator.d.ts +52 -0
- package/lib/ebml/EbmlIterator.js +220 -0
- package/lib/ebml/types.d.ts +36 -0
- package/lib/ebml/types.js +10 -0
- package/lib/flac/FlacParser.d.ts +3 -3
- package/lib/flac/FlacParser.js +9 -12
- package/lib/id3v1/ID3v1Parser.d.ts +1 -1
- package/lib/id3v1/ID3v1Parser.js +7 -4
- package/lib/id3v2/AbstractID3Parser.d.ts +1 -1
- package/lib/id3v2/AbstractID3Parser.js +2 -1
- package/lib/id3v2/FrameParser.d.ts +28 -3
- package/lib/id3v2/FrameParser.js +50 -28
- package/lib/id3v2/ID3v22TagMapper.d.ts +1 -1
- package/lib/id3v2/ID3v24TagMapper.d.ts +2 -1
- package/lib/id3v2/ID3v24TagMapper.js +23 -16
- package/lib/id3v2/ID3v2Parser.d.ts +2 -2
- package/lib/id3v2/ID3v2Parser.js +18 -8
- package/lib/iff/index.js +1 -0
- package/lib/index.d.ts +5 -6
- package/lib/index.js +7 -8
- package/lib/lyrics3/Lyrics3.d.ts +1 -1
- package/lib/lyrics3/Lyrics3.js +1 -1
- package/lib/matroska/MatroskaDtd.d.ts +2 -2
- package/lib/matroska/MatroskaDtd.js +247 -239
- package/lib/matroska/MatroskaParser.d.ts +10 -24
- package/lib/matroska/MatroskaParser.js +120 -205
- package/lib/matroska/types.d.ts +12 -46
- package/lib/matroska/types.js +0 -9
- package/lib/mp4/Atom.d.ts +3 -3
- package/lib/mp4/Atom.js +4 -7
- package/lib/mp4/AtomToken.js +2 -1
- package/lib/mp4/MP4Parser.js +29 -20
- package/lib/mp4/MP4TagMapper.d.ts +2 -2
- package/lib/mp4/MP4TagMapper.js +1 -1
- package/lib/mpeg/ExtendedLameHeader.d.ts +4 -4
- package/lib/mpeg/ExtendedLameHeader.js +2 -1
- package/lib/mpeg/MpegParser.d.ts +1 -1
- package/lib/mpeg/MpegParser.js +145 -96
- package/lib/mpeg/ReplayGainDataFormat.d.ts +1 -1
- package/lib/mpeg/ReplayGainDataFormat.js +1 -0
- package/lib/mpeg/XingTag.d.ts +4 -4
- package/lib/mpeg/XingTag.js +5 -4
- package/lib/musepack/index.js +1 -0
- package/lib/musepack/sv7/BitReader.js +14 -17
- package/lib/musepack/sv7/MpcSv7Parser.js +6 -1
- package/lib/musepack/sv7/StreamVersion7.js +1 -0
- package/lib/musepack/sv8/MpcSv8Parser.js +6 -2
- package/lib/musepack/sv8/StreamVersion8.d.ts +1 -1
- package/lib/musepack/sv8/StreamVersion8.js +1 -0
- package/lib/ogg/Ogg.d.ts +1 -1
- package/lib/ogg/Ogg.js +1 -0
- package/lib/ogg/OggParser.d.ts +3 -3
- package/lib/ogg/OggParser.js +25 -16
- package/lib/ogg/opus/Opus.d.ts +1 -1
- package/lib/ogg/opus/Opus.js +1 -0
- package/lib/ogg/opus/OpusParser.d.ts +4 -4
- package/lib/ogg/opus/OpusParser.js +2 -0
- package/lib/ogg/speex/Speex.js +1 -0
- package/lib/ogg/speex/SpeexParser.d.ts +4 -4
- package/lib/ogg/speex/SpeexParser.js +1 -0
- package/lib/ogg/theora/Theora.js +1 -0
- package/lib/ogg/theora/TheoraParser.d.ts +4 -4
- package/lib/ogg/theora/TheoraParser.js +1 -0
- package/lib/ogg/vorbis/Vorbis.d.ts +3 -3
- package/lib/ogg/vorbis/Vorbis.js +22 -11
- package/lib/ogg/vorbis/VorbisDecoder.d.ts +1 -1
- package/lib/ogg/vorbis/VorbisDecoder.js +1 -0
- package/lib/ogg/vorbis/VorbisParser.d.ts +4 -4
- package/lib/ogg/vorbis/VorbisParser.js +3 -2
- package/lib/ogg/vorbis/VorbisTagMapper.d.ts +2 -2
- package/lib/ogg/vorbis/VorbisTagMapper.js +2 -2
- package/lib/riff/RiffChunk.d.ts +3 -3
- package/lib/riff/RiffChunk.js +1 -0
- package/lib/riff/RiffInfoTagMap.d.ts +1 -1
- package/lib/type.d.ts +44 -25
- package/lib/wav/BwfChunk.js +1 -0
- package/lib/wav/WaveChunk.d.ts +1 -1
- package/lib/wav/WaveChunk.js +1 -0
- package/lib/wav/WaveParser.js +27 -17
- package/lib/wavpack/WavPackParser.d.ts +1 -1
- package/lib/wavpack/WavPackParser.js +22 -13
- package/lib/wavpack/WavPackToken.d.ts +13 -17
- package/lib/wavpack/WavPackToken.js +22 -23
- package/package.json +139 -150
package/lib/id3v2/FrameParser.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import initDebug from 'debug';
|
|
2
2
|
import * as Token from 'token-types';
|
|
3
3
|
import * as util from '../common/Util.js';
|
|
4
|
-
import { AttachedPictureType,
|
|
4
|
+
import { AttachedPictureType, SyncTextHeader, TextEncodingToken, TextHeader } from './ID3v2Token.js';
|
|
5
5
|
import { Genres } from '../id3v1/ID3v1Parser.js';
|
|
6
6
|
const debug = initDebug('music-metadata:id3v2:frame-parser');
|
|
7
7
|
const defaultEnc = 'latin1'; // latin1 == iso-8859-1;
|
|
@@ -39,9 +39,11 @@ export function parseGenre(origVal) {
|
|
|
39
39
|
}
|
|
40
40
|
if (word) {
|
|
41
41
|
if (genres.length === 0 && word.match(/^\d*$/)) {
|
|
42
|
-
word =
|
|
42
|
+
word = parseGenreCode(word);
|
|
43
|
+
}
|
|
44
|
+
if (word) {
|
|
45
|
+
genres.push(word);
|
|
43
46
|
}
|
|
44
|
-
genres.push(word);
|
|
45
47
|
}
|
|
46
48
|
return genres;
|
|
47
49
|
}
|
|
@@ -51,7 +53,7 @@ function parseGenreCode(code) {
|
|
|
51
53
|
if (code === 'CR')
|
|
52
54
|
return 'Cover';
|
|
53
55
|
if (code.match(/^\d*$/)) {
|
|
54
|
-
return Genres[code];
|
|
56
|
+
return Genres[Number.parseInt(code)];
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
export class FrameParser {
|
|
@@ -83,20 +85,23 @@ export class FrameParser {
|
|
|
83
85
|
case 'MVIN':
|
|
84
86
|
case 'MVNM':
|
|
85
87
|
case 'PCS':
|
|
86
|
-
case 'PCST':
|
|
88
|
+
case 'PCST': {
|
|
87
89
|
let text;
|
|
88
90
|
try {
|
|
89
91
|
text = util.decodeString(uint8Array.slice(1), encoding).replace(/\x00+$/, '');
|
|
90
92
|
}
|
|
91
93
|
catch (error) {
|
|
92
|
-
|
|
94
|
+
if (error instanceof Error) {
|
|
95
|
+
this.warningCollector.addWarning(`id3v2.${this.major} type=${type} header has invalid string value: ${error.message}`);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
93
99
|
}
|
|
94
100
|
switch (type) {
|
|
95
101
|
case 'TMCL': // Musician credits list
|
|
96
102
|
case 'TIPL': // Involved people list
|
|
97
103
|
case 'IPLS': // Involved people list
|
|
98
|
-
output = this.splitValue(type, text);
|
|
99
|
-
output = FrameParser.functionList(output);
|
|
104
|
+
output = FrameParser.functionList(this.splitValue(type, text));
|
|
100
105
|
break;
|
|
101
106
|
case 'TRK':
|
|
102
107
|
case 'TRCK':
|
|
@@ -126,13 +131,16 @@ export class FrameParser {
|
|
|
126
131
|
output = this.major >= 4 ? this.splitValue(type, text) : [text];
|
|
127
132
|
}
|
|
128
133
|
break;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
}
|
|
135
|
+
case 'TXXX': {
|
|
136
|
+
const idAndData = FrameParser.readIdentifierAndData(uint8Array, offset + 1, length, encoding);
|
|
137
|
+
const textTag = {
|
|
138
|
+
description: idAndData.id,
|
|
139
|
+
text: this.splitValue(type, util.decodeString(idAndData.data, encoding).replace(/\x00+$/, ''))
|
|
134
140
|
};
|
|
141
|
+
output = textTag;
|
|
135
142
|
break;
|
|
143
|
+
}
|
|
136
144
|
case 'PIC':
|
|
137
145
|
case 'APIC':
|
|
138
146
|
if (includeCovers) {
|
|
@@ -150,7 +158,7 @@ export class FrameParser {
|
|
|
150
158
|
offset = fzero + 1;
|
|
151
159
|
break;
|
|
152
160
|
default:
|
|
153
|
-
throw new Error(
|
|
161
|
+
throw new Error(`Warning: unexpected major versionIndex: ${this.major}`);
|
|
154
162
|
}
|
|
155
163
|
pic.format = FrameParser.fixPictureMimeType(pic.format);
|
|
156
164
|
pic.type = AttachedPictureType[uint8Array[offset]];
|
|
@@ -166,7 +174,7 @@ export class FrameParser {
|
|
|
166
174
|
case 'PCNT':
|
|
167
175
|
output = Token.UINT32_BE.get(uint8Array, 0);
|
|
168
176
|
break;
|
|
169
|
-
case 'SYLT':
|
|
177
|
+
case 'SYLT': {
|
|
170
178
|
const syltHeader = SyncTextHeader.get(uint8Array, 0);
|
|
171
179
|
offset += SyncTextHeader.len;
|
|
172
180
|
const result = {
|
|
@@ -195,10 +203,11 @@ export class FrameParser {
|
|
|
195
203
|
}
|
|
196
204
|
output = result;
|
|
197
205
|
break;
|
|
206
|
+
}
|
|
198
207
|
case 'ULT':
|
|
199
208
|
case 'USLT':
|
|
200
209
|
case 'COM':
|
|
201
|
-
case 'COMM':
|
|
210
|
+
case 'COMM': {
|
|
202
211
|
const textHeader = TextHeader.get(uint8Array, offset);
|
|
203
212
|
offset += TextHeader.len;
|
|
204
213
|
const descriptorStr = FrameParser.readNullTerminatedString(uint8Array.subarray(offset), textHeader.encoding);
|
|
@@ -211,15 +220,18 @@ export class FrameParser {
|
|
|
211
220
|
};
|
|
212
221
|
output = comment;
|
|
213
222
|
break;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
223
|
+
}
|
|
224
|
+
case 'UFID': {
|
|
225
|
+
const ufid = FrameParser.readIdentifierAndData(uint8Array, offset, length, defaultEnc);
|
|
226
|
+
output = { owner_identifier: ufid.id, identifier: ufid.data };
|
|
217
227
|
break;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
228
|
+
}
|
|
229
|
+
case 'PRIV': { // private frame
|
|
230
|
+
const priv = FrameParser.readIdentifierAndData(uint8Array, offset, length, defaultEnc);
|
|
231
|
+
output = { owner_identifier: priv.id, data: priv.data };
|
|
221
232
|
break;
|
|
222
|
-
|
|
233
|
+
}
|
|
234
|
+
case 'POPM': { // Popularimeter
|
|
223
235
|
fzero = util.findZero(uint8Array, offset, length, defaultEnc);
|
|
224
236
|
const email = util.decodeString(uint8Array.slice(offset, fzero), defaultEnc);
|
|
225
237
|
offset = fzero + 1;
|
|
@@ -230,6 +242,7 @@ export class FrameParser {
|
|
|
230
242
|
counter: dataLen >= 5 ? Token.UINT32_BE.get(uint8Array, offset + 1) : undefined
|
|
231
243
|
};
|
|
232
244
|
break;
|
|
245
|
+
}
|
|
233
246
|
case 'GEOB': { // General encapsulated object
|
|
234
247
|
fzero = util.findZero(uint8Array, offset + 1, length, encoding);
|
|
235
248
|
const mimeType = util.decodeString(uint8Array.slice(offset + 1, fzero), defaultEnc);
|
|
@@ -239,12 +252,13 @@ export class FrameParser {
|
|
|
239
252
|
offset = fzero + 1;
|
|
240
253
|
fzero = util.findZero(uint8Array, offset, length - offset, encoding);
|
|
241
254
|
const description = util.decodeString(uint8Array.slice(offset, fzero), defaultEnc);
|
|
242
|
-
|
|
255
|
+
const geob = {
|
|
243
256
|
type: mimeType,
|
|
244
257
|
filename,
|
|
245
258
|
description,
|
|
246
259
|
data: uint8Array.slice(offset + 1, length)
|
|
247
260
|
};
|
|
261
|
+
output = geob;
|
|
248
262
|
break;
|
|
249
263
|
}
|
|
250
264
|
// W-Frames:
|
|
@@ -257,6 +271,7 @@ export class FrameParser {
|
|
|
257
271
|
case 'WPAY':
|
|
258
272
|
case 'WPUB':
|
|
259
273
|
// Decode URL
|
|
274
|
+
fzero = util.findZero(uint8Array, offset + 1, length, encoding);
|
|
260
275
|
output = util.decodeString(uint8Array.slice(offset, fzero), defaultEnc);
|
|
261
276
|
break;
|
|
262
277
|
case 'WXXX': {
|
|
@@ -277,15 +292,21 @@ export class FrameParser {
|
|
|
277
292
|
break;
|
|
278
293
|
}
|
|
279
294
|
default:
|
|
280
|
-
debug(
|
|
295
|
+
debug(`Warning: unsupported id3v2-tag-type: ${type}`);
|
|
281
296
|
break;
|
|
282
297
|
}
|
|
283
298
|
return output;
|
|
284
299
|
}
|
|
285
300
|
static readNullTerminatedString(uint8Array, encoding) {
|
|
286
301
|
let offset = encoding.bom ? 2 : 0;
|
|
287
|
-
const
|
|
288
|
-
|
|
302
|
+
const zeroIndex = util.findZero(uint8Array, offset, uint8Array.length, encoding.encoding);
|
|
303
|
+
const txt = uint8Array.slice(offset, zeroIndex);
|
|
304
|
+
if (encoding.encoding === 'utf-16le') {
|
|
305
|
+
offset = zeroIndex + 2;
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
offset = zeroIndex + 1;
|
|
309
|
+
}
|
|
289
310
|
return {
|
|
290
311
|
text: util.decodeString(txt, encoding.encoding),
|
|
291
312
|
len: offset
|
|
@@ -309,7 +330,7 @@ export class FrameParser {
|
|
|
309
330
|
const res = {};
|
|
310
331
|
for (let i = 0; i + 1 < entries.length; i += 2) {
|
|
311
332
|
const names = entries[i + 1].split(',');
|
|
312
|
-
res[entries[i]] = res
|
|
333
|
+
res[entries[i]] = res[entries[i]] ? res[entries[i]].concat(names) : names;
|
|
313
334
|
}
|
|
314
335
|
return res;
|
|
315
336
|
}
|
|
@@ -349,3 +370,4 @@ export class FrameParser {
|
|
|
349
370
|
return enc === 'utf-16le' ? 2 : 1;
|
|
350
371
|
}
|
|
351
372
|
}
|
|
373
|
+
//# sourceMappingURL=FrameParser.js.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { CaseInsensitiveTagMap } from '../common/CaseInsensitiveTagMap.js';
|
|
2
2
|
import type { INativeMetadataCollector } from '../common/MetadataCollector.js';
|
|
3
3
|
import type { IRating, ITag } from '../type.js';
|
|
4
|
+
import type { IPopularimeter } from './FrameParser.js';
|
|
4
5
|
export declare class ID3v24TagMapper extends CaseInsensitiveTagMap {
|
|
5
|
-
static toRating(popm:
|
|
6
|
+
static toRating(popm: IPopularimeter): IRating;
|
|
6
7
|
constructor();
|
|
7
8
|
/**
|
|
8
9
|
* Handle post mapping exceptions / correction
|
|
@@ -156,25 +156,32 @@ export class ID3v24TagMapper extends CaseInsensitiveTagMap {
|
|
|
156
156
|
*/
|
|
157
157
|
postMap(tag, warnings) {
|
|
158
158
|
switch (tag.id) {
|
|
159
|
-
case 'UFID':
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
159
|
+
case 'UFID':
|
|
160
|
+
{
|
|
161
|
+
// decode MusicBrainz Recording Id
|
|
162
|
+
const idTag = tag.value;
|
|
163
|
+
if (idTag.owner_identifier === 'http://musicbrainz.org') {
|
|
164
|
+
tag.id += `:${idTag.owner_identifier}`;
|
|
165
|
+
tag.value = decodeString(idTag.identifier, 'latin1'); // latin1 == iso-8859-1
|
|
166
|
+
}
|
|
163
167
|
}
|
|
164
168
|
break;
|
|
165
169
|
case 'PRIV':
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
170
|
+
{
|
|
171
|
+
const customTag = tag.value;
|
|
172
|
+
switch (customTag.owner_identifier) {
|
|
173
|
+
// decode Windows Media Player
|
|
174
|
+
case 'AverageLevel':
|
|
175
|
+
case 'PeakValue':
|
|
176
|
+
tag.id += `:${customTag.owner_identifier}`;
|
|
177
|
+
tag.value = customTag.data.length === 4 ? UINT32_LE.get(customTag.data, 0) : null;
|
|
178
|
+
if (tag.value === null) {
|
|
179
|
+
warnings.addWarning('Failed to parse PRIV:PeakValue');
|
|
180
|
+
}
|
|
181
|
+
break;
|
|
182
|
+
default:
|
|
183
|
+
warnings.addWarning(`Unknown PRIV owner-identifier: ${customTag.data}`);
|
|
184
|
+
}
|
|
178
185
|
}
|
|
179
186
|
break;
|
|
180
187
|
case 'POPM':
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ITokenizer } from 'strtok3';
|
|
2
|
-
import { IOptions } from '../type.js';
|
|
3
|
-
import { INativeMetadataCollector } from '../common/MetadataCollector.js';
|
|
2
|
+
import type { IOptions } from '../type.js';
|
|
3
|
+
import type { INativeMetadataCollector } from '../common/MetadataCollector.js';
|
|
4
4
|
export declare class ID3v2Parser {
|
|
5
5
|
static removeUnsyncBytes(buffer: Uint8Array): Uint8Array;
|
|
6
6
|
private static getFrameHeaderLength;
|
package/lib/id3v2/ID3v2Parser.js
CHANGED
|
@@ -4,6 +4,13 @@ import { FrameParser } from './FrameParser.js';
|
|
|
4
4
|
import { ExtendedHeader, ID3v2Header, UINT32SYNCSAFE } from './ID3v2Token.js';
|
|
5
5
|
const asciiDecoder = new TextDecoder('ascii');
|
|
6
6
|
export class ID3v2Parser {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.tokenizer = undefined;
|
|
9
|
+
this.id3Header = undefined;
|
|
10
|
+
this.metadata = undefined;
|
|
11
|
+
this.headerType = undefined;
|
|
12
|
+
this.options = undefined;
|
|
13
|
+
}
|
|
7
14
|
static removeUnsyncBytes(buffer) {
|
|
8
15
|
let readI = 0;
|
|
9
16
|
let writeI = 0;
|
|
@@ -53,15 +60,15 @@ export class ID3v2Parser {
|
|
|
53
60
|
return frameParser.readData(uint8Array, frameHeader.id, includeCovers);
|
|
54
61
|
case 3:
|
|
55
62
|
case 4:
|
|
56
|
-
if (frameHeader.flags
|
|
63
|
+
if (frameHeader.flags?.format.unsynchronisation) {
|
|
57
64
|
uint8Array = ID3v2Parser.removeUnsyncBytes(uint8Array);
|
|
58
65
|
}
|
|
59
|
-
if (frameHeader.flags
|
|
66
|
+
if (frameHeader.flags?.format.data_length_indicator) {
|
|
60
67
|
uint8Array = uint8Array.slice(4, uint8Array.length);
|
|
61
68
|
}
|
|
62
69
|
return frameParser.readData(uint8Array, frameHeader.id, includeCovers);
|
|
63
70
|
default:
|
|
64
|
-
throw new Error(
|
|
71
|
+
throw new Error(`Unexpected majorVer: ${majorVer}`);
|
|
65
72
|
}
|
|
66
73
|
}
|
|
67
74
|
/**
|
|
@@ -71,7 +78,7 @@ export class ID3v2Parser {
|
|
|
71
78
|
* @returns string e.g. COM:iTunPGAP
|
|
72
79
|
*/
|
|
73
80
|
static makeDescriptionTagName(tag, description) {
|
|
74
|
-
return tag + (description ?
|
|
81
|
+
return tag + (description ? `:${description}` : '');
|
|
75
82
|
}
|
|
76
83
|
async parse(metadata, tokenizer, options) {
|
|
77
84
|
this.tokenizer = tokenizer;
|
|
@@ -82,7 +89,7 @@ export class ID3v2Parser {
|
|
|
82
89
|
throw new Error('expected ID3-header file-identifier \'ID3\' was not found');
|
|
83
90
|
}
|
|
84
91
|
this.id3Header = id3Header;
|
|
85
|
-
this.headerType = (
|
|
92
|
+
this.headerType = (`ID3v2.${id3Header.version.major}`);
|
|
86
93
|
return id3Header.flags.isExtendedHeader ? this.parseExtendedHeader() : this.parseId3Data(id3Header.size);
|
|
87
94
|
}
|
|
88
95
|
async parseExtendedHeader() {
|
|
@@ -125,9 +132,11 @@ export class ID3v2Parser {
|
|
|
125
132
|
this.metadata.addWarning('Illegal ID3v2 tag length');
|
|
126
133
|
break;
|
|
127
134
|
}
|
|
128
|
-
const frameHeaderBytes = data.slice(offset, offset
|
|
135
|
+
const frameHeaderBytes = data.slice(offset, offset + frameHeaderLength);
|
|
136
|
+
offset += frameHeaderLength;
|
|
129
137
|
const frameHeader = this.readFrameHeader(frameHeaderBytes, this.id3Header.version.major);
|
|
130
|
-
const frameDataBytes = data.slice(offset, offset
|
|
138
|
+
const frameDataBytes = data.slice(offset, offset + frameHeader.length);
|
|
139
|
+
offset += frameHeader.length;
|
|
131
140
|
const values = ID3v2Parser.readFrameData(frameDataBytes, frameHeader, this.id3Header.version.major, !this.options.skipCovers, this.metadata);
|
|
132
141
|
if (values) {
|
|
133
142
|
tags.push({ id: frameHeader.id, value: values });
|
|
@@ -159,8 +168,9 @@ export class ID3v2Parser {
|
|
|
159
168
|
}
|
|
160
169
|
break;
|
|
161
170
|
default:
|
|
162
|
-
throw new Error(
|
|
171
|
+
throw new Error(`Unexpected majorVer: ${majorVer}`);
|
|
163
172
|
}
|
|
164
173
|
return header;
|
|
165
174
|
}
|
|
166
175
|
}
|
|
176
|
+
//# sourceMappingURL=ID3v2Parser.js.map
|
package/lib/iff/index.js
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Node.js specific entry point.
|
|
3
3
|
*/
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import { IAudioMetadata, IOptions } from './type.js';
|
|
7
|
-
export
|
|
8
|
-
export { parseFromTokenizer, parseBuffer, parseBlob, parseWebStream, selectCover, orderTags, ratingToStars, IFileInfo } from './core.js';
|
|
4
|
+
import type { Readable } from 'node:stream';
|
|
5
|
+
import { type IFileInfo } from 'strtok3';
|
|
6
|
+
import type { IAudioMetadata, IOptions } from './type.js';
|
|
7
|
+
export * from './core.js';
|
|
9
8
|
/**
|
|
10
9
|
* Parse audio from Node Stream.Readable
|
|
11
10
|
* @param stream - Stream to read the audio track from
|
|
@@ -13,7 +12,7 @@ export { parseFromTokenizer, parseBuffer, parseBlob, parseWebStream, selectCover
|
|
|
13
12
|
* @param options - Parsing options
|
|
14
13
|
* @returns Metadata
|
|
15
14
|
*/
|
|
16
|
-
export declare function parseStream(stream:
|
|
15
|
+
export declare function parseStream(stream: Readable, fileInfo?: IFileInfo | string, options?: IOptions): Promise<IAudioMetadata>;
|
|
17
16
|
/**
|
|
18
17
|
* Parse audio from Node file
|
|
19
18
|
* @param filePath - Media file to read meta-data from
|
package/lib/index.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Node.js specific entry point.
|
|
3
3
|
*/
|
|
4
|
-
import
|
|
4
|
+
import { fromFile, fromStream } from 'strtok3';
|
|
5
5
|
import initDebug from 'debug';
|
|
6
6
|
import { parseFromTokenizer, scanAppendingHeaders } from './core.js';
|
|
7
|
-
import {
|
|
7
|
+
import { getParserIdForExtension, parse } from './ParserFactory.js';
|
|
8
8
|
import { RandomFileReader } from './common/RandomFileReader.js';
|
|
9
|
-
export
|
|
10
|
-
export { parseFromTokenizer, parseBuffer, parseBlob, parseWebStream, selectCover, orderTags, ratingToStars } from './core.js';
|
|
9
|
+
export * from './core.js';
|
|
11
10
|
const debug = initDebug('music-metadata:parser');
|
|
12
11
|
/**
|
|
13
12
|
* Parse audio from Node Stream.Readable
|
|
@@ -17,7 +16,7 @@ const debug = initDebug('music-metadata:parser');
|
|
|
17
16
|
* @returns Metadata
|
|
18
17
|
*/
|
|
19
18
|
export async function parseStream(stream, fileInfo, options = {}) {
|
|
20
|
-
const tokenizer = await
|
|
19
|
+
const tokenizer = await fromStream(stream, { fileInfo: typeof fileInfo === 'string' ? { mimeType: fileInfo } : fileInfo });
|
|
21
20
|
return parseFromTokenizer(tokenizer, options);
|
|
22
21
|
}
|
|
23
22
|
/**
|
|
@@ -28,7 +27,7 @@ export async function parseStream(stream, fileInfo, options = {}) {
|
|
|
28
27
|
*/
|
|
29
28
|
export async function parseFile(filePath, options = {}) {
|
|
30
29
|
debug(`parseFile: ${filePath}`);
|
|
31
|
-
const fileTokenizer = await
|
|
30
|
+
const fileTokenizer = await fromFile(filePath);
|
|
32
31
|
const fileReader = await RandomFileReader.init(filePath, fileTokenizer.fileInfo.size);
|
|
33
32
|
try {
|
|
34
33
|
await scanAppendingHeaders(fileReader, options);
|
|
@@ -37,10 +36,10 @@ export async function parseFile(filePath, options = {}) {
|
|
|
37
36
|
await fileReader.close();
|
|
38
37
|
}
|
|
39
38
|
try {
|
|
40
|
-
const parserName =
|
|
39
|
+
const parserName = getParserIdForExtension(filePath);
|
|
41
40
|
if (!parserName)
|
|
42
41
|
debug(' Parser could not be determined by file extension');
|
|
43
|
-
return await
|
|
42
|
+
return await parse(fileTokenizer, parserName, options);
|
|
44
43
|
}
|
|
45
44
|
finally {
|
|
46
45
|
await fileTokenizer.close();
|
package/lib/lyrics3/Lyrics3.d.ts
CHANGED
package/lib/lyrics3/Lyrics3.js
CHANGED
|
@@ -6,7 +6,7 @@ export async function getLyricsHeaderLength(reader) {
|
|
|
6
6
|
const txt = new TextDecoder('latin1').decode(buf);
|
|
7
7
|
const tag = txt.slice(6);
|
|
8
8
|
if (tag === endTag2) {
|
|
9
|
-
return parseInt(txt.slice(0, 6), 10) + 15;
|
|
9
|
+
return Number.parseInt(txt.slice(0, 6), 10) + 15;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
return 0;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type IElementType } from '../ebml/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Elements of document type description
|
|
4
4
|
* Derived from https://github.com/tungol/EBML/blob/master/doctypes/matroska.dtd
|
|
5
5
|
* Extended with:
|
|
6
6
|
* - https://www.matroska.org/technical/specs/index.html
|
|
7
7
|
*/
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const matroskaDtd: IElementType;
|