music-metadata 11.7.0 → 11.7.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.
- package/README.md +25 -25
- package/lib/ogg/OggParser.js +5 -2
- package/lib/ogg/OggToken.d.ts +4 -0
- package/lib/ogg/flac/FlacStream.d.ts +1 -0
- package/lib/ogg/flac/FlacStream.js +1 -0
- package/lib/ogg/opus/OpusStream.js +1 -0
- package/lib/ogg/speex/SpeexStream.d.ts +1 -2
- package/lib/ogg/speex/SpeexStream.js +1 -2
- package/lib/ogg/theora/TheoraStream.d.ts +2 -2
- package/lib/ogg/theora/TheoraStream.js +2 -2
- package/lib/ogg/vorbis/VorbisStream.d.ts +1 -0
- package/lib/ogg/vorbis/VorbisStream.js +1 -0
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -43,30 +43,30 @@ If you find this project useful and would like to support its development, consi
|
|
|
43
43
|
|
|
44
44
|
### Support for audio file types
|
|
45
45
|
|
|
46
|
-
| Audio format
|
|
47
|
-
|
|
48
|
-
| AIFF / AIFF-C
|
|
49
|
-
| AAC
|
|
50
|
-
| APE
|
|
51
|
-
| ASF
|
|
52
|
-
| BWF
|
|
53
|
-
| DSDIFF
|
|
54
|
-
| DSF
|
|
55
|
-
| FLAC
|
|
56
|
-
| MP2
|
|
57
|
-
| Matroska
|
|
58
|
-
| MP3
|
|
59
|
-
| MPC
|
|
60
|
-
| MPEG 4
|
|
61
|
-
| Ogg
|
|
62
|
-
| Opus
|
|
63
|
-
| Speex
|
|
64
|
-
| Theora
|
|
65
|
-
| Vorbis
|
|
66
|
-
| WAV
|
|
67
|
-
| WebM
|
|
68
|
-
| WV
|
|
69
|
-
| WMA
|
|
46
|
+
| Audio format | Description | Logo |
|
|
47
|
+
|---------------------------------------------------------------------------|-----------------------------------------------------------|--------------------------------------------------------------------------------------------------|
|
|
48
|
+
| [AIFF / AIFF-C](https://wikipedia.org/wiki/Audio_Interchange_File_Format) | Audio Interchange File Format | <img src="./image/logo-Apple_Computer_Logo_rainbow.svg" width="40" alt="Apple rainbow logo"> |
|
|
49
|
+
| [AAC](https://en.wikipedia.org/wiki/Advanced_Audio_Coding) | ADTS / Advanced Audio Coding | <img src="./image/logo-AAC_original.svg" width="40" alt="AAC logo"> |
|
|
50
|
+
| [APE](https://wikipedia.org/wiki/Monkey's_Audio) | Monkey's Audio | <img src="./image/logo-APE-AI.svg" width="40" alt="Monkey's Audio logo"> |
|
|
51
|
+
| [ASF](https://wikipedia.org/wiki/Advanced_Systems_Format) | Advanced Systems Format | |
|
|
52
|
+
| [BWF](https://en.wikipedia.org/wiki/Broadcast_Wave_Format) | Extended WAV format for broadcast and archiving | |
|
|
53
|
+
| [DSDIFF](https://wikipedia.org/wiki/Direct_Stream_Digital) | Philips DSDIFF | <img src="./image/logo-DSD.svg" width="80" alt="DSD logo"> |
|
|
54
|
+
| [DSF](https://wikipedia.org/wiki/Direct_Stream_Digital) | Sony's DSD Stream File | <img src="./image/logo-DSD.svg" width="80" alt="DSD logo"> |
|
|
55
|
+
| [FLAC](https://wikipedia.org/wiki/FLAC) | Free Lossless Audio Codec | <img src="./image/logo-FLAC.svg" width="80" alt="FLAC logo"> |
|
|
56
|
+
| [MP2](https://wikipedia.org/wiki/MPEG-1_Audio_Layer_II) | MPEG-1 Audio Layer II (predecessor to MP3) | |
|
|
57
|
+
| [Matroska](https://wikipedia.org/wiki/Matroska) | Matroska (EBML), mka, mkv | <img src="./image/logo-Matroska_2010.svg" width="80" alt="Matroska logo"> |
|
|
58
|
+
| [MP3](https://wikipedia.org/wiki/MP3) | MPEG-1 / MPEG-2 Audio Layer III | <img src="./image/logo-Mp3.svg" width="80" alt="MP3 logo"> |
|
|
59
|
+
| [MPC](https://wikipedia.org/wiki/Musepack) | Musepack SV7 | <img src="./image/logo-Musepack.svg" width="80" alt="musepack logo"> |
|
|
60
|
+
| [MPEG 4](https://wikipedia.org/wiki/MPEG-4) | mp4, m4a, m4v | <img src="./image/logo-MPEG4-350581.svg" width="80" alt="mpeg 4 logo"> |
|
|
61
|
+
| [Ogg](https://en.wikipedia.org/wiki/Ogg) | Open container format | <img src="./image/logo-Ogg.svg" width="80" alt="Ogg logo"> |
|
|
62
|
+
| [Opus](https://wikipedia.org/wiki/Opus_(audio_format)) | Low-latency, high-quality codec for speech and music | <img src="./image/logo-Opus.svg" width="80" alt="Opus logo"> |
|
|
63
|
+
| [Speex](https://wikipedia.org/wiki/Speex) | Open-source speech codec optimized for VoIP | <img src="./image/logo-Speex_2006.svg" width="80" alt="Speex logo"> |
|
|
64
|
+
| [Theora](https://en.wikipedia.org/wiki/Theora) | Open video compression format (typically paired with Ogg) | <img src="./image/logo-Theora_2007.svg" width="70" alt="Theora logo"> |
|
|
65
|
+
| [Vorbis](https://wikipedia.org/wiki/Ogg_Vorbis) | Vorbis audio compression | <img src="./image/logo-Vorbis_many_fish_2005.svg" width="70" alt="Vorbis logo"> |
|
|
66
|
+
| [WAV](https://wikipedia.org/wiki/WAV) | Uncompressed PCM audio in RIFF container | |
|
|
67
|
+
| [WebM](https://wikipedia.org/wiki/WebM) | WebM | <img src="./image/logo-WebM.svg" width="80" alt="Matroska logo"> |
|
|
68
|
+
| [WV](https://wikipedia.org/wiki/WavPack) | WavPack | <img src="./image/logo-wavpack.svg" width="60" alt="WavPack logo"> |
|
|
69
|
+
| [WMA](https://wikipedia.org/wiki/Windows_Media_Audio) | Windows Media Audio | <img src="./image/logo-Windows_Media_Player_simplified.svg" width="40" alt="Windows Media logo"> |
|
|
70
70
|
|
|
71
71
|
### Supported tag headers
|
|
72
72
|
|
|
@@ -870,4 +870,4 @@ This is the case using Next.js. See [issue #2370](https://github.com/Borewit/mus
|
|
|
870
870
|
|
|
871
871
|
## Licence
|
|
872
872
|
|
|
873
|
-
This project is licensed under the [MIT License](LICENSE.txt). Feel free to use, modify, and distribute as needed.
|
|
873
|
+
This project is licensed under the [MIT License](LICENSE.txt). Feel free to use, modify, and distribute as needed.
|
package/lib/ogg/OggParser.js
CHANGED
|
@@ -28,6 +28,7 @@ class OggStream {
|
|
|
28
28
|
const pageData = await tokenizer.readToken(new Token.Uint8ArrayType(segmentTable.totalPageSize));
|
|
29
29
|
debug('firstPage=%s, lastPage=%s, continued=%s', header.headerType.firstPage, header.headerType.lastPage, header.headerType.continued);
|
|
30
30
|
if (header.headerType.firstPage) {
|
|
31
|
+
this.metadata.setFormat('container', 'Ogg');
|
|
31
32
|
const idData = pageData.slice(0, 7); // Copy this portion
|
|
32
33
|
const asciiId = Array.from(idData)
|
|
33
34
|
.filter(b => b >= 32 && b <= 126) // Keep only printable ASCII
|
|
@@ -83,20 +84,22 @@ export class OggParser extends BasicParser {
|
|
|
83
84
|
*/
|
|
84
85
|
async parse() {
|
|
85
86
|
this.streams = new Map();
|
|
86
|
-
debug('pos=%s, parsePage()', this.tokenizer.position);
|
|
87
87
|
let header;
|
|
88
88
|
try {
|
|
89
89
|
do {
|
|
90
90
|
header = await this.tokenizer.readToken(PageHeader);
|
|
91
91
|
if (header.capturePattern !== 'OggS')
|
|
92
92
|
throw new OggContentError('Invalid Ogg capture pattern');
|
|
93
|
-
this.metadata.setFormat('container', 'Ogg');
|
|
94
93
|
let stream = this.streams.get(header.streamSerialNumber);
|
|
95
94
|
if (!stream) {
|
|
96
95
|
stream = new OggStream(this.metadata, header.streamSerialNumber, this.options);
|
|
97
96
|
this.streams.set(header.streamSerialNumber, stream);
|
|
98
97
|
}
|
|
99
98
|
await stream.parsePage(this.tokenizer, header);
|
|
99
|
+
if (stream.pageNumber > 12 && !(this.options.duration && [...this.streams.values()].find(stream => stream.pageConsumer?.durationOnLastPage))) {
|
|
100
|
+
debug("Stop processing Ogg stream");
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
100
103
|
} while (![...this.streams.values()].every(item => item.closed));
|
|
101
104
|
}
|
|
102
105
|
catch (err) {
|
package/lib/ogg/OggToken.d.ts
CHANGED
|
@@ -62,6 +62,10 @@ export declare class SegmentTable implements IGetToken<ISegmentTable> {
|
|
|
62
62
|
get(buf: Uint8Array, off: number): ISegmentTable;
|
|
63
63
|
}
|
|
64
64
|
export interface IPageConsumer {
|
|
65
|
+
/**
|
|
66
|
+
* Need to parse to end to be able to calculate the duration
|
|
67
|
+
*/
|
|
68
|
+
durationOnLastPage: boolean;
|
|
65
69
|
/**
|
|
66
70
|
* Parse Ogg page
|
|
67
71
|
* @param header Ogg page header
|
|
@@ -11,6 +11,7 @@ export declare class FlacStream implements Ogg.IPageConsumer {
|
|
|
11
11
|
private options;
|
|
12
12
|
private tokenizer;
|
|
13
13
|
private flacParser;
|
|
14
|
+
durationOnLastPage: boolean;
|
|
14
15
|
constructor(metadata: INativeMetadataCollector, options: IOptions, tokenizer: ITokenizer);
|
|
15
16
|
/**
|
|
16
17
|
* Vorbis 1 parser
|
|
@@ -10,6 +10,7 @@ const debug = initDebug('music-metadata:parser:ogg:theora');
|
|
|
10
10
|
*/
|
|
11
11
|
export class FlacStream {
|
|
12
12
|
constructor(metadata, options, tokenizer) {
|
|
13
|
+
this.durationOnLastPage = false;
|
|
13
14
|
this.metadata = metadata;
|
|
14
15
|
this.options = options;
|
|
15
16
|
this.tokenizer = tokenizer;
|
|
@@ -10,8 +10,7 @@ import type { INativeMetadataCollector } from '../../common/MetadataCollector.js
|
|
|
10
10
|
* - https://tools.ietf.org/html/rfc5574
|
|
11
11
|
*/
|
|
12
12
|
export declare class SpeexStream extends VorbisStream {
|
|
13
|
-
|
|
14
|
-
constructor(metadata: INativeMetadataCollector, options: IOptions, tokenizer: ITokenizer);
|
|
13
|
+
constructor(metadata: INativeMetadataCollector, options: IOptions, _tokenizer: ITokenizer);
|
|
15
14
|
/**
|
|
16
15
|
* Parse first Speex Ogg page
|
|
17
16
|
* @param {IPageHeader} header
|
|
@@ -9,9 +9,8 @@ const debug = initDebug('music-metadata:parser:ogg:speex');
|
|
|
9
9
|
* - https://tools.ietf.org/html/rfc5574
|
|
10
10
|
*/
|
|
11
11
|
export class SpeexStream extends VorbisStream {
|
|
12
|
-
constructor(metadata, options,
|
|
12
|
+
constructor(metadata, options, _tokenizer) {
|
|
13
13
|
super(metadata, options);
|
|
14
|
-
this.tokenizer = tokenizer;
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
16
|
* Parse first Speex Ogg page
|
|
@@ -8,8 +8,8 @@ import type { INativeMetadataCollector } from '../../common/MetadataCollector.js
|
|
|
8
8
|
*/
|
|
9
9
|
export declare class TheoraStream implements Ogg.IPageConsumer {
|
|
10
10
|
private metadata;
|
|
11
|
-
|
|
12
|
-
constructor(metadata: INativeMetadataCollector, _options: IOptions,
|
|
11
|
+
durationOnLastPage: boolean;
|
|
12
|
+
constructor(metadata: INativeMetadataCollector, _options: IOptions, _tokenizer: ITokenizer);
|
|
13
13
|
/**
|
|
14
14
|
* Vorbis 1 parser
|
|
15
15
|
* @param header Ogg Page Header
|
|
@@ -6,9 +6,9 @@ const debug = initDebug('music-metadata:parser:ogg:theora');
|
|
|
6
6
|
* - https://theora.org/doc/Theora.pdf
|
|
7
7
|
*/
|
|
8
8
|
export class TheoraStream {
|
|
9
|
-
constructor(metadata, _options,
|
|
9
|
+
constructor(metadata, _options, _tokenizer) {
|
|
10
|
+
this.durationOnLastPage = false;
|
|
10
11
|
this.metadata = metadata;
|
|
11
|
-
this.tokenizer = tokenizer;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Vorbis 1 parser
|
|
@@ -25,6 +25,7 @@ export declare class VorbisStream implements IPageConsumer {
|
|
|
25
25
|
protected metadata: INativeMetadataCollector;
|
|
26
26
|
protected options: IOptions;
|
|
27
27
|
protected lastPageHeader?: IPageHeader;
|
|
28
|
+
durationOnLastPage: boolean;
|
|
28
29
|
constructor(metadata: INativeMetadataCollector, options: IOptions);
|
|
29
30
|
/**
|
|
30
31
|
* Vorbis 1 parser
|
|
@@ -13,6 +13,7 @@ export class VorbisContentError extends makeUnexpectedFileContentError('Vorbis')
|
|
|
13
13
|
export class VorbisStream {
|
|
14
14
|
constructor(metadata, options) {
|
|
15
15
|
this.pageSegments = [];
|
|
16
|
+
this.durationOnLastPage = true;
|
|
16
17
|
this.metadata = metadata;
|
|
17
18
|
this.options = options;
|
|
18
19
|
}
|
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": "11.7.
|
|
4
|
+
"version": "11.7.2",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Borewit",
|
|
7
7
|
"url": "https://github.com/Borewit"
|
|
@@ -89,11 +89,11 @@
|
|
|
89
89
|
],
|
|
90
90
|
"scripts": {
|
|
91
91
|
"clean": "del-cli 'lib/**/*.js' 'lib/**/*.js.map' 'lib/**/*.d.ts' 'test/**/*.js' 'test/**/*.js.map' 'test/**/*.js' 'test/**/*.js.map' 'doc-gen/**/*.js' 'doc-gen/**/*.js.map'",
|
|
92
|
-
"compile-src": "tsc -p lib",
|
|
92
|
+
"compile-src": "tsc -p lib --sourceMap false",
|
|
93
93
|
"compile-test": "tsc -p test",
|
|
94
94
|
"compile-doc": "tsc -p doc-gen",
|
|
95
95
|
"compile": "yarn run compile-src && yarn compile-test && yarn compile-doc",
|
|
96
|
-
"lint:ts": "biome check
|
|
96
|
+
"lint:ts": "biome check",
|
|
97
97
|
"lint:md": "yarn run remark -u remark-preset-lint-consistent .",
|
|
98
98
|
"lint": "yarn run lint:ts && yarn run lint:md",
|
|
99
99
|
"test": "mocha",
|
|
@@ -111,19 +111,19 @@
|
|
|
111
111
|
"debug": "^4.4.1",
|
|
112
112
|
"file-type": "^21.0.0",
|
|
113
113
|
"media-typer": "^1.1.0",
|
|
114
|
-
"strtok3": "^10.3.
|
|
115
|
-
"token-types": "^6.0.
|
|
114
|
+
"strtok3": "^10.3.4",
|
|
115
|
+
"token-types": "^6.0.4",
|
|
116
116
|
"uint8array-extras": "^1.4.0"
|
|
117
117
|
},
|
|
118
118
|
"devDependencies": {
|
|
119
|
-
"@biomejs/biome": "2.1.
|
|
119
|
+
"@biomejs/biome": "2.1.2",
|
|
120
120
|
"@types/chai": "^5.2.2",
|
|
121
121
|
"@types/chai-as-promised": "^8.0.2",
|
|
122
122
|
"@types/content-type": "^1.1.9",
|
|
123
123
|
"@types/debug": "^4.1.12",
|
|
124
124
|
"@types/media-typer": "^1.1.3",
|
|
125
125
|
"@types/mocha": "^10.0.10",
|
|
126
|
-
"@types/node": "^24.0
|
|
126
|
+
"@types/node": "^24.1.0",
|
|
127
127
|
"c8": "^10.1.3",
|
|
128
128
|
"chai": "^5.2.1",
|
|
129
129
|
"chai-as-promised": "^8.0.1",
|