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/asf/AsfObject.js
CHANGED
|
@@ -1,384 +1,384 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// ASF Objects
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.WmPictureToken = exports.MetadataLibraryObjectState = exports.MetadataObjectState = exports.ExtendedStreamPropertiesObjectState = exports.ExtendedContentDescriptionObjectState = exports.ContentDescriptionObjectState = exports.readCodecEntries = exports.HeaderExtensionObject = exports.StreamPropertiesObject = exports.FilePropertiesObject = exports.IgnoreObjectState = exports.State = exports.HeaderObjectToken = exports.TopLevelHeaderObjectToken = exports.DataType = void 0;
|
|
5
|
-
const util = require("../common/Util");
|
|
6
|
-
const Token = require("token-types");
|
|
7
|
-
const GUID_1 = require("./GUID");
|
|
8
|
-
const AsfUtil_1 = require("./AsfUtil");
|
|
9
|
-
const ID3v2Token_1 = require("../id3v2/ID3v2Token");
|
|
10
|
-
/**
|
|
11
|
-
* Data Type: Specifies the type of information being stored. The following values are recognized.
|
|
12
|
-
*/
|
|
13
|
-
var DataType;
|
|
14
|
-
(function (DataType) {
|
|
15
|
-
/**
|
|
16
|
-
* Unicode string. The data consists of a sequence of Unicode characters.
|
|
17
|
-
*/
|
|
18
|
-
DataType[DataType["UnicodeString"] = 0] = "UnicodeString";
|
|
19
|
-
/**
|
|
20
|
-
* BYTE array. The type of data is implementation-specific.
|
|
21
|
-
*/
|
|
22
|
-
DataType[DataType["ByteArray"] = 1] = "ByteArray";
|
|
23
|
-
/**
|
|
24
|
-
* BOOL. The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer. Only 0x0000 or 0x0001 are permitted values.
|
|
25
|
-
*/
|
|
26
|
-
DataType[DataType["Bool"] = 2] = "Bool";
|
|
27
|
-
/**
|
|
28
|
-
* DWORD. The data is 4 bytes long and should be interpreted as a 32-bit unsigned integer.
|
|
29
|
-
*/
|
|
30
|
-
DataType[DataType["DWord"] = 3] = "DWord";
|
|
31
|
-
/**
|
|
32
|
-
* QWORD. The data is 8 bytes long and should be interpreted as a 64-bit unsigned integer.
|
|
33
|
-
*/
|
|
34
|
-
DataType[DataType["QWord"] = 4] = "QWord";
|
|
35
|
-
/**
|
|
36
|
-
* WORD. The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer.
|
|
37
|
-
*/
|
|
38
|
-
DataType[DataType["Word"] = 5] = "Word";
|
|
39
|
-
})(DataType = exports.DataType || (exports.DataType = {}));
|
|
40
|
-
/**
|
|
41
|
-
* Token for: 3. ASF top-level Header Object
|
|
42
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3
|
|
43
|
-
*/
|
|
44
|
-
exports.TopLevelHeaderObjectToken = {
|
|
45
|
-
len: 30,
|
|
46
|
-
get: (buf, off) => {
|
|
47
|
-
return {
|
|
48
|
-
objectId: GUID_1.default.fromBin(new Token.BufferType(16).get(buf, off)),
|
|
49
|
-
objectSize: Number(Token.UINT64_LE.get(buf, off + 16)),
|
|
50
|
-
numberOfHeaderObjects: Token.UINT32_LE.get(buf, off + 24)
|
|
51
|
-
// Reserved: 2 bytes
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* Token for: 3.1 Header Object (mandatory, one only)
|
|
57
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_1
|
|
58
|
-
*/
|
|
59
|
-
exports.HeaderObjectToken = {
|
|
60
|
-
len: 24,
|
|
61
|
-
get: (buf, off) => {
|
|
62
|
-
return {
|
|
63
|
-
objectId: GUID_1.default.fromBin(new Token.BufferType(16).get(buf, off)),
|
|
64
|
-
objectSize: Number(Token.UINT64_LE.get(buf, off + 16))
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
class State {
|
|
69
|
-
constructor(header) {
|
|
70
|
-
this.len = Number(header.objectSize) - exports.HeaderObjectToken.len;
|
|
71
|
-
}
|
|
72
|
-
postProcessTag(tags, name, valueType, data) {
|
|
73
|
-
if (name === 'WM/Picture') {
|
|
74
|
-
tags.push({ id: name, value: WmPictureToken.fromBuffer(data) });
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
const parseAttr = AsfUtil_1.AsfUtil.getParserForAttr(valueType);
|
|
78
|
-
if (!parseAttr) {
|
|
79
|
-
throw new Error('unexpected value headerType: ' + valueType);
|
|
80
|
-
}
|
|
81
|
-
tags.push({ id: name, value: parseAttr(data) });
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
exports.State = State;
|
|
86
|
-
// ToDo: use ignore type
|
|
87
|
-
class IgnoreObjectState extends State {
|
|
88
|
-
constructor(header) {
|
|
89
|
-
super(header);
|
|
90
|
-
}
|
|
91
|
-
get(buf, off) {
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
exports.IgnoreObjectState = IgnoreObjectState;
|
|
96
|
-
/**
|
|
97
|
-
* Token for: 3.2: File Properties Object (mandatory, one only)
|
|
98
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_2
|
|
99
|
-
*/
|
|
100
|
-
class FilePropertiesObject extends State {
|
|
101
|
-
constructor(header) {
|
|
102
|
-
super(header);
|
|
103
|
-
}
|
|
104
|
-
get(buf, off) {
|
|
105
|
-
return {
|
|
106
|
-
fileId: GUID_1.default.fromBin(buf, off),
|
|
107
|
-
fileSize: Token.UINT64_LE.get(buf, off + 16),
|
|
108
|
-
creationDate: Token.UINT64_LE.get(buf, off + 24),
|
|
109
|
-
dataPacketsCount: Token.UINT64_LE.get(buf, off + 32),
|
|
110
|
-
playDuration: Token.UINT64_LE.get(buf, off + 40),
|
|
111
|
-
sendDuration: Token.UINT64_LE.get(buf, off + 48),
|
|
112
|
-
preroll: Token.UINT64_LE.get(buf, off + 56),
|
|
113
|
-
flags: {
|
|
114
|
-
broadcast: util.getBit(buf, off + 64, 24),
|
|
115
|
-
seekable: util.getBit(buf, off + 64, 25)
|
|
116
|
-
},
|
|
117
|
-
// flagsNumeric: Token.UINT32_LE.get(buf, off + 64),
|
|
118
|
-
minimumDataPacketSize: Token.UINT32_LE.get(buf, off + 68),
|
|
119
|
-
maximumDataPacketSize: Token.UINT32_LE.get(buf, off + 72),
|
|
120
|
-
maximumBitrate: Token.UINT32_LE.get(buf, off + 76)
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
exports.FilePropertiesObject = FilePropertiesObject;
|
|
125
|
-
FilePropertiesObject.guid = GUID_1.default.FilePropertiesObject;
|
|
126
|
-
/**
|
|
127
|
-
* Token for: 3.3 Stream Properties Object (mandatory, one per stream)
|
|
128
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_3
|
|
129
|
-
*/
|
|
130
|
-
class StreamPropertiesObject extends State {
|
|
131
|
-
constructor(header) {
|
|
132
|
-
super(header);
|
|
133
|
-
}
|
|
134
|
-
get(buf, off) {
|
|
135
|
-
return {
|
|
136
|
-
streamType: GUID_1.default.decodeMediaType(GUID_1.default.fromBin(buf, off)),
|
|
137
|
-
errorCorrectionType: GUID_1.default.fromBin(buf, off + 8)
|
|
138
|
-
// ToDo
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
exports.StreamPropertiesObject = StreamPropertiesObject;
|
|
143
|
-
StreamPropertiesObject.guid = GUID_1.default.StreamPropertiesObject;
|
|
144
|
-
/**
|
|
145
|
-
* 3.4: Header Extension Object (mandatory, one only)
|
|
146
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_4
|
|
147
|
-
*/
|
|
148
|
-
class HeaderExtensionObject {
|
|
149
|
-
constructor() {
|
|
150
|
-
this.len = 22;
|
|
151
|
-
}
|
|
152
|
-
get(buf, off) {
|
|
153
|
-
return {
|
|
154
|
-
reserved1: GUID_1.default.fromBin(buf, off),
|
|
155
|
-
reserved2: buf.readUInt16LE(off + 16),
|
|
156
|
-
extensionDataSize: buf.readUInt32LE(off + 18)
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
exports.HeaderExtensionObject = HeaderExtensionObject;
|
|
161
|
-
HeaderExtensionObject.guid = GUID_1.default.HeaderExtensionObject;
|
|
162
|
-
/**
|
|
163
|
-
* 3.5: The Codec List Object provides user-friendly information about the codecs and formats used to encode the content found in the ASF file.
|
|
164
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_5
|
|
165
|
-
*/
|
|
166
|
-
const CodecListObjectHeader = {
|
|
167
|
-
len: 20,
|
|
168
|
-
get: (buf, off) => {
|
|
169
|
-
return {
|
|
170
|
-
entryCount: buf.readUInt16LE(off + 16)
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
async function readString(tokenizer) {
|
|
175
|
-
const length = await tokenizer.readNumber(Token.UINT16_LE);
|
|
176
|
-
return (await tokenizer.readToken(new Token.StringType(length * 2, 'utf16le'))).replace('\0', '');
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* 3.5: Read the Codec-List-Object, which provides user-friendly information about the codecs and formats used to encode the content found in the ASF file.
|
|
180
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_5
|
|
181
|
-
*/
|
|
182
|
-
async function readCodecEntries(tokenizer) {
|
|
183
|
-
const codecHeader = await tokenizer.readToken(CodecListObjectHeader);
|
|
184
|
-
const entries = [];
|
|
185
|
-
for (let i = 0; i < codecHeader.entryCount; ++i) {
|
|
186
|
-
entries.push(await readCodecEntry(tokenizer));
|
|
187
|
-
}
|
|
188
|
-
return entries;
|
|
189
|
-
}
|
|
190
|
-
exports.readCodecEntries = readCodecEntries;
|
|
191
|
-
async function readInformation(tokenizer) {
|
|
192
|
-
const length = await tokenizer.readNumber(Token.UINT16_LE);
|
|
193
|
-
const buf = Buffer.alloc(length);
|
|
194
|
-
await tokenizer.readBuffer(buf);
|
|
195
|
-
return buf;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Read Codec-Entries
|
|
199
|
-
* @param tokenizer
|
|
200
|
-
*/
|
|
201
|
-
async function readCodecEntry(tokenizer) {
|
|
202
|
-
const type = await tokenizer.readNumber(Token.UINT16_LE);
|
|
203
|
-
return {
|
|
204
|
-
type: {
|
|
205
|
-
videoCodec: (type & 0x0001) === 0x0001,
|
|
206
|
-
audioCodec: (type & 0x0002) === 0x0002
|
|
207
|
-
},
|
|
208
|
-
codecName: await readString(tokenizer),
|
|
209
|
-
description: await readString(tokenizer),
|
|
210
|
-
information: await readInformation(tokenizer)
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* 3.10 Content Description Object (optional, one only)
|
|
215
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_10
|
|
216
|
-
*/
|
|
217
|
-
class ContentDescriptionObjectState extends State {
|
|
218
|
-
constructor(header) {
|
|
219
|
-
super(header);
|
|
220
|
-
}
|
|
221
|
-
get(buf, off) {
|
|
222
|
-
const tags = [];
|
|
223
|
-
let pos = off + 10;
|
|
224
|
-
for (let i = 0; i < ContentDescriptionObjectState.contentDescTags.length; ++i) {
|
|
225
|
-
const length = buf.readUInt16LE(off + i * 2);
|
|
226
|
-
if (length > 0) {
|
|
227
|
-
const tagName = ContentDescriptionObjectState.contentDescTags[i];
|
|
228
|
-
const end = pos + length;
|
|
229
|
-
tags.push({ id: tagName, value: AsfUtil_1.AsfUtil.parseUnicodeAttr(buf.slice(pos, end)) });
|
|
230
|
-
pos = end;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return tags;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
exports.ContentDescriptionObjectState = ContentDescriptionObjectState;
|
|
237
|
-
ContentDescriptionObjectState.guid = GUID_1.default.ContentDescriptionObject;
|
|
238
|
-
ContentDescriptionObjectState.contentDescTags = ['Title', 'Author', 'Copyright', 'Description', 'Rating'];
|
|
239
|
-
/**
|
|
240
|
-
* 3.11 Extended Content Description Object (optional, one only)
|
|
241
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_11
|
|
242
|
-
*/
|
|
243
|
-
class ExtendedContentDescriptionObjectState extends State {
|
|
244
|
-
constructor(header) {
|
|
245
|
-
super(header);
|
|
246
|
-
}
|
|
247
|
-
get(buf, off) {
|
|
248
|
-
const tags = [];
|
|
249
|
-
const attrCount = buf.readUInt16LE(off);
|
|
250
|
-
let pos = off + 2;
|
|
251
|
-
for (let i = 0; i < attrCount; i += 1) {
|
|
252
|
-
const nameLen = buf.readUInt16LE(pos);
|
|
253
|
-
pos += 2;
|
|
254
|
-
const name = AsfUtil_1.AsfUtil.parseUnicodeAttr(buf.slice(pos, pos + nameLen));
|
|
255
|
-
pos += nameLen;
|
|
256
|
-
const valueType = buf.readUInt16LE(pos);
|
|
257
|
-
pos += 2;
|
|
258
|
-
const valueLen = buf.readUInt16LE(pos);
|
|
259
|
-
pos += 2;
|
|
260
|
-
const value = buf.slice(pos, pos + valueLen);
|
|
261
|
-
pos += valueLen;
|
|
262
|
-
this.postProcessTag(tags, name, valueType, value);
|
|
263
|
-
}
|
|
264
|
-
return tags;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
exports.ExtendedContentDescriptionObjectState = ExtendedContentDescriptionObjectState;
|
|
268
|
-
ExtendedContentDescriptionObjectState.guid = GUID_1.default.ExtendedContentDescriptionObject;
|
|
269
|
-
/**
|
|
270
|
-
* 4.1 Extended Stream Properties Object (optional, 1 per media stream)
|
|
271
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/04_objects_in_the_asf_header_extension_object.html#4_1
|
|
272
|
-
*/
|
|
273
|
-
class ExtendedStreamPropertiesObjectState extends State {
|
|
274
|
-
constructor(header) {
|
|
275
|
-
super(header);
|
|
276
|
-
}
|
|
277
|
-
get(buf, off) {
|
|
278
|
-
return {
|
|
279
|
-
startTime: Token.UINT64_LE.get(buf, off),
|
|
280
|
-
endTime: Token.UINT64_LE.get(buf, off + 8),
|
|
281
|
-
dataBitrate: buf.readInt32LE(off + 12),
|
|
282
|
-
bufferSize: buf.readInt32LE(off + 16),
|
|
283
|
-
initialBufferFullness: buf.readInt32LE(off + 20),
|
|
284
|
-
alternateDataBitrate: buf.readInt32LE(off + 24),
|
|
285
|
-
alternateBufferSize: buf.readInt32LE(off + 28),
|
|
286
|
-
alternateInitialBufferFullness: buf.readInt32LE(off + 32),
|
|
287
|
-
maximumObjectSize: buf.readInt32LE(off + 36),
|
|
288
|
-
flags: {
|
|
289
|
-
reliableFlag: util.getBit(buf, off + 40, 0),
|
|
290
|
-
seekableFlag: util.getBit(buf, off + 40, 1),
|
|
291
|
-
resendLiveCleanpointsFlag: util.getBit(buf, off + 40, 2)
|
|
292
|
-
},
|
|
293
|
-
// flagsNumeric: Token.UINT32_LE.get(buf, off + 64),
|
|
294
|
-
streamNumber: buf.readInt16LE(off + 42),
|
|
295
|
-
streamLanguageId: buf.readInt16LE(off + 44),
|
|
296
|
-
averageTimePerFrame: buf.readInt32LE(off + 52),
|
|
297
|
-
streamNameCount: buf.readInt32LE(off + 54),
|
|
298
|
-
payloadExtensionSystems: buf.readInt32LE(off + 56),
|
|
299
|
-
streamNames: [],
|
|
300
|
-
streamPropertiesObject: null
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
exports.ExtendedStreamPropertiesObjectState = ExtendedStreamPropertiesObjectState;
|
|
305
|
-
ExtendedStreamPropertiesObjectState.guid = GUID_1.default.ExtendedStreamPropertiesObject;
|
|
306
|
-
/**
|
|
307
|
-
* 4.7 Metadata Object (optional, 0 or 1)
|
|
308
|
-
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/04_objects_in_the_asf_header_extension_object.html#4_7
|
|
309
|
-
*/
|
|
310
|
-
class MetadataObjectState extends State {
|
|
311
|
-
constructor(header) {
|
|
312
|
-
super(header);
|
|
313
|
-
}
|
|
314
|
-
get(buf, off) {
|
|
315
|
-
const tags = [];
|
|
316
|
-
const descriptionRecordsCount = buf.readUInt16LE(off);
|
|
317
|
-
let pos = off + 2;
|
|
318
|
-
for (let i = 0; i < descriptionRecordsCount; i += 1) {
|
|
319
|
-
pos += 4;
|
|
320
|
-
const nameLen = buf.readUInt16LE(pos);
|
|
321
|
-
pos += 2;
|
|
322
|
-
const dataType = buf.readUInt16LE(pos);
|
|
323
|
-
pos += 2;
|
|
324
|
-
const dataLen = buf.readUInt32LE(pos);
|
|
325
|
-
pos += 4;
|
|
326
|
-
const name = AsfUtil_1.AsfUtil.parseUnicodeAttr(buf.slice(pos, pos + nameLen));
|
|
327
|
-
pos += nameLen;
|
|
328
|
-
const data = buf.slice(pos, pos + dataLen);
|
|
329
|
-
pos += dataLen;
|
|
330
|
-
const parseAttr = AsfUtil_1.AsfUtil.getParserForAttr(dataType);
|
|
331
|
-
if (!parseAttr) {
|
|
332
|
-
throw new Error('unexpected value headerType: ' + dataType);
|
|
333
|
-
}
|
|
334
|
-
this.postProcessTag(tags, name, dataType, data);
|
|
335
|
-
}
|
|
336
|
-
return tags;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
exports.MetadataObjectState = MetadataObjectState;
|
|
340
|
-
MetadataObjectState.guid = GUID_1.default.MetadataObject;
|
|
341
|
-
// 4.8 Metadata Library Object (optional, 0 or 1)
|
|
342
|
-
class MetadataLibraryObjectState extends MetadataObjectState {
|
|
343
|
-
constructor(header) {
|
|
344
|
-
super(header);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
exports.MetadataLibraryObjectState = MetadataLibraryObjectState;
|
|
348
|
-
MetadataLibraryObjectState.guid = GUID_1.default.MetadataLibraryObject;
|
|
349
|
-
/**
|
|
350
|
-
* Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd757977(v=vs.85).aspx
|
|
351
|
-
*/
|
|
352
|
-
class WmPictureToken {
|
|
353
|
-
constructor(len) {
|
|
354
|
-
this.len = len;
|
|
355
|
-
}
|
|
356
|
-
static fromBase64(base64str) {
|
|
357
|
-
return this.fromBuffer(Buffer.from(base64str, 'base64'));
|
|
358
|
-
}
|
|
359
|
-
static fromBuffer(buffer) {
|
|
360
|
-
const pic = new WmPictureToken(buffer.length);
|
|
361
|
-
return pic.get(buffer, 0);
|
|
362
|
-
}
|
|
363
|
-
get(buffer, offset) {
|
|
364
|
-
const typeId = buffer.readUInt8(offset++);
|
|
365
|
-
const size = buffer.readInt32LE(offset);
|
|
366
|
-
let index = 5;
|
|
367
|
-
while (buffer.readUInt16BE(index) !== 0) {
|
|
368
|
-
index += 2;
|
|
369
|
-
}
|
|
370
|
-
const format = buffer.slice(5, index).toString('utf16le');
|
|
371
|
-
while (buffer.readUInt16BE(index) !== 0) {
|
|
372
|
-
index += 2;
|
|
373
|
-
}
|
|
374
|
-
const description = buffer.slice(5, index).toString('utf16le');
|
|
375
|
-
return {
|
|
376
|
-
type: ID3v2Token_1.AttachedPictureType[typeId],
|
|
377
|
-
format,
|
|
378
|
-
description,
|
|
379
|
-
size,
|
|
380
|
-
data: buffer.slice(index + 4)
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
exports.WmPictureToken = WmPictureToken;
|
|
1
|
+
"use strict";
|
|
2
|
+
// ASF Objects
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.WmPictureToken = exports.MetadataLibraryObjectState = exports.MetadataObjectState = exports.ExtendedStreamPropertiesObjectState = exports.ExtendedContentDescriptionObjectState = exports.ContentDescriptionObjectState = exports.readCodecEntries = exports.HeaderExtensionObject = exports.StreamPropertiesObject = exports.FilePropertiesObject = exports.IgnoreObjectState = exports.State = exports.HeaderObjectToken = exports.TopLevelHeaderObjectToken = exports.DataType = void 0;
|
|
5
|
+
const util = require("../common/Util");
|
|
6
|
+
const Token = require("token-types");
|
|
7
|
+
const GUID_1 = require("./GUID");
|
|
8
|
+
const AsfUtil_1 = require("./AsfUtil");
|
|
9
|
+
const ID3v2Token_1 = require("../id3v2/ID3v2Token");
|
|
10
|
+
/**
|
|
11
|
+
* Data Type: Specifies the type of information being stored. The following values are recognized.
|
|
12
|
+
*/
|
|
13
|
+
var DataType;
|
|
14
|
+
(function (DataType) {
|
|
15
|
+
/**
|
|
16
|
+
* Unicode string. The data consists of a sequence of Unicode characters.
|
|
17
|
+
*/
|
|
18
|
+
DataType[DataType["UnicodeString"] = 0] = "UnicodeString";
|
|
19
|
+
/**
|
|
20
|
+
* BYTE array. The type of data is implementation-specific.
|
|
21
|
+
*/
|
|
22
|
+
DataType[DataType["ByteArray"] = 1] = "ByteArray";
|
|
23
|
+
/**
|
|
24
|
+
* BOOL. The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer. Only 0x0000 or 0x0001 are permitted values.
|
|
25
|
+
*/
|
|
26
|
+
DataType[DataType["Bool"] = 2] = "Bool";
|
|
27
|
+
/**
|
|
28
|
+
* DWORD. The data is 4 bytes long and should be interpreted as a 32-bit unsigned integer.
|
|
29
|
+
*/
|
|
30
|
+
DataType[DataType["DWord"] = 3] = "DWord";
|
|
31
|
+
/**
|
|
32
|
+
* QWORD. The data is 8 bytes long and should be interpreted as a 64-bit unsigned integer.
|
|
33
|
+
*/
|
|
34
|
+
DataType[DataType["QWord"] = 4] = "QWord";
|
|
35
|
+
/**
|
|
36
|
+
* WORD. The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer.
|
|
37
|
+
*/
|
|
38
|
+
DataType[DataType["Word"] = 5] = "Word";
|
|
39
|
+
})(DataType = exports.DataType || (exports.DataType = {}));
|
|
40
|
+
/**
|
|
41
|
+
* Token for: 3. ASF top-level Header Object
|
|
42
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3
|
|
43
|
+
*/
|
|
44
|
+
exports.TopLevelHeaderObjectToken = {
|
|
45
|
+
len: 30,
|
|
46
|
+
get: (buf, off) => {
|
|
47
|
+
return {
|
|
48
|
+
objectId: GUID_1.default.fromBin(new Token.BufferType(16).get(buf, off)),
|
|
49
|
+
objectSize: Number(Token.UINT64_LE.get(buf, off + 16)),
|
|
50
|
+
numberOfHeaderObjects: Token.UINT32_LE.get(buf, off + 24)
|
|
51
|
+
// Reserved: 2 bytes
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Token for: 3.1 Header Object (mandatory, one only)
|
|
57
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_1
|
|
58
|
+
*/
|
|
59
|
+
exports.HeaderObjectToken = {
|
|
60
|
+
len: 24,
|
|
61
|
+
get: (buf, off) => {
|
|
62
|
+
return {
|
|
63
|
+
objectId: GUID_1.default.fromBin(new Token.BufferType(16).get(buf, off)),
|
|
64
|
+
objectSize: Number(Token.UINT64_LE.get(buf, off + 16))
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
class State {
|
|
69
|
+
constructor(header) {
|
|
70
|
+
this.len = Number(header.objectSize) - exports.HeaderObjectToken.len;
|
|
71
|
+
}
|
|
72
|
+
postProcessTag(tags, name, valueType, data) {
|
|
73
|
+
if (name === 'WM/Picture') {
|
|
74
|
+
tags.push({ id: name, value: WmPictureToken.fromBuffer(data) });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const parseAttr = AsfUtil_1.AsfUtil.getParserForAttr(valueType);
|
|
78
|
+
if (!parseAttr) {
|
|
79
|
+
throw new Error('unexpected value headerType: ' + valueType);
|
|
80
|
+
}
|
|
81
|
+
tags.push({ id: name, value: parseAttr(data) });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.State = State;
|
|
86
|
+
// ToDo: use ignore type
|
|
87
|
+
class IgnoreObjectState extends State {
|
|
88
|
+
constructor(header) {
|
|
89
|
+
super(header);
|
|
90
|
+
}
|
|
91
|
+
get(buf, off) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.IgnoreObjectState = IgnoreObjectState;
|
|
96
|
+
/**
|
|
97
|
+
* Token for: 3.2: File Properties Object (mandatory, one only)
|
|
98
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_2
|
|
99
|
+
*/
|
|
100
|
+
class FilePropertiesObject extends State {
|
|
101
|
+
constructor(header) {
|
|
102
|
+
super(header);
|
|
103
|
+
}
|
|
104
|
+
get(buf, off) {
|
|
105
|
+
return {
|
|
106
|
+
fileId: GUID_1.default.fromBin(buf, off),
|
|
107
|
+
fileSize: Token.UINT64_LE.get(buf, off + 16),
|
|
108
|
+
creationDate: Token.UINT64_LE.get(buf, off + 24),
|
|
109
|
+
dataPacketsCount: Token.UINT64_LE.get(buf, off + 32),
|
|
110
|
+
playDuration: Token.UINT64_LE.get(buf, off + 40),
|
|
111
|
+
sendDuration: Token.UINT64_LE.get(buf, off + 48),
|
|
112
|
+
preroll: Token.UINT64_LE.get(buf, off + 56),
|
|
113
|
+
flags: {
|
|
114
|
+
broadcast: util.getBit(buf, off + 64, 24),
|
|
115
|
+
seekable: util.getBit(buf, off + 64, 25)
|
|
116
|
+
},
|
|
117
|
+
// flagsNumeric: Token.UINT32_LE.get(buf, off + 64),
|
|
118
|
+
minimumDataPacketSize: Token.UINT32_LE.get(buf, off + 68),
|
|
119
|
+
maximumDataPacketSize: Token.UINT32_LE.get(buf, off + 72),
|
|
120
|
+
maximumBitrate: Token.UINT32_LE.get(buf, off + 76)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
exports.FilePropertiesObject = FilePropertiesObject;
|
|
125
|
+
FilePropertiesObject.guid = GUID_1.default.FilePropertiesObject;
|
|
126
|
+
/**
|
|
127
|
+
* Token for: 3.3 Stream Properties Object (mandatory, one per stream)
|
|
128
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_3
|
|
129
|
+
*/
|
|
130
|
+
class StreamPropertiesObject extends State {
|
|
131
|
+
constructor(header) {
|
|
132
|
+
super(header);
|
|
133
|
+
}
|
|
134
|
+
get(buf, off) {
|
|
135
|
+
return {
|
|
136
|
+
streamType: GUID_1.default.decodeMediaType(GUID_1.default.fromBin(buf, off)),
|
|
137
|
+
errorCorrectionType: GUID_1.default.fromBin(buf, off + 8)
|
|
138
|
+
// ToDo
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.StreamPropertiesObject = StreamPropertiesObject;
|
|
143
|
+
StreamPropertiesObject.guid = GUID_1.default.StreamPropertiesObject;
|
|
144
|
+
/**
|
|
145
|
+
* 3.4: Header Extension Object (mandatory, one only)
|
|
146
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_4
|
|
147
|
+
*/
|
|
148
|
+
class HeaderExtensionObject {
|
|
149
|
+
constructor() {
|
|
150
|
+
this.len = 22;
|
|
151
|
+
}
|
|
152
|
+
get(buf, off) {
|
|
153
|
+
return {
|
|
154
|
+
reserved1: GUID_1.default.fromBin(buf, off),
|
|
155
|
+
reserved2: buf.readUInt16LE(off + 16),
|
|
156
|
+
extensionDataSize: buf.readUInt32LE(off + 18)
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
exports.HeaderExtensionObject = HeaderExtensionObject;
|
|
161
|
+
HeaderExtensionObject.guid = GUID_1.default.HeaderExtensionObject;
|
|
162
|
+
/**
|
|
163
|
+
* 3.5: The Codec List Object provides user-friendly information about the codecs and formats used to encode the content found in the ASF file.
|
|
164
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_5
|
|
165
|
+
*/
|
|
166
|
+
const CodecListObjectHeader = {
|
|
167
|
+
len: 20,
|
|
168
|
+
get: (buf, off) => {
|
|
169
|
+
return {
|
|
170
|
+
entryCount: buf.readUInt16LE(off + 16)
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
async function readString(tokenizer) {
|
|
175
|
+
const length = await tokenizer.readNumber(Token.UINT16_LE);
|
|
176
|
+
return (await tokenizer.readToken(new Token.StringType(length * 2, 'utf16le'))).replace('\0', '');
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* 3.5: Read the Codec-List-Object, which provides user-friendly information about the codecs and formats used to encode the content found in the ASF file.
|
|
180
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_5
|
|
181
|
+
*/
|
|
182
|
+
async function readCodecEntries(tokenizer) {
|
|
183
|
+
const codecHeader = await tokenizer.readToken(CodecListObjectHeader);
|
|
184
|
+
const entries = [];
|
|
185
|
+
for (let i = 0; i < codecHeader.entryCount; ++i) {
|
|
186
|
+
entries.push(await readCodecEntry(tokenizer));
|
|
187
|
+
}
|
|
188
|
+
return entries;
|
|
189
|
+
}
|
|
190
|
+
exports.readCodecEntries = readCodecEntries;
|
|
191
|
+
async function readInformation(tokenizer) {
|
|
192
|
+
const length = await tokenizer.readNumber(Token.UINT16_LE);
|
|
193
|
+
const buf = Buffer.alloc(length);
|
|
194
|
+
await tokenizer.readBuffer(buf);
|
|
195
|
+
return buf;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Read Codec-Entries
|
|
199
|
+
* @param tokenizer
|
|
200
|
+
*/
|
|
201
|
+
async function readCodecEntry(tokenizer) {
|
|
202
|
+
const type = await tokenizer.readNumber(Token.UINT16_LE);
|
|
203
|
+
return {
|
|
204
|
+
type: {
|
|
205
|
+
videoCodec: (type & 0x0001) === 0x0001,
|
|
206
|
+
audioCodec: (type & 0x0002) === 0x0002
|
|
207
|
+
},
|
|
208
|
+
codecName: await readString(tokenizer),
|
|
209
|
+
description: await readString(tokenizer),
|
|
210
|
+
information: await readInformation(tokenizer)
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 3.10 Content Description Object (optional, one only)
|
|
215
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_10
|
|
216
|
+
*/
|
|
217
|
+
class ContentDescriptionObjectState extends State {
|
|
218
|
+
constructor(header) {
|
|
219
|
+
super(header);
|
|
220
|
+
}
|
|
221
|
+
get(buf, off) {
|
|
222
|
+
const tags = [];
|
|
223
|
+
let pos = off + 10;
|
|
224
|
+
for (let i = 0; i < ContentDescriptionObjectState.contentDescTags.length; ++i) {
|
|
225
|
+
const length = buf.readUInt16LE(off + i * 2);
|
|
226
|
+
if (length > 0) {
|
|
227
|
+
const tagName = ContentDescriptionObjectState.contentDescTags[i];
|
|
228
|
+
const end = pos + length;
|
|
229
|
+
tags.push({ id: tagName, value: AsfUtil_1.AsfUtil.parseUnicodeAttr(buf.slice(pos, end)) });
|
|
230
|
+
pos = end;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return tags;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
exports.ContentDescriptionObjectState = ContentDescriptionObjectState;
|
|
237
|
+
ContentDescriptionObjectState.guid = GUID_1.default.ContentDescriptionObject;
|
|
238
|
+
ContentDescriptionObjectState.contentDescTags = ['Title', 'Author', 'Copyright', 'Description', 'Rating'];
|
|
239
|
+
/**
|
|
240
|
+
* 3.11 Extended Content Description Object (optional, one only)
|
|
241
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_11
|
|
242
|
+
*/
|
|
243
|
+
class ExtendedContentDescriptionObjectState extends State {
|
|
244
|
+
constructor(header) {
|
|
245
|
+
super(header);
|
|
246
|
+
}
|
|
247
|
+
get(buf, off) {
|
|
248
|
+
const tags = [];
|
|
249
|
+
const attrCount = buf.readUInt16LE(off);
|
|
250
|
+
let pos = off + 2;
|
|
251
|
+
for (let i = 0; i < attrCount; i += 1) {
|
|
252
|
+
const nameLen = buf.readUInt16LE(pos);
|
|
253
|
+
pos += 2;
|
|
254
|
+
const name = AsfUtil_1.AsfUtil.parseUnicodeAttr(buf.slice(pos, pos + nameLen));
|
|
255
|
+
pos += nameLen;
|
|
256
|
+
const valueType = buf.readUInt16LE(pos);
|
|
257
|
+
pos += 2;
|
|
258
|
+
const valueLen = buf.readUInt16LE(pos);
|
|
259
|
+
pos += 2;
|
|
260
|
+
const value = buf.slice(pos, pos + valueLen);
|
|
261
|
+
pos += valueLen;
|
|
262
|
+
this.postProcessTag(tags, name, valueType, value);
|
|
263
|
+
}
|
|
264
|
+
return tags;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
exports.ExtendedContentDescriptionObjectState = ExtendedContentDescriptionObjectState;
|
|
268
|
+
ExtendedContentDescriptionObjectState.guid = GUID_1.default.ExtendedContentDescriptionObject;
|
|
269
|
+
/**
|
|
270
|
+
* 4.1 Extended Stream Properties Object (optional, 1 per media stream)
|
|
271
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/04_objects_in_the_asf_header_extension_object.html#4_1
|
|
272
|
+
*/
|
|
273
|
+
class ExtendedStreamPropertiesObjectState extends State {
|
|
274
|
+
constructor(header) {
|
|
275
|
+
super(header);
|
|
276
|
+
}
|
|
277
|
+
get(buf, off) {
|
|
278
|
+
return {
|
|
279
|
+
startTime: Token.UINT64_LE.get(buf, off),
|
|
280
|
+
endTime: Token.UINT64_LE.get(buf, off + 8),
|
|
281
|
+
dataBitrate: buf.readInt32LE(off + 12),
|
|
282
|
+
bufferSize: buf.readInt32LE(off + 16),
|
|
283
|
+
initialBufferFullness: buf.readInt32LE(off + 20),
|
|
284
|
+
alternateDataBitrate: buf.readInt32LE(off + 24),
|
|
285
|
+
alternateBufferSize: buf.readInt32LE(off + 28),
|
|
286
|
+
alternateInitialBufferFullness: buf.readInt32LE(off + 32),
|
|
287
|
+
maximumObjectSize: buf.readInt32LE(off + 36),
|
|
288
|
+
flags: {
|
|
289
|
+
reliableFlag: util.getBit(buf, off + 40, 0),
|
|
290
|
+
seekableFlag: util.getBit(buf, off + 40, 1),
|
|
291
|
+
resendLiveCleanpointsFlag: util.getBit(buf, off + 40, 2)
|
|
292
|
+
},
|
|
293
|
+
// flagsNumeric: Token.UINT32_LE.get(buf, off + 64),
|
|
294
|
+
streamNumber: buf.readInt16LE(off + 42),
|
|
295
|
+
streamLanguageId: buf.readInt16LE(off + 44),
|
|
296
|
+
averageTimePerFrame: buf.readInt32LE(off + 52),
|
|
297
|
+
streamNameCount: buf.readInt32LE(off + 54),
|
|
298
|
+
payloadExtensionSystems: buf.readInt32LE(off + 56),
|
|
299
|
+
streamNames: [],
|
|
300
|
+
streamPropertiesObject: null
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
exports.ExtendedStreamPropertiesObjectState = ExtendedStreamPropertiesObjectState;
|
|
305
|
+
ExtendedStreamPropertiesObjectState.guid = GUID_1.default.ExtendedStreamPropertiesObject;
|
|
306
|
+
/**
|
|
307
|
+
* 4.7 Metadata Object (optional, 0 or 1)
|
|
308
|
+
* Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/04_objects_in_the_asf_header_extension_object.html#4_7
|
|
309
|
+
*/
|
|
310
|
+
class MetadataObjectState extends State {
|
|
311
|
+
constructor(header) {
|
|
312
|
+
super(header);
|
|
313
|
+
}
|
|
314
|
+
get(buf, off) {
|
|
315
|
+
const tags = [];
|
|
316
|
+
const descriptionRecordsCount = buf.readUInt16LE(off);
|
|
317
|
+
let pos = off + 2;
|
|
318
|
+
for (let i = 0; i < descriptionRecordsCount; i += 1) {
|
|
319
|
+
pos += 4;
|
|
320
|
+
const nameLen = buf.readUInt16LE(pos);
|
|
321
|
+
pos += 2;
|
|
322
|
+
const dataType = buf.readUInt16LE(pos);
|
|
323
|
+
pos += 2;
|
|
324
|
+
const dataLen = buf.readUInt32LE(pos);
|
|
325
|
+
pos += 4;
|
|
326
|
+
const name = AsfUtil_1.AsfUtil.parseUnicodeAttr(buf.slice(pos, pos + nameLen));
|
|
327
|
+
pos += nameLen;
|
|
328
|
+
const data = buf.slice(pos, pos + dataLen);
|
|
329
|
+
pos += dataLen;
|
|
330
|
+
const parseAttr = AsfUtil_1.AsfUtil.getParserForAttr(dataType);
|
|
331
|
+
if (!parseAttr) {
|
|
332
|
+
throw new Error('unexpected value headerType: ' + dataType);
|
|
333
|
+
}
|
|
334
|
+
this.postProcessTag(tags, name, dataType, data);
|
|
335
|
+
}
|
|
336
|
+
return tags;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
exports.MetadataObjectState = MetadataObjectState;
|
|
340
|
+
MetadataObjectState.guid = GUID_1.default.MetadataObject;
|
|
341
|
+
// 4.8 Metadata Library Object (optional, 0 or 1)
|
|
342
|
+
class MetadataLibraryObjectState extends MetadataObjectState {
|
|
343
|
+
constructor(header) {
|
|
344
|
+
super(header);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
exports.MetadataLibraryObjectState = MetadataLibraryObjectState;
|
|
348
|
+
MetadataLibraryObjectState.guid = GUID_1.default.MetadataLibraryObject;
|
|
349
|
+
/**
|
|
350
|
+
* Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd757977(v=vs.85).aspx
|
|
351
|
+
*/
|
|
352
|
+
class WmPictureToken {
|
|
353
|
+
constructor(len) {
|
|
354
|
+
this.len = len;
|
|
355
|
+
}
|
|
356
|
+
static fromBase64(base64str) {
|
|
357
|
+
return this.fromBuffer(Buffer.from(base64str, 'base64'));
|
|
358
|
+
}
|
|
359
|
+
static fromBuffer(buffer) {
|
|
360
|
+
const pic = new WmPictureToken(buffer.length);
|
|
361
|
+
return pic.get(buffer, 0);
|
|
362
|
+
}
|
|
363
|
+
get(buffer, offset) {
|
|
364
|
+
const typeId = buffer.readUInt8(offset++);
|
|
365
|
+
const size = buffer.readInt32LE(offset);
|
|
366
|
+
let index = 5;
|
|
367
|
+
while (buffer.readUInt16BE(index) !== 0) {
|
|
368
|
+
index += 2;
|
|
369
|
+
}
|
|
370
|
+
const format = buffer.slice(5, index).toString('utf16le');
|
|
371
|
+
while (buffer.readUInt16BE(index) !== 0) {
|
|
372
|
+
index += 2;
|
|
373
|
+
}
|
|
374
|
+
const description = buffer.slice(5, index).toString('utf16le');
|
|
375
|
+
return {
|
|
376
|
+
type: ID3v2Token_1.AttachedPictureType[typeId],
|
|
377
|
+
format,
|
|
378
|
+
description,
|
|
379
|
+
size,
|
|
380
|
+
data: buffer.slice(index + 4)
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
exports.WmPictureToken = WmPictureToken;
|