@remotion/media-parser 4.0.192 → 4.0.194
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/boxes.json +1 -0
- package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +21 -0
- package/dist/boxes/iso-base-media/esds/esds-descriptors.js +62 -0
- package/dist/boxes/iso-base-media/esds/esds.d.ts +15 -0
- package/dist/boxes/iso-base-media/esds/esds.js +27 -0
- package/dist/boxes/iso-base-media/esds-descriptors.d.ts +21 -0
- package/dist/boxes/iso-base-media/esds-descriptors.js +62 -0
- package/dist/boxes/iso-base-media/esds.d.ts +15 -0
- package/dist/boxes/iso-base-media/esds.js +27 -0
- package/dist/boxes/iso-base-media/mdat/mdat.d.ts +12 -0
- package/dist/boxes/iso-base-media/mdat/mdat.js +13 -0
- package/dist/boxes/iso-base-media/process-box.js +67 -0
- package/dist/boxes/iso-base-media/stsd/samples.d.ts +2 -0
- package/dist/boxes/iso-base-media/stsd/samples.js +27 -8
- package/dist/boxes/iso-base-media/stsd/stco.d.ts +14 -0
- package/dist/boxes/iso-base-media/stsd/stco.js +30 -0
- package/dist/boxes/iso-base-media/stsd/stsc.d.ts +19 -0
- package/dist/boxes/iso-base-media/stsd/stsc.js +34 -0
- package/dist/boxes/iso-base-media/stsd/stsz.d.ts +15 -0
- package/dist/boxes/iso-base-media/stsd/stsz.js +32 -0
- package/dist/boxes/webm/parse-webm-header.js +3 -3
- package/dist/boxes/webm/segments/track-entry.d.ts +20 -0
- package/dist/boxes/webm/segments/track-entry.js +37 -2
- package/dist/boxes/webm/segments.d.ts +2 -2
- package/dist/boxes/webm/segments.js +12 -0
- package/dist/buffer-iterator.d.ts +3 -1
- package/dist/buffer-iterator.js +41 -8
- package/dist/from-node.js +12 -4
- package/dist/from-web.js +12 -4
- package/dist/get-audio-codec.d.ts +4 -0
- package/dist/get-audio-codec.js +106 -0
- package/dist/get-dimensions.js +6 -2
- package/dist/get-fps.d.ts +1 -0
- package/dist/get-fps.js +34 -1
- package/dist/get-sample-positions.d.ts +12 -0
- package/dist/get-sample-positions.js +25 -0
- package/dist/get-samples.d.ts +0 -0
- package/dist/get-samples.js +1 -0
- package/dist/get-tracks.d.ts +10 -0
- package/dist/get-tracks.js +66 -0
- package/dist/get-video-codec.js +3 -0
- package/dist/has-all-info.d.ts +1 -1
- package/dist/has-all-info.js +4 -0
- package/dist/options.d.ts +7 -3
- package/dist/parse-media.js +37 -9
- package/dist/parse-result.d.ts +3 -1
- package/dist/parse-video.d.ts +1 -0
- package/dist/parse-video.js +1 -0
- package/dist/reader.d.ts +5 -1
- package/dist/traversal.d.ts +19 -0
- package/dist/traversal.js +88 -0
- package/package.json +2 -2
- package/src/boxes/iso-base-media/esds/esds-descriptors.ts +104 -0
- package/src/boxes/iso-base-media/esds/esds.ts +49 -0
- package/src/boxes/iso-base-media/process-box.ts +75 -0
- package/src/boxes/iso-base-media/stsd/samples.ts +35 -8
- package/src/boxes/webm/parse-webm-header.ts +3 -3
- package/src/boxes/webm/segments/track-entry.ts +66 -1
- package/src/boxes/webm/segments.ts +29 -1
- package/src/buffer-iterator.ts +54 -10
- package/src/from-node.ts +13 -6
- package/src/from-web.ts +14 -4
- package/src/get-audio-codec.ts +143 -0
- package/src/get-dimensions.ts +11 -4
- package/src/get-fps.ts +48 -0
- package/src/get-video-codec.ts +4 -0
- package/src/has-all-info.ts +14 -2
- package/src/options.ts +18 -3
- package/src/parse-media.ts +51 -10
- package/src/parse-result.ts +4 -1
- package/src/parse-video.ts +2 -0
- package/src/reader.ts +6 -2
- package/src/test/matroska.test.ts +6 -7
- package/src/test/parse-esds.test.ts +75 -0
- package/src/test/stream-local.test.ts +80 -3
- package/src/test/stsd.test.ts +52 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {BufferIterator} from '../../buffer-iterator';
|
|
2
2
|
import type {IsoBaseMediaBox, ParseResult} from '../../parse-result';
|
|
3
3
|
import type {BoxAndNext} from '../../parse-video';
|
|
4
|
+
import {parseEsds} from './esds/esds';
|
|
4
5
|
import {parseFtyp} from './ftyp';
|
|
5
6
|
import {parseMdhd} from './mdhd';
|
|
6
7
|
import {parseMoov} from './moov/moov';
|
|
@@ -25,6 +26,7 @@ const getChildren = ({
|
|
|
25
26
|
boxType === 'minf' ||
|
|
26
27
|
boxType === 'stbl' ||
|
|
27
28
|
boxType === 'dims' ||
|
|
29
|
+
boxType === 'wave' ||
|
|
28
30
|
boxType === 'stsb';
|
|
29
31
|
|
|
30
32
|
if (parseChildren) {
|
|
@@ -42,6 +44,10 @@ const getChildren = ({
|
|
|
42
44
|
return parsed.segments;
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
if (bytesRemainingInBox < 0) {
|
|
48
|
+
throw new Error('Box size is too big ' + JSON.stringify({boxType}));
|
|
49
|
+
}
|
|
50
|
+
|
|
45
51
|
iterator.discard(bytesRemainingInBox);
|
|
46
52
|
return [];
|
|
47
53
|
};
|
|
@@ -62,6 +68,32 @@ const processBox = ({
|
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
if (bytesRemaining < boxSize) {
|
|
71
|
+
if (bytesRemaining >= 4) {
|
|
72
|
+
const type = iterator.getByteString(4);
|
|
73
|
+
iterator.counter.decrement(4);
|
|
74
|
+
|
|
75
|
+
if (type === 'mdat') {
|
|
76
|
+
const skipTo = fileOffset + boxSize;
|
|
77
|
+
const bytesToSkip = skipTo - iterator.counter.getOffset();
|
|
78
|
+
|
|
79
|
+
// If there is a huge mdat chunk, we can skip it because we don't need it for the metadata
|
|
80
|
+
if (bytesToSkip > 1_000_000) {
|
|
81
|
+
return {
|
|
82
|
+
type: 'complete',
|
|
83
|
+
box: {
|
|
84
|
+
type: 'regular-box',
|
|
85
|
+
boxType: 'mdat',
|
|
86
|
+
children: [],
|
|
87
|
+
boxSize,
|
|
88
|
+
offset: fileOffset,
|
|
89
|
+
},
|
|
90
|
+
size: boxSize,
|
|
91
|
+
skipTo: fileOffset + boxSize,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
65
97
|
iterator.counter.decrement(iterator.counter.getOffset() - fileOffset);
|
|
66
98
|
if (allowIncompleteBoxes) {
|
|
67
99
|
return {
|
|
@@ -82,6 +114,7 @@ const processBox = ({
|
|
|
82
114
|
type: 'complete',
|
|
83
115
|
box,
|
|
84
116
|
size: boxSize,
|
|
117
|
+
skipTo: null,
|
|
85
118
|
};
|
|
86
119
|
}
|
|
87
120
|
|
|
@@ -92,6 +125,7 @@ const processBox = ({
|
|
|
92
125
|
type: 'complete',
|
|
93
126
|
box,
|
|
94
127
|
size: boxSize,
|
|
128
|
+
skipTo: null,
|
|
95
129
|
};
|
|
96
130
|
}
|
|
97
131
|
|
|
@@ -102,6 +136,7 @@ const processBox = ({
|
|
|
102
136
|
type: 'complete',
|
|
103
137
|
box,
|
|
104
138
|
size: boxSize,
|
|
139
|
+
skipTo: null,
|
|
105
140
|
};
|
|
106
141
|
}
|
|
107
142
|
|
|
@@ -112,6 +147,7 @@ const processBox = ({
|
|
|
112
147
|
type: 'complete',
|
|
113
148
|
box,
|
|
114
149
|
size: boxSize,
|
|
150
|
+
skipTo: null,
|
|
115
151
|
};
|
|
116
152
|
}
|
|
117
153
|
|
|
@@ -122,6 +158,7 @@ const processBox = ({
|
|
|
122
158
|
type: 'complete',
|
|
123
159
|
box,
|
|
124
160
|
size: boxSize,
|
|
161
|
+
skipTo: null,
|
|
125
162
|
};
|
|
126
163
|
}
|
|
127
164
|
|
|
@@ -132,6 +169,7 @@ const processBox = ({
|
|
|
132
169
|
type: 'complete',
|
|
133
170
|
box,
|
|
134
171
|
size: boxSize,
|
|
172
|
+
skipTo: null,
|
|
135
173
|
};
|
|
136
174
|
}
|
|
137
175
|
|
|
@@ -146,6 +184,7 @@ const processBox = ({
|
|
|
146
184
|
type: 'complete',
|
|
147
185
|
box,
|
|
148
186
|
size: boxSize,
|
|
187
|
+
skipTo: null,
|
|
149
188
|
};
|
|
150
189
|
}
|
|
151
190
|
|
|
@@ -160,6 +199,7 @@ const processBox = ({
|
|
|
160
199
|
type: 'complete',
|
|
161
200
|
box,
|
|
162
201
|
size: boxSize,
|
|
202
|
+
skipTo: null,
|
|
163
203
|
};
|
|
164
204
|
}
|
|
165
205
|
|
|
@@ -174,6 +214,22 @@ const processBox = ({
|
|
|
174
214
|
type: 'complete',
|
|
175
215
|
box,
|
|
176
216
|
size: boxSize,
|
|
217
|
+
skipTo: null,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (boxType === 'esds') {
|
|
222
|
+
const box = parseEsds({
|
|
223
|
+
data: iterator,
|
|
224
|
+
size: boxSize,
|
|
225
|
+
fileOffset,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
type: 'complete',
|
|
230
|
+
box,
|
|
231
|
+
size: boxSize,
|
|
232
|
+
skipTo: null,
|
|
177
233
|
};
|
|
178
234
|
}
|
|
179
235
|
|
|
@@ -196,6 +252,7 @@ const processBox = ({
|
|
|
196
252
|
offset: fileOffset,
|
|
197
253
|
},
|
|
198
254
|
size: boxSize,
|
|
255
|
+
skipTo: null,
|
|
199
256
|
};
|
|
200
257
|
};
|
|
201
258
|
|
|
@@ -237,10 +294,28 @@ export const parseBoxes = ({
|
|
|
237
294
|
initialBoxes: boxes,
|
|
238
295
|
});
|
|
239
296
|
},
|
|
297
|
+
skipTo: null,
|
|
240
298
|
};
|
|
241
299
|
}
|
|
242
300
|
|
|
243
301
|
boxes.push(result.box);
|
|
302
|
+
|
|
303
|
+
if (result.skipTo !== null) {
|
|
304
|
+
return {
|
|
305
|
+
status: 'incomplete',
|
|
306
|
+
segments: boxes,
|
|
307
|
+
continueParsing: () => {
|
|
308
|
+
return parseBoxes({
|
|
309
|
+
iterator,
|
|
310
|
+
maxBytes,
|
|
311
|
+
allowIncompleteBoxes,
|
|
312
|
+
initialBoxes: boxes,
|
|
313
|
+
});
|
|
314
|
+
},
|
|
315
|
+
skipTo: result.skipTo,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
244
319
|
iterator.discardFirstBytes();
|
|
245
320
|
}
|
|
246
321
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type {BufferIterator} from '../../../buffer-iterator';
|
|
2
|
+
import type {AnySegment} from '../../../parse-result';
|
|
3
|
+
import {parseBoxes} from '../process-box';
|
|
2
4
|
|
|
3
5
|
type SampleBase = {
|
|
4
6
|
format: string;
|
|
@@ -21,6 +23,7 @@ type AudioSample = SampleBase & {
|
|
|
21
23
|
bytesPerPacket: number | null;
|
|
22
24
|
bytesPerFrame: number | null;
|
|
23
25
|
bitsPerSample: number | null;
|
|
26
|
+
children: AnySegment[];
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
type VideoSample = SampleBase & {
|
|
@@ -164,7 +167,16 @@ export const processSample = ({
|
|
|
164
167
|
|
|
165
168
|
const bytesRemainingInBox =
|
|
166
169
|
boxSize - (iterator.counter.getOffset() - fileOffset);
|
|
167
|
-
|
|
170
|
+
const children = parseBoxes({
|
|
171
|
+
iterator,
|
|
172
|
+
allowIncompleteBoxes: false,
|
|
173
|
+
maxBytes: bytesRemainingInBox,
|
|
174
|
+
initialBoxes: [],
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (children.status === 'incomplete') {
|
|
178
|
+
throw new Error('Incomplete boxes are not allowed');
|
|
179
|
+
}
|
|
168
180
|
|
|
169
181
|
return {
|
|
170
182
|
sample: {
|
|
@@ -185,6 +197,7 @@ export const processSample = ({
|
|
|
185
197
|
bytesPerPacket: null,
|
|
186
198
|
bytesPerFrame: null,
|
|
187
199
|
bitsPerSample: null,
|
|
200
|
+
children: children.segments,
|
|
188
201
|
},
|
|
189
202
|
};
|
|
190
203
|
}
|
|
@@ -192,17 +205,29 @@ export const processSample = ({
|
|
|
192
205
|
if (version === 1) {
|
|
193
206
|
const numberOfChannels = iterator.getUint16();
|
|
194
207
|
const sampleSize = iterator.getUint16();
|
|
195
|
-
const compressionId = iterator.
|
|
208
|
+
const compressionId = iterator.getInt16();
|
|
196
209
|
const packetSize = iterator.getUint16();
|
|
197
210
|
const sampleRate = iterator.getFixedPoint1616Number();
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
const
|
|
211
|
+
|
|
212
|
+
const samplesPerPacket = iterator.getUint32();
|
|
213
|
+
|
|
214
|
+
const bytesPerPacket = iterator.getUint32();
|
|
215
|
+
const bytesPerFrame = iterator.getUint32();
|
|
216
|
+
const bytesPerSample = iterator.getUint32();
|
|
202
217
|
|
|
203
218
|
const bytesRemainingInBox =
|
|
204
219
|
boxSize - (iterator.counter.getOffset() - fileOffset);
|
|
205
|
-
|
|
220
|
+
|
|
221
|
+
const children = parseBoxes({
|
|
222
|
+
iterator,
|
|
223
|
+
allowIncompleteBoxes: false,
|
|
224
|
+
maxBytes: bytesRemainingInBox,
|
|
225
|
+
initialBoxes: [],
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
if (children.status === 'incomplete') {
|
|
229
|
+
throw new Error('Incomplete boxes are not allowed');
|
|
230
|
+
}
|
|
206
231
|
|
|
207
232
|
return {
|
|
208
233
|
sample: {
|
|
@@ -222,7 +247,8 @@ export const processSample = ({
|
|
|
222
247
|
samplesPerPacket,
|
|
223
248
|
bytesPerPacket,
|
|
224
249
|
bytesPerFrame,
|
|
225
|
-
bitsPerSample,
|
|
250
|
+
bitsPerSample: bytesPerSample,
|
|
251
|
+
children: children.segments,
|
|
226
252
|
},
|
|
227
253
|
};
|
|
228
254
|
}
|
|
@@ -245,6 +271,7 @@ export const processSample = ({
|
|
|
245
271
|
|
|
246
272
|
const bytesRemainingInBox =
|
|
247
273
|
boxSize - (iterator.counter.getOffset() - fileOffset);
|
|
274
|
+
|
|
248
275
|
iterator.discard(bytesRemainingInBox);
|
|
249
276
|
|
|
250
277
|
return {
|
|
@@ -7,12 +7,12 @@ export const parseWebm = (counter: BufferIterator): ParseResult => {
|
|
|
7
7
|
counter.discard(4);
|
|
8
8
|
const length = counter.getVint();
|
|
9
9
|
|
|
10
|
-
if (length !== 31) {
|
|
11
|
-
throw new Error(`Expected header length 31, got ${length}`);
|
|
10
|
+
if (length !== 31 && length !== 35) {
|
|
11
|
+
throw new Error(`Expected header length 31 or 25, got ${length}`);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
// Discard header for now
|
|
15
|
-
counter.discard(
|
|
15
|
+
counter.discard(length);
|
|
16
16
|
|
|
17
17
|
return {status: 'done', segments: [expectSegment(counter)]};
|
|
18
18
|
};
|
|
@@ -278,7 +278,7 @@ export type ColorSegment = {
|
|
|
278
278
|
export const parseColorSegment = (iterator: BufferIterator): ColorSegment => {
|
|
279
279
|
const length = iterator.getVint();
|
|
280
280
|
|
|
281
|
-
iterator.discard(length
|
|
281
|
+
iterator.discard(length);
|
|
282
282
|
|
|
283
283
|
return {
|
|
284
284
|
type: 'color-segment',
|
|
@@ -320,3 +320,68 @@ export const parseInterlacedSegment = (
|
|
|
320
320
|
interlaced: Boolean(interlaced),
|
|
321
321
|
};
|
|
322
322
|
};
|
|
323
|
+
|
|
324
|
+
export type CodecPrivateSegment = {
|
|
325
|
+
type: 'codec-private-segment';
|
|
326
|
+
codecPrivateData: number[];
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
export const parseCodecPrivateSegment = (
|
|
330
|
+
iterator: BufferIterator,
|
|
331
|
+
): CodecPrivateSegment => {
|
|
332
|
+
const length = iterator.getVint();
|
|
333
|
+
|
|
334
|
+
return {
|
|
335
|
+
type: 'codec-private-segment',
|
|
336
|
+
codecPrivateData: [...iterator.getSlice(length)],
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
export type Crc32Segment = {
|
|
341
|
+
type: 'crc32-segment';
|
|
342
|
+
crc32: number[];
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
export const parseCrc32Segment = (iterator: BufferIterator): Crc32Segment => {
|
|
346
|
+
const length = iterator.getVint();
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
type: 'crc32-segment',
|
|
350
|
+
crc32: [...iterator.getSlice(length)],
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
export type SegmentUUIDSegment = {
|
|
355
|
+
type: 'segment-uuid-segment';
|
|
356
|
+
segmentUUID: string;
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
export const parseSegmentUUIDSegment = (
|
|
360
|
+
iterator: BufferIterator,
|
|
361
|
+
): SegmentUUIDSegment => {
|
|
362
|
+
const length = iterator.getVint();
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
type: 'segment-uuid-segment',
|
|
366
|
+
segmentUUID: iterator.getSlice(length).toString(),
|
|
367
|
+
};
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
export type DefaultFlagSegment = {
|
|
371
|
+
type: 'default-flag-segment';
|
|
372
|
+
defaultFlag: boolean;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
export const parseDefaultFlagSegment = (
|
|
376
|
+
iterator: BufferIterator,
|
|
377
|
+
): DefaultFlagSegment => {
|
|
378
|
+
const length = iterator.getVint();
|
|
379
|
+
if (length !== 1) {
|
|
380
|
+
throw new Error('Expected default flag segment to be 1 byte');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return {
|
|
384
|
+
type: 'default-flag-segment',
|
|
385
|
+
defaultFlag: Boolean(iterator.getUint8()),
|
|
386
|
+
};
|
|
387
|
+
};
|
|
@@ -17,14 +17,18 @@ import type {TimestampScaleSegment} from './segments/timestamp-scale';
|
|
|
17
17
|
import {parseTimestampScaleSegment} from './segments/timestamp-scale';
|
|
18
18
|
import type {
|
|
19
19
|
AlphaModeSegment,
|
|
20
|
+
CodecPrivateSegment,
|
|
20
21
|
CodecSegment,
|
|
21
22
|
ColorSegment,
|
|
23
|
+
Crc32Segment,
|
|
22
24
|
DefaultDurationSegment,
|
|
25
|
+
DefaultFlagSegment,
|
|
23
26
|
FlagLacingSegment,
|
|
24
27
|
HeightSegment,
|
|
25
28
|
InterlacedSegment,
|
|
26
29
|
LanguageSegment,
|
|
27
30
|
MaxBlockAdditionId,
|
|
31
|
+
SegmentUUIDSegment,
|
|
28
32
|
TitleSegment,
|
|
29
33
|
TrackEntrySegment,
|
|
30
34
|
TrackNumberSegment,
|
|
@@ -35,14 +39,18 @@ import type {
|
|
|
35
39
|
} from './segments/track-entry';
|
|
36
40
|
import {
|
|
37
41
|
parseAlphaModeSegment,
|
|
42
|
+
parseCodecPrivateSegment,
|
|
38
43
|
parseCodecSegment,
|
|
39
44
|
parseColorSegment,
|
|
45
|
+
parseCrc32Segment,
|
|
40
46
|
parseDefaultDurationSegment,
|
|
47
|
+
parseDefaultFlagSegment,
|
|
41
48
|
parseFlagLacing,
|
|
42
49
|
parseHeightSegment,
|
|
43
50
|
parseInterlacedSegment,
|
|
44
51
|
parseLanguageSegment,
|
|
45
52
|
parseMaxBlockAdditionId,
|
|
53
|
+
parseSegmentUUIDSegment,
|
|
46
54
|
parseTitleSegment,
|
|
47
55
|
parseTrackEntry,
|
|
48
56
|
parseTrackNumber,
|
|
@@ -88,7 +96,11 @@ export type MatroskaSegment =
|
|
|
88
96
|
| MaxBlockAdditionId
|
|
89
97
|
| ColorSegment
|
|
90
98
|
| TitleSegment
|
|
91
|
-
| InterlacedSegment
|
|
99
|
+
| InterlacedSegment
|
|
100
|
+
| CodecPrivateSegment
|
|
101
|
+
| Crc32Segment
|
|
102
|
+
| SegmentUUIDSegment
|
|
103
|
+
| DefaultFlagSegment;
|
|
92
104
|
|
|
93
105
|
export const expectSegment = (iterator: BufferIterator): MatroskaSegment => {
|
|
94
106
|
const segmentId = iterator.getMatroskaSegmentId();
|
|
@@ -203,10 +215,26 @@ export const expectSegment = (iterator: BufferIterator): MatroskaSegment => {
|
|
|
203
215
|
return parseAlphaModeSegment(iterator);
|
|
204
216
|
}
|
|
205
217
|
|
|
218
|
+
if (segmentId === '0x63a2') {
|
|
219
|
+
return parseCodecPrivateSegment(iterator);
|
|
220
|
+
}
|
|
221
|
+
|
|
206
222
|
if (segmentId === '0x7ba9') {
|
|
207
223
|
return parseTitleSegment(iterator);
|
|
208
224
|
}
|
|
209
225
|
|
|
226
|
+
if (segmentId === '0xbf') {
|
|
227
|
+
return parseCrc32Segment(iterator);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (segmentId === '0x73a4') {
|
|
231
|
+
return parseSegmentUUIDSegment(iterator);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (segmentId === '0x88') {
|
|
235
|
+
return parseDefaultFlagSegment(iterator);
|
|
236
|
+
}
|
|
237
|
+
|
|
210
238
|
const length = iterator.getVint();
|
|
211
239
|
|
|
212
240
|
const bytesRemaining = iterator.byteLength() - iterator.counter.getOffset();
|
package/src/buffer-iterator.ts
CHANGED
|
@@ -48,8 +48,22 @@ const makeOffsetCounter = (): OffsetCounter => {
|
|
|
48
48
|
return new OffsetCounter(0);
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
export const getArrayBufferIterator = (
|
|
52
|
-
|
|
51
|
+
export const getArrayBufferIterator = (
|
|
52
|
+
initialData: Uint8Array,
|
|
53
|
+
maxBytes?: number,
|
|
54
|
+
) => {
|
|
55
|
+
const buf = new ArrayBuffer(initialData.byteLength, {
|
|
56
|
+
maxByteLength: maxBytes ?? 1_000_000_000,
|
|
57
|
+
});
|
|
58
|
+
if (!buf.resize) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
'`ArrayBuffer.resize` is not supported in this Runtime. Use at least Node.js 20 or Bun.',
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let data = new Uint8Array(buf);
|
|
65
|
+
data.set(initialData);
|
|
66
|
+
|
|
53
67
|
let view = new DataView(data.buffer);
|
|
54
68
|
const counter = makeOffsetCounter();
|
|
55
69
|
|
|
@@ -76,6 +90,15 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
76
90
|
);
|
|
77
91
|
};
|
|
78
92
|
|
|
93
|
+
const getPaddedFourByteNumber = () => {
|
|
94
|
+
let lastInt = 128;
|
|
95
|
+
while (((lastInt = getUint8()), lastInt === 128)) {
|
|
96
|
+
// Do nothing
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return lastInt;
|
|
100
|
+
};
|
|
101
|
+
|
|
79
102
|
const getUint32 = () => {
|
|
80
103
|
const val = view.getUint32(counter.getDiscardedOffset());
|
|
81
104
|
counter.increment(4);
|
|
@@ -83,11 +106,11 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
83
106
|
};
|
|
84
107
|
|
|
85
108
|
const addData = (newData: Uint8Array) => {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
);
|
|
89
|
-
newArray
|
|
90
|
-
newArray.set(
|
|
109
|
+
const oldLength = buf.byteLength;
|
|
110
|
+
const newLength = oldLength + newData.byteLength;
|
|
111
|
+
buf.resize(newLength);
|
|
112
|
+
const newArray = new Uint8Array(buf);
|
|
113
|
+
newArray.set(newData, oldLength);
|
|
91
114
|
data = newArray;
|
|
92
115
|
view = new DataView(data.buffer);
|
|
93
116
|
};
|
|
@@ -110,14 +133,28 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
110
133
|
|
|
111
134
|
const removeBytesRead = () => {
|
|
112
135
|
const bytesToRemove = counter.getDiscardedOffset();
|
|
136
|
+
|
|
137
|
+
// Only to this operation if it is really worth it 😇
|
|
138
|
+
if (bytesToRemove < 100_000) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
113
142
|
counter.discardBytes(bytesToRemove);
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
143
|
+
const newData = data.slice(bytesToRemove);
|
|
144
|
+
data.set(newData);
|
|
145
|
+
buf.resize(newData.byteLength);
|
|
117
146
|
view = new DataView(data.buffer);
|
|
118
147
|
};
|
|
119
148
|
|
|
149
|
+
const skipTo = (offset: number) => {
|
|
150
|
+
buf.resize(offset);
|
|
151
|
+
const currentOffset = counter.getOffset();
|
|
152
|
+
counter.increment(offset - currentOffset);
|
|
153
|
+
removeBytesRead();
|
|
154
|
+
};
|
|
155
|
+
|
|
120
156
|
return {
|
|
157
|
+
skipTo,
|
|
121
158
|
addData,
|
|
122
159
|
counter,
|
|
123
160
|
byteLength,
|
|
@@ -134,6 +171,7 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
134
171
|
const atom = getSlice(4);
|
|
135
172
|
return new TextDecoder().decode(atom);
|
|
136
173
|
},
|
|
174
|
+
getPaddedFourByteNumber,
|
|
137
175
|
getMatroskaSegmentId: () => {
|
|
138
176
|
const first = getSlice(1);
|
|
139
177
|
const firstOneString = `0x${Array.from(new Uint8Array(first))
|
|
@@ -155,6 +193,9 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
155
193
|
'0xb0',
|
|
156
194
|
'0xba',
|
|
157
195
|
'0x9a',
|
|
196
|
+
'0xe1',
|
|
197
|
+
'0xbf',
|
|
198
|
+
'0x88',
|
|
158
199
|
];
|
|
159
200
|
if (knownIdsWithOneLength.includes(firstOneString)) {
|
|
160
201
|
return firstOneString;
|
|
@@ -174,6 +215,8 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
174
215
|
'0x55ee',
|
|
175
216
|
'0x55b0',
|
|
176
217
|
'0x7ba9',
|
|
218
|
+
'0x63a2',
|
|
219
|
+
'0x73a4',
|
|
177
220
|
];
|
|
178
221
|
|
|
179
222
|
const firstTwoString = `${firstOneString}${Array.from(
|
|
@@ -267,6 +310,7 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
267
310
|
counter.increment(2);
|
|
268
311
|
return val;
|
|
269
312
|
},
|
|
313
|
+
|
|
270
314
|
getInt16: () => {
|
|
271
315
|
const val = view.getInt16(counter.getDiscardedOffset());
|
|
272
316
|
counter.increment(2);
|
package/src/from-node.ts
CHANGED
|
@@ -4,16 +4,23 @@ import {Readable} from 'stream';
|
|
|
4
4
|
import type {ReaderInterface} from './reader';
|
|
5
5
|
|
|
6
6
|
export const nodeReader: ReaderInterface = {
|
|
7
|
-
read: (src, range) => {
|
|
7
|
+
read: async (src, range) => {
|
|
8
8
|
const stream = createReadStream(src, {
|
|
9
|
-
start: range === null ? 0 : range[0],
|
|
10
|
-
end:
|
|
9
|
+
start: range === null ? 0 : typeof range === 'number' ? range : range[0],
|
|
10
|
+
end:
|
|
11
|
+
range === null
|
|
12
|
+
? Infinity
|
|
13
|
+
: typeof range === 'number'
|
|
14
|
+
? Infinity
|
|
15
|
+
: range[1],
|
|
11
16
|
});
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
const stats = await stat(src);
|
|
18
|
+
return {
|
|
19
|
+
reader: Readable.toWeb(
|
|
14
20
|
stream,
|
|
15
21
|
).getReader() as ReadableStreamDefaultReader<Uint8Array>,
|
|
16
|
-
|
|
22
|
+
contentLength: stats.size,
|
|
23
|
+
};
|
|
17
24
|
},
|
|
18
25
|
getLength: async (src) => {
|
|
19
26
|
const stats = await stat(src);
|
package/src/from-web.ts
CHANGED
|
@@ -23,17 +23,27 @@ export const webReader: ReaderInterface = {
|
|
|
23
23
|
headers:
|
|
24
24
|
range === null
|
|
25
25
|
? {}
|
|
26
|
-
:
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
: typeof range === 'number'
|
|
27
|
+
? {
|
|
28
|
+
Range: `bytes=${range}`,
|
|
29
|
+
}
|
|
30
|
+
: {
|
|
31
|
+
Range: `bytes=${`${range[0]}-${range[1]}`}`,
|
|
32
|
+
},
|
|
33
|
+
// Disable Next.js caching
|
|
34
|
+
cache: 'no-store',
|
|
29
35
|
});
|
|
30
36
|
if (!res.body) {
|
|
31
37
|
throw new Error('No body');
|
|
32
38
|
}
|
|
33
39
|
|
|
40
|
+
const length = res.headers.get('content-length');
|
|
41
|
+
|
|
42
|
+
const contentLength = length === null ? null : parseInt(length, 10);
|
|
43
|
+
|
|
34
44
|
const reader = res.body.getReader();
|
|
35
45
|
|
|
36
|
-
return reader;
|
|
46
|
+
return {reader, contentLength};
|
|
37
47
|
},
|
|
38
48
|
getLength: async (src) => {
|
|
39
49
|
const res = await fetch(src, {
|