music-metadata 7.12.5 → 7.13.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/README.md +3 -2
- package/lib/aiff/AiffParser.d.ts +1 -0
- package/lib/aiff/AiffParser.js +26 -2
- package/lib/aiff/AiffTagMap.d.ts +4 -0
- package/lib/aiff/AiffTagMap.js +20 -0
- package/lib/aiff/AiffToken.js +9 -4
- package/lib/common/CombinedTagMapper.js +3 -1
- package/lib/common/FourCC.js +2 -5
- package/lib/common/GenericTagTypes.d.ts +1 -1
- package/lib/common/MetadataCollector.js +2 -2
- package/package.json +10 -12
package/README.md
CHANGED
|
@@ -55,6 +55,7 @@ Following tag header formats are supported:
|
|
|
55
55
|
* [iTunes](https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata)
|
|
56
56
|
* [RIFF](https://wikipedia.org/wiki/Resource_Interchange_File_Format)/INFO
|
|
57
57
|
* [Vorbis comment](https://wikipedia.org/wiki/Vorbis_comment)
|
|
58
|
+
* [AIFF](https://wikipedia.org/wiki/Audio_Interchange_File_Format)
|
|
58
59
|
|
|
59
60
|
It allows many tags to be accessed in audio format, and tag format independent way.
|
|
60
61
|
|
|
@@ -90,8 +91,8 @@ import * as mm from 'music-metadata/lib/core';
|
|
|
90
91
|
```
|
|
91
92
|
|
|
92
93
|
| function | `music-metadata` | `music-metadata/lib/core` |
|
|
93
|
-
|
|
94
|
-
| [`parseBuffer`](#
|
|
94
|
+
|------------------------------------------------------| ---------------------------|----------------------------|
|
|
95
|
+
| [`parseBuffer`](#parsebuffer-function) | ✓ | ✓ |
|
|
95
96
|
| [`parseStream`](#parsestream-function) * | ✓ | ✓ |
|
|
96
97
|
| [`parseFromTokenizer`](#parsefromtokenizer-function) | ✓ | ✓ |
|
|
97
98
|
| [`parseFile`](#parsefile-function) | ✓ | |
|
package/lib/aiff/AiffParser.d.ts
CHANGED
package/lib/aiff/AiffParser.js
CHANGED
|
@@ -10,6 +10,17 @@ const BasicParser_1 = require("../common/BasicParser");
|
|
|
10
10
|
const AiffToken = require("./AiffToken");
|
|
11
11
|
const iff = require("../iff");
|
|
12
12
|
const debug = (0, debug_1.default)('music-metadata:parser:aiff');
|
|
13
|
+
const compressionTypes = {
|
|
14
|
+
NONE: 'not compressed PCM Apple Computer',
|
|
15
|
+
sowt: 'PCM (byte swapped)',
|
|
16
|
+
fl32: '32-bit floating point IEEE 32-bit float',
|
|
17
|
+
fl64: '64-bit floating point IEEE 64-bit float Apple Computer',
|
|
18
|
+
alaw: 'ALaw 2:1 8-bit ITU-T G.711 A-law',
|
|
19
|
+
ulaw: 'µLaw 2:1 8-bit ITU-T G.711 µ-law Apple Computer',
|
|
20
|
+
ULAW: 'CCITT G.711 u-law 8-bit ITU-T G.711 µ-law',
|
|
21
|
+
ALAW: 'CCITT G.711 A-law 8-bit ITU-T G.711 A-law',
|
|
22
|
+
FL32: 'Float 32 IEEE 32-bit float '
|
|
23
|
+
};
|
|
13
24
|
/**
|
|
14
25
|
* AIFF - Audio Interchange File Format
|
|
15
26
|
*
|
|
@@ -40,7 +51,6 @@ class AIFFParser extends BasicParser_1.BasicParser {
|
|
|
40
51
|
while (!this.tokenizer.fileInfo.size || this.tokenizer.fileInfo.size - this.tokenizer.position >= iff.Header.len) {
|
|
41
52
|
debug('Reading AIFF chunk at offset=' + this.tokenizer.position);
|
|
42
53
|
const chunkHeader = await this.tokenizer.readToken(iff.Header);
|
|
43
|
-
debug(`Chunk id=${chunkHeader.chunkID}`);
|
|
44
54
|
const nextChunk = 2 * Math.round(chunkHeader.chunkSize / 2);
|
|
45
55
|
const bytesRead = await this.readData(chunkHeader);
|
|
46
56
|
await this.tokenizer.ignore(nextChunk - bytesRead);
|
|
@@ -56,6 +66,7 @@ class AIFFParser extends BasicParser_1.BasicParser {
|
|
|
56
66
|
}
|
|
57
67
|
}
|
|
58
68
|
async readData(header) {
|
|
69
|
+
var _a;
|
|
59
70
|
switch (header.chunkID) {
|
|
60
71
|
case 'COMM': // The Common Chunk
|
|
61
72
|
const common = await this.tokenizer.readToken(new AiffToken.Common(header, this.isCompressed));
|
|
@@ -64,7 +75,7 @@ class AIFFParser extends BasicParser_1.BasicParser {
|
|
|
64
75
|
this.metadata.setFormat('numberOfChannels', common.numChannels);
|
|
65
76
|
this.metadata.setFormat('numberOfSamples', common.numSampleFrames);
|
|
66
77
|
this.metadata.setFormat('duration', common.numSampleFrames / common.sampleRate);
|
|
67
|
-
this.metadata.setFormat('codec', common.compressionName);
|
|
78
|
+
this.metadata.setFormat('codec', (_a = common.compressionName) !== null && _a !== void 0 ? _a : compressionTypes[common.compressionType]);
|
|
68
79
|
return header.chunkSize;
|
|
69
80
|
case 'ID3 ': // ID3-meta-data
|
|
70
81
|
const id3_data = await this.tokenizer.readToken(new Token.Uint8ArrayType(header.chunkSize));
|
|
@@ -76,9 +87,22 @@ class AIFFParser extends BasicParser_1.BasicParser {
|
|
|
76
87
|
this.metadata.setFormat('bitrate', 8 * header.chunkSize / this.metadata.format.duration);
|
|
77
88
|
}
|
|
78
89
|
return 0;
|
|
90
|
+
case 'NAME': // Sample name chunk
|
|
91
|
+
case 'AUTH': // Author chunk
|
|
92
|
+
case '(c) ': // Copyright chunk
|
|
93
|
+
case 'ANNO': // Annotation chunk
|
|
94
|
+
return this.readTextChunk(header);
|
|
79
95
|
default:
|
|
96
|
+
debug(`Ignore chunk id=${header.chunkID}, size=${header.chunkSize}`);
|
|
80
97
|
return 0;
|
|
81
98
|
}
|
|
82
99
|
}
|
|
100
|
+
async readTextChunk(header) {
|
|
101
|
+
const value = await this.tokenizer.readToken(new Token.StringType(header.chunkSize, 'ascii'));
|
|
102
|
+
value.split('\0').map(v => v.trim()).filter(v => v && v.length > 0).forEach(v => {
|
|
103
|
+
this.metadata.addTag('AIFF', header.chunkID, v.trim());
|
|
104
|
+
});
|
|
105
|
+
return header.chunkSize;
|
|
106
|
+
}
|
|
83
107
|
}
|
|
84
108
|
exports.AIFFParser = AIFFParser;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AiffTagMapper = void 0;
|
|
4
|
+
const GenericTagMapper_js_1 = require("../common/GenericTagMapper.js");
|
|
5
|
+
/**
|
|
6
|
+
* ID3v1 tag mappings
|
|
7
|
+
*/
|
|
8
|
+
const tagMap = {
|
|
9
|
+
NAME: 'title',
|
|
10
|
+
AUTH: 'artist',
|
|
11
|
+
'(c) ': 'copyright',
|
|
12
|
+
ANNO: 'comment'
|
|
13
|
+
};
|
|
14
|
+
class AiffTagMapper extends GenericTagMapper_js_1.CommonTagMapper {
|
|
15
|
+
constructor() {
|
|
16
|
+
super(['AIFF'], tagMap);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.AiffTagMapper = AiffTagMapper;
|
|
20
|
+
//# sourceMappingURL=AiffTagMap.js.map
|
package/lib/aiff/AiffToken.js
CHANGED
|
@@ -25,12 +25,17 @@ class Common {
|
|
|
25
25
|
res.compressionType = FourCC_1.FourCcToken.get(buf, off + 18);
|
|
26
26
|
if (this.len > 22) {
|
|
27
27
|
const strLen = buf.readInt8(off + 22);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
if (strLen > 0) {
|
|
29
|
+
const padding = (strLen + 1) % 2;
|
|
30
|
+
if (23 + strLen + padding === this.len) {
|
|
31
|
+
res.compressionName = new Token.StringType(strLen, 'binary').get(buf, off + 23);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
throw new Error('Illegal pstring length');
|
|
35
|
+
}
|
|
31
36
|
}
|
|
32
37
|
else {
|
|
33
|
-
|
|
38
|
+
res.compressionName = undefined;
|
|
34
39
|
}
|
|
35
40
|
}
|
|
36
41
|
}
|
|
@@ -10,6 +10,7 @@ const MP4TagMapper_1 = require("../mp4/MP4TagMapper");
|
|
|
10
10
|
const VorbisTagMapper_1 = require("../ogg/vorbis/VorbisTagMapper");
|
|
11
11
|
const RiffInfoTagMap_1 = require("../riff/RiffInfoTagMap");
|
|
12
12
|
const MatroskaTagMapper_1 = require("../matroska/MatroskaTagMapper");
|
|
13
|
+
const AiffTagMap_1 = require("../aiff/AiffTagMap");
|
|
13
14
|
class CombinedTagMapper {
|
|
14
15
|
constructor() {
|
|
15
16
|
this.tagMappers = {};
|
|
@@ -23,7 +24,8 @@ class CombinedTagMapper {
|
|
|
23
24
|
new APEv2TagMapper_1.APEv2TagMapper(),
|
|
24
25
|
new AsfTagMapper_1.AsfTagMapper(),
|
|
25
26
|
new RiffInfoTagMap_1.RiffInfoTagMapper(),
|
|
26
|
-
new MatroskaTagMapper_1.MatroskaTagMapper()
|
|
27
|
+
new MatroskaTagMapper_1.MatroskaTagMapper(),
|
|
28
|
+
new AiffTagMap_1.AiffTagMapper()
|
|
27
29
|
].forEach(mapper => {
|
|
28
30
|
this.registerTagMapper(mapper);
|
|
29
31
|
});
|
package/lib/common/FourCC.js
CHANGED
|
@@ -11,11 +11,8 @@ exports.FourCcToken = {
|
|
|
11
11
|
len: 4,
|
|
12
12
|
get: (buf, off) => {
|
|
13
13
|
const id = buf.toString('binary', off, off + exports.FourCcToken.len);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (!id.match(validFourCC)) {
|
|
17
|
-
throw new Error(`FourCC contains invalid characters: ${util.a2hex(id)} "${id}"`);
|
|
18
|
-
}
|
|
14
|
+
if (!id.match(validFourCC)) {
|
|
15
|
+
throw new Error(`FourCC contains invalid characters: ${util.a2hex(id)} "${id}"`);
|
|
19
16
|
}
|
|
20
17
|
return id;
|
|
21
18
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare type TagType = 'vorbis' | 'ID3v1' | 'ID3v2.2' | 'ID3v2.3' | 'ID3v2.4' | 'APEv2' | 'asf' | 'iTunes' | 'exif' | 'matroska';
|
|
1
|
+
export declare 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;
|
|
@@ -9,7 +9,7 @@ const GenericTagMapper_1 = require("./GenericTagMapper");
|
|
|
9
9
|
const Util_1 = require("./Util");
|
|
10
10
|
const FileType = require("file-type/core");
|
|
11
11
|
const debug = (0, debug_1.default)('music-metadata:collector');
|
|
12
|
-
const TagPriority = ['matroska', 'APEv2', 'vorbis', 'ID3v2.4', 'ID3v2.3', 'ID3v2.2', 'exif', 'asf', 'iTunes', 'ID3v1'];
|
|
12
|
+
const TagPriority = ['matroska', 'APEv2', 'vorbis', 'ID3v2.4', 'ID3v2.3', 'ID3v2.2', 'exif', 'asf', 'iTunes', 'AIFF', 'ID3v1'];
|
|
13
13
|
/**
|
|
14
14
|
* Provided to the parser to uodate the metadata result.
|
|
15
15
|
* Responsible for triggering async updates
|
|
@@ -44,7 +44,7 @@ class MetadataCollector {
|
|
|
44
44
|
this.originPriority[tagType] = priority++;
|
|
45
45
|
}
|
|
46
46
|
this.originPriority.artificial = 500; // Filled using alternative tags
|
|
47
|
-
this.originPriority.id3v1 = 600; // Consider worst
|
|
47
|
+
this.originPriority.id3v1 = 600; // Consider as the worst because of the field length limit
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
50
|
* @returns {boolean} true if one or more tags have been found
|
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.
|
|
4
|
+
"version": "7.13.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Borewit",
|
|
7
7
|
"url": "https://github.com/Borewit"
|
|
@@ -79,7 +79,6 @@
|
|
|
79
79
|
"build": "npm run clean && npm run compile && npm run doc-gen",
|
|
80
80
|
"start": "npm-run-all compile lint cover-test",
|
|
81
81
|
"test-coverage": "nyc npm run test",
|
|
82
|
-
"send-coveralls": "nyc report --reporter=text-lcov | coveralls",
|
|
83
82
|
"send-codacy": "nyc report --reporter=text-lcov | codacy-coverage",
|
|
84
83
|
"doc-gen": "node doc-gen/gen.js"
|
|
85
84
|
},
|
|
@@ -90,26 +89,25 @@
|
|
|
90
89
|
"file-type": "^16.5.4",
|
|
91
90
|
"media-typer": "^1.1.0",
|
|
92
91
|
"strtok3": "^6.3.0",
|
|
93
|
-
"token-types": "^4.2.
|
|
92
|
+
"token-types": "^4.2.1"
|
|
94
93
|
},
|
|
95
94
|
"devDependencies": {
|
|
96
|
-
"@types/chai": "^4.3.
|
|
95
|
+
"@types/chai": "^4.3.3",
|
|
97
96
|
"@types/chai-as-promised": "^7.1.5",
|
|
98
97
|
"@types/debug": "^4.1.7",
|
|
99
98
|
"@types/file-type": "^10.9.1",
|
|
100
99
|
"@types/mocha": "^9.1.0",
|
|
101
|
-
"@types/node": "^18.
|
|
102
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
103
|
-
"@typescript-eslint/parser": "^5.
|
|
100
|
+
"@types/node": "^18.7.14",
|
|
101
|
+
"@typescript-eslint/eslint-plugin": "^5.37.0",
|
|
102
|
+
"@typescript-eslint/parser": "^5.37.0",
|
|
104
103
|
"chai": "^4.3.6",
|
|
105
104
|
"chai-as-promised": "^7.1.1",
|
|
106
|
-
"coveralls": "^3.1.1",
|
|
107
105
|
"del-cli": "5.0.0",
|
|
108
|
-
"eslint": "^8.
|
|
106
|
+
"eslint": "^8.23.1",
|
|
109
107
|
"eslint-config-prettier": "^8.5.0",
|
|
110
|
-
"eslint-import-resolver-typescript": "^3.
|
|
108
|
+
"eslint-import-resolver-typescript": "^3.5.1",
|
|
111
109
|
"eslint-plugin-import": "^2.26.0",
|
|
112
|
-
"eslint-plugin-jsdoc": "^39.3.
|
|
110
|
+
"eslint-plugin-jsdoc": "^39.3.6",
|
|
113
111
|
"eslint-plugin-node": "^11.1.0",
|
|
114
112
|
"eslint-plugin-unicorn": "^43.0.2",
|
|
115
113
|
"mime": "^3.0.0",
|
|
@@ -120,7 +118,7 @@
|
|
|
120
118
|
"remark-preset-lint-recommended": "^6.1.2",
|
|
121
119
|
"source-map-support": "^0.5.21",
|
|
122
120
|
"ts-node": "^10.9.1",
|
|
123
|
-
"typescript": "^4.
|
|
121
|
+
"typescript": "^4.8.3"
|
|
124
122
|
},
|
|
125
123
|
"engines": {
|
|
126
124
|
"node": ">=10"
|