music-metadata 8.3.0 → 9.0.1
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 +519 -488
- package/lib/ParserFactory.d.ts +1 -1
- package/lib/ParserFactory.js +1 -2
- package/lib/aiff/AiffParser.js +3 -4
- package/lib/aiff/AiffToken.d.ts +2 -4
- package/lib/aiff/AiffToken.js +7 -7
- package/lib/apev2/APEv2Parser.d.ts +1 -1
- package/lib/apev2/APEv2Parser.js +10 -12
- package/lib/apev2/APEv2Token.d.ts +1 -1
- package/lib/asf/AsfObject.d.ts +15 -17
- package/lib/asf/AsfObject.js +51 -45
- package/lib/asf/AsfParser.js +6 -8
- package/lib/asf/AsfUtil.d.ts +1 -3
- package/lib/asf/AsfUtil.js +4 -5
- package/lib/asf/GUID.d.ts +4 -5
- package/lib/asf/GUID.js +14 -11
- package/lib/common/BasicParser.d.ts +1 -1
- package/lib/common/FourCC.d.ts +1 -1
- package/lib/common/FourCC.js +5 -3
- package/lib/common/MetadataCollector.d.ts +3 -3
- package/lib/common/MetadataCollector.js +7 -8
- package/lib/common/RandomFileReader.d.ts +2 -3
- package/lib/common/RandomFileReader.js +1 -1
- package/lib/common/Util.d.ts +1 -1
- package/lib/common/Util.js +4 -3
- package/lib/core.d.ts +16 -8
- package/lib/core.js +19 -5
- package/lib/dsdiff/DsdiffParser.js +1 -1
- package/lib/dsdiff/DsdiffToken.d.ts +1 -1
- package/lib/dsf/DsfChunk.d.ts +1 -1
- package/lib/flac/FlacParser.d.ts +1 -1
- package/lib/flac/FlacParser.js +6 -4
- package/lib/id3v1/ID3v1Parser.js +7 -7
- package/lib/id3v2/AbstractID3Parser.d.ts +1 -1
- package/lib/id3v2/AbstractID3Parser.js +1 -1
- package/lib/id3v2/FrameParser.js +3 -3
- package/lib/id3v2/ID3v24TagMapper.d.ts +2 -3
- package/lib/id3v2/ID3v24TagMapper.js +4 -4
- package/lib/id3v2/ID3v2Parser.d.ts +1 -1
- package/lib/id3v2/ID3v2Parser.js +10 -17
- package/lib/id3v2/ID3v2Token.d.ts +1 -1
- package/lib/id3v2/ID3v2Token.js +2 -2
- package/lib/iff/index.d.ts +1 -1
- package/lib/index.d.ts +1 -2
- package/lib/index.js +1 -1
- package/lib/lyrics3/Lyrics3.js +4 -4
- package/lib/matroska/MatroskaParser.d.ts +9 -2
- package/lib/matroska/MatroskaParser.js +44 -39
- package/lib/matroska/types.d.ts +13 -14
- package/lib/mp4/Atom.d.ts +1 -1
- package/lib/mp4/AtomToken.d.ts +11 -11
- package/lib/mp4/AtomToken.js +3 -2
- package/lib/mp4/MP4Parser.js +20 -19
- package/lib/mpeg/ExtendedLameHeader.d.ts +1 -1
- package/lib/mpeg/MpegParser.js +4 -4
- package/lib/mpeg/ReplayGainDataFormat.d.ts +1 -1
- package/lib/mpeg/XingTag.d.ts +2 -3
- package/lib/mpeg/XingTag.js +1 -1
- package/lib/musepack/index.js +1 -1
- package/lib/musepack/sv7/BitReader.d.ts +1 -1
- package/lib/musepack/sv7/StreamVersion7.d.ts +1 -1
- package/lib/musepack/sv7/StreamVersion7.js +1 -1
- package/lib/musepack/sv8/StreamVersion8.d.ts +1 -1
- package/lib/musepack/sv8/StreamVersion8.js +1 -1
- package/lib/ogg/Ogg.d.ts +2 -2
- package/lib/ogg/OggParser.d.ts +1 -1
- package/lib/ogg/OggParser.js +5 -5
- package/lib/ogg/opus/Opus.d.ts +1 -1
- package/lib/ogg/opus/Opus.js +6 -6
- package/lib/ogg/opus/OpusParser.d.ts +4 -5
- package/lib/ogg/opus/OpusParser.js +3 -3
- package/lib/ogg/speex/Speex.d.ts +1 -1
- package/lib/ogg/speex/Speex.js +13 -13
- package/lib/ogg/speex/SpeexParser.d.ts +3 -4
- package/lib/ogg/speex/SpeexParser.js +1 -1
- package/lib/ogg/theora/Theora.d.ts +1 -1
- package/lib/ogg/theora/Theora.js +6 -6
- package/lib/ogg/theora/TheoraParser.d.ts +4 -5
- package/lib/ogg/theora/TheoraParser.js +4 -4
- package/lib/ogg/vorbis/Vorbis.d.ts +3 -4
- package/lib/ogg/vorbis/Vorbis.js +11 -12
- package/lib/ogg/vorbis/VorbisDecoder.js +1 -1
- package/lib/ogg/vorbis/VorbisParser.d.ts +8 -8
- package/lib/ogg/vorbis/VorbisParser.js +21 -12
- package/lib/riff/RiffChunk.d.ts +1 -1
- package/lib/riff/RiffChunk.js +2 -2
- package/lib/type.d.ts +9 -11
- package/lib/wav/BwfChunk.d.ts +1 -1
- package/lib/wav/WaveChunk.d.ts +3 -4
- package/lib/wav/WaveChunk.js +8 -7
- package/lib/wav/WaveParser.js +2 -2
- package/lib/wavpack/WavPackParser.d.ts +1 -0
- package/lib/wavpack/WavPackParser.js +5 -3
- package/lib/wavpack/WavPackToken.d.ts +1 -1
- package/package.json +141 -140
package/lib/ogg/OggParser.d.ts
CHANGED
package/lib/ogg/OggParser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Token from 'token-types';
|
|
2
|
-
import { EndOfStreamError } from 'strtok3
|
|
2
|
+
import { EndOfStreamError } from 'strtok3';
|
|
3
3
|
import initDebug from 'debug';
|
|
4
4
|
import * as util from '../common/Util.js';
|
|
5
5
|
import { FourCcToken } from '../common/FourCC.js';
|
|
@@ -51,7 +51,7 @@ export class OggParser extends BasicParser {
|
|
|
51
51
|
const pageData = await this.tokenizer.readToken(new Token.Uint8ArrayType(segmentTable.totalPageSize));
|
|
52
52
|
debug('firstPage=%s, lastPage=%s, continued=%s', header.headerType.firstPage, header.headerType.lastPage, header.headerType.continued);
|
|
53
53
|
if (header.headerType.firstPage) {
|
|
54
|
-
const id = new
|
|
54
|
+
const id = new TextDecoder('ascii').decode(pageData.subarray(0, 7));
|
|
55
55
|
switch (id) {
|
|
56
56
|
case '\x01vorbis': // Ogg/Vorbis
|
|
57
57
|
debug('Set page consumer to Ogg/Vorbis');
|
|
@@ -74,7 +74,7 @@ export class OggParser extends BasicParser {
|
|
|
74
74
|
throw new Error('gg audio-codec not recognized (id=' + id + ')');
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
this.pageConsumer.parsePage(header, pageData);
|
|
77
|
+
await this.pageConsumer.parsePage(header, pageData);
|
|
78
78
|
} while (!header.headerType.lastPage);
|
|
79
79
|
}
|
|
80
80
|
catch (err) {
|
|
@@ -90,7 +90,7 @@ export class OggParser extends BasicParser {
|
|
|
90
90
|
if (this.pageNumber > 0) {
|
|
91
91
|
// ignore this error: work-around if last OGG-page is not marked with last-page flag
|
|
92
92
|
this.metadata.addWarning('Invalid FourCC ID, maybe last OGG-page is not marked with last-page flag');
|
|
93
|
-
this.pageConsumer.flush();
|
|
93
|
+
await this.pageConsumer.flush();
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
else {
|
|
@@ -110,7 +110,7 @@ OggParser.Header = {
|
|
|
110
110
|
firstPage: util.getBit(buf, off + 5, 1),
|
|
111
111
|
lastPage: util.getBit(buf, off + 5, 2)
|
|
112
112
|
},
|
|
113
|
-
// packet_flag:
|
|
113
|
+
// packet_flag: Token.UINT8.get(buf, off + 5),
|
|
114
114
|
absoluteGranulePosition: Number(Token.UINT64_LE.get(buf, off + 6)),
|
|
115
115
|
streamSerialNumber: Token.UINT32_LE.get(buf, off + 14),
|
|
116
116
|
pageSequenceNo: Token.UINT32_LE.get(buf, off + 18),
|
package/lib/ogg/opus/Opus.d.ts
CHANGED
package/lib/ogg/opus/Opus.js
CHANGED
|
@@ -13,12 +13,12 @@ export class IdHeader {
|
|
|
13
13
|
get(buf, off) {
|
|
14
14
|
return {
|
|
15
15
|
magicSignature: new Token.StringType(8, 'ascii').get(buf, off + 0),
|
|
16
|
-
version:
|
|
17
|
-
channelCount:
|
|
18
|
-
preSkip:
|
|
19
|
-
inputSampleRate:
|
|
20
|
-
outputGain:
|
|
21
|
-
channelMapping:
|
|
16
|
+
version: Token.UINT8.get(buf, off + 8),
|
|
17
|
+
channelCount: Token.UINT8.get(buf, off + 9),
|
|
18
|
+
preSkip: Token.UINT16_LE.get(buf, off + 10),
|
|
19
|
+
inputSampleRate: Token.UINT32_LE.get(buf, off + 12),
|
|
20
|
+
outputGain: Token.UINT16_LE.get(buf, off + 16),
|
|
21
|
+
channelMapping: Token.UINT8.get(buf, off + 18)
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { ITokenizer } from 'strtok3/core';
|
|
1
|
+
import { ITokenizer } from 'strtok3';
|
|
3
2
|
import { IPageHeader } from '../Ogg.js';
|
|
4
3
|
import { VorbisParser } from '../vorbis/VorbisParser.js';
|
|
5
4
|
import { IOptions } from '../../type.js';
|
|
@@ -17,9 +16,9 @@ export declare class OpusParser extends VorbisParser {
|
|
|
17
16
|
/**
|
|
18
17
|
* Parse first Opus Ogg page
|
|
19
18
|
* @param {IPageHeader} header
|
|
20
|
-
* @param {
|
|
19
|
+
* @param {Uint8Array} pageData
|
|
21
20
|
*/
|
|
22
|
-
protected parseFirstPage(header: IPageHeader, pageData:
|
|
23
|
-
protected parseFullPage(pageData:
|
|
21
|
+
protected parseFirstPage(header: IPageHeader, pageData: Uint8Array): void;
|
|
22
|
+
protected parseFullPage(pageData: Uint8Array): Promise<void>;
|
|
24
23
|
calculateDuration(header: IPageHeader): void;
|
|
25
24
|
}
|
|
@@ -15,7 +15,7 @@ export class OpusParser extends VorbisParser {
|
|
|
15
15
|
/**
|
|
16
16
|
* Parse first Opus Ogg page
|
|
17
17
|
* @param {IPageHeader} header
|
|
18
|
-
* @param {
|
|
18
|
+
* @param {Uint8Array} pageData
|
|
19
19
|
*/
|
|
20
20
|
parseFirstPage(header, pageData) {
|
|
21
21
|
this.metadata.setFormat('codec', 'Opus');
|
|
@@ -26,11 +26,11 @@ export class OpusParser extends VorbisParser {
|
|
|
26
26
|
this.metadata.setFormat('sampleRate', this.idHeader.inputSampleRate);
|
|
27
27
|
this.metadata.setFormat('numberOfChannels', this.idHeader.channelCount);
|
|
28
28
|
}
|
|
29
|
-
parseFullPage(pageData) {
|
|
29
|
+
async parseFullPage(pageData) {
|
|
30
30
|
const magicSignature = new Token.StringType(8, 'ascii').get(pageData, 0);
|
|
31
31
|
switch (magicSignature) {
|
|
32
32
|
case 'OpusTags':
|
|
33
|
-
this.parseUserCommentList(pageData, 8);
|
|
33
|
+
await this.parseUserCommentList(pageData, 8);
|
|
34
34
|
this.lastPos = this.tokenizer.position - pageData.length;
|
|
35
35
|
break;
|
|
36
36
|
default:
|
package/lib/ogg/speex/Speex.d.ts
CHANGED
package/lib/ogg/speex/Speex.js
CHANGED
|
@@ -10,19 +10,19 @@ export const Header = {
|
|
|
10
10
|
return {
|
|
11
11
|
speex: new Token.StringType(8, 'ascii').get(buf, off + 0),
|
|
12
12
|
version: util.trimRightNull(new Token.StringType(20, 'ascii').get(buf, off + 8)),
|
|
13
|
-
version_id:
|
|
14
|
-
header_size:
|
|
15
|
-
rate:
|
|
16
|
-
mode:
|
|
17
|
-
mode_bitstream_version:
|
|
18
|
-
nb_channels:
|
|
19
|
-
bitrate:
|
|
20
|
-
frame_size:
|
|
21
|
-
vbr:
|
|
22
|
-
frames_per_packet:
|
|
23
|
-
extra_headers:
|
|
24
|
-
reserved1:
|
|
25
|
-
reserved2:
|
|
13
|
+
version_id: Token.INT32_LE.get(buf, off + 28),
|
|
14
|
+
header_size: Token.INT32_LE.get(buf, off + 32),
|
|
15
|
+
rate: Token.INT32_LE.get(buf, off + 36),
|
|
16
|
+
mode: Token.INT32_LE.get(buf, off + 40),
|
|
17
|
+
mode_bitstream_version: Token.INT32_LE.get(buf, off + 44),
|
|
18
|
+
nb_channels: Token.INT32_LE.get(buf, off + 48),
|
|
19
|
+
bitrate: Token.INT32_LE.get(buf, off + 52),
|
|
20
|
+
frame_size: Token.INT32_LE.get(buf, off + 56),
|
|
21
|
+
vbr: Token.INT32_LE.get(buf, off + 60),
|
|
22
|
+
frames_per_packet: Token.INT32_LE.get(buf, off + 64),
|
|
23
|
+
extra_headers: Token.INT32_LE.get(buf, off + 68),
|
|
24
|
+
reserved1: Token.INT32_LE.get(buf, off + 72),
|
|
25
|
+
reserved2: Token.INT32_LE.get(buf, off + 76)
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { ITokenizer } from 'strtok3/core';
|
|
1
|
+
import { ITokenizer } from 'strtok3';
|
|
3
2
|
import { IPageHeader } from '../Ogg.js';
|
|
4
3
|
import { VorbisParser } from '../vorbis/VorbisParser.js';
|
|
5
4
|
import { IOptions } from '../../type.js';
|
|
@@ -16,7 +15,7 @@ export declare class SpeexParser extends VorbisParser {
|
|
|
16
15
|
/**
|
|
17
16
|
* Parse first Speex Ogg page
|
|
18
17
|
* @param {IPageHeader} header
|
|
19
|
-
* @param {
|
|
18
|
+
* @param {Uint8Array} pageData
|
|
20
19
|
*/
|
|
21
|
-
protected parseFirstPage(header: IPageHeader, pageData:
|
|
20
|
+
protected parseFirstPage(header: IPageHeader, pageData: Uint8Array): void;
|
|
22
21
|
}
|
|
@@ -16,7 +16,7 @@ export class SpeexParser extends VorbisParser {
|
|
|
16
16
|
/**
|
|
17
17
|
* Parse first Speex Ogg page
|
|
18
18
|
* @param {IPageHeader} header
|
|
19
|
-
* @param {
|
|
19
|
+
* @param {Uint8Array} pageData
|
|
20
20
|
*/
|
|
21
21
|
parseFirstPage(header, pageData) {
|
|
22
22
|
debug('First Ogg/Speex page');
|
package/lib/ogg/theora/Theora.js
CHANGED
|
@@ -8,13 +8,13 @@ export const IdentificationHeader = {
|
|
|
8
8
|
get: (buf, off) => {
|
|
9
9
|
return {
|
|
10
10
|
id: new Token.StringType(7, 'ascii').get(buf, off),
|
|
11
|
-
vmaj:
|
|
12
|
-
vmin:
|
|
13
|
-
vrev:
|
|
14
|
-
vmbw:
|
|
15
|
-
vmbh:
|
|
11
|
+
vmaj: Token.UINT8.get(buf, off + 7),
|
|
12
|
+
vmin: Token.UINT8.get(buf, off + 8),
|
|
13
|
+
vrev: Token.UINT8.get(buf, off + 9),
|
|
14
|
+
vmbw: Token.UINT16_BE.get(buf, off + 10),
|
|
15
|
+
vmbh: Token.UINT16_BE.get(buf, off + 17),
|
|
16
16
|
nombr: Token.UINT24_BE.get(buf, off + 37),
|
|
17
|
-
nqual:
|
|
17
|
+
nqual: Token.UINT8.get(buf, off + 40)
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { ITokenizer } from 'strtok3/core';
|
|
1
|
+
import { ITokenizer } from 'strtok3';
|
|
3
2
|
import * as Ogg from '../Ogg.js';
|
|
4
3
|
import { IOptions } from '../../type.js';
|
|
5
4
|
import { INativeMetadataCollector } from '../../common/MetadataCollector.js';
|
|
@@ -16,13 +15,13 @@ export declare class TheoraParser implements Ogg.IPageConsumer {
|
|
|
16
15
|
* @param header Ogg Page Header
|
|
17
16
|
* @param pageData Page data
|
|
18
17
|
*/
|
|
19
|
-
parsePage(header: Ogg.IPageHeader, pageData:
|
|
20
|
-
flush(): void
|
|
18
|
+
parsePage(header: Ogg.IPageHeader, pageData: Uint8Array): Promise<void>;
|
|
19
|
+
flush(): Promise<void>;
|
|
21
20
|
calculateDuration(header: Ogg.IPageHeader): void;
|
|
22
21
|
/**
|
|
23
22
|
* Parse first Theora Ogg page. the initial identification header packet
|
|
24
23
|
* @param {IPageHeader} header
|
|
25
24
|
* @param {Buffer} pageData
|
|
26
25
|
*/
|
|
27
|
-
protected parseFirstPage(header: Ogg.IPageHeader, pageData:
|
|
26
|
+
protected parseFirstPage(header: Ogg.IPageHeader, pageData: Uint8Array): Promise<void>;
|
|
28
27
|
}
|
|
@@ -15,12 +15,12 @@ export class TheoraParser {
|
|
|
15
15
|
* @param header Ogg Page Header
|
|
16
16
|
* @param pageData Page data
|
|
17
17
|
*/
|
|
18
|
-
parsePage(header, pageData) {
|
|
18
|
+
async parsePage(header, pageData) {
|
|
19
19
|
if (header.headerType.firstPage) {
|
|
20
|
-
this.parseFirstPage(header, pageData);
|
|
20
|
+
await this.parseFirstPage(header, pageData);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
flush() {
|
|
23
|
+
async flush() {
|
|
24
24
|
debug('flush');
|
|
25
25
|
}
|
|
26
26
|
calculateDuration(header) {
|
|
@@ -31,7 +31,7 @@ export class TheoraParser {
|
|
|
31
31
|
* @param {IPageHeader} header
|
|
32
32
|
* @param {Buffer} pageData
|
|
33
33
|
*/
|
|
34
|
-
parseFirstPage(header, pageData) {
|
|
34
|
+
async parseFirstPage(header, pageData) {
|
|
35
35
|
debug('First Ogg/Theora page');
|
|
36
36
|
this.metadata.setFormat('codec', 'Theora');
|
|
37
37
|
const idHeader = IdentificationHeader.get(pageData, 0);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
1
|
import { IPicture } from '../../type.js';
|
|
3
|
-
import { IGetToken } from 'strtok3
|
|
2
|
+
import type { IGetToken } from 'strtok3';
|
|
4
3
|
/**
|
|
5
4
|
* Interface to parsed result of METADATA_BLOCK_PICTURE
|
|
6
5
|
* Ref: https://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE
|
|
@@ -23,9 +22,9 @@ export interface IVorbisPicture extends IPicture {
|
|
|
23
22
|
export declare class VorbisPictureToken implements IGetToken<IVorbisPicture> {
|
|
24
23
|
len: any;
|
|
25
24
|
static fromBase64(base64str: string): IVorbisPicture;
|
|
26
|
-
static fromBuffer(buffer:
|
|
25
|
+
static fromBuffer(buffer: Uint8Array): IVorbisPicture;
|
|
27
26
|
constructor(len: any);
|
|
28
|
-
get(buffer:
|
|
27
|
+
get(buffer: Uint8Array, offset: number): IVorbisPicture;
|
|
29
28
|
}
|
|
30
29
|
/**
|
|
31
30
|
* Vorbis 1 decoding tokens
|
package/lib/ogg/vorbis/Vorbis.js
CHANGED
|
@@ -8,7 +8,7 @@ import { AttachedPictureType } from '../../id3v2/ID3v2Token.js';
|
|
|
8
8
|
*/
|
|
9
9
|
export class VorbisPictureToken {
|
|
10
10
|
static fromBase64(base64str) {
|
|
11
|
-
return this.fromBuffer(
|
|
11
|
+
return this.fromBuffer(Uint8Array.from(atob(base64str), c => c.charCodeAt(0)));
|
|
12
12
|
}
|
|
13
13
|
static fromBuffer(buffer) {
|
|
14
14
|
const pic = new VorbisPictureToken(buffer.length);
|
|
@@ -20,15 +20,15 @@ export class VorbisPictureToken {
|
|
|
20
20
|
get(buffer, offset) {
|
|
21
21
|
const type = AttachedPictureType[Token.UINT32_BE.get(buffer, offset)];
|
|
22
22
|
const mimeLen = Token.UINT32_BE.get(buffer, offset += 4);
|
|
23
|
-
const format =
|
|
23
|
+
const format = new Token.StringType(mimeLen, 'utf-8').get(buffer, offset += 4);
|
|
24
24
|
const descLen = Token.UINT32_BE.get(buffer, offset += mimeLen);
|
|
25
|
-
const description =
|
|
25
|
+
const description = new Token.StringType(descLen, 'utf-8').get(buffer, offset += 4);
|
|
26
26
|
const width = Token.UINT32_BE.get(buffer, offset += descLen);
|
|
27
27
|
const height = Token.UINT32_BE.get(buffer, offset += 4);
|
|
28
28
|
const colour_depth = Token.UINT32_BE.get(buffer, offset += 4);
|
|
29
29
|
const indexed_color = Token.UINT32_BE.get(buffer, offset += 4);
|
|
30
30
|
const picDataLen = Token.UINT32_BE.get(buffer, offset += 4);
|
|
31
|
-
const data =
|
|
31
|
+
const data = Uint8Array.from(buffer.slice(offset += 4, offset + picDataLen));
|
|
32
32
|
return {
|
|
33
33
|
type,
|
|
34
34
|
format,
|
|
@@ -49,7 +49,7 @@ export const CommonHeader = {
|
|
|
49
49
|
len: 7,
|
|
50
50
|
get: (buf, off) => {
|
|
51
51
|
return {
|
|
52
|
-
packetType:
|
|
52
|
+
packetType: Token.UINT8.get(buf, off),
|
|
53
53
|
vorbis: new Token.StringType(6, 'ascii').get(buf, off + 1)
|
|
54
54
|
};
|
|
55
55
|
}
|
|
@@ -61,14 +61,13 @@ export const CommonHeader = {
|
|
|
61
61
|
export const IdentificationHeader = {
|
|
62
62
|
len: 23,
|
|
63
63
|
get: (uint8Array, off) => {
|
|
64
|
-
const dataView = new DataView(uint8Array.buffer, uint8Array.byteOffset);
|
|
65
64
|
return {
|
|
66
|
-
version:
|
|
67
|
-
channelMode:
|
|
68
|
-
sampleRate:
|
|
69
|
-
bitrateMax:
|
|
70
|
-
bitrateNominal:
|
|
71
|
-
bitrateMin:
|
|
65
|
+
version: Token.UINT32_LE.get(uint8Array, off + 0),
|
|
66
|
+
channelMode: Token.UINT8.get(uint8Array, off + 4),
|
|
67
|
+
sampleRate: Token.UINT32_LE.get(uint8Array, off + 5),
|
|
68
|
+
bitrateMax: Token.UINT32_LE.get(uint8Array, off + 9),
|
|
69
|
+
bitrateNominal: Token.UINT32_LE.get(uint8Array, off + 13),
|
|
70
|
+
bitrateMin: Token.UINT32_LE.get(uint8Array, off + 17)
|
|
72
71
|
};
|
|
73
72
|
}
|
|
74
73
|
};
|
|
@@ -11,7 +11,7 @@ export class VorbisDecoder {
|
|
|
11
11
|
}
|
|
12
12
|
readStringUtf8() {
|
|
13
13
|
const len = this.readInt32();
|
|
14
|
-
const value =
|
|
14
|
+
const value = new TextDecoder('utf-8').decode(this.data.subarray(this.offset, this.offset + len));
|
|
15
15
|
this.offset += len;
|
|
16
16
|
return value;
|
|
17
17
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
1
|
import { IVorbisPicture } from './Vorbis.js';
|
|
3
2
|
import { IPageConsumer, IPageHeader } from '../Ogg.js';
|
|
4
3
|
import { IOptions } from '../../type.js';
|
|
@@ -17,20 +16,21 @@ export declare class VorbisParser implements IPageConsumer {
|
|
|
17
16
|
* @param header Ogg Page Header
|
|
18
17
|
* @param pageData Page data
|
|
19
18
|
*/
|
|
20
|
-
parsePage(header: IPageHeader, pageData:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
parsePage(header: IPageHeader, pageData: Uint8Array): Promise<void>;
|
|
20
|
+
private static mergeUint8Arrays;
|
|
21
|
+
flush(): Promise<void>;
|
|
22
|
+
parseUserComment(pageData: Uint8Array, offset: number): Promise<number>;
|
|
23
|
+
addTag(id: string, value: string | IVorbisPicture): Promise<void>;
|
|
24
24
|
calculateDuration(header: IPageHeader): void;
|
|
25
25
|
/**
|
|
26
26
|
* Parse first Ogg/Vorbis page
|
|
27
27
|
* @param header
|
|
28
28
|
* @param pageData
|
|
29
29
|
*/
|
|
30
|
-
protected parseFirstPage(header: IPageHeader, pageData:
|
|
31
|
-
protected parseFullPage(pageData:
|
|
30
|
+
protected parseFirstPage(header: IPageHeader, pageData: Uint8Array): void;
|
|
31
|
+
protected parseFullPage(pageData: Uint8Array): Promise<void>;
|
|
32
32
|
/**
|
|
33
33
|
* Ref: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-840005.2
|
|
34
34
|
*/
|
|
35
|
-
protected parseUserCommentList(pageData:
|
|
35
|
+
protected parseUserCommentList(pageData: Uint8Array, offset: number): Promise<void>;
|
|
36
36
|
}
|
|
@@ -18,7 +18,7 @@ export class VorbisParser {
|
|
|
18
18
|
* @param header Ogg Page Header
|
|
19
19
|
* @param pageData Page data
|
|
20
20
|
*/
|
|
21
|
-
parsePage(header, pageData) {
|
|
21
|
+
async parsePage(header, pageData) {
|
|
22
22
|
if (header.headerType.firstPage) {
|
|
23
23
|
this.parseFirstPage(header, pageData);
|
|
24
24
|
}
|
|
@@ -32,8 +32,8 @@ export class VorbisParser {
|
|
|
32
32
|
if (header.headerType.lastPage || !header.headerType.continued) {
|
|
33
33
|
// Flush page segments
|
|
34
34
|
if (this.pageSegments.length > 0) {
|
|
35
|
-
const fullPage =
|
|
36
|
-
this.parseFullPage(fullPage);
|
|
35
|
+
const fullPage = VorbisParser.mergeUint8Arrays(this.pageSegments);
|
|
36
|
+
await this.parseFullPage(fullPage);
|
|
37
37
|
}
|
|
38
38
|
// Reset page segments
|
|
39
39
|
this.pageSegments = header.headerType.lastPage ? [] : [pageData];
|
|
@@ -43,16 +43,25 @@ export class VorbisParser {
|
|
|
43
43
|
this.calculateDuration(header);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
static mergeUint8Arrays(arrays) {
|
|
47
|
+
const totalSize = arrays.reduce((acc, e) => acc + e.length, 0);
|
|
48
|
+
const merged = new Uint8Array(totalSize);
|
|
49
|
+
arrays.forEach((array, i, _arrays) => {
|
|
50
|
+
const offset = _arrays.slice(0, i).reduce((acc, e) => acc + e.length, 0);
|
|
51
|
+
merged.set(array, offset);
|
|
52
|
+
});
|
|
53
|
+
return merged;
|
|
48
54
|
}
|
|
49
|
-
|
|
55
|
+
async flush() {
|
|
56
|
+
await this.parseFullPage(VorbisParser.mergeUint8Arrays(this.pageSegments));
|
|
57
|
+
}
|
|
58
|
+
async parseUserComment(pageData, offset) {
|
|
50
59
|
const decoder = new VorbisDecoder(pageData, offset);
|
|
51
60
|
const tag = decoder.parseUserComment();
|
|
52
|
-
this.addTag(tag.key, tag.value);
|
|
61
|
+
await this.addTag(tag.key, tag.value);
|
|
53
62
|
return tag.len;
|
|
54
63
|
}
|
|
55
|
-
addTag(id, value) {
|
|
64
|
+
async addTag(id, value) {
|
|
56
65
|
if (id === 'METADATA_BLOCK_PICTURE' && (typeof value === 'string')) {
|
|
57
66
|
if (this.options.skipCovers) {
|
|
58
67
|
debug(`Ignore picture`);
|
|
@@ -64,7 +73,7 @@ export class VorbisParser {
|
|
|
64
73
|
else {
|
|
65
74
|
debug(`Push tag: id=${id}, value=${value}`);
|
|
66
75
|
}
|
|
67
|
-
this.metadata.addTag('vorbis', id, value);
|
|
76
|
+
await this.metadata.addTag('vorbis', id, value);
|
|
68
77
|
}
|
|
69
78
|
calculateDuration(header) {
|
|
70
79
|
if (this.metadata.format.sampleRate && header.absoluteGranulePosition >= 0) {
|
|
@@ -95,7 +104,7 @@ export class VorbisParser {
|
|
|
95
104
|
else
|
|
96
105
|
throw new Error('First Ogg page should be type 1: the identification header');
|
|
97
106
|
}
|
|
98
|
-
parseFullPage(pageData) {
|
|
107
|
+
async parseFullPage(pageData) {
|
|
99
108
|
// New page
|
|
100
109
|
const commonHeader = CommonHeader.get(pageData, 0);
|
|
101
110
|
debug('Parse full page: type=%s, byteLength=%s', commonHeader.packetType, pageData.byteLength);
|
|
@@ -110,7 +119,7 @@ export class VorbisParser {
|
|
|
110
119
|
/**
|
|
111
120
|
* Ref: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-840005.2
|
|
112
121
|
*/
|
|
113
|
-
parseUserCommentList(pageData, offset) {
|
|
122
|
+
async parseUserCommentList(pageData, offset) {
|
|
114
123
|
const strLen = Token.UINT32_LE.get(pageData, offset);
|
|
115
124
|
offset += 4;
|
|
116
125
|
// const vendorString = new Token.StringType(strLen, 'utf-8').get(pageData, offset);
|
|
@@ -118,7 +127,7 @@ export class VorbisParser {
|
|
|
118
127
|
let userCommentListLength = Token.UINT32_LE.get(pageData, offset);
|
|
119
128
|
offset += 4;
|
|
120
129
|
while (userCommentListLength-- > 0) {
|
|
121
|
-
offset += this.parseUserComment(pageData, offset);
|
|
130
|
+
offset += (await this.parseUserComment(pageData, offset));
|
|
122
131
|
}
|
|
123
132
|
}
|
|
124
133
|
}
|
package/lib/riff/RiffChunk.d.ts
CHANGED
package/lib/riff/RiffChunk.js
CHANGED
|
@@ -7,9 +7,9 @@ export const Header = {
|
|
|
7
7
|
get: (buf, off) => {
|
|
8
8
|
return {
|
|
9
9
|
// Group-ID
|
|
10
|
-
chunkID:
|
|
10
|
+
chunkID: new Token.StringType(4, 'latin1').get(buf, off),
|
|
11
11
|
// Size
|
|
12
|
-
chunkSize: Token.UINT32_LE.get(buf, 4)
|
|
12
|
+
chunkSize: Token.UINT32_LE.get(buf, off + 4)
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
};
|
package/lib/type.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
import { Buffer } from 'node:buffer';
|
|
3
1
|
import { GenericTagId, TagType } from './common/GenericTagTypes.js';
|
|
4
2
|
import { IFooter } from './apev2/APEv2Token.js';
|
|
5
3
|
import { TrackType } from './matroska/types.js';
|
|
@@ -15,7 +13,7 @@ export interface IPicture {
|
|
|
15
13
|
/**
|
|
16
14
|
* Image data
|
|
17
15
|
*/
|
|
18
|
-
data:
|
|
16
|
+
data: Uint8Array;
|
|
19
17
|
/**
|
|
20
18
|
* Optional description
|
|
21
19
|
*/
|
|
@@ -366,7 +364,7 @@ export interface IAudioTrack {
|
|
|
366
364
|
samplingFrequency?: number;
|
|
367
365
|
outputSamplingFrequency?: number;
|
|
368
366
|
channels?: number;
|
|
369
|
-
channelPositions?:
|
|
367
|
+
channelPositions?: Uint8Array;
|
|
370
368
|
bitDepth?: number;
|
|
371
369
|
}
|
|
372
370
|
export interface IVideoTrack {
|
|
@@ -378,7 +376,7 @@ export interface IVideoTrack {
|
|
|
378
376
|
displayHeight?: number;
|
|
379
377
|
displayUnit?: number;
|
|
380
378
|
aspectRatioType?: number;
|
|
381
|
-
colourSpace?:
|
|
379
|
+
colourSpace?: Uint8Array;
|
|
382
380
|
gammaValue?: number;
|
|
383
381
|
}
|
|
384
382
|
export interface ITrackInfo {
|
|
@@ -445,7 +443,7 @@ export interface IFormat {
|
|
|
445
443
|
/**
|
|
446
444
|
* 16-byte MD5 of raw audio
|
|
447
445
|
*/
|
|
448
|
-
readonly audioMD5?:
|
|
446
|
+
readonly audioMD5?: Uint8Array;
|
|
449
447
|
/**
|
|
450
448
|
* Chapters in audio stream
|
|
451
449
|
*/
|
|
@@ -587,11 +585,11 @@ export interface IRandomReader {
|
|
|
587
585
|
fileSize: number;
|
|
588
586
|
/**
|
|
589
587
|
* Read from a given position of an abstracted file or buffer.
|
|
590
|
-
* @param
|
|
591
|
-
* @param
|
|
592
|
-
* @param
|
|
593
|
-
* @param
|
|
588
|
+
* @param {Uint8Array} buffer the buffer that the data will be written to.
|
|
589
|
+
* @param {number} offset the offset in the buffer to start writing at.
|
|
590
|
+
* @param {number} length an integer specifying the number of bytes to read.
|
|
591
|
+
* @param {number} position an argument specifying where to begin reading from in the file.
|
|
594
592
|
* @return {Promise<number>} bytes read
|
|
595
593
|
*/
|
|
596
|
-
randomRead(buffer:
|
|
594
|
+
randomRead(buffer: Uint8Array, offset: number, length: number, position: number): Promise<number>;
|
|
597
595
|
}
|
package/lib/wav/BwfChunk.d.ts
CHANGED
package/lib/wav/WaveChunk.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { IGetToken } from 'strtok3/core';
|
|
1
|
+
import type { IGetToken } from 'strtok3';
|
|
3
2
|
import { IChunkHeader } from '../iff/index.js';
|
|
4
3
|
/**
|
|
5
4
|
* Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317599(v=vs.85).aspx
|
|
@@ -47,7 +46,7 @@ export interface IWaveFormat {
|
|
|
47
46
|
export declare class Format implements IGetToken<IWaveFormat> {
|
|
48
47
|
len: number;
|
|
49
48
|
constructor(header: IChunkHeader);
|
|
50
|
-
get(buf:
|
|
49
|
+
get(buf: Uint8Array, off: number): IWaveFormat;
|
|
51
50
|
}
|
|
52
51
|
export interface IFactChunk {
|
|
53
52
|
dwSampleLength: number;
|
|
@@ -60,5 +59,5 @@ export interface IFactChunk {
|
|
|
60
59
|
export declare class FactChunk implements IGetToken<IFactChunk> {
|
|
61
60
|
len: number;
|
|
62
61
|
constructor(header: IChunkHeader);
|
|
63
|
-
get(buf:
|
|
62
|
+
get(buf: Uint8Array, off: number): IFactChunk;
|
|
64
63
|
}
|
package/lib/wav/WaveChunk.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as Token from 'token-types';
|
|
1
2
|
/**
|
|
2
3
|
* Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317599(v=vs.85).aspx
|
|
3
4
|
*/
|
|
@@ -31,12 +32,12 @@ export class Format {
|
|
|
31
32
|
}
|
|
32
33
|
get(buf, off) {
|
|
33
34
|
return {
|
|
34
|
-
wFormatTag:
|
|
35
|
-
nChannels:
|
|
36
|
-
nSamplesPerSec:
|
|
37
|
-
nAvgBytesPerSec:
|
|
38
|
-
nBlockAlign:
|
|
39
|
-
wBitsPerSample:
|
|
35
|
+
wFormatTag: Token.UINT16_LE.get(buf, off),
|
|
36
|
+
nChannels: Token.UINT16_LE.get(buf, off + 2),
|
|
37
|
+
nSamplesPerSec: Token.UINT32_LE.get(buf, off + 4),
|
|
38
|
+
nAvgBytesPerSec: Token.UINT32_LE.get(buf, off + 8),
|
|
39
|
+
nBlockAlign: Token.UINT16_LE.get(buf, off + 12),
|
|
40
|
+
wBitsPerSample: Token.UINT16_LE.get(buf, off + 14)
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
}
|
|
@@ -54,7 +55,7 @@ export class FactChunk {
|
|
|
54
55
|
}
|
|
55
56
|
get(buf, off) {
|
|
56
57
|
return {
|
|
57
|
-
dwSampleLength:
|
|
58
|
+
dwSampleLength: Token.UINT32_LE.get(buf, off)
|
|
58
59
|
};
|
|
59
60
|
}
|
|
60
61
|
}
|
package/lib/wav/WaveParser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as strtok3 from 'strtok3
|
|
1
|
+
import * as strtok3 from 'strtok3';
|
|
2
2
|
import * as Token from 'token-types';
|
|
3
3
|
import initDebug from 'debug';
|
|
4
4
|
import * as riff from '../riff/RiffChunk.js';
|
|
@@ -129,7 +129,7 @@ export class WaveParser extends BasicParser {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
async parseListTag(listHeader) {
|
|
132
|
-
const listType = await this.tokenizer.readToken(new Token.StringType(4, '
|
|
132
|
+
const listType = await this.tokenizer.readToken(new Token.StringType(4, 'latin1'));
|
|
133
133
|
debug('pos=%s, parseListTag: chunkID=RIFF/WAVE/LIST/%s', this.tokenizer.position, listType);
|
|
134
134
|
switch (listType) {
|
|
135
135
|
case 'INFO':
|