@remotion/media-parser 4.0.199 → 4.0.200
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/dist/boxes/iso-base-media/mdat/mdat.js +0 -1
- package/dist/boxes/webm/ebml.d.ts +2 -0
- package/dist/boxes/webm/ebml.js +72 -0
- package/dist/boxes/webm/make-header.d.ts +2 -0
- package/dist/boxes/webm/make-header.js +44 -0
- package/dist/boxes/webm/segments/all-segments.d.ts +5 -0
- package/dist/boxes/webm/segments/all-segments.js +5 -0
- package/dist/boxes/webm/segments/block-simple-block-flags.d.ts +9 -0
- package/dist/boxes/webm/segments/block-simple-block-flags.js +38 -0
- package/dist/boxes/webm/segments/track-entry.d.ts +20 -8
- package/dist/boxes/webm/segments/track-entry.js +64 -23
- package/dist/boxes/webm/segments.d.ts +2 -2
- package/dist/boxes/webm/segments.js +35 -6
- package/dist/buffer-iterator.d.ts +1 -0
- package/dist/buffer-iterator.js +9 -2
- package/dist/get-audio-codec.d.ts +1 -1
- package/dist/parser-state.d.ts +4 -6
- package/dist/parser-state.js +24 -16
- package/dist/webcodec-sample-types.d.ts +0 -1
- package/package.json +2 -2
- package/src/boxes/iso-base-media/mdat/mdat.ts +0 -1
- package/src/boxes/webm/ebml.ts +78 -0
- package/src/boxes/webm/make-header.ts +48 -0
- package/src/boxes/webm/segments/all-segments.ts +5 -0
- package/src/boxes/webm/segments/block-simple-block-flags.ts +52 -0
- package/src/boxes/webm/segments/track-entry.ts +108 -29
- package/src/boxes/webm/segments.ts +71 -9
- package/src/buffer-iterator.ts +8 -1
- package/src/parser-state.ts +30 -20
- package/src/test/create-matroska.test.ts +14 -0
- package/src/test/matroska.test.ts +75 -100
- package/src/test/stream-local.test.ts +47 -5
- package/src/webcodec-sample-types.ts +0 -1
- package/tsconfig.tsbuildinfo +1 -1
package/src/parser-state.ts
CHANGED
|
@@ -9,9 +9,7 @@ import type {
|
|
|
9
9
|
VideoSample,
|
|
10
10
|
} from './webcodec-sample-types';
|
|
11
11
|
|
|
12
|
-
export type InternalStats = {
|
|
13
|
-
samplesThatHadToBeQueued: number;
|
|
14
|
-
};
|
|
12
|
+
export type InternalStats = {};
|
|
15
13
|
|
|
16
14
|
export const makeParserState = ({
|
|
17
15
|
hasAudioCallbacks,
|
|
@@ -43,8 +41,6 @@ export const makeParserState = ({
|
|
|
43
41
|
const videoSampleCallbacks: Record<number, OnVideoSample> = {};
|
|
44
42
|
const audioSampleCallbacks: Record<number, OnAudioSample> = {};
|
|
45
43
|
|
|
46
|
-
let samplesThatHadToBeQueued = 0;
|
|
47
|
-
|
|
48
44
|
const queuedAudioSamples: Record<number, AudioSample[]> = {};
|
|
49
45
|
const queuedVideoSamples: Record<number, VideoSample[]> = {};
|
|
50
46
|
|
|
@@ -64,6 +60,30 @@ export const makeParserState = ({
|
|
|
64
60
|
timescale = newTimescale;
|
|
65
61
|
};
|
|
66
62
|
|
|
63
|
+
const timestampMap = new Map<number, number>();
|
|
64
|
+
|
|
65
|
+
const setTimestampOffset = (byteOffset: number, timestamp: number) => {
|
|
66
|
+
timestampMap.set(byteOffset, timestamp);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const getTimestampOffsetForByteOffset = (byteOffset: number) => {
|
|
70
|
+
const entries = Array.from(timestampMap.entries());
|
|
71
|
+
const sortedByByteOffset = entries
|
|
72
|
+
.sort((a, b) => {
|
|
73
|
+
return a[0] - b[0];
|
|
74
|
+
})
|
|
75
|
+
.reverse();
|
|
76
|
+
for (const [offset, timestamp] of sortedByByteOffset) {
|
|
77
|
+
if (offset >= byteOffset) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return timestamp;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return timestampMap.get(byteOffset);
|
|
85
|
+
};
|
|
86
|
+
|
|
67
87
|
return {
|
|
68
88
|
onTrackEntrySegment,
|
|
69
89
|
getTrackInfoByNumber: (id: number) => trackEntries[id],
|
|
@@ -85,6 +105,8 @@ export const makeParserState = ({
|
|
|
85
105
|
|
|
86
106
|
queuedVideoSamples[id] = [];
|
|
87
107
|
},
|
|
108
|
+
setTimestampOffset,
|
|
109
|
+
getTimestampOffsetForByteOffset,
|
|
88
110
|
registerAudioSampleCallback: async (
|
|
89
111
|
id: number,
|
|
90
112
|
callback: OnAudioSample | null,
|
|
@@ -112,12 +134,8 @@ export const makeParserState = ({
|
|
|
112
134
|
}
|
|
113
135
|
|
|
114
136
|
if (!hasAudioCallbacks) {
|
|
115
|
-
|
|
137
|
+
throw new Error('No audio callbacks registered');
|
|
116
138
|
}
|
|
117
|
-
|
|
118
|
-
queuedAudioSamples[trackId] ??= [];
|
|
119
|
-
queuedAudioSamples[trackId].push(audioSample);
|
|
120
|
-
samplesThatHadToBeQueued++;
|
|
121
139
|
}
|
|
122
140
|
},
|
|
123
141
|
onVideoSample: async (trackId: number, videoSample: VideoSample) => {
|
|
@@ -130,19 +148,11 @@ export const makeParserState = ({
|
|
|
130
148
|
}
|
|
131
149
|
|
|
132
150
|
if (!hasVideoCallbacks) {
|
|
133
|
-
|
|
151
|
+
throw new Error('No video callbacks registered');
|
|
134
152
|
}
|
|
135
|
-
|
|
136
|
-
queuedVideoSamples[trackId] ??= [];
|
|
137
|
-
queuedVideoSamples[trackId].push(videoSample);
|
|
138
|
-
samplesThatHadToBeQueued++;
|
|
139
153
|
}
|
|
140
154
|
},
|
|
141
|
-
getInternalStats: () => {
|
|
142
|
-
return {
|
|
143
|
-
samplesThatHadToBeQueued,
|
|
144
|
-
};
|
|
145
|
-
},
|
|
155
|
+
getInternalStats: () => ({}),
|
|
146
156
|
getTimescale,
|
|
147
157
|
setTimescale,
|
|
148
158
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {RenderInternals} from '@remotion/renderer';
|
|
2
|
+
import {expect, test} from 'bun:test';
|
|
3
|
+
import {makeMatroskaHeader} from '../boxes/webm/make-header';
|
|
4
|
+
|
|
5
|
+
test('Should make Matroska header that is same as input', async () => {
|
|
6
|
+
const exampleVideo = RenderInternals.exampleVideos.matroskaMp3;
|
|
7
|
+
const file = await Bun.file(exampleVideo).arrayBuffer();
|
|
8
|
+
|
|
9
|
+
const headerInput = new Uint8Array(file.slice(0, 0x23 + 5));
|
|
10
|
+
|
|
11
|
+
const headerOutput = makeMatroskaHeader();
|
|
12
|
+
|
|
13
|
+
expect(headerInput).toEqual(headerOutput);
|
|
14
|
+
});
|
|
@@ -193,279 +193,254 @@ test('Should get duration of AV1 video', async () => {
|
|
|
193
193
|
timestamp: 0,
|
|
194
194
|
},
|
|
195
195
|
{
|
|
196
|
-
type: 'simple-block-segment',
|
|
196
|
+
type: 'simple-block-or-block-segment',
|
|
197
197
|
length: 279307,
|
|
198
198
|
trackNumber: 1,
|
|
199
199
|
timecode: 0,
|
|
200
|
-
headerFlags: 128,
|
|
201
200
|
keyframe: true,
|
|
202
|
-
lacing:
|
|
201
|
+
lacing: 0,
|
|
203
202
|
invisible: false,
|
|
204
|
-
|
|
203
|
+
videoSample: null,
|
|
205
204
|
},
|
|
206
205
|
{
|
|
207
|
-
type: 'simple-block-segment',
|
|
206
|
+
type: 'simple-block-or-block-segment',
|
|
208
207
|
length: 96,
|
|
209
208
|
trackNumber: 1,
|
|
210
209
|
timecode: 40,
|
|
211
|
-
headerFlags: 0,
|
|
212
210
|
keyframe: false,
|
|
213
|
-
lacing:
|
|
211
|
+
lacing: 0,
|
|
214
212
|
invisible: false,
|
|
215
|
-
|
|
213
|
+
videoSample: null,
|
|
216
214
|
},
|
|
217
215
|
{
|
|
218
|
-
type: 'simple-block-segment',
|
|
216
|
+
type: 'simple-block-or-block-segment',
|
|
219
217
|
length: 556,
|
|
220
218
|
trackNumber: 1,
|
|
221
219
|
timecode: 80,
|
|
222
|
-
headerFlags: 0,
|
|
223
220
|
keyframe: false,
|
|
224
|
-
lacing:
|
|
221
|
+
lacing: 0,
|
|
225
222
|
invisible: false,
|
|
226
|
-
|
|
223
|
+
videoSample: null,
|
|
227
224
|
},
|
|
228
225
|
{
|
|
229
|
-
type: 'simple-block-segment',
|
|
226
|
+
type: 'simple-block-or-block-segment',
|
|
230
227
|
length: 948,
|
|
231
228
|
trackNumber: 1,
|
|
232
229
|
timecode: 120,
|
|
233
|
-
headerFlags: 0,
|
|
234
230
|
keyframe: false,
|
|
235
|
-
lacing:
|
|
231
|
+
lacing: 0,
|
|
236
232
|
invisible: false,
|
|
237
|
-
|
|
233
|
+
videoSample: null,
|
|
238
234
|
},
|
|
239
235
|
{
|
|
240
|
-
type: 'simple-block-segment',
|
|
236
|
+
type: 'simple-block-or-block-segment',
|
|
241
237
|
length: 577,
|
|
242
238
|
trackNumber: 1,
|
|
243
239
|
timecode: 160,
|
|
244
|
-
headerFlags: 0,
|
|
245
240
|
keyframe: false,
|
|
246
|
-
lacing:
|
|
241
|
+
lacing: 0,
|
|
247
242
|
invisible: false,
|
|
248
|
-
|
|
243
|
+
videoSample: null,
|
|
249
244
|
},
|
|
250
245
|
{
|
|
251
|
-
type: 'simple-block-segment',
|
|
246
|
+
type: 'simple-block-or-block-segment',
|
|
252
247
|
length: 779,
|
|
253
248
|
trackNumber: 1,
|
|
254
249
|
timecode: 200,
|
|
255
|
-
headerFlags: 0,
|
|
256
250
|
keyframe: false,
|
|
257
|
-
lacing:
|
|
251
|
+
lacing: 0,
|
|
258
252
|
invisible: false,
|
|
259
|
-
|
|
253
|
+
videoSample: null,
|
|
260
254
|
},
|
|
261
255
|
{
|
|
262
|
-
type: 'simple-block-segment',
|
|
256
|
+
type: 'simple-block-or-block-segment',
|
|
263
257
|
length: 793,
|
|
264
258
|
trackNumber: 1,
|
|
265
259
|
timecode: 240,
|
|
266
|
-
headerFlags: 0,
|
|
267
260
|
keyframe: false,
|
|
268
|
-
lacing:
|
|
261
|
+
lacing: 0,
|
|
269
262
|
invisible: false,
|
|
270
|
-
|
|
263
|
+
videoSample: null,
|
|
271
264
|
},
|
|
272
265
|
{
|
|
273
|
-
type: 'simple-block-segment',
|
|
266
|
+
type: 'simple-block-or-block-segment',
|
|
274
267
|
length: 740,
|
|
275
268
|
trackNumber: 1,
|
|
276
269
|
timecode: 280,
|
|
277
|
-
headerFlags: 0,
|
|
278
270
|
keyframe: false,
|
|
279
|
-
lacing:
|
|
271
|
+
lacing: 0,
|
|
280
272
|
invisible: false,
|
|
281
|
-
|
|
273
|
+
videoSample: null,
|
|
282
274
|
},
|
|
283
275
|
{
|
|
284
|
-
type: 'simple-block-segment',
|
|
276
|
+
type: 'simple-block-or-block-segment',
|
|
285
277
|
length: 1095,
|
|
286
278
|
trackNumber: 1,
|
|
287
279
|
timecode: 320,
|
|
288
|
-
headerFlags: 0,
|
|
289
280
|
keyframe: false,
|
|
290
|
-
lacing:
|
|
281
|
+
lacing: 0,
|
|
291
282
|
invisible: false,
|
|
292
|
-
|
|
283
|
+
videoSample: null,
|
|
293
284
|
},
|
|
294
285
|
{
|
|
295
|
-
type: 'simple-block-segment',
|
|
286
|
+
type: 'simple-block-or-block-segment',
|
|
296
287
|
length: 1097,
|
|
297
288
|
trackNumber: 1,
|
|
298
289
|
timecode: 360,
|
|
299
|
-
headerFlags: 0,
|
|
300
290
|
keyframe: false,
|
|
301
|
-
lacing:
|
|
291
|
+
lacing: 0,
|
|
302
292
|
invisible: false,
|
|
303
|
-
|
|
293
|
+
videoSample: null,
|
|
304
294
|
},
|
|
305
295
|
{
|
|
306
|
-
type: 'simple-block-segment',
|
|
296
|
+
type: 'simple-block-or-block-segment',
|
|
307
297
|
length: 1155,
|
|
308
298
|
trackNumber: 1,
|
|
309
299
|
timecode: 400,
|
|
310
|
-
headerFlags: 0,
|
|
311
300
|
keyframe: false,
|
|
312
|
-
lacing:
|
|
301
|
+
lacing: 0,
|
|
313
302
|
invisible: false,
|
|
314
|
-
|
|
303
|
+
videoSample: null,
|
|
315
304
|
},
|
|
316
305
|
{
|
|
317
|
-
type: 'simple-block-segment',
|
|
306
|
+
type: 'simple-block-or-block-segment',
|
|
318
307
|
length: 1526,
|
|
319
308
|
trackNumber: 1,
|
|
320
309
|
timecode: 440,
|
|
321
|
-
headerFlags: 0,
|
|
322
310
|
keyframe: false,
|
|
323
|
-
lacing:
|
|
311
|
+
lacing: 0,
|
|
324
312
|
invisible: false,
|
|
325
|
-
|
|
313
|
+
videoSample: null,
|
|
326
314
|
},
|
|
327
315
|
{
|
|
328
|
-
type: 'simple-block-segment',
|
|
316
|
+
type: 'simple-block-or-block-segment',
|
|
329
317
|
length: 1487,
|
|
330
318
|
trackNumber: 1,
|
|
331
319
|
timecode: 480,
|
|
332
|
-
headerFlags: 0,
|
|
333
320
|
keyframe: false,
|
|
334
|
-
lacing:
|
|
321
|
+
lacing: 0,
|
|
335
322
|
invisible: false,
|
|
336
|
-
|
|
323
|
+
videoSample: null,
|
|
337
324
|
},
|
|
338
325
|
{
|
|
339
|
-
type: 'simple-block-segment',
|
|
326
|
+
type: 'simple-block-or-block-segment',
|
|
340
327
|
length: 2046,
|
|
341
328
|
trackNumber: 1,
|
|
342
329
|
timecode: 520,
|
|
343
|
-
headerFlags: 0,
|
|
344
330
|
keyframe: false,
|
|
345
|
-
lacing:
|
|
331
|
+
lacing: 0,
|
|
346
332
|
invisible: false,
|
|
347
|
-
|
|
333
|
+
videoSample: null,
|
|
348
334
|
},
|
|
349
335
|
{
|
|
350
|
-
type: 'simple-block-segment',
|
|
336
|
+
type: 'simple-block-or-block-segment',
|
|
351
337
|
length: 1372,
|
|
352
338
|
trackNumber: 1,
|
|
353
339
|
timecode: 560,
|
|
354
|
-
headerFlags: 0,
|
|
355
340
|
keyframe: false,
|
|
356
|
-
lacing:
|
|
341
|
+
lacing: 0,
|
|
357
342
|
invisible: false,
|
|
358
|
-
|
|
343
|
+
videoSample: null,
|
|
359
344
|
},
|
|
360
345
|
{
|
|
361
|
-
type: 'simple-block-segment',
|
|
346
|
+
type: 'simple-block-or-block-segment',
|
|
362
347
|
length: 1441,
|
|
363
348
|
trackNumber: 1,
|
|
364
349
|
timecode: 600,
|
|
365
|
-
headerFlags: 0,
|
|
366
350
|
keyframe: false,
|
|
367
|
-
lacing:
|
|
351
|
+
lacing: 0,
|
|
368
352
|
invisible: false,
|
|
369
|
-
|
|
353
|
+
videoSample: null,
|
|
370
354
|
},
|
|
371
355
|
{
|
|
372
|
-
type: 'simple-block-segment',
|
|
356
|
+
type: 'simple-block-or-block-segment',
|
|
373
357
|
length: 2947,
|
|
374
358
|
trackNumber: 1,
|
|
375
359
|
timecode: 640,
|
|
376
|
-
headerFlags: 0,
|
|
377
360
|
keyframe: false,
|
|
378
|
-
lacing:
|
|
361
|
+
lacing: 0,
|
|
379
362
|
invisible: false,
|
|
380
|
-
|
|
363
|
+
videoSample: null,
|
|
381
364
|
},
|
|
382
365
|
{
|
|
383
|
-
type: 'simple-block-segment',
|
|
366
|
+
type: 'simple-block-or-block-segment',
|
|
384
367
|
length: 2652,
|
|
385
368
|
trackNumber: 1,
|
|
386
369
|
timecode: 680,
|
|
387
|
-
headerFlags: 0,
|
|
388
370
|
keyframe: false,
|
|
389
|
-
lacing:
|
|
371
|
+
lacing: 0,
|
|
390
372
|
invisible: false,
|
|
391
|
-
|
|
373
|
+
videoSample: null,
|
|
392
374
|
},
|
|
393
375
|
{
|
|
394
|
-
type: 'simple-block-segment',
|
|
376
|
+
type: 'simple-block-or-block-segment',
|
|
395
377
|
length: 4199,
|
|
396
378
|
trackNumber: 1,
|
|
397
379
|
timecode: 720,
|
|
398
|
-
headerFlags: 0,
|
|
399
380
|
keyframe: false,
|
|
400
|
-
lacing:
|
|
381
|
+
lacing: 0,
|
|
401
382
|
invisible: false,
|
|
402
|
-
|
|
383
|
+
videoSample: null,
|
|
403
384
|
},
|
|
404
385
|
{
|
|
405
|
-
type: 'simple-block-segment',
|
|
386
|
+
type: 'simple-block-or-block-segment',
|
|
406
387
|
length: 3998,
|
|
407
388
|
trackNumber: 1,
|
|
408
389
|
timecode: 760,
|
|
409
|
-
headerFlags: 0,
|
|
410
390
|
keyframe: false,
|
|
411
|
-
lacing:
|
|
391
|
+
lacing: 0,
|
|
412
392
|
invisible: false,
|
|
413
|
-
|
|
393
|
+
videoSample: null,
|
|
414
394
|
},
|
|
415
395
|
{
|
|
416
|
-
type: 'simple-block-segment',
|
|
396
|
+
type: 'simple-block-or-block-segment',
|
|
417
397
|
length: 6373,
|
|
418
398
|
trackNumber: 1,
|
|
419
399
|
timecode: 800,
|
|
420
|
-
headerFlags: 0,
|
|
421
400
|
keyframe: false,
|
|
422
|
-
lacing:
|
|
401
|
+
lacing: 0,
|
|
423
402
|
invisible: false,
|
|
424
|
-
|
|
403
|
+
videoSample: null,
|
|
425
404
|
},
|
|
426
405
|
{
|
|
427
|
-
type: 'simple-block-segment',
|
|
406
|
+
type: 'simple-block-or-block-segment',
|
|
428
407
|
length: 5955,
|
|
429
408
|
trackNumber: 1,
|
|
430
409
|
timecode: 840,
|
|
431
|
-
headerFlags: 0,
|
|
432
410
|
keyframe: false,
|
|
433
|
-
lacing:
|
|
411
|
+
lacing: 0,
|
|
434
412
|
invisible: false,
|
|
435
|
-
|
|
413
|
+
videoSample: null,
|
|
436
414
|
},
|
|
437
415
|
{
|
|
438
|
-
type: 'simple-block-segment',
|
|
416
|
+
type: 'simple-block-or-block-segment',
|
|
439
417
|
length: 7943,
|
|
440
418
|
trackNumber: 1,
|
|
441
419
|
timecode: 880,
|
|
442
|
-
headerFlags: 0,
|
|
443
420
|
keyframe: false,
|
|
444
|
-
lacing:
|
|
421
|
+
lacing: 0,
|
|
445
422
|
invisible: false,
|
|
446
|
-
|
|
423
|
+
videoSample: null,
|
|
447
424
|
},
|
|
448
425
|
{
|
|
449
|
-
type: 'simple-block-segment',
|
|
426
|
+
type: 'simple-block-or-block-segment',
|
|
450
427
|
length: 8241,
|
|
451
428
|
trackNumber: 1,
|
|
452
429
|
timecode: 920,
|
|
453
|
-
headerFlags: 0,
|
|
454
430
|
keyframe: false,
|
|
455
|
-
lacing:
|
|
431
|
+
lacing: 0,
|
|
456
432
|
invisible: false,
|
|
457
|
-
|
|
433
|
+
videoSample: null,
|
|
458
434
|
},
|
|
459
435
|
{
|
|
460
|
-
type: 'simple-block-segment',
|
|
436
|
+
type: 'simple-block-or-block-segment',
|
|
461
437
|
length: 9506,
|
|
462
438
|
trackNumber: 1,
|
|
463
439
|
timecode: 960,
|
|
464
|
-
headerFlags: 0,
|
|
465
440
|
keyframe: false,
|
|
466
|
-
lacing:
|
|
441
|
+
lacing: 0,
|
|
467
442
|
invisible: false,
|
|
468
|
-
|
|
443
|
+
videoSample: null,
|
|
469
444
|
},
|
|
470
445
|
],
|
|
471
446
|
},
|
|
@@ -248,6 +248,7 @@ test('Should stream ProRes video', async () => {
|
|
|
248
248
|
|
|
249
249
|
test('Should stream variable fps video', async () => {
|
|
250
250
|
let audioTracks = 0;
|
|
251
|
+
let samples = 0;
|
|
251
252
|
const parsed = await parseMedia({
|
|
252
253
|
src: RenderInternals.exampleVideos.variablefps,
|
|
253
254
|
fields: {
|
|
@@ -269,8 +270,9 @@ test('Should stream variable fps video', async () => {
|
|
|
269
270
|
expect(track.numberOfChannels).toBe(1);
|
|
270
271
|
expect(track.sampleRate).toBe(48000);
|
|
271
272
|
audioTracks++;
|
|
272
|
-
|
|
273
|
-
|
|
273
|
+
return () => {
|
|
274
|
+
samples++;
|
|
275
|
+
};
|
|
274
276
|
},
|
|
275
277
|
});
|
|
276
278
|
|
|
@@ -314,6 +316,7 @@ test('Should stream variable fps video', async () => {
|
|
|
314
316
|
description: undefined,
|
|
315
317
|
});
|
|
316
318
|
expect(audioTracks).toBe(1);
|
|
319
|
+
expect(samples).toBe(381);
|
|
317
320
|
});
|
|
318
321
|
|
|
319
322
|
test('Should stream MKV video', async () => {
|
|
@@ -357,7 +360,7 @@ test('Should stream MKV video', async () => {
|
|
|
357
360
|
|
|
358
361
|
expect(videoSamples).toBe(10);
|
|
359
362
|
expect(audioSamples).toBe(16);
|
|
360
|
-
expect(parsed.internalStats
|
|
363
|
+
expect(parsed.internalStats).toEqual({});
|
|
361
364
|
});
|
|
362
365
|
|
|
363
366
|
test('Should stream MP3 in MP4 video', async () => {
|
|
@@ -660,7 +663,7 @@ test('MP3 in matroska', async () => {
|
|
|
660
663
|
expect(parsed.audioCodec).toEqual('mp3');
|
|
661
664
|
expect(parsed.videoTracks.length).toBe(1);
|
|
662
665
|
expect(parsed.audioTracks.length).toBe(1);
|
|
663
|
-
expect(audioSamples).toBe(
|
|
666
|
+
expect(audioSamples).toBe(140);
|
|
664
667
|
expect(videoSamples).toBe(100);
|
|
665
668
|
});
|
|
666
669
|
|
|
@@ -685,5 +688,44 @@ test('Should stream OPUS', async () => {
|
|
|
685
688
|
|
|
686
689
|
expect(parsed.audioCodec).toEqual('opus');
|
|
687
690
|
expect(parsed.audioTracks.length).toBe(1);
|
|
688
|
-
expect(audioSamples).toBe(
|
|
691
|
+
expect(audioSamples).toBe(167);
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
test('Should stream transparent video', async () => {
|
|
695
|
+
let videoTracks = 0;
|
|
696
|
+
let audioTracks = 0;
|
|
697
|
+
let videoSamples = 0;
|
|
698
|
+
let keyFrames = 0;
|
|
699
|
+
|
|
700
|
+
await parseMedia({
|
|
701
|
+
src: RenderInternals.exampleVideos.transparentwithdar,
|
|
702
|
+
reader: nodeReader,
|
|
703
|
+
onVideoTrack: (track) => {
|
|
704
|
+
expect(track.codedHeight).toBe(512);
|
|
705
|
+
expect(track.codedWidth).toBe(512);
|
|
706
|
+
videoTracks++;
|
|
707
|
+
return (sample) => {
|
|
708
|
+
// https://ffmpeg.org/pipermail/ffmpeg-devel/2015-June/173825.html
|
|
709
|
+
// For Blocks, keyframes is
|
|
710
|
+
// inferred by the absence of ReferenceBlock element (as done by matroskadec).
|
|
711
|
+
if (sample.type === 'key') {
|
|
712
|
+
keyFrames++;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
videoSamples++;
|
|
716
|
+
};
|
|
717
|
+
},
|
|
718
|
+
onAudioTrack: () => {
|
|
719
|
+
audioTracks++;
|
|
720
|
+
return null;
|
|
721
|
+
},
|
|
722
|
+
fields: {
|
|
723
|
+
tracks: true,
|
|
724
|
+
},
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
expect(videoTracks).toBe(1);
|
|
728
|
+
expect(audioTracks).toBe(0);
|
|
729
|
+
expect(videoSamples).toBe(39);
|
|
730
|
+
expect(keyFrames).toBe(1);
|
|
689
731
|
});
|