music-metadata 7.11.3 → 7.11.7
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/README.md +432 -432
- package/lib/ParserFactory.d.ts +49 -49
- package/lib/ParserFactory.js +251 -251
- package/lib/aiff/AiffParser.d.ts +15 -15
- package/lib/aiff/AiffParser.js +85 -85
- package/lib/aiff/AiffToken.d.ts +22 -22
- package/lib/aiff/AiffToken.js +43 -43
- package/lib/apev2/APEv2Parser.d.ts +30 -30
- package/lib/apev2/APEv2Parser.js +162 -162
- package/lib/apev2/APEv2TagMapper.d.ts +4 -4
- package/lib/apev2/APEv2TagMapper.js +87 -86
- package/lib/apev2/APEv2Token.d.ts +100 -100
- package/lib/apev2/APEv2Token.js +127 -126
- package/lib/asf/AsfObject.d.ts +319 -319
- package/lib/asf/AsfObject.js +384 -384
- package/lib/asf/AsfParser.d.ts +17 -17
- package/lib/asf/AsfParser.js +135 -135
- package/lib/asf/AsfTagMapper.d.ts +7 -7
- package/lib/asf/AsfTagMapper.js +96 -95
- package/lib/asf/AsfUtil.d.ts +13 -13
- package/lib/asf/AsfUtil.js +40 -40
- package/lib/asf/GUID.d.ts +86 -86
- package/lib/asf/GUID.js +123 -123
- package/lib/common/BasicParser.d.ts +17 -17
- package/lib/common/BasicParser.js +18 -18
- package/lib/common/CaseInsensitiveTagMap.d.ts +10 -10
- package/lib/common/CaseInsensitiveTagMap.js +22 -21
- package/lib/common/CombinedTagMapper.d.ts +19 -19
- package/lib/common/CombinedTagMapper.js +52 -51
- package/lib/common/FourCC.d.ts +6 -6
- package/lib/common/FourCC.js +29 -28
- package/lib/common/GenericTagMapper.d.ts +51 -51
- package/lib/common/GenericTagMapper.js +56 -55
- package/lib/common/GenericTagTypes.d.ts +33 -33
- package/lib/common/GenericTagTypes.js +132 -131
- package/lib/common/MetadataCollector.d.ts +76 -76
- package/lib/common/MetadataCollector.js +276 -274
- package/lib/common/RandomFileReader.d.ts +20 -20
- package/lib/common/RandomFileReader.js +37 -37
- package/lib/common/RandomUint8ArrayReader.d.ts +18 -18
- package/lib/common/RandomUint8ArrayReader.js +25 -25
- package/lib/common/Util.d.ts +58 -57
- package/lib/common/Util.js +163 -169
- package/lib/core.d.ts +48 -48
- package/lib/core.js +90 -90
- package/lib/dsdiff/DsdiffParser.d.ts +14 -14
- package/lib/dsdiff/DsdiffParser.js +143 -143
- package/lib/dsdiff/DsdiffToken.d.ts +9 -9
- package/lib/dsdiff/DsdiffToken.js +21 -21
- package/lib/dsf/DsfChunk.d.ts +86 -86
- package/lib/dsf/DsfChunk.js +54 -54
- package/lib/dsf/DsfParser.d.ts +9 -9
- package/lib/dsf/DsfParser.js +56 -56
- package/lib/flac/FlacParser.d.ts +28 -28
- package/lib/flac/FlacParser.js +175 -175
- package/lib/id3v1/ID3v1Parser.d.ts +13 -13
- package/lib/id3v1/ID3v1Parser.js +134 -134
- package/lib/id3v1/ID3v1TagMap.d.ts +4 -4
- package/lib/id3v1/ID3v1TagMap.js +23 -22
- package/lib/id3v2/AbstractID3Parser.d.ts +17 -17
- package/lib/id3v2/AbstractID3Parser.js +60 -60
- package/lib/id3v2/FrameParser.d.ts +32 -32
- package/lib/id3v2/FrameParser.js +329 -323
- package/lib/id3v2/ID3v22TagMapper.d.ts +9 -9
- package/lib/id3v2/ID3v22TagMapper.js +56 -54
- package/lib/id3v2/ID3v24TagMapper.d.ts +14 -14
- package/lib/id3v2/ID3v24TagMapper.js +194 -193
- package/lib/id3v2/ID3v2Parser.d.ts +29 -29
- package/lib/id3v2/ID3v2Parser.js +194 -194
- package/lib/id3v2/ID3v2Token.d.ts +73 -73
- package/lib/id3v2/ID3v2Token.js +106 -106
- package/lib/iff/index.d.ts +33 -33
- package/lib/iff/index.js +19 -19
- package/lib/index.d.ts +45 -34
- package/lib/index.js +74 -64
- package/lib/lyrics3/Lyrics3.d.ts +3 -3
- package/lib/lyrics3/Lyrics3.js +17 -17
- package/lib/matroska/MatroskaDtd.d.ts +8 -8
- package/lib/matroska/MatroskaDtd.js +279 -279
- package/lib/matroska/MatroskaParser.d.ts +37 -37
- package/lib/matroska/MatroskaParser.js +235 -234
- package/lib/matroska/MatroskaTagMapper.d.ts +4 -4
- package/lib/matroska/MatroskaTagMapper.js +36 -35
- package/lib/matroska/types.d.ts +175 -175
- package/lib/matroska/types.js +32 -32
- package/lib/mp4/Atom.d.ts +16 -16
- package/lib/mp4/Atom.js +70 -70
- package/lib/mp4/AtomToken.d.ts +395 -395
- package/lib/mp4/AtomToken.js +406 -406
- package/lib/mp4/MP4Parser.d.ts +30 -30
- package/lib/mp4/MP4Parser.js +511 -511
- package/lib/mp4/MP4TagMapper.d.ts +5 -5
- package/lib/mp4/MP4TagMapper.js +116 -115
- package/lib/mpeg/ExtendedLameHeader.d.ts +27 -27
- package/lib/mpeg/ExtendedLameHeader.js +31 -31
- package/lib/mpeg/MpegParser.d.ts +49 -49
- package/lib/mpeg/MpegParser.js +529 -529
- package/lib/mpeg/ReplayGainDataFormat.d.ts +55 -55
- package/lib/mpeg/ReplayGainDataFormat.js +69 -69
- package/lib/mpeg/XingTag.d.ts +45 -45
- package/lib/mpeg/XingTag.js +69 -69
- package/lib/musepack/index.d.ts +5 -5
- package/lib/musepack/index.js +32 -32
- package/lib/musepack/sv7/BitReader.d.ts +13 -13
- package/lib/musepack/sv7/BitReader.js +54 -54
- package/lib/musepack/sv7/MpcSv7Parser.d.ts +8 -8
- package/lib/musepack/sv7/MpcSv7Parser.js +46 -46
- package/lib/musepack/sv7/StreamVersion7.d.ts +28 -28
- package/lib/musepack/sv7/StreamVersion7.js +41 -41
- package/lib/musepack/sv8/MpcSv8Parser.d.ts +6 -6
- package/lib/musepack/sv8/MpcSv8Parser.js +55 -55
- package/lib/musepack/sv8/StreamVersion8.d.ts +40 -40
- package/lib/musepack/sv8/StreamVersion8.js +80 -80
- package/lib/ogg/Ogg.d.ts +72 -72
- package/lib/ogg/Ogg.js +2 -2
- package/lib/ogg/OggParser.d.ts +23 -23
- package/lib/ogg/OggParser.js +126 -126
- package/lib/ogg/opus/Opus.d.ts +48 -48
- package/lib/ogg/opus/Opus.js +28 -28
- package/lib/ogg/opus/OpusParser.d.ts +25 -25
- package/lib/ogg/opus/OpusParser.js +56 -56
- package/lib/ogg/speex/Speex.d.ts +36 -36
- package/lib/ogg/speex/Speex.js +31 -31
- package/lib/ogg/speex/SpeexParser.d.ts +22 -22
- package/lib/ogg/speex/SpeexParser.js +35 -35
- package/lib/ogg/theora/Theora.d.ts +20 -20
- package/lib/ogg/theora/Theora.js +23 -23
- package/lib/ogg/theora/TheoraParser.d.ts +28 -28
- package/lib/ogg/theora/TheoraParser.js +44 -44
- package/lib/ogg/vorbis/Vorbis.d.ts +79 -79
- package/lib/ogg/vorbis/Vorbis.js +78 -78
- package/lib/ogg/vorbis/VorbisDecoder.d.ts +12 -12
- package/lib/ogg/vorbis/VorbisDecoder.js +32 -32
- package/lib/ogg/vorbis/VorbisParser.d.ts +36 -36
- package/lib/ogg/vorbis/VorbisParser.js +128 -128
- package/lib/ogg/vorbis/VorbisTagMapper.d.ts +7 -7
- package/lib/ogg/vorbis/VorbisTagMapper.js +133 -132
- package/lib/riff/RiffChunk.d.ts +16 -16
- package/lib/riff/RiffChunk.js +32 -32
- package/lib/riff/RiffInfoTagMap.d.ts +10 -10
- package/lib/riff/RiffInfoTagMap.js +38 -37
- package/lib/type.d.ts +599 -599
- package/lib/type.js +14 -13
- package/lib/wav/WaveChunk.d.ts +64 -64
- package/lib/wav/WaveChunk.js +65 -65
- package/lib/wav/WaveParser.d.ts +24 -24
- package/lib/wav/WaveParser.js +144 -144
- package/lib/wavpack/WavPackParser.d.ts +14 -14
- package/lib/wavpack/WavPackParser.js +105 -105
- package/lib/wavpack/WavPackToken.d.ts +64 -64
- package/lib/wavpack/WavPackToken.js +76 -76
- package/package.json +142 -142
package/lib/ParserFactory.d.ts
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { IOptions, IAudioMetadata, ParserType } from './type';
|
|
2
|
-
import { ITokenizer } from 'strtok3/lib/core';
|
|
3
|
-
import { INativeMetadataCollector } from './common/MetadataCollector';
|
|
4
|
-
export interface ITokenParser {
|
|
5
|
-
/**
|
|
6
|
-
* Initialize parser with output (metadata), input (tokenizer) & parsing options (options).
|
|
7
|
-
* @param metadata - Output
|
|
8
|
-
* @param tokenizer - Input
|
|
9
|
-
* @param options - Parsing options
|
|
10
|
-
*/
|
|
11
|
-
init(metadata: INativeMetadataCollector, tokenizer: ITokenizer, options: IOptions): ITokenParser;
|
|
12
|
-
/**
|
|
13
|
-
* Parse audio track.
|
|
14
|
-
* Called after init(...).
|
|
15
|
-
* @returns Promise
|
|
16
|
-
*/
|
|
17
|
-
parse(): Promise<void>;
|
|
18
|
-
}
|
|
19
|
-
export declare function parseHttpContentType(contentType: string): {
|
|
20
|
-
type: string;
|
|
21
|
-
subtype: string;
|
|
22
|
-
suffix?: string;
|
|
23
|
-
parameters: {
|
|
24
|
-
[id: string]: string;
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
export declare class ParserFactory {
|
|
28
|
-
/**
|
|
29
|
-
* Parse metadata from tokenizer
|
|
30
|
-
* @param tokenizer - Tokenizer
|
|
31
|
-
* @param opts - Options
|
|
32
|
-
* @returns Native metadata
|
|
33
|
-
*/
|
|
34
|
-
static parseOnContentType(tokenizer: ITokenizer, opts: IOptions): Promise<IAudioMetadata>;
|
|
35
|
-
static parse(tokenizer: ITokenizer, parserId: ParserType, opts: IOptions): Promise<IAudioMetadata>;
|
|
36
|
-
/**
|
|
37
|
-
* @param filePath - Path, filename or extension to audio file
|
|
38
|
-
* @return Parser sub-module name
|
|
39
|
-
*/
|
|
40
|
-
static getParserIdForExtension(filePath: string): ParserType;
|
|
41
|
-
static loadParser(moduleName: ParserType): Promise<ITokenParser>;
|
|
42
|
-
private static _parse;
|
|
43
|
-
private static getExtension;
|
|
44
|
-
/**
|
|
45
|
-
* @param httpContentType - HTTP Content-Type, extension, path or filename
|
|
46
|
-
* @returns Parser sub-module name
|
|
47
|
-
*/
|
|
48
|
-
private static getParserIdForMimeType;
|
|
49
|
-
}
|
|
1
|
+
import { IOptions, IAudioMetadata, ParserType } from './type';
|
|
2
|
+
import { ITokenizer } from 'strtok3/lib/core';
|
|
3
|
+
import { INativeMetadataCollector } from './common/MetadataCollector';
|
|
4
|
+
export interface ITokenParser {
|
|
5
|
+
/**
|
|
6
|
+
* Initialize parser with output (metadata), input (tokenizer) & parsing options (options).
|
|
7
|
+
* @param metadata - Output
|
|
8
|
+
* @param tokenizer - Input
|
|
9
|
+
* @param options - Parsing options
|
|
10
|
+
*/
|
|
11
|
+
init(metadata: INativeMetadataCollector, tokenizer: ITokenizer, options: IOptions): ITokenParser;
|
|
12
|
+
/**
|
|
13
|
+
* Parse audio track.
|
|
14
|
+
* Called after init(...).
|
|
15
|
+
* @returns Promise
|
|
16
|
+
*/
|
|
17
|
+
parse(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare function parseHttpContentType(contentType: string): {
|
|
20
|
+
type: string;
|
|
21
|
+
subtype: string;
|
|
22
|
+
suffix?: string;
|
|
23
|
+
parameters: {
|
|
24
|
+
[id: string]: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export declare class ParserFactory {
|
|
28
|
+
/**
|
|
29
|
+
* Parse metadata from tokenizer
|
|
30
|
+
* @param tokenizer - Tokenizer
|
|
31
|
+
* @param opts - Options
|
|
32
|
+
* @returns Native metadata
|
|
33
|
+
*/
|
|
34
|
+
static parseOnContentType(tokenizer: ITokenizer, opts: IOptions): Promise<IAudioMetadata>;
|
|
35
|
+
static parse(tokenizer: ITokenizer, parserId: ParserType, opts: IOptions): Promise<IAudioMetadata>;
|
|
36
|
+
/**
|
|
37
|
+
* @param filePath - Path, filename or extension to audio file
|
|
38
|
+
* @return Parser sub-module name
|
|
39
|
+
*/
|
|
40
|
+
static getParserIdForExtension(filePath: string): ParserType;
|
|
41
|
+
static loadParser(moduleName: ParserType): Promise<ITokenParser>;
|
|
42
|
+
private static _parse;
|
|
43
|
+
private static getExtension;
|
|
44
|
+
/**
|
|
45
|
+
* @param httpContentType - HTTP Content-Type, extension, path or filename
|
|
46
|
+
* @returns Parser sub-module name
|
|
47
|
+
*/
|
|
48
|
+
private static getParserIdForMimeType;
|
|
49
|
+
}
|
package/lib/ParserFactory.js
CHANGED
|
@@ -1,251 +1,251 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ParserFactory = exports.parseHttpContentType = void 0;
|
|
4
|
-
const FileType = require("file-type/core");
|
|
5
|
-
const ContentType = require("content-type");
|
|
6
|
-
const MimeType = require("media-typer");
|
|
7
|
-
const _debug = require("debug");
|
|
8
|
-
const MetadataCollector_1 = require("./common/MetadataCollector");
|
|
9
|
-
const AiffParser_1 = require("./aiff/AiffParser");
|
|
10
|
-
const APEv2Parser_1 = require("./apev2/APEv2Parser");
|
|
11
|
-
const AsfParser_1 = require("./asf/AsfParser");
|
|
12
|
-
const FlacParser_1 = require("./flac/FlacParser");
|
|
13
|
-
const MP4Parser_1 = require("./mp4/MP4Parser");
|
|
14
|
-
const MpegParser_1 = require("./mpeg/MpegParser");
|
|
15
|
-
const musepack_1 = require("./musepack");
|
|
16
|
-
const OggParser_1 = require("./ogg/OggParser");
|
|
17
|
-
const WaveParser_1 = require("./wav/WaveParser");
|
|
18
|
-
const WavPackParser_1 = require("./wavpack/WavPackParser");
|
|
19
|
-
const DsfParser_1 = require("./dsf/DsfParser");
|
|
20
|
-
const DsdiffParser_1 = require("./dsdiff/DsdiffParser");
|
|
21
|
-
const MatroskaParser_1 = require("./matroska/MatroskaParser");
|
|
22
|
-
const debug = _debug('music-metadata:parser:factory');
|
|
23
|
-
function parseHttpContentType(contentType) {
|
|
24
|
-
const type = ContentType.parse(contentType);
|
|
25
|
-
const mime = MimeType.parse(type.type);
|
|
26
|
-
return {
|
|
27
|
-
type: mime.type,
|
|
28
|
-
subtype: mime.subtype,
|
|
29
|
-
suffix: mime.suffix,
|
|
30
|
-
parameters: type.parameters
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
exports.parseHttpContentType = parseHttpContentType;
|
|
34
|
-
class ParserFactory {
|
|
35
|
-
/**
|
|
36
|
-
* Parse metadata from tokenizer
|
|
37
|
-
* @param tokenizer - Tokenizer
|
|
38
|
-
* @param opts - Options
|
|
39
|
-
* @returns Native metadata
|
|
40
|
-
*/
|
|
41
|
-
static async parseOnContentType(tokenizer, opts) {
|
|
42
|
-
const { mimeType, path, url } = await tokenizer.fileInfo;
|
|
43
|
-
// Resolve parser based on MIME-type or file extension
|
|
44
|
-
const parserId = ParserFactory.getParserIdForMimeType(mimeType) || ParserFactory.getParserIdForExtension(path) || ParserFactory.getParserIdForExtension(url);
|
|
45
|
-
if (!parserId) {
|
|
46
|
-
debug('No parser found for MIME-type / extension: ' + mimeType);
|
|
47
|
-
}
|
|
48
|
-
return this.parse(tokenizer, parserId, opts);
|
|
49
|
-
}
|
|
50
|
-
static async parse(tokenizer, parserId, opts) {
|
|
51
|
-
if (!parserId) {
|
|
52
|
-
// Parser could not be determined on MIME-type or extension
|
|
53
|
-
debug('Guess parser on content...');
|
|
54
|
-
const buf = Buffer.alloc(4100);
|
|
55
|
-
await tokenizer.peekBuffer(buf, { mayBeLess: true });
|
|
56
|
-
if (tokenizer.fileInfo.path) {
|
|
57
|
-
parserId = this.getParserIdForExtension(tokenizer.fileInfo.path);
|
|
58
|
-
}
|
|
59
|
-
if (!parserId) {
|
|
60
|
-
const guessedType = await FileType.fromBuffer(buf);
|
|
61
|
-
if (!guessedType) {
|
|
62
|
-
throw new Error('Failed to determine audio format');
|
|
63
|
-
}
|
|
64
|
-
debug(`Guessed file type is mime=${guessedType.mime}, extension=${guessedType.ext}`);
|
|
65
|
-
parserId = ParserFactory.getParserIdForMimeType(guessedType.mime);
|
|
66
|
-
if (!parserId) {
|
|
67
|
-
throw new Error('Guessed MIME-type not supported: ' + guessedType.mime);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// Parser found, execute parser
|
|
72
|
-
return this._parse(tokenizer, parserId, opts);
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* @param filePath - Path, filename or extension to audio file
|
|
76
|
-
* @return Parser sub-module name
|
|
77
|
-
*/
|
|
78
|
-
static getParserIdForExtension(filePath) {
|
|
79
|
-
if (!filePath)
|
|
80
|
-
return;
|
|
81
|
-
const extension = this.getExtension(filePath).toLocaleLowerCase() || filePath;
|
|
82
|
-
switch (extension) {
|
|
83
|
-
case '.mp2':
|
|
84
|
-
case '.mp3':
|
|
85
|
-
case '.m2a':
|
|
86
|
-
case '.aac': // Assume it is ADTS-container
|
|
87
|
-
return 'mpeg';
|
|
88
|
-
case '.ape':
|
|
89
|
-
return 'apev2';
|
|
90
|
-
case '.mp4':
|
|
91
|
-
case '.m4a':
|
|
92
|
-
case '.m4b':
|
|
93
|
-
case '.m4pa':
|
|
94
|
-
case '.m4v':
|
|
95
|
-
case '.m4r':
|
|
96
|
-
case '.3gp':
|
|
97
|
-
return 'mp4';
|
|
98
|
-
case '.wma':
|
|
99
|
-
case '.wmv':
|
|
100
|
-
case '.asf':
|
|
101
|
-
return 'asf';
|
|
102
|
-
case '.flac':
|
|
103
|
-
return 'flac';
|
|
104
|
-
case '.ogg':
|
|
105
|
-
case '.ogv':
|
|
106
|
-
case '.oga':
|
|
107
|
-
case '.ogm':
|
|
108
|
-
case '.ogx':
|
|
109
|
-
case '.opus': // recommended filename extension for Ogg Opus
|
|
110
|
-
case '.spx': // recommended filename extension for Ogg Speex
|
|
111
|
-
return 'ogg';
|
|
112
|
-
case '.aif':
|
|
113
|
-
case '.aiff':
|
|
114
|
-
case '.aifc':
|
|
115
|
-
return 'aiff';
|
|
116
|
-
case '.wav':
|
|
117
|
-
return 'riff';
|
|
118
|
-
case '.wv':
|
|
119
|
-
case '.wvp':
|
|
120
|
-
return 'wavpack';
|
|
121
|
-
case '.mpc':
|
|
122
|
-
return 'musepack';
|
|
123
|
-
case '.dsf':
|
|
124
|
-
return 'dsf';
|
|
125
|
-
case '.dff':
|
|
126
|
-
return 'dsdiff';
|
|
127
|
-
case '.mka':
|
|
128
|
-
case '.mkv':
|
|
129
|
-
case '.mk3d':
|
|
130
|
-
case '.mks':
|
|
131
|
-
case '.webm':
|
|
132
|
-
return 'matroska';
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
static async loadParser(moduleName) {
|
|
136
|
-
switch (moduleName) {
|
|
137
|
-
case 'aiff': return new AiffParser_1.AIFFParser();
|
|
138
|
-
case 'adts':
|
|
139
|
-
case 'mpeg':
|
|
140
|
-
return new MpegParser_1.MpegParser();
|
|
141
|
-
case 'apev2': return new APEv2Parser_1.APEv2Parser();
|
|
142
|
-
case 'asf': return new AsfParser_1.AsfParser();
|
|
143
|
-
case 'dsf': return new DsfParser_1.DsfParser();
|
|
144
|
-
case 'dsdiff': return new DsdiffParser_1.DsdiffParser();
|
|
145
|
-
case 'flac': return new FlacParser_1.FlacParser();
|
|
146
|
-
case 'mp4': return new MP4Parser_1.MP4Parser();
|
|
147
|
-
case 'musepack': return new musepack_1.default();
|
|
148
|
-
case 'ogg': return new OggParser_1.OggParser();
|
|
149
|
-
case 'riff': return new WaveParser_1.WaveParser();
|
|
150
|
-
case 'wavpack': return new WavPackParser_1.WavPackParser();
|
|
151
|
-
case 'matroska': return new MatroskaParser_1.MatroskaParser();
|
|
152
|
-
default:
|
|
153
|
-
throw new Error(`Unknown parser type: ${moduleName}`);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
static async _parse(tokenizer, parserId, opts = {}) {
|
|
157
|
-
// Parser found, execute parser
|
|
158
|
-
const parser = await ParserFactory.loadParser(parserId);
|
|
159
|
-
const metadata = new MetadataCollector_1.MetadataCollector(opts);
|
|
160
|
-
await parser.init(metadata, tokenizer, opts).parse();
|
|
161
|
-
return metadata.toCommonMetadata();
|
|
162
|
-
}
|
|
163
|
-
static getExtension(fname) {
|
|
164
|
-
const i = fname.lastIndexOf('.');
|
|
165
|
-
return i === -1 ? '' : fname.slice(i);
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* @param httpContentType - HTTP Content-Type, extension, path or filename
|
|
169
|
-
* @returns Parser sub-module name
|
|
170
|
-
*/
|
|
171
|
-
static getParserIdForMimeType(httpContentType) {
|
|
172
|
-
let mime;
|
|
173
|
-
try {
|
|
174
|
-
mime = parseHttpContentType(httpContentType);
|
|
175
|
-
}
|
|
176
|
-
catch (err) {
|
|
177
|
-
debug(`Invalid HTTP Content-Type header value: ${httpContentType}`);
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
const subType = mime.subtype.indexOf('x-') === 0 ? mime.subtype.substring(2) : mime.subtype;
|
|
181
|
-
switch (mime.type) {
|
|
182
|
-
case 'audio':
|
|
183
|
-
switch (subType) {
|
|
184
|
-
case 'mp3': // Incorrect MIME-type, Chrome, in Web API File object
|
|
185
|
-
case 'mpeg':
|
|
186
|
-
return 'mpeg';
|
|
187
|
-
case 'aac':
|
|
188
|
-
case 'aacp':
|
|
189
|
-
return 'adts';
|
|
190
|
-
case 'flac':
|
|
191
|
-
return 'flac';
|
|
192
|
-
case 'ape':
|
|
193
|
-
case 'monkeys-audio':
|
|
194
|
-
return 'apev2';
|
|
195
|
-
case 'mp4':
|
|
196
|
-
case 'm4a':
|
|
197
|
-
return 'mp4';
|
|
198
|
-
case 'ogg': // RFC 7845
|
|
199
|
-
case 'opus': // RFC 6716
|
|
200
|
-
case 'speex': // RFC 5574
|
|
201
|
-
return 'ogg';
|
|
202
|
-
case 'ms-wma':
|
|
203
|
-
case 'ms-wmv':
|
|
204
|
-
case 'ms-asf':
|
|
205
|
-
return 'asf';
|
|
206
|
-
case 'aiff':
|
|
207
|
-
case 'aif':
|
|
208
|
-
case 'aifc':
|
|
209
|
-
return 'aiff';
|
|
210
|
-
case 'vnd.wave':
|
|
211
|
-
case 'wav':
|
|
212
|
-
case 'wave':
|
|
213
|
-
return 'riff';
|
|
214
|
-
case 'wavpack':
|
|
215
|
-
return 'wavpack';
|
|
216
|
-
case 'musepack':
|
|
217
|
-
return 'musepack';
|
|
218
|
-
case 'matroska':
|
|
219
|
-
case 'webm':
|
|
220
|
-
return 'matroska';
|
|
221
|
-
case 'dsf':
|
|
222
|
-
return 'dsf';
|
|
223
|
-
}
|
|
224
|
-
break;
|
|
225
|
-
case 'video':
|
|
226
|
-
switch (subType) {
|
|
227
|
-
case 'ms-asf':
|
|
228
|
-
case 'ms-wmv':
|
|
229
|
-
return 'asf';
|
|
230
|
-
case 'm4v':
|
|
231
|
-
case 'mp4':
|
|
232
|
-
return 'mp4';
|
|
233
|
-
case 'ogg':
|
|
234
|
-
return 'ogg';
|
|
235
|
-
case 'matroska':
|
|
236
|
-
case 'webm':
|
|
237
|
-
return 'matroska';
|
|
238
|
-
}
|
|
239
|
-
break;
|
|
240
|
-
case 'application':
|
|
241
|
-
switch (subType) {
|
|
242
|
-
case 'vnd.ms-asf':
|
|
243
|
-
return 'asf';
|
|
244
|
-
case 'ogg':
|
|
245
|
-
return 'ogg';
|
|
246
|
-
}
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
exports.ParserFactory = ParserFactory;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ParserFactory = exports.parseHttpContentType = void 0;
|
|
4
|
+
const FileType = require("file-type/core");
|
|
5
|
+
const ContentType = require("content-type");
|
|
6
|
+
const MimeType = require("media-typer");
|
|
7
|
+
const _debug = require("debug");
|
|
8
|
+
const MetadataCollector_1 = require("./common/MetadataCollector");
|
|
9
|
+
const AiffParser_1 = require("./aiff/AiffParser");
|
|
10
|
+
const APEv2Parser_1 = require("./apev2/APEv2Parser");
|
|
11
|
+
const AsfParser_1 = require("./asf/AsfParser");
|
|
12
|
+
const FlacParser_1 = require("./flac/FlacParser");
|
|
13
|
+
const MP4Parser_1 = require("./mp4/MP4Parser");
|
|
14
|
+
const MpegParser_1 = require("./mpeg/MpegParser");
|
|
15
|
+
const musepack_1 = require("./musepack");
|
|
16
|
+
const OggParser_1 = require("./ogg/OggParser");
|
|
17
|
+
const WaveParser_1 = require("./wav/WaveParser");
|
|
18
|
+
const WavPackParser_1 = require("./wavpack/WavPackParser");
|
|
19
|
+
const DsfParser_1 = require("./dsf/DsfParser");
|
|
20
|
+
const DsdiffParser_1 = require("./dsdiff/DsdiffParser");
|
|
21
|
+
const MatroskaParser_1 = require("./matroska/MatroskaParser");
|
|
22
|
+
const debug = _debug('music-metadata:parser:factory');
|
|
23
|
+
function parseHttpContentType(contentType) {
|
|
24
|
+
const type = ContentType.parse(contentType);
|
|
25
|
+
const mime = MimeType.parse(type.type);
|
|
26
|
+
return {
|
|
27
|
+
type: mime.type,
|
|
28
|
+
subtype: mime.subtype,
|
|
29
|
+
suffix: mime.suffix,
|
|
30
|
+
parameters: type.parameters
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
exports.parseHttpContentType = parseHttpContentType;
|
|
34
|
+
class ParserFactory {
|
|
35
|
+
/**
|
|
36
|
+
* Parse metadata from tokenizer
|
|
37
|
+
* @param tokenizer - Tokenizer
|
|
38
|
+
* @param opts - Options
|
|
39
|
+
* @returns Native metadata
|
|
40
|
+
*/
|
|
41
|
+
static async parseOnContentType(tokenizer, opts) {
|
|
42
|
+
const { mimeType, path, url } = await tokenizer.fileInfo;
|
|
43
|
+
// Resolve parser based on MIME-type or file extension
|
|
44
|
+
const parserId = ParserFactory.getParserIdForMimeType(mimeType) || ParserFactory.getParserIdForExtension(path) || ParserFactory.getParserIdForExtension(url);
|
|
45
|
+
if (!parserId) {
|
|
46
|
+
debug('No parser found for MIME-type / extension: ' + mimeType);
|
|
47
|
+
}
|
|
48
|
+
return this.parse(tokenizer, parserId, opts);
|
|
49
|
+
}
|
|
50
|
+
static async parse(tokenizer, parserId, opts) {
|
|
51
|
+
if (!parserId) {
|
|
52
|
+
// Parser could not be determined on MIME-type or extension
|
|
53
|
+
debug('Guess parser on content...');
|
|
54
|
+
const buf = Buffer.alloc(4100);
|
|
55
|
+
await tokenizer.peekBuffer(buf, { mayBeLess: true });
|
|
56
|
+
if (tokenizer.fileInfo.path) {
|
|
57
|
+
parserId = this.getParserIdForExtension(tokenizer.fileInfo.path);
|
|
58
|
+
}
|
|
59
|
+
if (!parserId) {
|
|
60
|
+
const guessedType = await FileType.fromBuffer(buf);
|
|
61
|
+
if (!guessedType) {
|
|
62
|
+
throw new Error('Failed to determine audio format');
|
|
63
|
+
}
|
|
64
|
+
debug(`Guessed file type is mime=${guessedType.mime}, extension=${guessedType.ext}`);
|
|
65
|
+
parserId = ParserFactory.getParserIdForMimeType(guessedType.mime);
|
|
66
|
+
if (!parserId) {
|
|
67
|
+
throw new Error('Guessed MIME-type not supported: ' + guessedType.mime);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Parser found, execute parser
|
|
72
|
+
return this._parse(tokenizer, parserId, opts);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* @param filePath - Path, filename or extension to audio file
|
|
76
|
+
* @return Parser sub-module name
|
|
77
|
+
*/
|
|
78
|
+
static getParserIdForExtension(filePath) {
|
|
79
|
+
if (!filePath)
|
|
80
|
+
return;
|
|
81
|
+
const extension = this.getExtension(filePath).toLocaleLowerCase() || filePath;
|
|
82
|
+
switch (extension) {
|
|
83
|
+
case '.mp2':
|
|
84
|
+
case '.mp3':
|
|
85
|
+
case '.m2a':
|
|
86
|
+
case '.aac': // Assume it is ADTS-container
|
|
87
|
+
return 'mpeg';
|
|
88
|
+
case '.ape':
|
|
89
|
+
return 'apev2';
|
|
90
|
+
case '.mp4':
|
|
91
|
+
case '.m4a':
|
|
92
|
+
case '.m4b':
|
|
93
|
+
case '.m4pa':
|
|
94
|
+
case '.m4v':
|
|
95
|
+
case '.m4r':
|
|
96
|
+
case '.3gp':
|
|
97
|
+
return 'mp4';
|
|
98
|
+
case '.wma':
|
|
99
|
+
case '.wmv':
|
|
100
|
+
case '.asf':
|
|
101
|
+
return 'asf';
|
|
102
|
+
case '.flac':
|
|
103
|
+
return 'flac';
|
|
104
|
+
case '.ogg':
|
|
105
|
+
case '.ogv':
|
|
106
|
+
case '.oga':
|
|
107
|
+
case '.ogm':
|
|
108
|
+
case '.ogx':
|
|
109
|
+
case '.opus': // recommended filename extension for Ogg Opus
|
|
110
|
+
case '.spx': // recommended filename extension for Ogg Speex
|
|
111
|
+
return 'ogg';
|
|
112
|
+
case '.aif':
|
|
113
|
+
case '.aiff':
|
|
114
|
+
case '.aifc':
|
|
115
|
+
return 'aiff';
|
|
116
|
+
case '.wav':
|
|
117
|
+
return 'riff';
|
|
118
|
+
case '.wv':
|
|
119
|
+
case '.wvp':
|
|
120
|
+
return 'wavpack';
|
|
121
|
+
case '.mpc':
|
|
122
|
+
return 'musepack';
|
|
123
|
+
case '.dsf':
|
|
124
|
+
return 'dsf';
|
|
125
|
+
case '.dff':
|
|
126
|
+
return 'dsdiff';
|
|
127
|
+
case '.mka':
|
|
128
|
+
case '.mkv':
|
|
129
|
+
case '.mk3d':
|
|
130
|
+
case '.mks':
|
|
131
|
+
case '.webm':
|
|
132
|
+
return 'matroska';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
static async loadParser(moduleName) {
|
|
136
|
+
switch (moduleName) {
|
|
137
|
+
case 'aiff': return new AiffParser_1.AIFFParser();
|
|
138
|
+
case 'adts':
|
|
139
|
+
case 'mpeg':
|
|
140
|
+
return new MpegParser_1.MpegParser();
|
|
141
|
+
case 'apev2': return new APEv2Parser_1.APEv2Parser();
|
|
142
|
+
case 'asf': return new AsfParser_1.AsfParser();
|
|
143
|
+
case 'dsf': return new DsfParser_1.DsfParser();
|
|
144
|
+
case 'dsdiff': return new DsdiffParser_1.DsdiffParser();
|
|
145
|
+
case 'flac': return new FlacParser_1.FlacParser();
|
|
146
|
+
case 'mp4': return new MP4Parser_1.MP4Parser();
|
|
147
|
+
case 'musepack': return new musepack_1.default();
|
|
148
|
+
case 'ogg': return new OggParser_1.OggParser();
|
|
149
|
+
case 'riff': return new WaveParser_1.WaveParser();
|
|
150
|
+
case 'wavpack': return new WavPackParser_1.WavPackParser();
|
|
151
|
+
case 'matroska': return new MatroskaParser_1.MatroskaParser();
|
|
152
|
+
default:
|
|
153
|
+
throw new Error(`Unknown parser type: ${moduleName}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
static async _parse(tokenizer, parserId, opts = {}) {
|
|
157
|
+
// Parser found, execute parser
|
|
158
|
+
const parser = await ParserFactory.loadParser(parserId);
|
|
159
|
+
const metadata = new MetadataCollector_1.MetadataCollector(opts);
|
|
160
|
+
await parser.init(metadata, tokenizer, opts).parse();
|
|
161
|
+
return metadata.toCommonMetadata();
|
|
162
|
+
}
|
|
163
|
+
static getExtension(fname) {
|
|
164
|
+
const i = fname.lastIndexOf('.');
|
|
165
|
+
return i === -1 ? '' : fname.slice(i);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* @param httpContentType - HTTP Content-Type, extension, path or filename
|
|
169
|
+
* @returns Parser sub-module name
|
|
170
|
+
*/
|
|
171
|
+
static getParserIdForMimeType(httpContentType) {
|
|
172
|
+
let mime;
|
|
173
|
+
try {
|
|
174
|
+
mime = parseHttpContentType(httpContentType);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
debug(`Invalid HTTP Content-Type header value: ${httpContentType}`);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const subType = mime.subtype.indexOf('x-') === 0 ? mime.subtype.substring(2) : mime.subtype;
|
|
181
|
+
switch (mime.type) {
|
|
182
|
+
case 'audio':
|
|
183
|
+
switch (subType) {
|
|
184
|
+
case 'mp3': // Incorrect MIME-type, Chrome, in Web API File object
|
|
185
|
+
case 'mpeg':
|
|
186
|
+
return 'mpeg';
|
|
187
|
+
case 'aac':
|
|
188
|
+
case 'aacp':
|
|
189
|
+
return 'adts';
|
|
190
|
+
case 'flac':
|
|
191
|
+
return 'flac';
|
|
192
|
+
case 'ape':
|
|
193
|
+
case 'monkeys-audio':
|
|
194
|
+
return 'apev2';
|
|
195
|
+
case 'mp4':
|
|
196
|
+
case 'm4a':
|
|
197
|
+
return 'mp4';
|
|
198
|
+
case 'ogg': // RFC 7845
|
|
199
|
+
case 'opus': // RFC 6716
|
|
200
|
+
case 'speex': // RFC 5574
|
|
201
|
+
return 'ogg';
|
|
202
|
+
case 'ms-wma':
|
|
203
|
+
case 'ms-wmv':
|
|
204
|
+
case 'ms-asf':
|
|
205
|
+
return 'asf';
|
|
206
|
+
case 'aiff':
|
|
207
|
+
case 'aif':
|
|
208
|
+
case 'aifc':
|
|
209
|
+
return 'aiff';
|
|
210
|
+
case 'vnd.wave':
|
|
211
|
+
case 'wav':
|
|
212
|
+
case 'wave':
|
|
213
|
+
return 'riff';
|
|
214
|
+
case 'wavpack':
|
|
215
|
+
return 'wavpack';
|
|
216
|
+
case 'musepack':
|
|
217
|
+
return 'musepack';
|
|
218
|
+
case 'matroska':
|
|
219
|
+
case 'webm':
|
|
220
|
+
return 'matroska';
|
|
221
|
+
case 'dsf':
|
|
222
|
+
return 'dsf';
|
|
223
|
+
}
|
|
224
|
+
break;
|
|
225
|
+
case 'video':
|
|
226
|
+
switch (subType) {
|
|
227
|
+
case 'ms-asf':
|
|
228
|
+
case 'ms-wmv':
|
|
229
|
+
return 'asf';
|
|
230
|
+
case 'm4v':
|
|
231
|
+
case 'mp4':
|
|
232
|
+
return 'mp4';
|
|
233
|
+
case 'ogg':
|
|
234
|
+
return 'ogg';
|
|
235
|
+
case 'matroska':
|
|
236
|
+
case 'webm':
|
|
237
|
+
return 'matroska';
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
case 'application':
|
|
241
|
+
switch (subType) {
|
|
242
|
+
case 'vnd.ms-asf':
|
|
243
|
+
return 'asf';
|
|
244
|
+
case 'ogg':
|
|
245
|
+
return 'ogg';
|
|
246
|
+
}
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
exports.ParserFactory = ParserFactory;
|
package/lib/aiff/AiffParser.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { BasicParser } from '../common/BasicParser';
|
|
2
|
-
import * as iff from '../iff';
|
|
3
|
-
/**
|
|
4
|
-
* AIFF - Audio Interchange File Format
|
|
5
|
-
*
|
|
6
|
-
* Ref:
|
|
7
|
-
* http://www.onicos.com/staff/iz/formats/aiff.html
|
|
8
|
-
* http://muratnkonar.com/aiff/index.html
|
|
9
|
-
* http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/AIFF.html
|
|
10
|
-
*/
|
|
11
|
-
export declare class AIFFParser extends BasicParser {
|
|
12
|
-
private isCompressed;
|
|
13
|
-
parse(): Promise<void>;
|
|
14
|
-
readData(header: iff.IChunkHeader): Promise<number>;
|
|
15
|
-
}
|
|
1
|
+
import { BasicParser } from '../common/BasicParser';
|
|
2
|
+
import * as iff from '../iff';
|
|
3
|
+
/**
|
|
4
|
+
* AIFF - Audio Interchange File Format
|
|
5
|
+
*
|
|
6
|
+
* Ref:
|
|
7
|
+
* http://www.onicos.com/staff/iz/formats/aiff.html
|
|
8
|
+
* http://muratnkonar.com/aiff/index.html
|
|
9
|
+
* http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/AIFF.html
|
|
10
|
+
*/
|
|
11
|
+
export declare class AIFFParser extends BasicParser {
|
|
12
|
+
private isCompressed;
|
|
13
|
+
parse(): Promise<void>;
|
|
14
|
+
readData(header: iff.IChunkHeader): Promise<number>;
|
|
15
|
+
}
|