music-metadata 10.4.0 → 10.5.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 +1 -0
- package/lib/ParserFactory.js +5 -1
- package/lib/amr/AmrLoader.d.ts +2 -0
- package/lib/amr/AmrLoader.js +8 -0
- package/lib/amr/AmrParser.d.ts +7 -0
- package/lib/amr/AmrParser.js +49 -0
- package/lib/amr/AmrToken.d.ts +11 -0
- package/lib/amr/AmrToken.js +15 -0
- package/lib/asf/AsfObject.d.ts +7 -1
- package/lib/type.d.ts +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ If you find this project useful and would like to support its development, consi
|
|
|
48
48
|
| ------------- |---------------------------------| -------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------:|
|
|
49
49
|
| AIFF / AIFF-C | Audio Interchange File Format | [:link:](https://wikipedia.org/wiki/Audio_Interchange_File_Format) | <img src="https://upload.wikimedia.org/wikipedia/commons/8/84/Apple_Computer_Logo_rainbow.svg" width="40" alt="Apple rainbow logo"> |
|
|
50
50
|
| AAC | ADTS / Advanced Audio Coding | [:link:](https://en.wikipedia.org/wiki/Advanced_Audio_Coding) | <img src="https://svgshare.com/i/UT8.svg" width="40" alt="AAC logo"> |
|
|
51
|
+
| AMR | Adaptive Multi-Rate audio codec | [:link:](https://en.wikipedia.org/wiki/Adaptive_Multi-Rate_audio_codec) | <img src="https://foreverhits.files.wordpress.com/2015/05/ape_audio.jpg" width="40" alt="Monkey's Audio logo"> |
|
|
51
52
|
| APE | Monkey's Audio | [:link:](https://wikipedia.org/wiki/Monkey's_Audio) | <img src="https://foreverhits.files.wordpress.com/2015/05/ape_audio.jpg" width="40" alt="Monkey's Audio logo"> |
|
|
52
53
|
| ASF | Advanced Systems Format | [:link:](https://wikipedia.org/wiki/Advanced_Systems_Format) | |
|
|
53
54
|
| BWF | Broadcast Wave Format | [:link:](https://en.wikipedia.org/wiki/Broadcast_Wave_Format) | |
|
package/lib/ParserFactory.js
CHANGED
|
@@ -17,6 +17,7 @@ import { musepackParserLoader } from './musepack/MusepackLoader.js';
|
|
|
17
17
|
import { oggParserLoader } from './ogg/OggLoader.js';
|
|
18
18
|
import { wavpackParserLoader } from './wavpack/WavPackLoader.js';
|
|
19
19
|
import { riffParserLoader } from './wav/WaveLoader.js';
|
|
20
|
+
import { amrParserLoader } from './amr/AmrLoader.js';
|
|
20
21
|
const debug = initDebug('music-metadata:parser:factory');
|
|
21
22
|
export function parseHttpContentType(contentType) {
|
|
22
23
|
const type = ContentType.parse(contentType);
|
|
@@ -44,7 +45,8 @@ export class ParserFactory {
|
|
|
44
45
|
wavpackParserLoader,
|
|
45
46
|
musepackParserLoader,
|
|
46
47
|
dsfParserLoader,
|
|
47
|
-
dsdiffParserLoader
|
|
48
|
+
dsdiffParserLoader,
|
|
49
|
+
amrParserLoader
|
|
48
50
|
].forEach(parser => this.registerParser(parser));
|
|
49
51
|
}
|
|
50
52
|
registerParser(parser) {
|
|
@@ -158,6 +160,8 @@ function getParserIdForMimeType(httpContentType) {
|
|
|
158
160
|
return 'matroska';
|
|
159
161
|
case 'dsf':
|
|
160
162
|
return 'dsf';
|
|
163
|
+
case 'amr':
|
|
164
|
+
return 'amr';
|
|
161
165
|
}
|
|
162
166
|
break;
|
|
163
167
|
case 'video':
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { BasicParser } from '../common/BasicParser.js';
|
|
2
|
+
import { AnsiStringType } from 'token-types';
|
|
3
|
+
import initDebug from 'debug';
|
|
4
|
+
import { FrameHeader } from './AmrToken.js';
|
|
5
|
+
const debug = initDebug('music-metadata:parser:AMR');
|
|
6
|
+
/**
|
|
7
|
+
* There are 8 varying levels of compression. First byte of the frame specifies CMR
|
|
8
|
+
* (codec mode request), values 0-7 are valid for AMR. Each mode have different frame size.
|
|
9
|
+
* This table reflects that fact.
|
|
10
|
+
*/
|
|
11
|
+
const m_block_size = [12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0];
|
|
12
|
+
/**
|
|
13
|
+
* Adaptive Multi-Rate audio codec
|
|
14
|
+
*/
|
|
15
|
+
export class AmrParser extends BasicParser {
|
|
16
|
+
async parse() {
|
|
17
|
+
const magicNr = await this.tokenizer.readToken(new AnsiStringType(5));
|
|
18
|
+
if (magicNr !== '#!AMR') {
|
|
19
|
+
throw new Error('Invalid AMR file: invalid MAGIC number');
|
|
20
|
+
}
|
|
21
|
+
this.metadata.setFormat('container', 'AMR');
|
|
22
|
+
this.metadata.setFormat('codec', 'AMR');
|
|
23
|
+
this.metadata.setFormat('sampleRate', 8000);
|
|
24
|
+
this.metadata.setFormat('bitrate', 64000);
|
|
25
|
+
this.metadata.setFormat('numberOfChannels', 1);
|
|
26
|
+
let total_size = 0;
|
|
27
|
+
let frames = 0;
|
|
28
|
+
const assumedFileLength = this.tokenizer.fileInfo?.size ?? Number.MAX_SAFE_INTEGER;
|
|
29
|
+
if (this.options.duration) {
|
|
30
|
+
while (this.tokenizer.position < assumedFileLength) {
|
|
31
|
+
const header = await this.tokenizer.readToken(FrameHeader);
|
|
32
|
+
/* first byte is rate mode. each rate mode has frame of given length. look it up. */
|
|
33
|
+
const size = m_block_size[header.frameType];
|
|
34
|
+
if (size > 0) {
|
|
35
|
+
total_size += size + 1;
|
|
36
|
+
if (total_size > assumedFileLength)
|
|
37
|
+
break;
|
|
38
|
+
await this.tokenizer.ignore(size);
|
|
39
|
+
++frames;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
debug(`Found no-data frame, frame-type: ${header.frameType}. Skipping`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
this.metadata.setFormat('duration', frames * 0.02);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=AmrParser.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getBitAllignedNumber } from '../common/Util.js';
|
|
2
|
+
/**
|
|
3
|
+
* ID3v2 header
|
|
4
|
+
* Ref: http://id3.org/id3v2.3.0#ID3v2_header
|
|
5
|
+
* ToDo
|
|
6
|
+
*/
|
|
7
|
+
export const FrameHeader = {
|
|
8
|
+
len: 1,
|
|
9
|
+
get: (buf, off) => {
|
|
10
|
+
return {
|
|
11
|
+
frameType: getBitAllignedNumber(buf, off, 1, 4)
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=AmrToken.js.map
|
package/lib/asf/AsfObject.d.ts
CHANGED
|
@@ -10,7 +10,13 @@ declare const AsfContentParseError_base: {
|
|
|
10
10
|
stack?: string;
|
|
11
11
|
};
|
|
12
12
|
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
|
|
13
|
-
prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite
|
|
13
|
+
prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite /**
|
|
14
|
+
* Specifies the amount of time to buffer data before starting to play the file, in millisecond units.
|
|
15
|
+
* If this value is nonzero, the Play Duration field and all of the payload Presentation Time fields have been offset
|
|
16
|
+
* by this amount. Therefore, player software must subtract the value in the preroll field from the play duration and
|
|
17
|
+
* presentation times to calculate their actual values. It follows that all payload Presentation Time fields need to
|
|
18
|
+
* be at least this value.
|
|
19
|
+
*/[]) => any) | undefined;
|
|
14
20
|
stackTraceLimit: number;
|
|
15
21
|
};
|
|
16
22
|
export declare class AsfContentParseError extends AsfContentParseError_base {
|
package/lib/type.d.ts
CHANGED
|
@@ -521,7 +521,7 @@ export interface IAudioMetadata extends INativeAudioMetadata {
|
|
|
521
521
|
/**
|
|
522
522
|
* Corresponds with parser module name
|
|
523
523
|
*/
|
|
524
|
-
export type ParserType = 'mpeg' | 'apev2' | 'mp4' | 'asf' | 'flac' | 'ogg' | 'aiff' | 'wavpack' | 'riff' | 'musepack' | 'dsf' | 'dsdiff' | 'adts' | 'matroska';
|
|
524
|
+
export type ParserType = 'mpeg' | 'apev2' | 'mp4' | 'asf' | 'flac' | 'ogg' | 'aiff' | 'wavpack' | 'riff' | 'musepack' | 'dsf' | 'dsdiff' | 'adts' | 'matroska' | 'amr';
|
|
525
525
|
export interface IOptions {
|
|
526
526
|
/**
|
|
527
527
|
* default: `false`, if set to `true`, it will parse the whole media file if required to determine the duration.
|
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": "10.
|
|
4
|
+
"version": "10.5.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Borewit",
|
|
7
7
|
"url": "https://github.com/Borewit"
|
|
@@ -105,8 +105,8 @@
|
|
|
105
105
|
"dependencies": {
|
|
106
106
|
"@tokenizer/token": "^0.3.0",
|
|
107
107
|
"content-type": "^1.0.5",
|
|
108
|
-
"debug": "^4.3.
|
|
109
|
-
"file-type": "^19.
|
|
108
|
+
"debug": "^4.3.7",
|
|
109
|
+
"file-type": "^19.5.0",
|
|
110
110
|
"media-typer": "^1.1.0",
|
|
111
111
|
"strtok3": "^9.0.0",
|
|
112
112
|
"token-types": "^6.0.0",
|