@remotion/webcodecs 4.0.228 → 4.0.229
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/audio-decoder-config.js +3 -0
- package/dist/calculate-progress.d.ts +2 -2
- package/dist/calculate-progress.js +3 -3
- package/dist/can-copy-audio-track.d.ts +8 -0
- package/dist/can-copy-audio-track.js +10 -0
- package/dist/can-copy-video-track.d.ts +8 -0
- package/dist/can-copy-video-track.js +13 -0
- package/dist/can-reencode-audio-track.d.ts +7 -0
- package/dist/can-reencode-audio-track.js +21 -0
- package/dist/can-reencode-audio.d.ts +7 -0
- package/dist/can-reencode-audio.js +21 -0
- package/dist/can-reencode-video-track.d.ts +6 -0
- package/dist/can-reencode-video-track.js +15 -0
- package/dist/can-reencode-video.d.ts +6 -0
- package/dist/can-reencode-video.js +15 -0
- package/dist/codec-id.d.ts +7 -2
- package/dist/codec-id.js +7 -0
- package/dist/convert-encoded-chunk.d.ts +2 -0
- package/dist/convert-encoded-chunk.js +15 -0
- package/dist/convert-media.d.ts +16 -7
- package/dist/convert-media.js +15 -12
- package/dist/esm/index.mjs +294 -178
- package/dist/index.d.ts +8 -1
- package/dist/index.js +12 -1
- package/dist/on-audio-track.d.ts +4 -4
- package/dist/on-audio-track.js +21 -21
- package/dist/on-frame.d.ts +11 -0
- package/dist/on-frame.js +32 -0
- package/dist/on-video-track.d.ts +7 -6
- package/dist/on-video-track.js +24 -20
- package/dist/polyfill-encoded-audio-chunk.d.ts +3 -0
- package/dist/polyfill-encoded-audio-chunk.js +5 -0
- package/dist/resolve-audio-action.d.ts +15 -11
- package/dist/resolve-audio-action.js +23 -21
- package/dist/resolve-video-action.d.ts +14 -11
- package/dist/resolve-video-action.js +17 -24
- package/dist/video-encoder-config.d.ts +6 -1
- package/dist/video-encoder-config.js +6 -1
- package/dist/video-encoder.d.ts +1 -1
- package/package.json +4 -4
package/dist/esm/index.mjs
CHANGED
|
@@ -290,6 +290,147 @@ var createAudioEncoder = ({
|
|
|
290
290
|
}
|
|
291
291
|
};
|
|
292
292
|
};
|
|
293
|
+
// src/can-copy-audio-track.ts
|
|
294
|
+
var canCopyAudioTrack = ({
|
|
295
|
+
inputCodec,
|
|
296
|
+
outputCodec,
|
|
297
|
+
container
|
|
298
|
+
}) => {
|
|
299
|
+
if (outputCodec === "opus") {
|
|
300
|
+
return inputCodec === "opus" && container === "webm";
|
|
301
|
+
}
|
|
302
|
+
throw new Error(`Unhandled codec: ${outputCodec}`);
|
|
303
|
+
};
|
|
304
|
+
// src/can-copy-video-track.ts
|
|
305
|
+
var canCopyVideoTrack = ({
|
|
306
|
+
inputCodec,
|
|
307
|
+
outputCodec,
|
|
308
|
+
container
|
|
309
|
+
}) => {
|
|
310
|
+
if (outputCodec === "vp8") {
|
|
311
|
+
return inputCodec === "vp8" && container === "webm";
|
|
312
|
+
}
|
|
313
|
+
if (outputCodec === "vp9") {
|
|
314
|
+
return inputCodec === "vp9" && container === "webm";
|
|
315
|
+
}
|
|
316
|
+
throw new Error(`Unhandled codec: ${outputCodec}`);
|
|
317
|
+
};
|
|
318
|
+
// src/audio-decoder-config.ts
|
|
319
|
+
var getAudioDecoderConfig = async (config) => {
|
|
320
|
+
if (typeof AudioDecoder === "undefined") {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
if (typeof EncodedAudioChunk === "undefined") {
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
if ((await AudioDecoder.isConfigSupported(config)).supported) {
|
|
327
|
+
return config;
|
|
328
|
+
}
|
|
329
|
+
return null;
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
// src/audio-encoder-config.ts
|
|
333
|
+
var getAudioEncoderConfig = async (config) => {
|
|
334
|
+
if (typeof AudioEncoder === "undefined") {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
if ((await AudioEncoder.isConfigSupported(config)).supported) {
|
|
338
|
+
return config;
|
|
339
|
+
}
|
|
340
|
+
return null;
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// src/can-reencode-audio-track.ts
|
|
344
|
+
var canReencodeAudioTrack = async ({
|
|
345
|
+
track,
|
|
346
|
+
audioCodec,
|
|
347
|
+
bitrate
|
|
348
|
+
}) => {
|
|
349
|
+
const audioDecoderConfig = await getAudioDecoderConfig({
|
|
350
|
+
codec: track.codec,
|
|
351
|
+
numberOfChannels: track.numberOfChannels,
|
|
352
|
+
sampleRate: track.sampleRate,
|
|
353
|
+
description: track.description
|
|
354
|
+
});
|
|
355
|
+
const audioEncoderConfig = await getAudioEncoderConfig({
|
|
356
|
+
codec: audioCodec,
|
|
357
|
+
numberOfChannels: track.numberOfChannels,
|
|
358
|
+
sampleRate: track.sampleRate,
|
|
359
|
+
bitrate
|
|
360
|
+
});
|
|
361
|
+
return Boolean(audioDecoderConfig && audioEncoderConfig);
|
|
362
|
+
};
|
|
363
|
+
// src/video-decoder-config.ts
|
|
364
|
+
var getVideoDecoderConfigWithHardwareAcceleration = async (config) => {
|
|
365
|
+
if (typeof VideoDecoder === "undefined") {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
const hardware = {
|
|
369
|
+
...config,
|
|
370
|
+
hardwareAcceleration: "prefer-hardware"
|
|
371
|
+
};
|
|
372
|
+
if ((await VideoDecoder.isConfigSupported(hardware)).supported) {
|
|
373
|
+
return hardware;
|
|
374
|
+
}
|
|
375
|
+
const software = {
|
|
376
|
+
...config,
|
|
377
|
+
hardwareAcceleration: "prefer-software"
|
|
378
|
+
};
|
|
379
|
+
if ((await VideoDecoder.isConfigSupported(software)).supported) {
|
|
380
|
+
return software;
|
|
381
|
+
}
|
|
382
|
+
return null;
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// src/video-encoder-config.ts
|
|
386
|
+
var getVideoEncoderConfig = async ({
|
|
387
|
+
width,
|
|
388
|
+
height,
|
|
389
|
+
codec
|
|
390
|
+
}) => {
|
|
391
|
+
if (typeof VideoEncoder === "undefined") {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
const config = {
|
|
395
|
+
codec: codec === "vp9" ? "vp09.00.10.08" : codec,
|
|
396
|
+
height,
|
|
397
|
+
width
|
|
398
|
+
};
|
|
399
|
+
const hardware = {
|
|
400
|
+
...config,
|
|
401
|
+
hardwareAcceleration: "prefer-hardware"
|
|
402
|
+
};
|
|
403
|
+
if ((await VideoEncoder.isConfigSupported(hardware)).supported) {
|
|
404
|
+
return hardware;
|
|
405
|
+
}
|
|
406
|
+
const software = {
|
|
407
|
+
...config,
|
|
408
|
+
hardwareAcceleration: "prefer-software"
|
|
409
|
+
};
|
|
410
|
+
if ((await VideoEncoder.isConfigSupported(software)).supported) {
|
|
411
|
+
return software;
|
|
412
|
+
}
|
|
413
|
+
return null;
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
// src/can-reencode-video-track.ts
|
|
417
|
+
var canReencodeVideoTrack = async ({
|
|
418
|
+
videoCodec,
|
|
419
|
+
track
|
|
420
|
+
}) => {
|
|
421
|
+
const videoEncoderConfig = await getVideoEncoderConfig({
|
|
422
|
+
codec: videoCodec,
|
|
423
|
+
height: track.displayAspectHeight,
|
|
424
|
+
width: track.displayAspectWidth
|
|
425
|
+
});
|
|
426
|
+
const videoDecoderConfig = await getVideoDecoderConfigWithHardwareAcceleration(track);
|
|
427
|
+
return Boolean(videoDecoderConfig && videoEncoderConfig);
|
|
428
|
+
};
|
|
429
|
+
// src/codec-id.ts
|
|
430
|
+
var availableVideoCodecs = ["vp8", "vp9"];
|
|
431
|
+
var getAvailableVideoCodecs = () => availableVideoCodecs;
|
|
432
|
+
var availableAudioCodecs = ["opus"];
|
|
433
|
+
var getAvailableAudioCodecs = () => availableAudioCodecs;
|
|
293
434
|
// src/convert-media.ts
|
|
294
435
|
import {
|
|
295
436
|
MediaParserInternals as MediaParserInternals2,
|
|
@@ -316,72 +457,58 @@ var autoSelectWriter = async (writer, logLevel) => {
|
|
|
316
457
|
// src/calculate-progress.ts
|
|
317
458
|
var calculateProgress = ({
|
|
318
459
|
millisecondsWritten,
|
|
319
|
-
|
|
460
|
+
expectedOutputDurationInMs
|
|
320
461
|
}) => {
|
|
321
|
-
if (
|
|
462
|
+
if (expectedOutputDurationInMs === null) {
|
|
322
463
|
return null;
|
|
323
464
|
}
|
|
324
|
-
return millisecondsWritten /
|
|
465
|
+
return millisecondsWritten / expectedOutputDurationInMs;
|
|
325
466
|
};
|
|
326
467
|
|
|
327
468
|
// src/error-cause.ts
|
|
328
469
|
var error_cause_default = Error;
|
|
329
470
|
|
|
330
|
-
// src/
|
|
331
|
-
var
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
// src/audio-encoder-config.ts
|
|
342
|
-
var getAudioEncoderConfig = async (config) => {
|
|
343
|
-
if (typeof AudioEncoder === "undefined") {
|
|
344
|
-
return null;
|
|
345
|
-
}
|
|
346
|
-
if ((await AudioEncoder.isConfigSupported(config)).supported) {
|
|
347
|
-
return config;
|
|
348
|
-
}
|
|
349
|
-
return null;
|
|
471
|
+
// src/convert-encoded-chunk.ts
|
|
472
|
+
var convertEncodedChunk = (chunk) => {
|
|
473
|
+
const arr = new Uint8Array(chunk.byteLength);
|
|
474
|
+
chunk.copyTo(arr);
|
|
475
|
+
return {
|
|
476
|
+
data: arr,
|
|
477
|
+
duration: chunk.duration ?? undefined,
|
|
478
|
+
timestamp: chunk.timestamp,
|
|
479
|
+
type: chunk.type
|
|
480
|
+
};
|
|
350
481
|
};
|
|
351
482
|
|
|
352
483
|
// src/resolve-audio-action.ts
|
|
353
|
-
var
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
var defaultResolveAudioAction = ({
|
|
360
|
-
canReencode,
|
|
361
|
-
canCopy
|
|
484
|
+
var DEFAULT_BITRATE = 128000;
|
|
485
|
+
var defaultResolveAudioAction = async ({
|
|
486
|
+
track,
|
|
487
|
+
audioCodec,
|
|
488
|
+
logLevel,
|
|
489
|
+
container
|
|
362
490
|
}) => {
|
|
491
|
+
const bitrate = DEFAULT_BITRATE;
|
|
492
|
+
const canCopy = canCopyAudioTrack({
|
|
493
|
+
inputCodec: track.codecWithoutConfig,
|
|
494
|
+
outputCodec: audioCodec,
|
|
495
|
+
container
|
|
496
|
+
});
|
|
363
497
|
if (canCopy) {
|
|
364
|
-
|
|
498
|
+
Log.verbose(logLevel, `Track ${track.trackId} (audio): Can copy = ${canCopy}, action = copy`);
|
|
499
|
+
return Promise.resolve({ type: "copy" });
|
|
365
500
|
}
|
|
501
|
+
const canReencode = await canReencodeAudioTrack({
|
|
502
|
+
audioCodec,
|
|
503
|
+
track,
|
|
504
|
+
bitrate
|
|
505
|
+
});
|
|
366
506
|
if (canReencode) {
|
|
367
|
-
|
|
507
|
+
Log.verbose(logLevel, `Track ${track.trackId} (audio): Can re-encode = ${canReencode}, can copy = ${canCopy}, action = reencode`);
|
|
508
|
+
return Promise.resolve({ type: "reencode", bitrate, audioCodec });
|
|
368
509
|
}
|
|
369
|
-
|
|
370
|
-
};
|
|
371
|
-
var resolveAudioAction = async ({
|
|
372
|
-
audioDecoderConfig,
|
|
373
|
-
audioEncoderConfig,
|
|
374
|
-
track,
|
|
375
|
-
audioCodec,
|
|
376
|
-
resolverFunction
|
|
377
|
-
}) => {
|
|
378
|
-
const canReencode = Boolean(audioDecoderConfig && audioEncoderConfig);
|
|
379
|
-
const canCopy = canCopyAudioTrack(track.codecWithoutConfig, audioCodec);
|
|
380
|
-
const resolved = await resolverFunction({
|
|
381
|
-
canReencode,
|
|
382
|
-
canCopy
|
|
383
|
-
});
|
|
384
|
-
return resolved;
|
|
510
|
+
Log.verbose(logLevel, `Track ${track.trackId} (audio): Can re-encode = ${canReencode}, can copy = ${canCopy}, action = drop`);
|
|
511
|
+
return Promise.resolve({ type: "drop" });
|
|
385
512
|
};
|
|
386
513
|
|
|
387
514
|
// src/on-audio-track.ts
|
|
@@ -393,32 +520,19 @@ var makeAudioTrackHandler = ({
|
|
|
393
520
|
abortConversion,
|
|
394
521
|
onMediaStateUpdate,
|
|
395
522
|
onAudioTrack,
|
|
396
|
-
|
|
397
|
-
|
|
523
|
+
logLevel,
|
|
524
|
+
container
|
|
398
525
|
}) => async (track) => {
|
|
399
|
-
const
|
|
400
|
-
codec: audioCodec,
|
|
401
|
-
numberOfChannels: track.numberOfChannels,
|
|
402
|
-
sampleRate: track.sampleRate,
|
|
403
|
-
bitrate
|
|
404
|
-
});
|
|
405
|
-
const audioDecoderConfig = await getAudioDecoderConfig({
|
|
406
|
-
codec: track.codec,
|
|
407
|
-
numberOfChannels: track.numberOfChannels,
|
|
408
|
-
sampleRate: track.sampleRate,
|
|
409
|
-
description: track.description
|
|
410
|
-
});
|
|
411
|
-
const audioOperation = await resolveAudioAction({
|
|
412
|
-
audioDecoderConfig,
|
|
413
|
-
audioEncoderConfig,
|
|
526
|
+
const audioOperation = await (onAudioTrack ?? defaultResolveAudioAction)({
|
|
414
527
|
audioCodec,
|
|
415
528
|
track,
|
|
416
|
-
|
|
529
|
+
logLevel,
|
|
530
|
+
container
|
|
417
531
|
});
|
|
418
|
-
if (audioOperation === "drop") {
|
|
532
|
+
if (audioOperation.type === "drop") {
|
|
419
533
|
return null;
|
|
420
534
|
}
|
|
421
|
-
if (audioOperation === "copy") {
|
|
535
|
+
if (audioOperation.type === "copy") {
|
|
422
536
|
const addedTrack = await state.addTrack({
|
|
423
537
|
type: "audio",
|
|
424
538
|
codec: audioCodec,
|
|
@@ -427,11 +541,23 @@ var makeAudioTrackHandler = ({
|
|
|
427
541
|
codecPrivate: track.codecPrivate
|
|
428
542
|
});
|
|
429
543
|
return async (audioSample) => {
|
|
430
|
-
await state.addSample(
|
|
544
|
+
await state.addSample(audioSample, addedTrack.trackNumber, false);
|
|
431
545
|
convertMediaState.encodedAudioFrames++;
|
|
432
546
|
onMediaStateUpdate?.({ ...convertMediaState });
|
|
433
547
|
};
|
|
434
548
|
}
|
|
549
|
+
const audioEncoderConfig = await getAudioEncoderConfig({
|
|
550
|
+
numberOfChannels: track.numberOfChannels,
|
|
551
|
+
sampleRate: track.sampleRate,
|
|
552
|
+
codec: audioOperation.audioCodec,
|
|
553
|
+
bitrate: audioOperation.bitrate
|
|
554
|
+
});
|
|
555
|
+
const audioDecoderConfig = await getAudioDecoderConfig({
|
|
556
|
+
codec: track.codec,
|
|
557
|
+
numberOfChannels: track.numberOfChannels,
|
|
558
|
+
sampleRate: track.sampleRate,
|
|
559
|
+
description: track.description
|
|
560
|
+
});
|
|
435
561
|
if (!audioEncoderConfig) {
|
|
436
562
|
abortConversion(new error_cause_default(`Could not configure audio encoder of track ${track.trackId}`));
|
|
437
563
|
return null;
|
|
@@ -449,7 +575,7 @@ var makeAudioTrackHandler = ({
|
|
|
449
575
|
});
|
|
450
576
|
const audioEncoder = createAudioEncoder({
|
|
451
577
|
onChunk: async (chunk) => {
|
|
452
|
-
await state.addSample(chunk, trackNumber, false);
|
|
578
|
+
await state.addSample(convertEncodedChunk(chunk), trackNumber, false);
|
|
453
579
|
convertMediaState.encodedAudioFrames++;
|
|
454
580
|
onMediaStateUpdate?.({ ...convertMediaState });
|
|
455
581
|
},
|
|
@@ -490,47 +616,71 @@ var makeAudioTrackHandler = ({
|
|
|
490
616
|
};
|
|
491
617
|
};
|
|
492
618
|
|
|
493
|
-
// src/
|
|
494
|
-
var
|
|
495
|
-
|
|
496
|
-
|
|
619
|
+
// src/on-frame.ts
|
|
620
|
+
var onFrame = async ({
|
|
621
|
+
frame,
|
|
622
|
+
onVideoFrame,
|
|
623
|
+
videoEncoder,
|
|
624
|
+
onMediaStateUpdate,
|
|
625
|
+
track,
|
|
626
|
+
convertMediaState
|
|
627
|
+
}) => {
|
|
628
|
+
const newFrame = onVideoFrame ? await onVideoFrame({ frame, track }) : frame;
|
|
629
|
+
if (newFrame.codedHeight !== frame.codedHeight) {
|
|
630
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different codedHeight (${newFrame.codedHeight}) than the input frame (${frame.codedHeight})`);
|
|
497
631
|
}
|
|
498
|
-
if (
|
|
499
|
-
|
|
632
|
+
if (newFrame.codedWidth !== frame.codedWidth) {
|
|
633
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different codedWidth (${newFrame.codedWidth}) than the input frame (${frame.codedWidth})`);
|
|
500
634
|
}
|
|
501
|
-
|
|
502
|
-
};
|
|
503
|
-
var defaultResolveVideoAction = ({
|
|
504
|
-
canReencode,
|
|
505
|
-
canCopy
|
|
506
|
-
}) => {
|
|
507
|
-
if (canCopy) {
|
|
508
|
-
return "copy";
|
|
635
|
+
if (newFrame.displayWidth !== frame.displayWidth) {
|
|
636
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different displayWidth (${newFrame.displayWidth}) than the input frame (${newFrame.displayHeight})`);
|
|
509
637
|
}
|
|
510
|
-
if (
|
|
511
|
-
|
|
638
|
+
if (newFrame.displayHeight !== frame.displayHeight) {
|
|
639
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different displayHeight (${newFrame.displayHeight}) than the input frame (${newFrame.displayHeight})`);
|
|
640
|
+
}
|
|
641
|
+
if (newFrame.timestamp !== frame.timestamp) {
|
|
642
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different timestamp (${newFrame.timestamp}) than the input frame (${newFrame.timestamp}). When calling new VideoFrame(), pass {timestamp: frame.timestamp} as second argument`);
|
|
643
|
+
}
|
|
644
|
+
if (newFrame.duration !== frame.duration) {
|
|
645
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different duration (${newFrame.duration}) than the input frame (${newFrame.duration}). When calling new VideoFrame(), pass {duration: frame.duration} as second argument`);
|
|
646
|
+
}
|
|
647
|
+
await videoEncoder.encodeFrame(newFrame, newFrame.timestamp);
|
|
648
|
+
convertMediaState.decodedVideoFrames++;
|
|
649
|
+
onMediaStateUpdate?.({ ...convertMediaState });
|
|
650
|
+
newFrame.close();
|
|
651
|
+
if (frame !== newFrame) {
|
|
652
|
+
frame.close();
|
|
512
653
|
}
|
|
513
|
-
return "drop";
|
|
514
654
|
};
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
655
|
+
|
|
656
|
+
// src/resolve-video-action.ts
|
|
657
|
+
var defaultResolveVideoAction = async ({
|
|
518
658
|
track,
|
|
519
659
|
videoCodec,
|
|
520
|
-
|
|
660
|
+
logLevel,
|
|
661
|
+
container
|
|
521
662
|
}) => {
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
canCopy
|
|
663
|
+
const canCopy = canCopyVideoTrack({
|
|
664
|
+
inputCodec: track.codecWithoutConfig,
|
|
665
|
+
outputCodec: videoCodec,
|
|
666
|
+
container
|
|
527
667
|
});
|
|
528
|
-
|
|
668
|
+
if (canCopy) {
|
|
669
|
+
Log.verbose(logLevel, `Track ${track.trackId} (video): Can copy, therefore copying`);
|
|
670
|
+
return Promise.resolve({ type: "copy" });
|
|
671
|
+
}
|
|
672
|
+
const canReencode = await canReencodeVideoTrack({ videoCodec, track });
|
|
673
|
+
if (canReencode) {
|
|
674
|
+
Log.verbose(logLevel, `Track ${track.trackId} (video): Cannot copy, but re-enconde, therefore re-encoding`);
|
|
675
|
+
return Promise.resolve({ type: "reencode", videoCodec });
|
|
676
|
+
}
|
|
677
|
+
Log.verbose(logLevel, `Track ${track.trackId} (video): Can neither copy nor re-encode, therefore dropping`);
|
|
678
|
+
return Promise.resolve({ type: "drop" });
|
|
529
679
|
};
|
|
530
680
|
|
|
531
681
|
// src/video-decoder.ts
|
|
532
682
|
var createVideoDecoder = ({
|
|
533
|
-
onFrame,
|
|
683
|
+
onFrame: onFrame2,
|
|
534
684
|
onError,
|
|
535
685
|
signal,
|
|
536
686
|
config,
|
|
@@ -549,7 +699,7 @@ var createVideoDecoder = ({
|
|
|
549
699
|
if (signal.aborted) {
|
|
550
700
|
return;
|
|
551
701
|
}
|
|
552
|
-
return
|
|
702
|
+
return onFrame2(inputFrame);
|
|
553
703
|
}).then(() => {
|
|
554
704
|
ioSynchronizer.onProcessed();
|
|
555
705
|
signal.removeEventListener("abort", abortHandler);
|
|
@@ -608,28 +758,6 @@ var createVideoDecoder = ({
|
|
|
608
758
|
};
|
|
609
759
|
};
|
|
610
760
|
|
|
611
|
-
// src/video-decoder-config.ts
|
|
612
|
-
var getVideoDecoderConfigWithHardwareAcceleration = async (config) => {
|
|
613
|
-
if (typeof VideoDecoder === "undefined") {
|
|
614
|
-
return null;
|
|
615
|
-
}
|
|
616
|
-
const hardware = {
|
|
617
|
-
...config,
|
|
618
|
-
hardwareAcceleration: "prefer-hardware"
|
|
619
|
-
};
|
|
620
|
-
if ((await VideoDecoder.isConfigSupported(hardware)).supported) {
|
|
621
|
-
return hardware;
|
|
622
|
-
}
|
|
623
|
-
const software = {
|
|
624
|
-
...config,
|
|
625
|
-
hardwareAcceleration: "prefer-software"
|
|
626
|
-
};
|
|
627
|
-
if ((await VideoDecoder.isConfigSupported(software)).supported) {
|
|
628
|
-
return software;
|
|
629
|
-
}
|
|
630
|
-
return null;
|
|
631
|
-
};
|
|
632
|
-
|
|
633
761
|
// src/video-encoder.ts
|
|
634
762
|
var createVideoEncoder = ({
|
|
635
763
|
onChunk,
|
|
@@ -715,28 +843,6 @@ var createVideoEncoder = ({
|
|
|
715
843
|
};
|
|
716
844
|
};
|
|
717
845
|
|
|
718
|
-
// src/video-encoder-config.ts
|
|
719
|
-
var getVideoEncoderConfig = async (config) => {
|
|
720
|
-
if (typeof VideoEncoder === "undefined") {
|
|
721
|
-
return null;
|
|
722
|
-
}
|
|
723
|
-
const hardware = {
|
|
724
|
-
...config,
|
|
725
|
-
hardwareAcceleration: "prefer-hardware"
|
|
726
|
-
};
|
|
727
|
-
if ((await VideoEncoder.isConfigSupported(hardware)).supported) {
|
|
728
|
-
return hardware;
|
|
729
|
-
}
|
|
730
|
-
const software = {
|
|
731
|
-
...config,
|
|
732
|
-
hardwareAcceleration: "prefer-software"
|
|
733
|
-
};
|
|
734
|
-
if ((await VideoEncoder.isConfigSupported(software)).supported) {
|
|
735
|
-
return software;
|
|
736
|
-
}
|
|
737
|
-
return null;
|
|
738
|
-
};
|
|
739
|
-
|
|
740
846
|
// src/on-video-track.ts
|
|
741
847
|
var makeVideoTrackHandler = ({
|
|
742
848
|
state,
|
|
@@ -747,28 +853,22 @@ var makeVideoTrackHandler = ({
|
|
|
747
853
|
controller,
|
|
748
854
|
videoCodec,
|
|
749
855
|
onVideoTrack,
|
|
750
|
-
logLevel
|
|
856
|
+
logLevel,
|
|
857
|
+
container
|
|
751
858
|
}) => async (track) => {
|
|
752
859
|
if (controller.signal.aborted) {
|
|
753
860
|
throw new error_cause_default("Aborted");
|
|
754
861
|
}
|
|
755
|
-
const
|
|
756
|
-
codec: videoCodec === "vp9" ? "vp09.00.10.08" : videoCodec,
|
|
757
|
-
height: track.displayAspectHeight,
|
|
758
|
-
width: track.displayAspectWidth
|
|
759
|
-
});
|
|
760
|
-
const videoDecoderConfig = await getVideoDecoderConfigWithHardwareAcceleration(track);
|
|
761
|
-
const videoOperation = await resolveVideoAction({
|
|
762
|
-
videoDecoderConfig,
|
|
763
|
-
videoEncoderConfig,
|
|
862
|
+
const videoOperation = await (onVideoTrack ?? defaultResolveVideoAction)({
|
|
764
863
|
track,
|
|
765
864
|
videoCodec,
|
|
766
|
-
|
|
865
|
+
logLevel,
|
|
866
|
+
container
|
|
767
867
|
});
|
|
768
|
-
if (videoOperation === "drop") {
|
|
868
|
+
if (videoOperation.type === "drop") {
|
|
769
869
|
return null;
|
|
770
870
|
}
|
|
771
|
-
if (videoOperation === "copy") {
|
|
871
|
+
if (videoOperation.type === "copy") {
|
|
772
872
|
const videoTrack = await state.addTrack({
|
|
773
873
|
type: "video",
|
|
774
874
|
color: track.color,
|
|
@@ -778,11 +878,17 @@ var makeVideoTrackHandler = ({
|
|
|
778
878
|
codecPrivate: track.codecPrivate
|
|
779
879
|
});
|
|
780
880
|
return async (sample) => {
|
|
781
|
-
await state.addSample(
|
|
881
|
+
await state.addSample(sample, videoTrack.trackNumber, true);
|
|
782
882
|
convertMediaState.decodedVideoFrames++;
|
|
783
883
|
onMediaStateUpdate?.({ ...convertMediaState });
|
|
784
884
|
};
|
|
785
885
|
}
|
|
886
|
+
const videoEncoderConfig = await getVideoEncoderConfig({
|
|
887
|
+
codec: videoOperation.videoCodec,
|
|
888
|
+
height: track.displayAspectHeight,
|
|
889
|
+
width: track.displayAspectWidth
|
|
890
|
+
});
|
|
891
|
+
const videoDecoderConfig = await getVideoDecoderConfigWithHardwareAcceleration(track);
|
|
786
892
|
if (videoEncoderConfig === null) {
|
|
787
893
|
abortConversion(new error_cause_default(`Could not configure video encoder of track ${track.trackId}`));
|
|
788
894
|
return null;
|
|
@@ -801,7 +907,7 @@ var makeVideoTrackHandler = ({
|
|
|
801
907
|
});
|
|
802
908
|
const videoEncoder = createVideoEncoder({
|
|
803
909
|
onChunk: async (chunk) => {
|
|
804
|
-
await state.addSample(chunk, trackNumber, true);
|
|
910
|
+
await state.addSample(convertEncodedChunk(chunk), trackNumber, true);
|
|
805
911
|
convertMediaState.encodedVideoFrames++;
|
|
806
912
|
onMediaStateUpdate?.({ ...convertMediaState });
|
|
807
913
|
},
|
|
@@ -817,11 +923,14 @@ var makeVideoTrackHandler = ({
|
|
|
817
923
|
const videoDecoder = createVideoDecoder({
|
|
818
924
|
config: videoDecoderConfig,
|
|
819
925
|
onFrame: async (frame) => {
|
|
820
|
-
await
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
926
|
+
await onFrame({
|
|
927
|
+
convertMediaState,
|
|
928
|
+
frame,
|
|
929
|
+
onMediaStateUpdate,
|
|
930
|
+
track,
|
|
931
|
+
videoEncoder,
|
|
932
|
+
onVideoFrame
|
|
933
|
+
});
|
|
825
934
|
},
|
|
826
935
|
onError: (err) => {
|
|
827
936
|
abortConversion(new error_cause_default(`Video decoder of track ${track.trackId} failed (see .cause of this error)`, {
|
|
@@ -848,7 +957,7 @@ var convertMedia = async function({
|
|
|
848
957
|
onVideoFrame,
|
|
849
958
|
onMediaStateUpdate: onMediaStateDoNoCallDirectly,
|
|
850
959
|
audioCodec,
|
|
851
|
-
|
|
960
|
+
container,
|
|
852
961
|
videoCodec,
|
|
853
962
|
signal: userPassedAbortSignal,
|
|
854
963
|
onAudioTrack: userAudioResolver,
|
|
@@ -862,7 +971,7 @@ var convertMedia = async function({
|
|
|
862
971
|
if (userPassedAbortSignal?.aborted) {
|
|
863
972
|
return Promise.reject(new error_cause_default("Aborted"));
|
|
864
973
|
}
|
|
865
|
-
if (
|
|
974
|
+
if (container !== "webm") {
|
|
866
975
|
return Promise.reject(new TypeError('Only `to: "webm"` is supported currently'));
|
|
867
976
|
}
|
|
868
977
|
if (audioCodec !== "opus") {
|
|
@@ -890,7 +999,7 @@ var convertMedia = async function({
|
|
|
890
999
|
encodedAudioFrames: 0,
|
|
891
1000
|
bytesWritten: 0,
|
|
892
1001
|
millisecondsWritten: 0,
|
|
893
|
-
|
|
1002
|
+
expectedOutputDurationInMs: null,
|
|
894
1003
|
overallProgress: 0
|
|
895
1004
|
};
|
|
896
1005
|
const onMediaStateUpdate = (newState) => {
|
|
@@ -910,7 +1019,7 @@ var convertMedia = async function({
|
|
|
910
1019
|
convertMediaState.millisecondsWritten = millisecondsWritten;
|
|
911
1020
|
convertMediaState.overallProgress = calculateProgress({
|
|
912
1021
|
millisecondsWritten: convertMediaState.millisecondsWritten,
|
|
913
|
-
|
|
1022
|
+
expectedOutputDurationInMs: convertMediaState.expectedOutputDurationInMs
|
|
914
1023
|
});
|
|
915
1024
|
onMediaStateUpdate?.(convertMediaState);
|
|
916
1025
|
}
|
|
@@ -924,8 +1033,9 @@ var convertMedia = async function({
|
|
|
924
1033
|
convertMediaState,
|
|
925
1034
|
controller,
|
|
926
1035
|
videoCodec,
|
|
927
|
-
onVideoTrack: userVideoResolver ??
|
|
928
|
-
logLevel
|
|
1036
|
+
onVideoTrack: userVideoResolver ?? null,
|
|
1037
|
+
logLevel,
|
|
1038
|
+
container
|
|
929
1039
|
});
|
|
930
1040
|
const onAudioTrack = makeAudioTrackHandler({
|
|
931
1041
|
abortConversion,
|
|
@@ -934,9 +1044,9 @@ var convertMedia = async function({
|
|
|
934
1044
|
convertMediaState,
|
|
935
1045
|
onMediaStateUpdate: onMediaStateUpdate ?? null,
|
|
936
1046
|
state,
|
|
937
|
-
onAudioTrack: userAudioResolver ??
|
|
938
|
-
|
|
939
|
-
|
|
1047
|
+
onAudioTrack: userAudioResolver ?? null,
|
|
1048
|
+
logLevel,
|
|
1049
|
+
container
|
|
940
1050
|
});
|
|
941
1051
|
parseMedia({
|
|
942
1052
|
src,
|
|
@@ -957,11 +1067,11 @@ var convertMedia = async function({
|
|
|
957
1067
|
if (casted.onDurationInSeconds) {
|
|
958
1068
|
casted.onDurationInSeconds(durationInSeconds);
|
|
959
1069
|
}
|
|
960
|
-
const
|
|
961
|
-
convertMediaState.
|
|
1070
|
+
const expectedOutputDurationInMs = durationInSeconds * 1000;
|
|
1071
|
+
convertMediaState.expectedOutputDurationInMs = expectedOutputDurationInMs;
|
|
962
1072
|
convertMediaState.overallProgress = calculateProgress({
|
|
963
1073
|
millisecondsWritten: convertMediaState.millisecondsWritten,
|
|
964
|
-
|
|
1074
|
+
expectedOutputDurationInMs
|
|
965
1075
|
});
|
|
966
1076
|
onMediaStateUpdate(convertMediaState);
|
|
967
1077
|
}
|
|
@@ -977,9 +1087,15 @@ var convertMedia = async function({
|
|
|
977
1087
|
});
|
|
978
1088
|
};
|
|
979
1089
|
export {
|
|
1090
|
+
getAvailableVideoCodecs,
|
|
1091
|
+
getAvailableAudioCodecs,
|
|
980
1092
|
createVideoEncoder,
|
|
981
1093
|
createVideoDecoder,
|
|
982
1094
|
createAudioEncoder,
|
|
983
1095
|
createAudioDecoder,
|
|
984
|
-
convertMedia
|
|
1096
|
+
convertMedia,
|
|
1097
|
+
canReencodeVideoTrack,
|
|
1098
|
+
canReencodeAudioTrack,
|
|
1099
|
+
canCopyVideoTrack,
|
|
1100
|
+
canCopyAudioTrack
|
|
985
1101
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
export { WebCodecsAudioDecoder, createAudioDecoder } from './audio-decoder';
|
|
2
2
|
export { WebCodecsAudioEncoder, createAudioEncoder } from './audio-encoder';
|
|
3
|
-
export {
|
|
3
|
+
export { canCopyAudioTrack } from './can-copy-audio-track';
|
|
4
|
+
export { canCopyVideoTrack } from './can-copy-video-track';
|
|
5
|
+
export { canReencodeAudioTrack } from './can-reencode-audio-track';
|
|
6
|
+
export { canReencodeVideoTrack } from './can-reencode-video-track';
|
|
7
|
+
export { ConvertMediaAudioCodec, ConvertMediaVideoCodec, getAvailableAudioCodecs, getAvailableVideoCodecs, } from './codec-id';
|
|
8
|
+
export { ConvertMediaContainer, ConvertMediaOnMediaStateUpdate, ConvertMediaOnVideoFrame, ConvertMediaResult, ConvertMediaState, convertMedia, } from './convert-media';
|
|
9
|
+
export { AudioOperation, ResolveAudioActionFn } from './resolve-audio-action';
|
|
10
|
+
export { ResolveVideoActionFn, VideoOperation } from './resolve-video-action';
|
|
4
11
|
export { WebCodecsVideoDecoder, createVideoDecoder } from './video-decoder';
|
|
5
12
|
export { WebCodecsVideoEncoder, createVideoEncoder } from './video-encoder';
|