@remotion/media-parser 4.0.191 → 4.0.193
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/ftype.d.ts +9 -0
- package/dist/boxes/iso-base-media/ftype.js +31 -0
- package/dist/boxes/iso-base-media/mdhd.d.ts +14 -0
- package/dist/boxes/iso-base-media/mdhd.js +33 -0
- package/dist/boxes/iso-base-media/process-box.js +30 -0
- package/dist/boxes/iso-base-media/stsd/samples.d.ts +2 -0
- package/dist/boxes/iso-base-media/stsd/samples.js +28 -8
- package/dist/boxes/webm/parse-webm-header.js +4 -4
- package/dist/boxes/webm/segments/track-entry.d.ts +30 -0
- package/dist/boxes/webm/segments/track-entry.js +59 -8
- package/dist/boxes/webm/segments.d.ts +2 -2
- package/dist/boxes/webm/segments.js +18 -0
- package/dist/buffer-iterator.d.ts +2 -1
- package/dist/buffer-iterator.js +29 -8
- package/dist/from-node.js +6 -2
- package/dist/from-web.js +6 -1
- 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 +8 -0
- package/dist/get-fps.js +117 -9
- package/dist/get-video-codec.d.ts +4 -0
- package/dist/get-video-codec.js +79 -0
- package/dist/get-video-metadata.d.ts +2 -0
- package/dist/get-video-metadata.js +44 -0
- package/dist/has-all-info.d.ts +1 -1
- package/dist/has-all-info.js +8 -0
- package/dist/options.d.ts +11 -3
- package/dist/parse-media.js +27 -6
- package/dist/parse-result.d.ts +3 -1
- package/dist/read-and-increment-offset.d.ts +28 -0
- package/dist/read-and-increment-offset.js +177 -0
- package/dist/reader.d.ts +5 -1
- 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/mdhd.ts +56 -0
- package/src/boxes/iso-base-media/process-box.ts +35 -0
- package/src/boxes/iso-base-media/stsd/samples.ts +36 -8
- package/src/boxes/webm/parse-webm-header.ts +4 -4
- package/src/boxes/webm/segments/track-entry.ts +103 -11
- package/src/boxes/webm/segments.ts +43 -1
- package/src/buffer-iterator.ts +36 -10
- package/src/from-node.ts +6 -4
- package/src/from-web.ts +8 -1
- package/src/get-audio-codec.ts +143 -0
- package/src/get-dimensions.ts +11 -4
- package/src/get-fps.ts +175 -9
- package/src/get-video-codec.ts +104 -0
- package/src/has-all-info.ts +19 -2
- package/src/options.ts +43 -3
- package/src/parse-media.ts +35 -7
- package/src/parse-result.ts +5 -1
- package/src/reader.ts +5 -1
- package/src/test/matroska.test.ts +6 -7
- package/src/test/parse-esds.test.ts +75 -0
- package/src/test/parse-webm.test.ts +2 -0
- package/src/test/stream-local.test.ts +93 -5
- package/src/test/stream-remote.test.ts +41 -0
- package/src/test/stsd.test.ts +52 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -5,14 +5,14 @@ import {expectSegment} from './segments';
|
|
|
5
5
|
// Parsing according to https://darkcoding.net/software/reading-mediarecorders-webm-opus-output/
|
|
6
6
|
export const parseWebm = (counter: BufferIterator): ParseResult => {
|
|
7
7
|
counter.discard(4);
|
|
8
|
-
const length = counter.
|
|
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
|
};
|
|
@@ -51,10 +51,6 @@ export type TrackUIDSegment = {
|
|
|
51
51
|
|
|
52
52
|
export const parseTrackUID = (iterator: BufferIterator): TrackUIDSegment => {
|
|
53
53
|
const length = iterator.getVint();
|
|
54
|
-
// Observation: AV1 has 8 bytes, WebM has 7
|
|
55
|
-
if (length !== 8 && length !== 7) {
|
|
56
|
-
throw new Error('Expected track number to be 8 byte');
|
|
57
|
-
}
|
|
58
54
|
|
|
59
55
|
const bytes = iterator.getSlice(length);
|
|
60
56
|
|
|
@@ -187,16 +183,11 @@ export type VideoSegment = {
|
|
|
187
183
|
};
|
|
188
184
|
|
|
189
185
|
export const parseVideoSegment = (iterator: BufferIterator): VideoSegment => {
|
|
190
|
-
const offset = iterator.counter.getOffset();
|
|
191
|
-
|
|
192
186
|
const length = iterator.getVint();
|
|
193
187
|
|
|
194
188
|
return {
|
|
195
189
|
type: 'video-segment',
|
|
196
|
-
children: expectChildren(
|
|
197
|
-
iterator,
|
|
198
|
-
length - (iterator.counter.getOffset() - offset),
|
|
199
|
-
),
|
|
190
|
+
children: expectChildren(iterator, length),
|
|
200
191
|
};
|
|
201
192
|
};
|
|
202
193
|
|
|
@@ -287,9 +278,110 @@ export type ColorSegment = {
|
|
|
287
278
|
export const parseColorSegment = (iterator: BufferIterator): ColorSegment => {
|
|
288
279
|
const length = iterator.getVint();
|
|
289
280
|
|
|
290
|
-
iterator.discard(length
|
|
281
|
+
iterator.discard(length);
|
|
291
282
|
|
|
292
283
|
return {
|
|
293
284
|
type: 'color-segment',
|
|
294
285
|
};
|
|
295
286
|
};
|
|
287
|
+
|
|
288
|
+
export type TitleSegment = {
|
|
289
|
+
type: 'title-segment';
|
|
290
|
+
title: string;
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
export const parseTitleSegment = (iterator: BufferIterator): TitleSegment => {
|
|
294
|
+
const length = iterator.getVint();
|
|
295
|
+
const title = iterator.getByteString(length);
|
|
296
|
+
|
|
297
|
+
return {
|
|
298
|
+
type: 'title-segment',
|
|
299
|
+
title,
|
|
300
|
+
};
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
export type InterlacedSegment = {
|
|
304
|
+
type: 'interlaced-segment';
|
|
305
|
+
interlaced: boolean;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export const parseInterlacedSegment = (
|
|
309
|
+
iterator: BufferIterator,
|
|
310
|
+
): InterlacedSegment => {
|
|
311
|
+
const length = iterator.getVint();
|
|
312
|
+
if (length !== 1) {
|
|
313
|
+
throw new Error('Expected interlaced segment to be 1 byte');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const interlaced = iterator.getUint8();
|
|
317
|
+
|
|
318
|
+
return {
|
|
319
|
+
type: 'interlaced-segment',
|
|
320
|
+
interlaced: Boolean(interlaced),
|
|
321
|
+
};
|
|
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,13 +17,19 @@ 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,
|
|
28
|
+
InterlacedSegment,
|
|
25
29
|
LanguageSegment,
|
|
26
30
|
MaxBlockAdditionId,
|
|
31
|
+
SegmentUUIDSegment,
|
|
32
|
+
TitleSegment,
|
|
27
33
|
TrackEntrySegment,
|
|
28
34
|
TrackNumberSegment,
|
|
29
35
|
TrackTypeSegment,
|
|
@@ -33,13 +39,19 @@ import type {
|
|
|
33
39
|
} from './segments/track-entry';
|
|
34
40
|
import {
|
|
35
41
|
parseAlphaModeSegment,
|
|
42
|
+
parseCodecPrivateSegment,
|
|
36
43
|
parseCodecSegment,
|
|
37
44
|
parseColorSegment,
|
|
45
|
+
parseCrc32Segment,
|
|
38
46
|
parseDefaultDurationSegment,
|
|
47
|
+
parseDefaultFlagSegment,
|
|
39
48
|
parseFlagLacing,
|
|
40
49
|
parseHeightSegment,
|
|
50
|
+
parseInterlacedSegment,
|
|
41
51
|
parseLanguageSegment,
|
|
42
52
|
parseMaxBlockAdditionId,
|
|
53
|
+
parseSegmentUUIDSegment,
|
|
54
|
+
parseTitleSegment,
|
|
43
55
|
parseTrackEntry,
|
|
44
56
|
parseTrackNumber,
|
|
45
57
|
parseTrackTypeSegment,
|
|
@@ -82,7 +94,13 @@ export type MatroskaSegment =
|
|
|
82
94
|
| HeightSegment
|
|
83
95
|
| AlphaModeSegment
|
|
84
96
|
| MaxBlockAdditionId
|
|
85
|
-
| ColorSegment
|
|
97
|
+
| ColorSegment
|
|
98
|
+
| TitleSegment
|
|
99
|
+
| InterlacedSegment
|
|
100
|
+
| CodecPrivateSegment
|
|
101
|
+
| Crc32Segment
|
|
102
|
+
| SegmentUUIDSegment
|
|
103
|
+
| DefaultFlagSegment;
|
|
86
104
|
|
|
87
105
|
export const expectSegment = (iterator: BufferIterator): MatroskaSegment => {
|
|
88
106
|
const segmentId = iterator.getMatroskaSegmentId();
|
|
@@ -189,10 +207,34 @@ export const expectSegment = (iterator: BufferIterator): MatroskaSegment => {
|
|
|
189
207
|
return parseHeightSegment(iterator);
|
|
190
208
|
}
|
|
191
209
|
|
|
210
|
+
if (segmentId === '0x9a') {
|
|
211
|
+
return parseInterlacedSegment(iterator);
|
|
212
|
+
}
|
|
213
|
+
|
|
192
214
|
if (segmentId === '0x53c0') {
|
|
193
215
|
return parseAlphaModeSegment(iterator);
|
|
194
216
|
}
|
|
195
217
|
|
|
218
|
+
if (segmentId === '0x63a2') {
|
|
219
|
+
return parseCodecPrivateSegment(iterator);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (segmentId === '0x7ba9') {
|
|
223
|
+
return parseTitleSegment(iterator);
|
|
224
|
+
}
|
|
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
|
+
|
|
196
238
|
const length = iterator.getVint();
|
|
197
239
|
|
|
198
240
|
const bytesRemaining = iterator.byteLength() - iterator.counter.getOffset();
|
package/src/buffer-iterator.ts
CHANGED
|
@@ -48,8 +48,16 @@ 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
|
+
let data = new Uint8Array(buf);
|
|
59
|
+
data.set(initialData);
|
|
60
|
+
|
|
53
61
|
let view = new DataView(data.buffer);
|
|
54
62
|
const counter = makeOffsetCounter();
|
|
55
63
|
|
|
@@ -76,6 +84,15 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
76
84
|
);
|
|
77
85
|
};
|
|
78
86
|
|
|
87
|
+
const getPaddedFourByteNumber = () => {
|
|
88
|
+
let lastInt = 128;
|
|
89
|
+
while (((lastInt = getUint8()), lastInt === 128)) {
|
|
90
|
+
// Do nothing
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return lastInt;
|
|
94
|
+
};
|
|
95
|
+
|
|
79
96
|
const getUint32 = () => {
|
|
80
97
|
const val = view.getUint32(counter.getDiscardedOffset());
|
|
81
98
|
counter.increment(4);
|
|
@@ -83,11 +100,11 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
83
100
|
};
|
|
84
101
|
|
|
85
102
|
const addData = (newData: Uint8Array) => {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
);
|
|
89
|
-
newArray
|
|
90
|
-
newArray.set(
|
|
103
|
+
const oldLength = buf.byteLength;
|
|
104
|
+
const newLength = oldLength + newData.byteLength;
|
|
105
|
+
buf.resize(newLength);
|
|
106
|
+
const newArray = new Uint8Array(buf);
|
|
107
|
+
newArray.set(newData, oldLength);
|
|
91
108
|
data = newArray;
|
|
92
109
|
view = new DataView(data.buffer);
|
|
93
110
|
};
|
|
@@ -111,9 +128,9 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
111
128
|
const removeBytesRead = () => {
|
|
112
129
|
const bytesToRemove = counter.getDiscardedOffset();
|
|
113
130
|
counter.discardBytes(bytesToRemove);
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
const newData = data.slice(bytesToRemove);
|
|
132
|
+
data.set(newData);
|
|
133
|
+
buf.resize(newData.byteLength);
|
|
117
134
|
view = new DataView(data.buffer);
|
|
118
135
|
};
|
|
119
136
|
|
|
@@ -134,6 +151,7 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
134
151
|
const atom = getSlice(4);
|
|
135
152
|
return new TextDecoder().decode(atom);
|
|
136
153
|
},
|
|
154
|
+
getPaddedFourByteNumber,
|
|
137
155
|
getMatroskaSegmentId: () => {
|
|
138
156
|
const first = getSlice(1);
|
|
139
157
|
const firstOneString = `0x${Array.from(new Uint8Array(first))
|
|
@@ -154,6 +172,10 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
154
172
|
'0xe0',
|
|
155
173
|
'0xb0',
|
|
156
174
|
'0xba',
|
|
175
|
+
'0x9a',
|
|
176
|
+
'0xe1',
|
|
177
|
+
'0xbf',
|
|
178
|
+
'0x88',
|
|
157
179
|
];
|
|
158
180
|
if (knownIdsWithOneLength.includes(firstOneString)) {
|
|
159
181
|
return firstOneString;
|
|
@@ -172,6 +194,9 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
172
194
|
'0x4489',
|
|
173
195
|
'0x55ee',
|
|
174
196
|
'0x55b0',
|
|
197
|
+
'0x7ba9',
|
|
198
|
+
'0x63a2',
|
|
199
|
+
'0x73a4',
|
|
175
200
|
];
|
|
176
201
|
|
|
177
202
|
const firstTwoString = `${firstOneString}${Array.from(
|
|
@@ -265,6 +290,7 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
265
290
|
counter.increment(2);
|
|
266
291
|
return val;
|
|
267
292
|
},
|
|
293
|
+
|
|
268
294
|
getInt16: () => {
|
|
269
295
|
const val = view.getInt16(counter.getDiscardedOffset());
|
|
270
296
|
counter.increment(2);
|
package/src/from-node.ts
CHANGED
|
@@ -4,16 +4,18 @@ 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
9
|
start: range === null ? 0 : range[0],
|
|
10
10
|
end: range === null ? Infinity : range[1],
|
|
11
11
|
});
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const stats = await stat(src);
|
|
13
|
+
return {
|
|
14
|
+
reader: Readable.toWeb(
|
|
14
15
|
stream,
|
|
15
16
|
).getReader() as ReadableStreamDefaultReader<Uint8Array>,
|
|
16
|
-
|
|
17
|
+
contentLength: stats.size,
|
|
18
|
+
};
|
|
17
19
|
},
|
|
18
20
|
getLength: async (src) => {
|
|
19
21
|
const stats = await stat(src);
|
package/src/from-web.ts
CHANGED
|
@@ -31,9 +31,16 @@ export const webReader: ReaderInterface = {
|
|
|
31
31
|
throw new Error('No body');
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
const length = res.headers.get('content-length');
|
|
35
|
+
if (!length) {
|
|
36
|
+
throw new Error('No content-length');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const contentLength = length === null ? null : parseInt(length, 10);
|
|
40
|
+
|
|
34
41
|
const reader = res.body.getReader();
|
|
35
42
|
|
|
36
|
-
return reader;
|
|
43
|
+
return {reader, contentLength};
|
|
37
44
|
},
|
|
38
45
|
getLength: async (src) => {
|
|
39
46
|
const res = await fetch(src, {
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/* eslint-disable max-depth */
|
|
2
|
+
import type {Sample} from './boxes/iso-base-media/stsd/samples';
|
|
3
|
+
import {trakBoxContainsAudio} from './get-fps';
|
|
4
|
+
import type {KnownAudioCodecs} from './options';
|
|
5
|
+
import type {AnySegment} from './parse-result';
|
|
6
|
+
|
|
7
|
+
export const hasAudioCodec = (boxes: AnySegment[]): boolean => {
|
|
8
|
+
try {
|
|
9
|
+
return getAudioCodec(boxes) !== null;
|
|
10
|
+
} catch (e) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const onEsdsBox = (child: AnySegment): KnownAudioCodecs | null => {
|
|
16
|
+
if (child && child.type === 'esds-box') {
|
|
17
|
+
const descriptor = child.descriptors.find(
|
|
18
|
+
(d) => d.type === 'decoder-config-descriptor',
|
|
19
|
+
);
|
|
20
|
+
if (descriptor && descriptor.type === 'decoder-config-descriptor') {
|
|
21
|
+
return descriptor.objectTypeIndication;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return null;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const onSample = (sample: Sample): KnownAudioCodecs | null | undefined => {
|
|
29
|
+
if (!sample) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (sample.type !== 'audio') {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (sample.format === 'sowt') {
|
|
38
|
+
return 'aiff';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const child = sample.children.find((c) => c.type === 'esds-box');
|
|
42
|
+
|
|
43
|
+
if (child && child.type === 'esds-box') {
|
|
44
|
+
const ret = onEsdsBox(child);
|
|
45
|
+
if (ret) {
|
|
46
|
+
return ret;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const getAudioCodec = (boxes: AnySegment[]): KnownAudioCodecs | null => {
|
|
52
|
+
const moovBox = boxes.find((b) => b.type === 'moov-box');
|
|
53
|
+
if (moovBox && moovBox.type === 'moov-box') {
|
|
54
|
+
const trakBox = moovBox.children.find(
|
|
55
|
+
(b) => b.type === 'trak-box' && trakBoxContainsAudio(b),
|
|
56
|
+
);
|
|
57
|
+
if (trakBox && trakBox.type === 'trak-box') {
|
|
58
|
+
const mdiaBox = trakBox.children.find(
|
|
59
|
+
(b) => b.type === 'regular-box' && b.boxType === 'mdia',
|
|
60
|
+
);
|
|
61
|
+
if (
|
|
62
|
+
mdiaBox &&
|
|
63
|
+
mdiaBox.type === 'regular-box' &&
|
|
64
|
+
mdiaBox.boxType === 'mdia'
|
|
65
|
+
) {
|
|
66
|
+
const minfBox = mdiaBox?.children.find(
|
|
67
|
+
(b) => b.type === 'regular-box' && b.boxType === 'minf',
|
|
68
|
+
);
|
|
69
|
+
if (
|
|
70
|
+
minfBox &&
|
|
71
|
+
minfBox.type === 'regular-box' &&
|
|
72
|
+
minfBox.boxType === 'minf'
|
|
73
|
+
) {
|
|
74
|
+
const stblBox = minfBox?.children.find(
|
|
75
|
+
(b) => b.type === 'regular-box' && b.boxType === 'stbl',
|
|
76
|
+
);
|
|
77
|
+
if (stblBox && stblBox.type === 'regular-box') {
|
|
78
|
+
const stsdBox = stblBox?.children.find(
|
|
79
|
+
(b) => b.type === 'stsd-box',
|
|
80
|
+
);
|
|
81
|
+
if (stsdBox && stsdBox.type === 'stsd-box') {
|
|
82
|
+
const sample = stsdBox.samples.find((s) => s.type === 'audio');
|
|
83
|
+
if (sample && sample.type === 'audio') {
|
|
84
|
+
const ret = onSample(sample);
|
|
85
|
+
if (ret) {
|
|
86
|
+
return ret;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const waveBox = sample.children.find(
|
|
90
|
+
(b) => b.type === 'regular-box' && b.boxType === 'wave',
|
|
91
|
+
);
|
|
92
|
+
if (
|
|
93
|
+
waveBox &&
|
|
94
|
+
waveBox.type === 'regular-box' &&
|
|
95
|
+
waveBox.boxType === 'wave'
|
|
96
|
+
) {
|
|
97
|
+
const esdsBox = waveBox.children.find(
|
|
98
|
+
(b) => b.type === 'esds-box',
|
|
99
|
+
);
|
|
100
|
+
if (esdsBox && esdsBox.type === 'esds-box') {
|
|
101
|
+
const ret2 = onEsdsBox(esdsBox);
|
|
102
|
+
if (ret2) {
|
|
103
|
+
return ret2;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const mainSegment = boxes.find((b) => b.type === 'main-segment');
|
|
116
|
+
if (!mainSegment || mainSegment.type !== 'main-segment') {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const tracksSegment = mainSegment.children.find(
|
|
121
|
+
(b) => b.type === 'tracks-segment',
|
|
122
|
+
);
|
|
123
|
+
if (!tracksSegment || tracksSegment.type !== 'tracks-segment') {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (const track of tracksSegment.children) {
|
|
128
|
+
if (track.type === 'track-entry-segment') {
|
|
129
|
+
const trackType = track.children.find((b) => b.type === 'codec-segment');
|
|
130
|
+
if (trackType && trackType.type === 'codec-segment') {
|
|
131
|
+
if (trackType.codec === 'A_OPUS') {
|
|
132
|
+
return 'opus';
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (trackType.codec === 'A_PCM/INT/LIT') {
|
|
136
|
+
return 'pcm';
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return null;
|
|
143
|
+
};
|
package/src/get-dimensions.ts
CHANGED
|
@@ -14,10 +14,17 @@ const getDimensionsFromMatroska = (segments: MainSegment): Dimensions => {
|
|
|
14
14
|
throw new Error('No tracks segment');
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
const trackEntrySegment = tracksSegment.children.find((b) => {
|
|
18
|
+
if (b.type !== 'track-entry-segment') {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
b.children.find(
|
|
24
|
+
(c) => c.type === 'codec-segment' && c.codec.startsWith('V_'),
|
|
25
|
+
) !== undefined
|
|
26
|
+
);
|
|
27
|
+
});
|
|
21
28
|
if (!trackEntrySegment || trackEntrySegment.type !== 'track-entry-segment') {
|
|
22
29
|
throw new Error('No track entry segment');
|
|
23
30
|
}
|