@agentdocumentformat/cli 0.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/LICENSE +21 -0
- package/README.md +45 -0
- package/dist/adf.mjs +162 -0
- package/dist/chunks/APEv2Parser-2CNNHMXV.mjs +22 -0
- package/dist/chunks/AiffParser-7BR4RL6G.mjs +162 -0
- package/dist/chunks/App-L5L37JI5.mjs +16747 -0
- package/dist/chunks/AsfParser-VVRSLFOM.mjs +538 -0
- package/dist/chunks/DsdiffParser-CMD4AX7A.mjs +156 -0
- package/dist/chunks/DsfParser-UOGZDS2M.mjs +94 -0
- package/dist/chunks/FlacParser-HB3T3CD4.mjs +23 -0
- package/dist/chunks/MP4Parser-66HBRUSX.mjs +973 -0
- package/dist/chunks/MatroskaParser-J3HUIMEW.mjs +579 -0
- package/dist/chunks/MpegParser-YW6LIUEW.mjs +442 -0
- package/dist/chunks/MusepackParser-PAUSXP7D.mjs +252 -0
- package/dist/chunks/OggParser-NUBV3GWC.mjs +359 -0
- package/dist/chunks/WavPackParser-WQAGT7TC.mjs +171 -0
- package/dist/chunks/WaveParser-EWLQVDX4.mjs +238 -0
- package/dist/chunks/adf-schema-JRU2BTOG.mjs +62 -0
- package/dist/chunks/build-QF5W473T.mjs +60 -0
- package/dist/chunks/chatgpt-subscription-BQGWYZXE.mjs +23 -0
- package/dist/chunks/chunk-2DIECGFL.mjs +6 -0
- package/dist/chunks/chunk-2NAP2ZF7.mjs +60 -0
- package/dist/chunks/chunk-3AT7IIP7.mjs +25696 -0
- package/dist/chunks/chunk-3GNIDM53.mjs +35 -0
- package/dist/chunks/chunk-3M4ZPOA3.mjs +1477 -0
- package/dist/chunks/chunk-4MQPTCXY.mjs +510 -0
- package/dist/chunks/chunk-5PO5PKRV.mjs +366 -0
- package/dist/chunks/chunk-5QU5VY7N.mjs +52 -0
- package/dist/chunks/chunk-5W7KES6P.mjs +436 -0
- package/dist/chunks/chunk-62NE4LG4.mjs +61 -0
- package/dist/chunks/chunk-64OKE4X3.mjs +45 -0
- package/dist/chunks/chunk-6GJ4QHRI.mjs +1278 -0
- package/dist/chunks/chunk-6VQEXLE2.mjs +144 -0
- package/dist/chunks/chunk-6XUV6EK6.mjs +41 -0
- package/dist/chunks/chunk-776TSXEP.mjs +43 -0
- package/dist/chunks/chunk-7CV2SA3H.mjs +285 -0
- package/dist/chunks/chunk-7MTRVW2U.mjs +3103 -0
- package/dist/chunks/chunk-7N2R2VCG.mjs +1434 -0
- package/dist/chunks/chunk-7T2YMTWL.mjs +374 -0
- package/dist/chunks/chunk-7XYNI52E.mjs +149 -0
- package/dist/chunks/chunk-APHX6HSV.mjs +7731 -0
- package/dist/chunks/chunk-APRU6PHC.mjs +40 -0
- package/dist/chunks/chunk-AUYKRQPJ.mjs +499 -0
- package/dist/chunks/chunk-DXWDD5XJ.mjs +136 -0
- package/dist/chunks/chunk-EWL5FG4I.mjs +39 -0
- package/dist/chunks/chunk-EYX2YLJW.mjs +117 -0
- package/dist/chunks/chunk-F5ELW46V.mjs +27 -0
- package/dist/chunks/chunk-G426FACA.mjs +49 -0
- package/dist/chunks/chunk-GEKSJHIV.mjs +2472 -0
- package/dist/chunks/chunk-HBUENVQL.mjs +570 -0
- package/dist/chunks/chunk-HPVFJYXR.mjs +112 -0
- package/dist/chunks/chunk-HWLWPXQ7.mjs +721 -0
- package/dist/chunks/chunk-I2HJYHFT.mjs +665 -0
- package/dist/chunks/chunk-I3UYSITV.mjs +68 -0
- package/dist/chunks/chunk-IC4JDZCI.mjs +3864 -0
- package/dist/chunks/chunk-IHDDCZBS.mjs +112 -0
- package/dist/chunks/chunk-IIGMZHQQ.mjs +10416 -0
- package/dist/chunks/chunk-KWFOS5WC.mjs +41 -0
- package/dist/chunks/chunk-LAZIXV2F.mjs +5290 -0
- package/dist/chunks/chunk-LFMB4PAA.mjs +10814 -0
- package/dist/chunks/chunk-M2RX3S2T.mjs +49 -0
- package/dist/chunks/chunk-M3WPIJYM.mjs +65 -0
- package/dist/chunks/chunk-NBTUWMGP.mjs +263 -0
- package/dist/chunks/chunk-NGK6PVSF.mjs +2676 -0
- package/dist/chunks/chunk-NZ7JTHEO.mjs +85 -0
- package/dist/chunks/chunk-OQN33RGQ.mjs +52 -0
- package/dist/chunks/chunk-RIX34QHC.mjs +2935 -0
- package/dist/chunks/chunk-SGUTYISF.mjs +16 -0
- package/dist/chunks/chunk-SLJ5L7PY.mjs +1473 -0
- package/dist/chunks/chunk-SLUKGXKH.mjs +68 -0
- package/dist/chunks/chunk-TMT32MXT.mjs +419 -0
- package/dist/chunks/chunk-UYY5M2PB.mjs +151 -0
- package/dist/chunks/chunk-VAUOM3IN.mjs +298 -0
- package/dist/chunks/chunk-VMHTYDH4.mjs +172 -0
- package/dist/chunks/chunk-VZS54AA5.mjs +200 -0
- package/dist/chunks/chunk-WFQUVXML.mjs +295 -0
- package/dist/chunks/chunk-X34PDRUH.mjs +809 -0
- package/dist/chunks/chunk-XNPZBLYL.mjs +33 -0
- package/dist/chunks/chunk-XX7OSWTO.mjs +157 -0
- package/dist/chunks/chunk-XYTWGHFS.mjs +600 -0
- package/dist/chunks/chunk-XYV3VCIX.mjs +336 -0
- package/dist/chunks/chunk-Y5ZLKFLE.mjs +1469 -0
- package/dist/chunks/chunk-ZJKXHM4Q.mjs +230 -0
- package/dist/chunks/cli-TCMBNZF6.mjs +1030 -0
- package/dist/chunks/commands-DTEKM4ZL.mjs +20 -0
- package/dist/chunks/daemon-ZC3FZ2P4.mjs +112449 -0
- package/dist/chunks/daemon-control-WDX7PMTC.mjs +300 -0
- package/dist/chunks/daemon-token-WRSULP7G.mjs +23 -0
- package/dist/chunks/devtools-H7CI2ZVG.mjs +85 -0
- package/dist/chunks/discord-IWDQJA7A.mjs +70588 -0
- package/dist/chunks/dist-C57KYFS2.mjs +4952 -0
- package/dist/chunks/dist-I3XBAGDL.mjs +11 -0
- package/dist/chunks/email-V4Q4VJON.mjs +58679 -0
- package/dist/chunks/environment-NX277MQG.mjs +15 -0
- package/dist/chunks/grok-subscription-4PYX7TBF.mjs +19 -0
- package/dist/chunks/layout-EPJQNFAI.mjs +22 -0
- package/dist/chunks/lib-N7FCZWKH.mjs +4038 -0
- package/dist/chunks/open-OTQDGDH5.mjs +36 -0
- package/dist/chunks/parser-JVY2PWSM.mjs +19 -0
- package/dist/chunks/pipeline-executor-BHBSJX2K.mjs +19 -0
- package/dist/chunks/react-IUIDQ5LX.mjs +11 -0
- package/dist/chunks/screen-54BUTYCW.mjs +27 -0
- package/dist/chunks/slack-3L5QTDZX.mjs +8113 -0
- package/dist/chunks/store-WR7TZJZS.mjs +32 -0
- package/dist/chunks/telegram-5ISVFBV3.mjs +14918 -0
- package/dist/chunks/terminal-O5WO7C5U.mjs +48 -0
- package/dist/chunks/theme-NORU4J74.mjs +20 -0
- package/dist/chunks/themes-F2FKU7CP.mjs +23 -0
- package/dist/chunks/token-6G3HCMNX.mjs +54 -0
- package/dist/chunks/token-util-UXYSDQIW.mjs +12 -0
- package/dist/chunks/tui-ODVYUIMT.mjs +197 -0
- package/dist/chunks/welcome-XHXFV7SH.mjs +32 -0
- package/dist/chunks/whatsapp-XSAMNGPJ.mjs +85412 -0
- package/dist/chunks/xterm-headless-YF53XWXE.mjs +3353 -0
- package/package.json +53 -0
- package/resources/wasm/coreutils.LICENSE +18 -0
- package/resources/wasm/coreutils.wasm +0 -0
|
@@ -0,0 +1,973 @@
|
|
|
1
|
+
import { createRequire as __adfCreateRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __adfFileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __adfDirname } from 'node:path';
|
|
4
|
+
const require = __adfCreateRequire(import.meta.url);
|
|
5
|
+
const __filename = __adfFileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = __adfDirname(__filename);
|
|
7
|
+
import "./chunk-2DIECGFL.mjs";
|
|
8
|
+
import {
|
|
9
|
+
TrackType
|
|
10
|
+
} from "./chunk-EWL5FG4I.mjs";
|
|
11
|
+
import {
|
|
12
|
+
Genres
|
|
13
|
+
} from "./chunk-VAUOM3IN.mjs";
|
|
14
|
+
import "./chunk-DXWDD5XJ.mjs";
|
|
15
|
+
import {
|
|
16
|
+
FourCcToken
|
|
17
|
+
} from "./chunk-NBTUWMGP.mjs";
|
|
18
|
+
import {
|
|
19
|
+
getBit,
|
|
20
|
+
uint8ArrayToHex
|
|
21
|
+
} from "./chunk-XX7OSWTO.mjs";
|
|
22
|
+
import "./chunk-HBUENVQL.mjs";
|
|
23
|
+
import {
|
|
24
|
+
BasicParser,
|
|
25
|
+
FieldDecodingError,
|
|
26
|
+
INT16_BE,
|
|
27
|
+
INT24_BE,
|
|
28
|
+
INT32_BE,
|
|
29
|
+
INT8,
|
|
30
|
+
StringType,
|
|
31
|
+
UINT16_BE,
|
|
32
|
+
UINT24_BE,
|
|
33
|
+
UINT32_BE,
|
|
34
|
+
UINT64_BE,
|
|
35
|
+
UINT8,
|
|
36
|
+
Uint8ArrayType,
|
|
37
|
+
lib_exports,
|
|
38
|
+
makeUnexpectedFileContentError,
|
|
39
|
+
textDecode
|
|
40
|
+
} from "./chunk-I2HJYHFT.mjs";
|
|
41
|
+
import {
|
|
42
|
+
require_src
|
|
43
|
+
} from "./chunk-AUYKRQPJ.mjs";
|
|
44
|
+
import "./chunk-NZ7JTHEO.mjs";
|
|
45
|
+
import {
|
|
46
|
+
__toESM
|
|
47
|
+
} from "./chunk-M2RX3S2T.mjs";
|
|
48
|
+
|
|
49
|
+
// node_modules/music-metadata/lib/mp4/MP4Parser.js
|
|
50
|
+
var import_debug3 = __toESM(require_src(), 1);
|
|
51
|
+
|
|
52
|
+
// node_modules/music-metadata/lib/mp4/Atom.js
|
|
53
|
+
var import_debug2 = __toESM(require_src(), 1);
|
|
54
|
+
|
|
55
|
+
// node_modules/music-metadata/lib/mp4/AtomToken.js
|
|
56
|
+
var import_debug = __toESM(require_src(), 1);
|
|
57
|
+
var debug = (0, import_debug.default)("music-metadata:parser:MP4:atom"), Mp4ContentError = class extends makeUnexpectedFileContentError("MP4") {
|
|
58
|
+
}, Header = {
|
|
59
|
+
len: 8,
|
|
60
|
+
get: (buf, off) => {
|
|
61
|
+
let length = UINT32_BE.get(buf, off);
|
|
62
|
+
if (length < 0)
|
|
63
|
+
throw new Mp4ContentError("Invalid atom header length");
|
|
64
|
+
return {
|
|
65
|
+
length: BigInt(length),
|
|
66
|
+
name: new StringType(4, "latin1").get(buf, off + 4)
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
put: (buf, off, hdr) => (UINT32_BE.put(buf, off, Number(hdr.length)), FourCcToken.put(buf, off + 4, hdr.name))
|
|
70
|
+
}, ExtendedSize = UINT64_BE, ftyp = {
|
|
71
|
+
len: 4,
|
|
72
|
+
get: (buf, off) => ({
|
|
73
|
+
type: new StringType(4, "ascii").get(buf, off)
|
|
74
|
+
})
|
|
75
|
+
};
|
|
76
|
+
var FixedLengthAtom = class {
|
|
77
|
+
/**
|
|
78
|
+
*
|
|
79
|
+
* @param {number} len Length as specified in the size field
|
|
80
|
+
* @param {number} expLen Total length of sum of specified fields in the standard
|
|
81
|
+
* @param atomId Atom ID
|
|
82
|
+
*/
|
|
83
|
+
constructor(len, expLen, atomId) {
|
|
84
|
+
if (len < expLen)
|
|
85
|
+
throw new Mp4ContentError(`Atom ${atomId} expected to be ${expLen}, but specifies ${len} bytes long.`);
|
|
86
|
+
len > expLen && debug(`Warning: atom ${atomId} expected to be ${expLen}, but was actually ${len} bytes long.`), this.len = len;
|
|
87
|
+
}
|
|
88
|
+
}, SecondsSinceMacEpoch = {
|
|
89
|
+
len: 4,
|
|
90
|
+
get: (buf, off) => {
|
|
91
|
+
let secondsSinceUnixEpoch = UINT32_BE.get(buf, off) - 2082844800;
|
|
92
|
+
return new Date(secondsSinceUnixEpoch * 1e3);
|
|
93
|
+
}
|
|
94
|
+
}, SecondsSinceMacEpoch64 = {
|
|
95
|
+
len: 8,
|
|
96
|
+
get: (buf, off) => {
|
|
97
|
+
let secondsSinceUnixEpoch = Number(UINT64_BE.get(buf, off)) - 2082844800;
|
|
98
|
+
return new Date(secondsSinceUnixEpoch * 1e3);
|
|
99
|
+
}
|
|
100
|
+
}, MdhdAtom = class extends FixedLengthAtom {
|
|
101
|
+
constructor(len) {
|
|
102
|
+
super(len, 24, "mdhd");
|
|
103
|
+
}
|
|
104
|
+
get(buf, off) {
|
|
105
|
+
let version = UINT8.get(buf, off + 0), flags = UINT24_BE.get(buf, off + 1);
|
|
106
|
+
switch (version) {
|
|
107
|
+
case 0:
|
|
108
|
+
return {
|
|
109
|
+
version,
|
|
110
|
+
flags,
|
|
111
|
+
creationTime: SecondsSinceMacEpoch.get(buf, off + 4),
|
|
112
|
+
modificationTime: SecondsSinceMacEpoch.get(buf, off + 8),
|
|
113
|
+
timeScale: UINT32_BE.get(buf, off + 12),
|
|
114
|
+
duration: UINT32_BE.get(buf, off + 16),
|
|
115
|
+
language: UINT16_BE.get(buf, off + 20),
|
|
116
|
+
quality: UINT16_BE.get(buf, off + 22)
|
|
117
|
+
};
|
|
118
|
+
case 1:
|
|
119
|
+
return {
|
|
120
|
+
version,
|
|
121
|
+
flags,
|
|
122
|
+
creationTime: SecondsSinceMacEpoch64.get(buf, off + 4),
|
|
123
|
+
modificationTime: SecondsSinceMacEpoch64.get(buf, off + 12),
|
|
124
|
+
timeScale: UINT32_BE.get(buf, off + 20),
|
|
125
|
+
duration: Number(UINT64_BE.get(buf, off + 24)),
|
|
126
|
+
language: UINT16_BE.get(buf, off + 32),
|
|
127
|
+
quality: UINT16_BE.get(buf, off + 34)
|
|
128
|
+
};
|
|
129
|
+
default:
|
|
130
|
+
throw new FieldDecodingError("Invalid mdhd version header");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}, MvhdAtom = class extends FixedLengthAtom {
|
|
134
|
+
constructor(len) {
|
|
135
|
+
super(len, 100, "mvhd");
|
|
136
|
+
}
|
|
137
|
+
get(buf, off) {
|
|
138
|
+
let version = UINT8.get(buf, off), flags = UINT24_BE.get(buf, off + 1);
|
|
139
|
+
return version === 1 ? {
|
|
140
|
+
version,
|
|
141
|
+
flags,
|
|
142
|
+
creationTime: SecondsSinceMacEpoch64.get(buf, off + 4),
|
|
143
|
+
modificationTime: SecondsSinceMacEpoch64.get(buf, off + 12),
|
|
144
|
+
timeScale: UINT32_BE.get(buf, off + 20),
|
|
145
|
+
duration: Number(UINT64_BE.get(buf, off + 24)),
|
|
146
|
+
preferredRate: UINT32_BE.get(buf, off + 32),
|
|
147
|
+
preferredVolume: UINT16_BE.get(buf, off + 36),
|
|
148
|
+
// ignore reserved: 10 bytes
|
|
149
|
+
// ignore matrix structure: 36 bytes
|
|
150
|
+
previewTime: UINT32_BE.get(buf, off + 84),
|
|
151
|
+
previewDuration: UINT32_BE.get(buf, off + 88),
|
|
152
|
+
posterTime: UINT32_BE.get(buf, off + 92),
|
|
153
|
+
selectionTime: UINT32_BE.get(buf, off + 96),
|
|
154
|
+
selectionDuration: UINT32_BE.get(buf, off + 100),
|
|
155
|
+
currentTime: UINT32_BE.get(buf, off + 104),
|
|
156
|
+
nextTrackID: UINT32_BE.get(buf, off + 108)
|
|
157
|
+
} : {
|
|
158
|
+
version,
|
|
159
|
+
flags,
|
|
160
|
+
creationTime: SecondsSinceMacEpoch.get(buf, off + 4),
|
|
161
|
+
modificationTime: SecondsSinceMacEpoch.get(buf, off + 8),
|
|
162
|
+
timeScale: UINT32_BE.get(buf, off + 12),
|
|
163
|
+
duration: UINT32_BE.get(buf, off + 16),
|
|
164
|
+
preferredRate: UINT32_BE.get(buf, off + 20),
|
|
165
|
+
preferredVolume: UINT16_BE.get(buf, off + 24),
|
|
166
|
+
// ignore reserved: 10 bytes
|
|
167
|
+
// ignore matrix structure: 36 bytes
|
|
168
|
+
previewTime: UINT32_BE.get(buf, off + 72),
|
|
169
|
+
previewDuration: UINT32_BE.get(buf, off + 76),
|
|
170
|
+
posterTime: UINT32_BE.get(buf, off + 80),
|
|
171
|
+
selectionTime: UINT32_BE.get(buf, off + 84),
|
|
172
|
+
selectionDuration: UINT32_BE.get(buf, off + 88),
|
|
173
|
+
currentTime: UINT32_BE.get(buf, off + 92),
|
|
174
|
+
nextTrackID: UINT32_BE.get(buf, off + 96)
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}, DataAtom = class {
|
|
178
|
+
constructor(len) {
|
|
179
|
+
this.len = len;
|
|
180
|
+
}
|
|
181
|
+
get(buf, off) {
|
|
182
|
+
return {
|
|
183
|
+
type: {
|
|
184
|
+
set: UINT8.get(buf, off + 0),
|
|
185
|
+
type: UINT24_BE.get(buf, off + 1)
|
|
186
|
+
},
|
|
187
|
+
locale: UINT24_BE.get(buf, off + 4),
|
|
188
|
+
value: new Uint8ArrayType(this.len - 8).get(buf, off + 8)
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}, NameAtom = class {
|
|
192
|
+
constructor(len) {
|
|
193
|
+
this.len = len;
|
|
194
|
+
}
|
|
195
|
+
get(buf, off) {
|
|
196
|
+
return {
|
|
197
|
+
version: UINT8.get(buf, off),
|
|
198
|
+
flags: UINT24_BE.get(buf, off + 1),
|
|
199
|
+
name: new StringType(this.len - 4, "utf-8").get(buf, off + 4)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}, TrackHeaderAtom = class {
|
|
203
|
+
constructor(len) {
|
|
204
|
+
this.len = len;
|
|
205
|
+
}
|
|
206
|
+
get(buf, off) {
|
|
207
|
+
let version = UINT8.get(buf, off), flags = UINT24_BE.get(buf, off + 1);
|
|
208
|
+
switch (version) {
|
|
209
|
+
case 0:
|
|
210
|
+
return {
|
|
211
|
+
version,
|
|
212
|
+
flags,
|
|
213
|
+
creationTime: SecondsSinceMacEpoch.get(buf, off + 4),
|
|
214
|
+
modificationTime: SecondsSinceMacEpoch.get(buf, off + 8),
|
|
215
|
+
trackId: UINT32_BE.get(buf, off + 12),
|
|
216
|
+
// reserved 4 bytes
|
|
217
|
+
duration: UINT32_BE.get(buf, off + 20),
|
|
218
|
+
// reserved 8 bytes
|
|
219
|
+
layer: UINT16_BE.get(buf, off + 32),
|
|
220
|
+
alternateGroup: UINT16_BE.get(buf, off + 34),
|
|
221
|
+
volume: UINT16_BE.get(buf, off + 36)
|
|
222
|
+
// ToDo: fixed point
|
|
223
|
+
// ToDo: add remaining fields
|
|
224
|
+
};
|
|
225
|
+
case 1:
|
|
226
|
+
return {
|
|
227
|
+
version,
|
|
228
|
+
flags,
|
|
229
|
+
creationTime: SecondsSinceMacEpoch64.get(buf, off + 4),
|
|
230
|
+
modificationTime: SecondsSinceMacEpoch64.get(buf, off + 12),
|
|
231
|
+
trackId: UINT32_BE.get(buf, off + 20),
|
|
232
|
+
// reserved 4 bytes
|
|
233
|
+
duration: Number(UINT64_BE.get(buf, off + 28)),
|
|
234
|
+
// reserved 8 bytes
|
|
235
|
+
layer: UINT16_BE.get(buf, off + 44),
|
|
236
|
+
alternateGroup: UINT16_BE.get(buf, off + 46),
|
|
237
|
+
volume: UINT16_BE.get(buf, off + 48)
|
|
238
|
+
// ToDo: fixed point
|
|
239
|
+
// ToDo: add remaining fields
|
|
240
|
+
};
|
|
241
|
+
default:
|
|
242
|
+
throw new FieldDecodingError("Invalid tkhd version header");
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}, stsdHeader = {
|
|
246
|
+
len: 8,
|
|
247
|
+
get: (buf, off) => ({
|
|
248
|
+
version: UINT8.get(buf, off),
|
|
249
|
+
flags: UINT24_BE.get(buf, off + 1),
|
|
250
|
+
numberOfEntries: UINT32_BE.get(buf, off + 4)
|
|
251
|
+
})
|
|
252
|
+
}, SampleDescriptionTable = class {
|
|
253
|
+
constructor(len) {
|
|
254
|
+
this.len = len;
|
|
255
|
+
}
|
|
256
|
+
get(buf, off) {
|
|
257
|
+
let descrLen = this.len - 12;
|
|
258
|
+
return {
|
|
259
|
+
dataFormat: FourCcToken.get(buf, off),
|
|
260
|
+
dataReferenceIndex: UINT16_BE.get(buf, off + 10),
|
|
261
|
+
description: descrLen > 0 ? new Uint8ArrayType(descrLen).get(buf, off + 12) : void 0
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
}, StsdAtom = class {
|
|
265
|
+
constructor(len) {
|
|
266
|
+
this.len = len;
|
|
267
|
+
}
|
|
268
|
+
get(buf, off) {
|
|
269
|
+
let header = stsdHeader.get(buf, off);
|
|
270
|
+
off += stsdHeader.len;
|
|
271
|
+
let table = [];
|
|
272
|
+
for (let n = 0; n < header.numberOfEntries; ++n) {
|
|
273
|
+
let size = UINT32_BE.get(buf, off);
|
|
274
|
+
off += UINT32_BE.len, table.push(new SampleDescriptionTable(size - UINT32_BE.len).get(buf, off)), off += size;
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
header,
|
|
278
|
+
table
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
}, SoundSampleDescriptionVersion = {
|
|
282
|
+
len: 8,
|
|
283
|
+
get(buf, off) {
|
|
284
|
+
return {
|
|
285
|
+
version: INT16_BE.get(buf, off),
|
|
286
|
+
revision: INT16_BE.get(buf, off + 2),
|
|
287
|
+
vendor: INT32_BE.get(buf, off + 4)
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}, SoundSampleDescriptionV0 = {
|
|
291
|
+
len: 12,
|
|
292
|
+
get(buf, off) {
|
|
293
|
+
return {
|
|
294
|
+
numAudioChannels: INT16_BE.get(buf, off + 0),
|
|
295
|
+
sampleSize: INT16_BE.get(buf, off + 2),
|
|
296
|
+
compressionId: INT16_BE.get(buf, off + 4),
|
|
297
|
+
packetSize: INT16_BE.get(buf, off + 6),
|
|
298
|
+
sampleRate: UINT16_BE.get(buf, off + 8) + UINT16_BE.get(buf, off + 10) / 1e4
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
}, SimpleTableAtom = class {
|
|
302
|
+
constructor(len, token) {
|
|
303
|
+
this.len = len, this.token = token;
|
|
304
|
+
}
|
|
305
|
+
get(buf, off) {
|
|
306
|
+
let nrOfEntries = INT32_BE.get(buf, off + 4);
|
|
307
|
+
return {
|
|
308
|
+
version: INT8.get(buf, off + 0),
|
|
309
|
+
flags: INT24_BE.get(buf, off + 1),
|
|
310
|
+
numberOfEntries: nrOfEntries,
|
|
311
|
+
entries: readTokenTable(buf, this.token, off + 8, this.len - 8, nrOfEntries)
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
}, TimeToSampleToken = {
|
|
315
|
+
len: 8,
|
|
316
|
+
get(buf, off) {
|
|
317
|
+
return {
|
|
318
|
+
count: INT32_BE.get(buf, off + 0),
|
|
319
|
+
duration: INT32_BE.get(buf, off + 4)
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
}, SttsAtom = class extends SimpleTableAtom {
|
|
323
|
+
constructor(len) {
|
|
324
|
+
super(len, TimeToSampleToken);
|
|
325
|
+
}
|
|
326
|
+
}, SampleToChunkToken = {
|
|
327
|
+
len: 12,
|
|
328
|
+
get(buf, off) {
|
|
329
|
+
return {
|
|
330
|
+
firstChunk: INT32_BE.get(buf, off),
|
|
331
|
+
samplesPerChunk: INT32_BE.get(buf, off + 4),
|
|
332
|
+
sampleDescriptionId: INT32_BE.get(buf, off + 8)
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
}, StscAtom = class extends SimpleTableAtom {
|
|
336
|
+
constructor(len) {
|
|
337
|
+
super(len, SampleToChunkToken);
|
|
338
|
+
}
|
|
339
|
+
}, StszAtom = class {
|
|
340
|
+
constructor(len) {
|
|
341
|
+
this.len = len;
|
|
342
|
+
}
|
|
343
|
+
get(buf, off) {
|
|
344
|
+
let nrOfEntries = INT32_BE.get(buf, off + 8);
|
|
345
|
+
return {
|
|
346
|
+
version: INT8.get(buf, off),
|
|
347
|
+
flags: INT24_BE.get(buf, off + 1),
|
|
348
|
+
sampleSize: INT32_BE.get(buf, off + 4),
|
|
349
|
+
numberOfEntries: nrOfEntries,
|
|
350
|
+
entries: readTokenTable(buf, INT32_BE, off + 12, this.len - 12, nrOfEntries)
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
}, StcoAtom = class extends SimpleTableAtom {
|
|
354
|
+
constructor(len) {
|
|
355
|
+
super(len, INT32_BE), this.len = len;
|
|
356
|
+
}
|
|
357
|
+
}, ChapterText = class {
|
|
358
|
+
constructor(len) {
|
|
359
|
+
this.len = len;
|
|
360
|
+
}
|
|
361
|
+
get(buf, off) {
|
|
362
|
+
let titleLen = INT16_BE.get(buf, off + 0);
|
|
363
|
+
return new StringType(titleLen, "utf-8").get(buf, off + 2);
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
function readTokenTable(buf, token, off, remainingLen, numberOfEntries) {
|
|
367
|
+
if (debug(`remainingLen=${remainingLen}, numberOfEntries=${numberOfEntries} * token-len=${token.len}`), remainingLen === 0)
|
|
368
|
+
return [];
|
|
369
|
+
if (remainingLen !== numberOfEntries * token.len)
|
|
370
|
+
throw new Mp4ContentError("mismatch number-of-entries with remaining atom-length");
|
|
371
|
+
let entries = [];
|
|
372
|
+
for (let n = 0; n < numberOfEntries; ++n)
|
|
373
|
+
entries.push(token.get(buf, off)), off += token.len;
|
|
374
|
+
return entries;
|
|
375
|
+
}
|
|
376
|
+
var TrackFragmentHeaderBox = class {
|
|
377
|
+
constructor(len) {
|
|
378
|
+
this.len = len;
|
|
379
|
+
}
|
|
380
|
+
get(buf, off) {
|
|
381
|
+
let flagOffset = off + 1, header = {
|
|
382
|
+
version: INT8.get(buf, off),
|
|
383
|
+
flags: {
|
|
384
|
+
baseDataOffsetPresent: getBit(buf, flagOffset + 2, 0),
|
|
385
|
+
sampleDescriptionIndexPresent: getBit(buf, flagOffset + 2, 1),
|
|
386
|
+
defaultSampleDurationPresent: getBit(buf, flagOffset + 2, 3),
|
|
387
|
+
defaultSampleSizePresent: getBit(buf, flagOffset + 2, 4),
|
|
388
|
+
defaultSampleFlagsPresent: getBit(buf, flagOffset + 2, 5),
|
|
389
|
+
defaultDurationIsEmpty: getBit(buf, flagOffset, 0),
|
|
390
|
+
defaultBaseIsMoof: getBit(buf, flagOffset, 1)
|
|
391
|
+
},
|
|
392
|
+
trackId: UINT32_BE.get(buf, 4)
|
|
393
|
+
}, dynOffset = 8;
|
|
394
|
+
return header.flags.baseDataOffsetPresent && (header.baseDataOffset = UINT64_BE.get(buf, dynOffset), dynOffset += 8), header.flags.sampleDescriptionIndexPresent && (header.sampleDescriptionIndex = UINT32_BE.get(buf, dynOffset), dynOffset += 4), header.flags.defaultSampleDurationPresent && (header.defaultSampleDuration = UINT32_BE.get(buf, dynOffset), dynOffset += 4), header.flags.defaultSampleSizePresent && (header.defaultSampleSize = UINT32_BE.get(buf, dynOffset), dynOffset += 4), header.flags.defaultSampleFlagsPresent && (header.defaultSampleFlags = UINT32_BE.get(buf, dynOffset)), header;
|
|
395
|
+
}
|
|
396
|
+
}, TrackRunBox = class {
|
|
397
|
+
constructor(len) {
|
|
398
|
+
this.len = len;
|
|
399
|
+
}
|
|
400
|
+
get(buf, off) {
|
|
401
|
+
let flagOffset = off + 1, trun = {
|
|
402
|
+
version: INT8.get(buf, off),
|
|
403
|
+
flags: {
|
|
404
|
+
dataOffsetPresent: getBit(buf, flagOffset + 2, 0),
|
|
405
|
+
firstSampleFlagsPresent: getBit(buf, flagOffset + 2, 2),
|
|
406
|
+
sampleDurationPresent: getBit(buf, flagOffset + 1, 0),
|
|
407
|
+
sampleSizePresent: getBit(buf, flagOffset + 1, 1),
|
|
408
|
+
sampleFlagsPresent: getBit(buf, flagOffset + 1, 2),
|
|
409
|
+
sampleCompositionTimeOffsetsPresent: getBit(buf, flagOffset + 1, 3)
|
|
410
|
+
},
|
|
411
|
+
sampleCount: UINT32_BE.get(buf, off + 4),
|
|
412
|
+
samples: []
|
|
413
|
+
}, dynOffset = off + 8;
|
|
414
|
+
trun.flags.dataOffsetPresent && (trun.dataOffset = UINT32_BE.get(buf, dynOffset), dynOffset += 4), trun.flags.firstSampleFlagsPresent && (trun.firstSampleFlags = UINT32_BE.get(buf, dynOffset), dynOffset += 4);
|
|
415
|
+
for (let n = 0; n < trun.sampleCount; ++n) {
|
|
416
|
+
if (dynOffset >= this.len) {
|
|
417
|
+
debug("TrackRunBox size mismatch");
|
|
418
|
+
break;
|
|
419
|
+
}
|
|
420
|
+
let sample = {};
|
|
421
|
+
trun.flags.sampleDurationPresent && (sample.sampleDuration = UINT32_BE.get(buf, dynOffset), dynOffset += 4), trun.flags.sampleSizePresent && (sample.sampleSize = UINT32_BE.get(buf, dynOffset), dynOffset += 4), trun.flags.sampleFlagsPresent && (sample.sampleFlags = UINT32_BE.get(buf, dynOffset), dynOffset += 4), trun.flags.sampleCompositionTimeOffsetsPresent && (sample.sampleCompositionTimeOffset = UINT32_BE.get(buf, dynOffset), dynOffset += 4), trun.samples.push(sample);
|
|
422
|
+
}
|
|
423
|
+
return trun;
|
|
424
|
+
}
|
|
425
|
+
}, HandlerBox = class {
|
|
426
|
+
constructor(len) {
|
|
427
|
+
this.len = len;
|
|
428
|
+
}
|
|
429
|
+
get(buf, off) {
|
|
430
|
+
let _flagOffset = off + 1, charTypeToken = new StringType(4, "utf-8");
|
|
431
|
+
return {
|
|
432
|
+
version: INT8.get(buf, off),
|
|
433
|
+
flags: UINT24_BE.get(buf, off + 1),
|
|
434
|
+
componentType: charTypeToken.get(buf, off + 4),
|
|
435
|
+
handlerType: charTypeToken.get(buf, off + 8),
|
|
436
|
+
componentName: new StringType(this.len - 28, "utf-8").get(buf, off + 28)
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
}, ChapterTrackReferenceBox = class {
|
|
440
|
+
constructor(len) {
|
|
441
|
+
this.len = len;
|
|
442
|
+
}
|
|
443
|
+
get(buf, off) {
|
|
444
|
+
let dynOffset = 0, trackIds = [];
|
|
445
|
+
for (; dynOffset < this.len; )
|
|
446
|
+
trackIds.push(UINT32_BE.get(buf, off + dynOffset)), dynOffset += 4;
|
|
447
|
+
return trackIds;
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
// node_modules/music-metadata/lib/mp4/Atom.js
|
|
452
|
+
var debug2 = (0, import_debug2.default)("music-metadata:parser:MP4:Atom"), Atom = class _Atom {
|
|
453
|
+
static async readAtom(tokenizer, dataHandler, parent, remaining) {
|
|
454
|
+
let offset = tokenizer.position;
|
|
455
|
+
debug2(`Reading next token on offset=${offset}...`);
|
|
456
|
+
let header = await tokenizer.readToken(Header), extended = header.length === 1n;
|
|
457
|
+
extended && (header.length = await tokenizer.readToken(ExtendedSize));
|
|
458
|
+
let atomBean = new _Atom(header, extended, parent), payloadLength = atomBean.getPayloadLength(remaining);
|
|
459
|
+
return debug2(`parse atom name=${atomBean.atomPath}, extended=${atomBean.extended}, offset=${offset}, len=${atomBean.header.length}`), await atomBean.readData(tokenizer, dataHandler, payloadLength), atomBean;
|
|
460
|
+
}
|
|
461
|
+
constructor(header, extended, parent) {
|
|
462
|
+
this.header = header, this.extended = extended, this.parent = parent, this.children = [], this.atomPath = (this.parent ? `${this.parent.atomPath}.` : "") + this.header.name;
|
|
463
|
+
}
|
|
464
|
+
getHeaderLength() {
|
|
465
|
+
return this.extended ? 16 : 8;
|
|
466
|
+
}
|
|
467
|
+
getPayloadLength(remaining) {
|
|
468
|
+
return (this.header.length === 0n ? remaining : Number(this.header.length)) - this.getHeaderLength();
|
|
469
|
+
}
|
|
470
|
+
async readAtoms(tokenizer, dataHandler, size) {
|
|
471
|
+
for (; size > 0; ) {
|
|
472
|
+
let atomBean = await _Atom.readAtom(tokenizer, dataHandler, this, size);
|
|
473
|
+
this.children.push(atomBean), size -= atomBean.header.length === 0n ? size : Number(atomBean.header.length);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
async readData(tokenizer, dataHandler, remaining) {
|
|
477
|
+
switch (this.header.name) {
|
|
478
|
+
// "Container" atoms, contains nested atoms
|
|
479
|
+
case "moov":
|
|
480
|
+
// The Movie Atom: contains other atoms
|
|
481
|
+
case "udta":
|
|
482
|
+
// User defined atom
|
|
483
|
+
case "mdia":
|
|
484
|
+
// Media atom
|
|
485
|
+
case "minf":
|
|
486
|
+
// Media Information Atom
|
|
487
|
+
case "stbl":
|
|
488
|
+
// The Sample Table Atom
|
|
489
|
+
case "<id>":
|
|
490
|
+
case "ilst":
|
|
491
|
+
case "tref":
|
|
492
|
+
case "moof":
|
|
493
|
+
return this.readAtoms(tokenizer, dataHandler, this.getPayloadLength(remaining));
|
|
494
|
+
case "meta": {
|
|
495
|
+
let paddingLength = (await tokenizer.peekToken(Header)).name === "hdlr" ? 0 : 4;
|
|
496
|
+
return await tokenizer.ignore(paddingLength), this.readAtoms(tokenizer, dataHandler, this.getPayloadLength(remaining) - paddingLength);
|
|
497
|
+
}
|
|
498
|
+
default:
|
|
499
|
+
return dataHandler(this, remaining);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
// node_modules/music-metadata/lib/mp4/MP4Parser.js
|
|
505
|
+
var debug3 = (0, import_debug3.default)("music-metadata:parser:MP4"), tagFormat = "iTunes", encoderDict = {
|
|
506
|
+
raw: {
|
|
507
|
+
lossy: !1,
|
|
508
|
+
format: "raw"
|
|
509
|
+
},
|
|
510
|
+
MAC3: {
|
|
511
|
+
lossy: !0,
|
|
512
|
+
format: "MACE 3:1"
|
|
513
|
+
},
|
|
514
|
+
MAC6: {
|
|
515
|
+
lossy: !0,
|
|
516
|
+
format: "MACE 6:1"
|
|
517
|
+
},
|
|
518
|
+
ima4: {
|
|
519
|
+
lossy: !0,
|
|
520
|
+
format: "IMA 4:1"
|
|
521
|
+
},
|
|
522
|
+
ulaw: {
|
|
523
|
+
lossy: !0,
|
|
524
|
+
format: "uLaw 2:1"
|
|
525
|
+
},
|
|
526
|
+
alaw: {
|
|
527
|
+
lossy: !0,
|
|
528
|
+
format: "uLaw 2:1"
|
|
529
|
+
},
|
|
530
|
+
Qclp: {
|
|
531
|
+
lossy: !0,
|
|
532
|
+
format: "QUALCOMM PureVoice"
|
|
533
|
+
},
|
|
534
|
+
".mp3": {
|
|
535
|
+
lossy: !0,
|
|
536
|
+
format: "MPEG-1 layer 3"
|
|
537
|
+
},
|
|
538
|
+
alac: {
|
|
539
|
+
lossy: !1,
|
|
540
|
+
format: "ALAC"
|
|
541
|
+
},
|
|
542
|
+
"ac-3": {
|
|
543
|
+
lossy: !0,
|
|
544
|
+
format: "AC-3"
|
|
545
|
+
},
|
|
546
|
+
mp4a: {
|
|
547
|
+
lossy: !0,
|
|
548
|
+
format: "MPEG-4/AAC"
|
|
549
|
+
},
|
|
550
|
+
mp4s: {
|
|
551
|
+
lossy: !0,
|
|
552
|
+
format: "MP4S"
|
|
553
|
+
},
|
|
554
|
+
// Closed Captioning Media, https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-SW87
|
|
555
|
+
c608: {
|
|
556
|
+
lossy: !0,
|
|
557
|
+
format: "CEA-608"
|
|
558
|
+
},
|
|
559
|
+
c708: {
|
|
560
|
+
lossy: !0,
|
|
561
|
+
format: "CEA-708"
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
function distinct(value, index, self) {
|
|
565
|
+
return self.indexOf(value) === index;
|
|
566
|
+
}
|
|
567
|
+
var MP4Parser = class _MP4Parser extends BasicParser {
|
|
568
|
+
constructor() {
|
|
569
|
+
super(...arguments), this.tracks = /* @__PURE__ */ new Map(), this.hasVideoTrack = !1, this.hasAudioTrack = !0, this.atomParsers = {
|
|
570
|
+
/**
|
|
571
|
+
* Parse movie header (mvhd) atom
|
|
572
|
+
* Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-56313
|
|
573
|
+
*/
|
|
574
|
+
mvhd: async (len) => {
|
|
575
|
+
let mvhd = await this.tokenizer.readToken(new MvhdAtom(len));
|
|
576
|
+
this.metadata.setFormat("creationTime", mvhd.creationTime), this.metadata.setFormat("modificationTime", mvhd.modificationTime);
|
|
577
|
+
},
|
|
578
|
+
chap: async (len) => {
|
|
579
|
+
let td = this.getTrackDescription(), trackIds = [];
|
|
580
|
+
for (; len >= UINT32_BE.len; )
|
|
581
|
+
trackIds.push(await this.tokenizer.readNumber(UINT32_BE)), len -= UINT32_BE.len;
|
|
582
|
+
td.chapterList = trackIds;
|
|
583
|
+
},
|
|
584
|
+
/**
|
|
585
|
+
* Parse mdat atom.
|
|
586
|
+
* Will scan for chapters
|
|
587
|
+
*/
|
|
588
|
+
mdat: async (len) => {
|
|
589
|
+
if (this.options.includeChapters) {
|
|
590
|
+
let trackWithChapters = [...this.tracks.values()].filter((track) => track.chapterList);
|
|
591
|
+
if (trackWithChapters.length === 1) {
|
|
592
|
+
let chapterTrackIds = trackWithChapters[0].chapterList, chapterTracks = [...this.tracks.values()].filter((track) => chapterTrackIds.indexOf(track.header.trackId) !== -1);
|
|
593
|
+
if (chapterTracks.length === 1)
|
|
594
|
+
return this.parseChapterTrack(chapterTracks[0], trackWithChapters[0], len);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
await this.tokenizer.ignore(len);
|
|
598
|
+
},
|
|
599
|
+
ftyp: async (len) => {
|
|
600
|
+
let types = [];
|
|
601
|
+
for (; len > 0; ) {
|
|
602
|
+
let ftype = await this.tokenizer.readToken(ftyp);
|
|
603
|
+
len -= ftyp.len;
|
|
604
|
+
let value = ftype.type.replace(/\W/g, "");
|
|
605
|
+
value.length > 0 && types.push(value);
|
|
606
|
+
}
|
|
607
|
+
debug3(`ftyp: ${types.join("/")}`);
|
|
608
|
+
let x = types.filter(distinct).join("/");
|
|
609
|
+
this.metadata.setFormat("container", x);
|
|
610
|
+
},
|
|
611
|
+
/**
|
|
612
|
+
* Parse sample description atom
|
|
613
|
+
*/
|
|
614
|
+
stsd: async (len) => {
|
|
615
|
+
let stsd = await this.tokenizer.readToken(new StsdAtom(len)), trackDescription = this.getTrackDescription();
|
|
616
|
+
trackDescription.soundSampleDescription = stsd.table.map((dfEntry) => this.parseSoundSampleDescription(dfEntry));
|
|
617
|
+
},
|
|
618
|
+
/**
|
|
619
|
+
* Parse sample-sizes atom ('stsz')
|
|
620
|
+
*/
|
|
621
|
+
stsz: async (len) => {
|
|
622
|
+
let stsz = await this.tokenizer.readToken(new StszAtom(len)), td = this.getTrackDescription();
|
|
623
|
+
td.sampleSize = stsz.sampleSize, td.sampleSizeTable = stsz.entries;
|
|
624
|
+
},
|
|
625
|
+
date: async (len) => {
|
|
626
|
+
let date = await this.tokenizer.readToken(new StringType(len, "utf-8"));
|
|
627
|
+
await this.addTag("date", date);
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
static read_BE_Integer(array, signed) {
|
|
632
|
+
let integerType = (signed ? "INT" : "UINT") + array.length * 8 + (array.length > 1 ? "_BE" : ""), token = lib_exports[integerType];
|
|
633
|
+
if (!token)
|
|
634
|
+
throw new Mp4ContentError(`Token for integer type not found: "${integerType}"`);
|
|
635
|
+
return Number(token.get(array, 0));
|
|
636
|
+
}
|
|
637
|
+
async parse() {
|
|
638
|
+
this.hasVideoTrack = !1, this.hasAudioTrack = !0, this.tracks.clear();
|
|
639
|
+
let remainingFileSize = this.tokenizer.fileInfo.size || 0;
|
|
640
|
+
for (; !this.tokenizer.fileInfo.size || remainingFileSize > 0; ) {
|
|
641
|
+
try {
|
|
642
|
+
if ((await this.tokenizer.peekToken(Header)).name === "\0\0\0\0") {
|
|
643
|
+
let errMsg = `Error at offset=${this.tokenizer.position}: box.id=0`;
|
|
644
|
+
debug3(errMsg), this.addWarning(errMsg);
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
647
|
+
} catch (error) {
|
|
648
|
+
if (error instanceof Error) {
|
|
649
|
+
let errMsg = `Error at offset=${this.tokenizer.position}: ${error.message}`;
|
|
650
|
+
debug3(errMsg), this.addWarning(errMsg);
|
|
651
|
+
} else
|
|
652
|
+
throw error;
|
|
653
|
+
break;
|
|
654
|
+
}
|
|
655
|
+
let rootAtom = await Atom.readAtom(this.tokenizer, (atom, remaining) => this.handleAtom(atom, remaining), null, remainingFileSize);
|
|
656
|
+
remainingFileSize -= rootAtom.header.length === BigInt(0) ? remainingFileSize : Number(rootAtom.header.length);
|
|
657
|
+
}
|
|
658
|
+
let formatList = [];
|
|
659
|
+
this.tracks.forEach((track) => {
|
|
660
|
+
let trackFormats = [];
|
|
661
|
+
track.soundSampleDescription.forEach((ssd) => {
|
|
662
|
+
let streamInfo = {}, encoderInfo = encoderDict[ssd.dataFormat];
|
|
663
|
+
if (encoderInfo ? (trackFormats.push(encoderInfo.format), streamInfo.codecName = encoderInfo.format) : streamInfo.codecName = `<${ssd.dataFormat}>`, ssd.description) {
|
|
664
|
+
let { description } = ssd;
|
|
665
|
+
description.sampleRate > 0 && (streamInfo.type = TrackType.audio, streamInfo.audio = {
|
|
666
|
+
samplingFrequency: description.sampleRate,
|
|
667
|
+
bitDepth: description.sampleSize,
|
|
668
|
+
channels: description.numAudioChannels
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
this.metadata.addStreamInfo(streamInfo);
|
|
672
|
+
}), trackFormats.length >= 1 && formatList.push(trackFormats.join("/"));
|
|
673
|
+
}), formatList.length > 0 && this.metadata.setFormat("codec", formatList.filter(distinct).join("+"));
|
|
674
|
+
let audioTracks = [...this.tracks.values()].filter((track) => track.soundSampleDescription.length >= 1 && track.soundSampleDescription[0].description && track.soundSampleDescription[0].description.numAudioChannels > 0);
|
|
675
|
+
for (let audioTrack of audioTracks) {
|
|
676
|
+
if (audioTrack.media.header && audioTrack.media.header.timeScale > 0)
|
|
677
|
+
if (audioTrack.sampleRate = audioTrack.media.header.timeScale, audioTrack.media.header.duration > 0 && (debug3("Using duration defined on audio track"), audioTrack.samples = audioTrack.media.header.duration, audioTrack.duration = audioTrack.samples / audioTrack.sampleRate), audioTrack.fragments.length > 0) {
|
|
678
|
+
debug3("Calculate duration defined in track fragments");
|
|
679
|
+
let totalTimeUnits = 0;
|
|
680
|
+
audioTrack.sizeInBytes = 0;
|
|
681
|
+
for (let fragment of audioTrack.fragments)
|
|
682
|
+
for (let sample of fragment.trackRun.samples) {
|
|
683
|
+
let dur = sample.sampleDuration ?? fragment.header.defaultSampleDuration ?? 0, size = sample.sampleSize ?? fragment.header.defaultSampleSize ?? 0;
|
|
684
|
+
if (dur === 0)
|
|
685
|
+
throw new Error("Missing sampleDuration and no defaultSampleDuration in track fragment header");
|
|
686
|
+
if (size === 0)
|
|
687
|
+
throw new Error("Missing sampleSize and no defaultSampleSize in track fragment header");
|
|
688
|
+
totalTimeUnits += dur, audioTrack.sizeInBytes += size;
|
|
689
|
+
}
|
|
690
|
+
audioTrack.samples || (audioTrack.samples = totalTimeUnits), audioTrack.duration || (audioTrack.duration = totalTimeUnits / audioTrack.sampleRate);
|
|
691
|
+
} else audioTrack.sampleSizeTable.length > 0 && (audioTrack.sizeInBytes = audioTrack.sampleSizeTable.reduce((sum, n) => sum + n, 0));
|
|
692
|
+
let ssd = audioTrack.soundSampleDescription[0];
|
|
693
|
+
if (ssd.description && audioTrack.media.header && (this.metadata.setFormat("sampleRate", ssd.description.sampleRate), this.metadata.setFormat("bitsPerSample", ssd.description.sampleSize), this.metadata.setFormat("numberOfChannels", ssd.description.numAudioChannels), audioTrack.media.header.timeScale === 0 && audioTrack.timeToSampleTable.length > 0)) {
|
|
694
|
+
let totalSampleSize = audioTrack.timeToSampleTable.map((ttstEntry) => ttstEntry.count * ttstEntry.duration).reduce((total, sampleSize) => total + sampleSize);
|
|
695
|
+
audioTrack.duration = totalSampleSize / ssd.description.sampleRate;
|
|
696
|
+
}
|
|
697
|
+
let encoderInfo = encoderDict[ssd.dataFormat];
|
|
698
|
+
encoderInfo && this.metadata.setFormat("lossless", !encoderInfo.lossy);
|
|
699
|
+
}
|
|
700
|
+
if (audioTracks.length >= 1) {
|
|
701
|
+
let firstAudioTrack = audioTracks[0];
|
|
702
|
+
firstAudioTrack.duration && (this.metadata.setFormat("duration", firstAudioTrack.duration), firstAudioTrack.sizeInBytes && this.metadata.setFormat("bitrate", 8 * firstAudioTrack.sizeInBytes / firstAudioTrack.duration));
|
|
703
|
+
}
|
|
704
|
+
this.metadata.setFormat("hasAudio", this.hasAudioTrack), this.metadata.setFormat("hasVideo", this.hasVideoTrack);
|
|
705
|
+
}
|
|
706
|
+
async handleAtom(atom, remaining) {
|
|
707
|
+
if (atom.parent)
|
|
708
|
+
switch (atom.parent.header.name) {
|
|
709
|
+
case "ilst":
|
|
710
|
+
case "<id>":
|
|
711
|
+
return this.parseMetadataItemData(atom);
|
|
712
|
+
case "moov":
|
|
713
|
+
switch (atom.header.name) {
|
|
714
|
+
case "trak":
|
|
715
|
+
return this.parseTrackBox(atom);
|
|
716
|
+
case "udta":
|
|
717
|
+
return this.parseTrackBox(atom);
|
|
718
|
+
}
|
|
719
|
+
break;
|
|
720
|
+
case "moof":
|
|
721
|
+
if (atom.header.name === "traf")
|
|
722
|
+
return this.parseTrackFragmentBox(atom);
|
|
723
|
+
}
|
|
724
|
+
if (this.atomParsers[atom.header.name])
|
|
725
|
+
return this.atomParsers[atom.header.name](remaining);
|
|
726
|
+
debug3(`No parser for atom path=${atom.atomPath}, payload-len=${remaining}, ignoring atom`), await this.tokenizer.ignore(remaining);
|
|
727
|
+
}
|
|
728
|
+
getTrackDescription() {
|
|
729
|
+
let tracks = [...this.tracks.values()];
|
|
730
|
+
return tracks[tracks.length - 1];
|
|
731
|
+
}
|
|
732
|
+
async addTag(id, value) {
|
|
733
|
+
await this.metadata.addTag(tagFormat, id, value);
|
|
734
|
+
}
|
|
735
|
+
addWarning(message) {
|
|
736
|
+
debug3(`Warning: ${message}`), this.metadata.addWarning(message);
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Parse data of Meta-item-list-atom (item of 'ilst' atom)
|
|
740
|
+
* @param metaAtom
|
|
741
|
+
* Ref: https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW8
|
|
742
|
+
*/
|
|
743
|
+
parseMetadataItemData(metaAtom) {
|
|
744
|
+
let tagKey = metaAtom.header.name;
|
|
745
|
+
return metaAtom.readAtoms(this.tokenizer, async (child, remaining) => {
|
|
746
|
+
let payLoadLength = child.getPayloadLength(remaining);
|
|
747
|
+
switch (child.header.name) {
|
|
748
|
+
case "data":
|
|
749
|
+
return this.parseValueAtom(tagKey, child);
|
|
750
|
+
case "name":
|
|
751
|
+
// name atom (optional)
|
|
752
|
+
case "mean":
|
|
753
|
+
case "rate": {
|
|
754
|
+
let name = await this.tokenizer.readToken(new NameAtom(payLoadLength));
|
|
755
|
+
tagKey += `:${name.name}`;
|
|
756
|
+
break;
|
|
757
|
+
}
|
|
758
|
+
default: {
|
|
759
|
+
let uint8Array = await this.tokenizer.readToken(new Uint8ArrayType(payLoadLength));
|
|
760
|
+
this.addWarning(`Unsupported meta-item: ${tagKey}[${child.header.name}] => value=${uint8ArrayToHex(uint8Array)} ascii=${textDecode(uint8Array, "ascii")}`);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}, metaAtom.getPayloadLength(0));
|
|
764
|
+
}
|
|
765
|
+
async parseValueAtom(tagKey, metaAtom) {
|
|
766
|
+
let dataAtom = await this.tokenizer.readToken(new DataAtom(Number(metaAtom.header.length) - Header.len));
|
|
767
|
+
if (dataAtom.type.set !== 0)
|
|
768
|
+
throw new Mp4ContentError(`Unsupported type-set != 0: ${dataAtom.type.set}`);
|
|
769
|
+
switch (dataAtom.type.type) {
|
|
770
|
+
case 0:
|
|
771
|
+
switch (tagKey) {
|
|
772
|
+
case "trkn":
|
|
773
|
+
case "disk": {
|
|
774
|
+
let num = UINT8.get(dataAtom.value, 3), of = UINT8.get(dataAtom.value, 5);
|
|
775
|
+
await this.addTag(tagKey, `${num}/${of}`);
|
|
776
|
+
break;
|
|
777
|
+
}
|
|
778
|
+
case "gnre": {
|
|
779
|
+
let genreInt = UINT8.get(dataAtom.value, 1), genreStr = Genres[genreInt - 1];
|
|
780
|
+
await this.addTag(tagKey, genreStr);
|
|
781
|
+
break;
|
|
782
|
+
}
|
|
783
|
+
case "rate": {
|
|
784
|
+
let rate = textDecode(dataAtom.value, "ascii");
|
|
785
|
+
await this.addTag(tagKey, rate);
|
|
786
|
+
break;
|
|
787
|
+
}
|
|
788
|
+
default:
|
|
789
|
+
debug3(`unknown proprietary value type for: ${metaAtom.atomPath}`);
|
|
790
|
+
}
|
|
791
|
+
break;
|
|
792
|
+
case 1:
|
|
793
|
+
// UTF-8: Without any count or NULL terminator
|
|
794
|
+
case 18:
|
|
795
|
+
await this.addTag(tagKey, textDecode(dataAtom.value));
|
|
796
|
+
break;
|
|
797
|
+
case 13:
|
|
798
|
+
if (this.options.skipCovers)
|
|
799
|
+
break;
|
|
800
|
+
await this.addTag(tagKey, {
|
|
801
|
+
format: "image/jpeg",
|
|
802
|
+
data: Uint8Array.from(dataAtom.value)
|
|
803
|
+
});
|
|
804
|
+
break;
|
|
805
|
+
case 14:
|
|
806
|
+
if (this.options.skipCovers)
|
|
807
|
+
break;
|
|
808
|
+
await this.addTag(tagKey, {
|
|
809
|
+
format: "image/png",
|
|
810
|
+
data: Uint8Array.from(dataAtom.value)
|
|
811
|
+
});
|
|
812
|
+
break;
|
|
813
|
+
case 21:
|
|
814
|
+
await this.addTag(tagKey, _MP4Parser.read_BE_Integer(dataAtom.value, !0));
|
|
815
|
+
break;
|
|
816
|
+
case 22:
|
|
817
|
+
await this.addTag(tagKey, _MP4Parser.read_BE_Integer(dataAtom.value, !1));
|
|
818
|
+
break;
|
|
819
|
+
case 65:
|
|
820
|
+
await this.addTag(tagKey, UINT8.get(dataAtom.value, 0));
|
|
821
|
+
break;
|
|
822
|
+
case 66:
|
|
823
|
+
await this.addTag(tagKey, UINT16_BE.get(dataAtom.value, 0));
|
|
824
|
+
break;
|
|
825
|
+
case 67:
|
|
826
|
+
await this.addTag(tagKey, UINT32_BE.get(dataAtom.value, 0));
|
|
827
|
+
break;
|
|
828
|
+
default:
|
|
829
|
+
this.addWarning(`atom key=${tagKey}, has unknown well-known-type (data-type): ${dataAtom.type.type}`);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
async parseTrackBox(trakBox) {
|
|
833
|
+
let track = {
|
|
834
|
+
media: {},
|
|
835
|
+
fragments: []
|
|
836
|
+
};
|
|
837
|
+
await trakBox.readAtoms(this.tokenizer, async (child, remaining) => {
|
|
838
|
+
let payLoadLength = child.getPayloadLength(remaining);
|
|
839
|
+
switch (child.header.name) {
|
|
840
|
+
case "chap": {
|
|
841
|
+
let chap = await this.tokenizer.readToken(new ChapterTrackReferenceBox(remaining));
|
|
842
|
+
track.chapterList = chap;
|
|
843
|
+
break;
|
|
844
|
+
}
|
|
845
|
+
case "tkhd":
|
|
846
|
+
track.header = await this.tokenizer.readToken(new TrackHeaderAtom(payLoadLength));
|
|
847
|
+
break;
|
|
848
|
+
case "hdlr":
|
|
849
|
+
track.handler = await this.tokenizer.readToken(new HandlerBox(payLoadLength)), track.isAudio = () => track.handler.handlerType === "audi" || track.handler.handlerType === "soun", track.isVideo = () => track.handler.handlerType === "vide", track.isAudio() ? this.hasAudioTrack = !0 : track.isVideo() && (this.hasVideoTrack = !0);
|
|
850
|
+
break;
|
|
851
|
+
case "mdhd": {
|
|
852
|
+
let mdhd_data = await this.tokenizer.readToken(new MdhdAtom(payLoadLength));
|
|
853
|
+
track.media.header = mdhd_data;
|
|
854
|
+
break;
|
|
855
|
+
}
|
|
856
|
+
case "stco": {
|
|
857
|
+
let stco = await this.tokenizer.readToken(new StcoAtom(payLoadLength));
|
|
858
|
+
track.chunkOffsetTable = stco.entries;
|
|
859
|
+
break;
|
|
860
|
+
}
|
|
861
|
+
case "stsc": {
|
|
862
|
+
let stsc = await this.tokenizer.readToken(new StscAtom(payLoadLength));
|
|
863
|
+
track.sampleToChunkTable = stsc.entries;
|
|
864
|
+
break;
|
|
865
|
+
}
|
|
866
|
+
case "stsd": {
|
|
867
|
+
let stsd = await this.tokenizer.readToken(new StsdAtom(payLoadLength));
|
|
868
|
+
track.soundSampleDescription = stsd.table.map((dfEntry) => this.parseSoundSampleDescription(dfEntry));
|
|
869
|
+
break;
|
|
870
|
+
}
|
|
871
|
+
case "stts": {
|
|
872
|
+
let stts = await this.tokenizer.readToken(new SttsAtom(payLoadLength));
|
|
873
|
+
track.timeToSampleTable = stts.entries;
|
|
874
|
+
break;
|
|
875
|
+
}
|
|
876
|
+
case "stsz": {
|
|
877
|
+
let stsz = await this.tokenizer.readToken(new StszAtom(payLoadLength));
|
|
878
|
+
track.sampleSize = stsz.sampleSize, track.sampleSizeTable = stsz.entries;
|
|
879
|
+
break;
|
|
880
|
+
}
|
|
881
|
+
case "dinf":
|
|
882
|
+
case "vmhd":
|
|
883
|
+
case "smhd":
|
|
884
|
+
debug3(`Ignoring: ${child.header.name}`), await this.tokenizer.ignore(payLoadLength);
|
|
885
|
+
break;
|
|
886
|
+
default:
|
|
887
|
+
debug3(`Unexpected track box: ${child.header.name}`), await this.tokenizer.ignore(payLoadLength);
|
|
888
|
+
}
|
|
889
|
+
}, trakBox.getPayloadLength(0)), this.tracks.set(track.header.trackId, track);
|
|
890
|
+
}
|
|
891
|
+
parseTrackFragmentBox(trafBox) {
|
|
892
|
+
let tfhd;
|
|
893
|
+
return trafBox.readAtoms(this.tokenizer, async (child, remaining) => {
|
|
894
|
+
let payLoadLength = child.getPayloadLength(remaining);
|
|
895
|
+
switch (child.header.name) {
|
|
896
|
+
case "tfhd": {
|
|
897
|
+
let fragmentHeaderBox = new TrackFragmentHeaderBox(child.getPayloadLength(remaining));
|
|
898
|
+
tfhd = await this.tokenizer.readToken(fragmentHeaderBox);
|
|
899
|
+
break;
|
|
900
|
+
}
|
|
901
|
+
case "tfdt":
|
|
902
|
+
await this.tokenizer.ignore(payLoadLength);
|
|
903
|
+
break;
|
|
904
|
+
case "trun": {
|
|
905
|
+
let trackRunBox = new TrackRunBox(payLoadLength), trun = await this.tokenizer.readToken(trackRunBox);
|
|
906
|
+
tfhd && this.tracks.get(tfhd.trackId)?.fragments.push({ header: tfhd, trackRun: trun });
|
|
907
|
+
break;
|
|
908
|
+
}
|
|
909
|
+
default:
|
|
910
|
+
debug3(`Unexpected box: ${child.header.name}`), await this.tokenizer.ignore(payLoadLength);
|
|
911
|
+
}
|
|
912
|
+
}, trafBox.getPayloadLength(0));
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* @param sampleDescription
|
|
916
|
+
* Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-128916
|
|
917
|
+
*/
|
|
918
|
+
parseSoundSampleDescription(sampleDescription) {
|
|
919
|
+
let ssd = {
|
|
920
|
+
dataFormat: sampleDescription.dataFormat,
|
|
921
|
+
dataReferenceIndex: sampleDescription.dataReferenceIndex
|
|
922
|
+
}, offset = 0;
|
|
923
|
+
if (sampleDescription.description) {
|
|
924
|
+
let version = SoundSampleDescriptionVersion.get(sampleDescription.description, offset);
|
|
925
|
+
offset += SoundSampleDescriptionVersion.len, version.version === 0 || version.version === 1 ? ssd.description = SoundSampleDescriptionV0.get(sampleDescription.description, offset) : debug3(`Warning: sound-sample-description ${version} not implemented`);
|
|
926
|
+
}
|
|
927
|
+
return ssd;
|
|
928
|
+
}
|
|
929
|
+
async parseChapterTrack(chapterTrack, track, len) {
|
|
930
|
+
if (!chapterTrack.sampleSize && chapterTrack.chunkOffsetTable.length !== chapterTrack.sampleSizeTable.length)
|
|
931
|
+
throw new Error("Expected equal chunk-offset-table & sample-size-table length.");
|
|
932
|
+
let chapters = [];
|
|
933
|
+
for (let i = 0; i < chapterTrack.chunkOffsetTable.length && len > 0; ++i) {
|
|
934
|
+
let start = chapterTrack.timeToSampleTable.slice(0, i).reduce((acc, cur) => acc + cur.duration, 0), nextChunkLen = chapterTrack.chunkOffsetTable[i] - this.tokenizer.position, sampleSize = chapterTrack.sampleSize > 0 ? chapterTrack.sampleSize : chapterTrack.sampleSizeTable[i];
|
|
935
|
+
if (len -= nextChunkLen + sampleSize, len < 0)
|
|
936
|
+
throw new Mp4ContentError("Chapter chunk exceeding token length");
|
|
937
|
+
await this.tokenizer.ignore(nextChunkLen);
|
|
938
|
+
let title = await this.tokenizer.readToken(new ChapterText(sampleSize));
|
|
939
|
+
debug3(`Chapter ${i + 1}: ${title}`);
|
|
940
|
+
let chapter = {
|
|
941
|
+
title,
|
|
942
|
+
timeScale: chapterTrack.media.header ? chapterTrack.media.header.timeScale : 0,
|
|
943
|
+
start,
|
|
944
|
+
sampleOffset: this.findSampleOffset(track, this.tokenizer.position)
|
|
945
|
+
};
|
|
946
|
+
debug3(`Chapter title=${chapter.title}, offset=${chapter.sampleOffset}/${track.header.duration}`), chapters.push(chapter);
|
|
947
|
+
}
|
|
948
|
+
this.metadata.setFormat("chapters", chapters), await this.tokenizer.ignore(len);
|
|
949
|
+
}
|
|
950
|
+
findSampleOffset(track, chapterOffset) {
|
|
951
|
+
let chunkIndex = 0;
|
|
952
|
+
for (; chunkIndex < track.chunkOffsetTable.length && track.chunkOffsetTable[chunkIndex] < chapterOffset; )
|
|
953
|
+
++chunkIndex;
|
|
954
|
+
return this.getChunkDuration(chunkIndex + 1, track);
|
|
955
|
+
}
|
|
956
|
+
getChunkDuration(chunkId, track) {
|
|
957
|
+
let ttsi = 0, ttsc = track.timeToSampleTable[ttsi].count, ttsd = track.timeToSampleTable[ttsi].duration, curChunkId = 1, samplesPerChunk = this.getSamplesPerChunk(curChunkId, track.sampleToChunkTable), totalDuration = 0;
|
|
958
|
+
for (; curChunkId < chunkId; ) {
|
|
959
|
+
let nrOfSamples = Math.min(ttsc, samplesPerChunk);
|
|
960
|
+
totalDuration += nrOfSamples * ttsd, ttsc -= nrOfSamples, samplesPerChunk -= nrOfSamples, samplesPerChunk === 0 ? (++curChunkId, samplesPerChunk = this.getSamplesPerChunk(curChunkId, track.sampleToChunkTable)) : (++ttsi, ttsc = track.timeToSampleTable[ttsi].count, ttsd = track.timeToSampleTable[ttsi].duration);
|
|
961
|
+
}
|
|
962
|
+
return totalDuration;
|
|
963
|
+
}
|
|
964
|
+
getSamplesPerChunk(chunkId, stcTable) {
|
|
965
|
+
for (let i = 0; i < stcTable.length - 1; ++i)
|
|
966
|
+
if (chunkId >= stcTable[i].firstChunk && chunkId < stcTable[i + 1].firstChunk)
|
|
967
|
+
return stcTable[i].samplesPerChunk;
|
|
968
|
+
return stcTable[stcTable.length - 1].samplesPerChunk;
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
export {
|
|
972
|
+
MP4Parser
|
|
973
|
+
};
|