@remotion/webcodecs 4.0.251 → 4.0.253
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.d.ts +3 -2
- package/dist/audio-decoder.js +11 -9
- package/dist/audio-encoder.d.ts +4 -3
- package/dist/audio-encoder.js +10 -9
- package/dist/auto-select-writer.d.ts +1 -1
- package/dist/can-copy-video-track.js +2 -1
- package/dist/choose-correct-hevc-profile.d.ts +5 -0
- package/dist/choose-correct-hevc-profile.js +42 -0
- package/dist/controller.d.ts +16 -0
- package/dist/controller.js +16 -0
- package/dist/convert-media.d.ts +6 -6
- package/dist/convert-media.js +53 -21
- package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.d.ts +11 -0
- package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.js +29 -11
- package/dist/create/iso-base-media/codec-specific/hvc1.d.ts +2 -0
- package/dist/create/iso-base-media/codec-specific/hvc1.js +48 -0
- package/dist/create/iso-base-media/create-iso-base-media.js +8 -4
- package/dist/create/iso-base-media/serialize-track.js +3 -1
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-hvcc.d.ts +1 -0
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-hvcc.js +16 -0
- package/dist/create/matroska/cluster.d.ts +1 -1
- package/dist/create/matroska/create-matroska-media.js +8 -4
- package/dist/create/matroska/matroska-trackentry.js +3 -0
- package/dist/create/matroska/matroska-utils.d.ts +1 -1
- package/dist/create/media-fn.d.ts +2 -3
- package/dist/create/wav/create-wav.js +8 -4
- package/dist/emitter.d.ts +20 -0
- package/dist/emitter.js +29 -0
- package/dist/esm/buffer.mjs +5 -22
- package/dist/esm/index.mjs +633 -159
- package/dist/esm/web-fs.mjs +4 -22
- package/dist/get-available-containers.d.ts +1 -2
- package/dist/get-available-containers.js +3 -3
- package/dist/get-available-video-codecs.d.ts +1 -2
- package/dist/get-available-video-codecs.js +3 -4
- package/dist/get-codec-string.d.ts +7 -0
- package/dist/get-codec-string.js +21 -0
- package/dist/hevc-levels.d.ts +13 -0
- package/dist/hevc-levels.js +233 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/io-manager/io-synchronizer.d.ts +4 -3
- package/dist/io-manager/io-synchronizer.js +19 -14
- package/dist/io-manager/make-timeout-promise.d.ts +6 -1
- package/dist/io-manager/make-timeout-promise.js +23 -5
- package/dist/on-audio-track.d.ts +2 -2
- package/dist/on-audio-track.js +13 -16
- package/dist/on-video-track.d.ts +2 -2
- package/dist/on-video-track.js +10 -14
- package/dist/select-container-creator.d.ts +1 -1
- package/dist/test/remux-serverside.test.js +2 -2
- package/dist/throttled-state-update.d.ts +1 -1
- package/dist/throttled-state-update.js +2 -2
- package/dist/video-decoder.d.ts +3 -2
- package/dist/video-decoder.js +10 -8
- package/dist/video-encoder-config.js +4 -6
- package/dist/video-encoder.d.ts +4 -3
- package/dist/video-encoder.js +13 -8
- package/dist/wav-audio-encoder.d.ts +1 -1
- package/dist/wav-audio-encoder.js +2 -2
- package/dist/webcodecs-controller.d.ts +16 -0
- package/dist/webcodecs-controller.js +16 -0
- package/dist/writers/buffer-implementation/writer.d.ts +1 -1
- package/dist/writers/buffer-implementation/writer.js +5 -4
- package/dist/writers/buffer.d.ts +1 -1
- package/dist/writers/web-fs.d.ts +1 -1
- package/dist/writers/web-fs.js +4 -4
- package/package.json +5 -5
package/dist/esm/index.mjs
CHANGED
|
@@ -125,11 +125,14 @@ var createContent = async ({ filename }) => {
|
|
|
125
125
|
writPromise = writPromise.then(() => write(arr));
|
|
126
126
|
return writPromise;
|
|
127
127
|
},
|
|
128
|
-
|
|
128
|
+
finish: async () => {
|
|
129
|
+
await writPromise;
|
|
129
130
|
try {
|
|
130
131
|
await writable.close();
|
|
131
132
|
} catch {
|
|
132
133
|
}
|
|
134
|
+
},
|
|
135
|
+
async getBlob() {
|
|
133
136
|
const newHandle = await directoryHandle.getFileHandle(actualFilename, {
|
|
134
137
|
create: true
|
|
135
138
|
});
|
|
@@ -141,9 +144,6 @@ var createContent = async ({ filename }) => {
|
|
|
141
144
|
writPromise = writPromise.then(() => updateDataAt(position, data));
|
|
142
145
|
return writPromise;
|
|
143
146
|
},
|
|
144
|
-
waitForFinish: async () => {
|
|
145
|
-
await writPromise;
|
|
146
|
-
},
|
|
147
147
|
remove
|
|
148
148
|
};
|
|
149
149
|
return writer;
|
|
@@ -192,10 +192,14 @@ var createContent2 = ({ filename, mimeType }) => {
|
|
|
192
192
|
writPromise = writPromise.then(() => write(arr));
|
|
193
193
|
return writPromise;
|
|
194
194
|
},
|
|
195
|
-
|
|
195
|
+
finish: async () => {
|
|
196
|
+
await writPromise;
|
|
196
197
|
if (removed) {
|
|
197
198
|
return Promise.reject(new Error("Already called .remove() on the result"));
|
|
198
199
|
}
|
|
200
|
+
return Promise.resolve();
|
|
201
|
+
},
|
|
202
|
+
getBlob() {
|
|
199
203
|
const arr = new Uint8Array(buf);
|
|
200
204
|
return Promise.resolve(new File([arr.slice()], filename, { type: mimeType }));
|
|
201
205
|
},
|
|
@@ -207,9 +211,6 @@ var createContent2 = ({ filename, mimeType }) => {
|
|
|
207
211
|
updateDataAt: (position, newData) => {
|
|
208
212
|
writPromise = writPromise.then(() => updateDataAt(position, newData));
|
|
209
213
|
return writPromise;
|
|
210
|
-
},
|
|
211
|
-
waitForFinish: async () => {
|
|
212
|
-
await writPromise;
|
|
213
214
|
}
|
|
214
215
|
};
|
|
215
216
|
return Promise.resolve(writer);
|
|
@@ -504,16 +505,38 @@ import { MediaParserInternals } from "@remotion/media-parser";
|
|
|
504
505
|
var { Log } = MediaParserInternals;
|
|
505
506
|
|
|
506
507
|
// src/io-manager/make-timeout-promise.ts
|
|
507
|
-
var makeTimeoutPromise = (
|
|
508
|
+
var makeTimeoutPromise = ({
|
|
509
|
+
label,
|
|
510
|
+
ms,
|
|
511
|
+
controller
|
|
512
|
+
}) => {
|
|
508
513
|
const { promise, reject, resolve } = withResolvers();
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
514
|
+
let timeout = null;
|
|
515
|
+
const set = () => {
|
|
516
|
+
timeout = setTimeout(() => {
|
|
517
|
+
reject(new Error(`${label()} (timed out after ${ms}ms)`));
|
|
518
|
+
}, ms);
|
|
519
|
+
};
|
|
520
|
+
set();
|
|
521
|
+
const onPause = () => {
|
|
522
|
+
if (timeout) {
|
|
523
|
+
clearTimeout(timeout);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
const onResume = () => {
|
|
527
|
+
set();
|
|
528
|
+
};
|
|
529
|
+
controller.addEventListener("pause", onPause);
|
|
530
|
+
controller.addEventListener("resume", onResume);
|
|
512
531
|
return {
|
|
513
532
|
timeoutPromise: promise,
|
|
514
533
|
clear: () => {
|
|
515
|
-
|
|
534
|
+
if (timeout) {
|
|
535
|
+
clearTimeout(timeout);
|
|
536
|
+
}
|
|
516
537
|
resolve();
|
|
538
|
+
controller.removeEventListener("pause", onPause);
|
|
539
|
+
controller.removeEventListener("resume", onResume);
|
|
517
540
|
}
|
|
518
541
|
};
|
|
519
542
|
};
|
|
@@ -589,19 +612,24 @@ var makeIoSynchronizer = ({
|
|
|
589
612
|
unprocessed,
|
|
590
613
|
unemitted,
|
|
591
614
|
minimumProgress,
|
|
592
|
-
|
|
615
|
+
controller
|
|
593
616
|
}) => {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
`
|
|
604
|
-
|
|
617
|
+
await controller._internals.checkForAbortAndPause();
|
|
618
|
+
const { timeoutPromise, clear } = makeTimeoutPromise({
|
|
619
|
+
label: () => [
|
|
620
|
+
`Waited too long for ${label} to finish:`,
|
|
621
|
+
`${getUnemittedItems()} unemitted items`,
|
|
622
|
+
`${getUnprocessed()} unprocessed items: ${JSON.stringify(_unprocessed)}`,
|
|
623
|
+
`smallest progress: ${progress.getSmallestProgress()}`,
|
|
624
|
+
`inputs: ${JSON.stringify(inputs)}`,
|
|
625
|
+
`last output: ${lastOutput}`,
|
|
626
|
+
`wanted: ${unemitted} unemitted items, ${unprocessed} unprocessed items, minimum progress ${minimumProgress}`
|
|
627
|
+
].join(`
|
|
628
|
+
`),
|
|
629
|
+
ms: 1e4,
|
|
630
|
+
controller
|
|
631
|
+
});
|
|
632
|
+
controller._internals.signal.addEventListener("abort", clear);
|
|
605
633
|
await Promise.race([
|
|
606
634
|
timeoutPromise,
|
|
607
635
|
Promise.all([
|
|
@@ -622,14 +650,14 @@ var makeIoSynchronizer = ({
|
|
|
622
650
|
})()
|
|
623
651
|
])
|
|
624
652
|
]).finally(() => clear());
|
|
625
|
-
signal.removeEventListener("abort", clear);
|
|
653
|
+
controller._internals.signal.removeEventListener("abort", clear);
|
|
626
654
|
};
|
|
627
|
-
const waitForFinish = async (
|
|
655
|
+
const waitForFinish = async (controller) => {
|
|
628
656
|
await waitFor({
|
|
629
657
|
unprocessed: 0,
|
|
630
658
|
unemitted: 0,
|
|
631
659
|
minimumProgress: null,
|
|
632
|
-
|
|
660
|
+
controller
|
|
633
661
|
});
|
|
634
662
|
};
|
|
635
663
|
const onProcessed = () => {
|
|
@@ -650,13 +678,13 @@ var makeIoSynchronizer = ({
|
|
|
650
678
|
var createAudioDecoder = ({
|
|
651
679
|
onFrame,
|
|
652
680
|
onError,
|
|
653
|
-
|
|
681
|
+
controller,
|
|
654
682
|
config,
|
|
655
683
|
logLevel,
|
|
656
684
|
track,
|
|
657
685
|
progressTracker
|
|
658
686
|
}) => {
|
|
659
|
-
if (signal.aborted) {
|
|
687
|
+
if (controller._internals.signal.aborted) {
|
|
660
688
|
throw new Error("Not creating audio decoder, already aborted");
|
|
661
689
|
}
|
|
662
690
|
if (config.codec === "pcm-s16") {
|
|
@@ -674,15 +702,17 @@ var createAudioDecoder = ({
|
|
|
674
702
|
const abortHandler = () => {
|
|
675
703
|
frame.close();
|
|
676
704
|
};
|
|
677
|
-
signal.addEventListener("abort", abortHandler, {
|
|
705
|
+
controller._internals.signal.addEventListener("abort", abortHandler, {
|
|
706
|
+
once: true
|
|
707
|
+
});
|
|
678
708
|
outputQueue = outputQueue.then(() => {
|
|
679
|
-
if (signal.aborted) {
|
|
709
|
+
if (controller._internals.signal.aborted) {
|
|
680
710
|
return;
|
|
681
711
|
}
|
|
682
712
|
return onFrame(frame);
|
|
683
713
|
}).then(() => {
|
|
684
714
|
ioSynchronizer.onProcessed();
|
|
685
|
-
signal.removeEventListener("abort", abortHandler);
|
|
715
|
+
controller._internals.signal.removeEventListener("abort", abortHandler);
|
|
686
716
|
return Promise.resolve();
|
|
687
717
|
}).catch((err) => {
|
|
688
718
|
frame.close();
|
|
@@ -694,7 +724,7 @@ var createAudioDecoder = ({
|
|
|
694
724
|
}
|
|
695
725
|
});
|
|
696
726
|
const close = () => {
|
|
697
|
-
signal.removeEventListener("abort", onAbort);
|
|
727
|
+
controller._internals.signal.removeEventListener("abort", onAbort);
|
|
698
728
|
if (audioDecoder.state === "closed") {
|
|
699
729
|
return;
|
|
700
730
|
}
|
|
@@ -703,7 +733,7 @@ var createAudioDecoder = ({
|
|
|
703
733
|
const onAbort = () => {
|
|
704
734
|
close();
|
|
705
735
|
};
|
|
706
|
-
signal.addEventListener("abort", onAbort);
|
|
736
|
+
controller._internals.signal.addEventListener("abort", onAbort);
|
|
707
737
|
audioDecoder.configure(config);
|
|
708
738
|
const processSample = async (audioSample) => {
|
|
709
739
|
if (audioDecoder.state === "closed") {
|
|
@@ -714,7 +744,7 @@ var createAudioDecoder = ({
|
|
|
714
744
|
unemitted: 20,
|
|
715
745
|
unprocessed: 20,
|
|
716
746
|
minimumProgress: audioSample.timestamp - 1e7,
|
|
717
|
-
|
|
747
|
+
controller
|
|
718
748
|
});
|
|
719
749
|
const chunk = new EncodedAudioChunk(audioSample);
|
|
720
750
|
audioDecoder.decode(chunk);
|
|
@@ -732,7 +762,7 @@ var createAudioDecoder = ({
|
|
|
732
762
|
} catch {
|
|
733
763
|
}
|
|
734
764
|
await queue;
|
|
735
|
-
await ioSynchronizer.waitForFinish(
|
|
765
|
+
await ioSynchronizer.waitForFinish(controller);
|
|
736
766
|
await outputQueue;
|
|
737
767
|
},
|
|
738
768
|
close,
|
|
@@ -741,17 +771,20 @@ var createAudioDecoder = ({
|
|
|
741
771
|
}
|
|
742
772
|
};
|
|
743
773
|
};
|
|
774
|
+
// src/audio-encoder.ts
|
|
775
|
+
import { MediaParserAbortError } from "@remotion/media-parser";
|
|
776
|
+
|
|
744
777
|
// src/wav-audio-encoder.ts
|
|
745
778
|
var getWaveAudioEncoder = ({
|
|
746
779
|
onChunk,
|
|
747
|
-
|
|
780
|
+
controller
|
|
748
781
|
}) => {
|
|
749
782
|
return {
|
|
750
783
|
close: () => {
|
|
751
784
|
return Promise.resolve();
|
|
752
785
|
},
|
|
753
786
|
encodeFrame: (audioData) => {
|
|
754
|
-
if (signal.aborted) {
|
|
787
|
+
if (controller._internals.signal.aborted) {
|
|
755
788
|
return Promise.resolve();
|
|
756
789
|
}
|
|
757
790
|
const chunk = {
|
|
@@ -773,17 +806,17 @@ var createAudioEncoder = ({
|
|
|
773
806
|
onChunk,
|
|
774
807
|
onError,
|
|
775
808
|
codec,
|
|
776
|
-
|
|
809
|
+
controller,
|
|
777
810
|
config: audioEncoderConfig,
|
|
778
811
|
logLevel,
|
|
779
812
|
onNewAudioSampleRate,
|
|
780
813
|
progressTracker
|
|
781
814
|
}) => {
|
|
782
|
-
if (signal.aborted) {
|
|
783
|
-
throw new
|
|
815
|
+
if (controller._internals.signal.aborted) {
|
|
816
|
+
throw new MediaParserAbortError("Not creating audio encoder, already aborted");
|
|
784
817
|
}
|
|
785
818
|
if (codec === "wav") {
|
|
786
|
-
return getWaveAudioEncoder({ onChunk,
|
|
819
|
+
return getWaveAudioEncoder({ onChunk, controller });
|
|
787
820
|
}
|
|
788
821
|
const ioSynchronizer = makeIoSynchronizer({
|
|
789
822
|
logLevel,
|
|
@@ -795,7 +828,7 @@ var createAudioEncoder = ({
|
|
|
795
828
|
output: (chunk) => {
|
|
796
829
|
ioSynchronizer.onOutput(chunk.timestamp);
|
|
797
830
|
prom = prom.then(() => {
|
|
798
|
-
if (signal.aborted) {
|
|
831
|
+
if (controller._internals.signal.aborted) {
|
|
799
832
|
return;
|
|
800
833
|
}
|
|
801
834
|
return onChunk(chunk);
|
|
@@ -811,7 +844,7 @@ var createAudioEncoder = ({
|
|
|
811
844
|
}
|
|
812
845
|
});
|
|
813
846
|
const close = () => {
|
|
814
|
-
signal.removeEventListener("abort", onAbort);
|
|
847
|
+
controller._internals.signal.removeEventListener("abort", onAbort);
|
|
815
848
|
if (encoder.state === "closed") {
|
|
816
849
|
return;
|
|
817
850
|
}
|
|
@@ -820,7 +853,7 @@ var createAudioEncoder = ({
|
|
|
820
853
|
const onAbort = () => {
|
|
821
854
|
close();
|
|
822
855
|
};
|
|
823
|
-
signal.addEventListener("abort", onAbort);
|
|
856
|
+
controller._internals.signal.addEventListener("abort", onAbort);
|
|
824
857
|
if (codec !== "opus" && codec !== "aac") {
|
|
825
858
|
throw new Error('Only `codec: "opus"` and `codec: "aac"` is supported currently');
|
|
826
859
|
}
|
|
@@ -834,7 +867,7 @@ var createAudioEncoder = ({
|
|
|
834
867
|
unemitted: 20,
|
|
835
868
|
unprocessed: 20,
|
|
836
869
|
minimumProgress: audioData.timestamp - 1e7,
|
|
837
|
-
|
|
870
|
+
controller
|
|
838
871
|
});
|
|
839
872
|
if (encoder.state === "closed") {
|
|
840
873
|
return;
|
|
@@ -861,7 +894,7 @@ var createAudioEncoder = ({
|
|
|
861
894
|
},
|
|
862
895
|
waitForFinish: async () => {
|
|
863
896
|
await encoder.flush();
|
|
864
|
-
await ioSynchronizer.waitForFinish(
|
|
897
|
+
await ioSynchronizer.waitForFinish(controller);
|
|
865
898
|
await prom;
|
|
866
899
|
},
|
|
867
900
|
close,
|
|
@@ -912,7 +945,7 @@ var canCopyVideoTrack = ({
|
|
|
912
945
|
return inputTrack.codecWithoutConfig === "vp8" || inputTrack.codecWithoutConfig === "vp9";
|
|
913
946
|
}
|
|
914
947
|
if (outputContainer === "mp4") {
|
|
915
|
-
return inputTrack.codecWithoutConfig === "h264" && (inputContainer === "mp4" || inputContainer === "avi");
|
|
948
|
+
return (inputTrack.codecWithoutConfig === "h264" || inputTrack.codecWithoutConfig === "h265") && (inputContainer === "mp4" || inputContainer === "avi");
|
|
916
949
|
}
|
|
917
950
|
if (outputContainer === "wav") {
|
|
918
951
|
return false;
|
|
@@ -1049,6 +1082,284 @@ var chooseCorrectAvc1Profile = ({
|
|
|
1049
1082
|
return `avc1.6400${profile.hex}`;
|
|
1050
1083
|
};
|
|
1051
1084
|
|
|
1085
|
+
// src/hevc-levels.ts
|
|
1086
|
+
var hevcLevels = [
|
|
1087
|
+
{
|
|
1088
|
+
level: "3.1",
|
|
1089
|
+
maxBitrateMainTier: 1e4,
|
|
1090
|
+
maxBitrateHighTier: null,
|
|
1091
|
+
maxResolutionsAndFrameRates: [
|
|
1092
|
+
{
|
|
1093
|
+
width: 720,
|
|
1094
|
+
height: 480,
|
|
1095
|
+
fps: 84.3
|
|
1096
|
+
},
|
|
1097
|
+
{
|
|
1098
|
+
width: 720,
|
|
1099
|
+
height: 576,
|
|
1100
|
+
fps: 75
|
|
1101
|
+
},
|
|
1102
|
+
{
|
|
1103
|
+
width: 960,
|
|
1104
|
+
height: 540,
|
|
1105
|
+
fps: 60
|
|
1106
|
+
},
|
|
1107
|
+
{
|
|
1108
|
+
width: 1280,
|
|
1109
|
+
height: 720,
|
|
1110
|
+
fps: 33.7
|
|
1111
|
+
}
|
|
1112
|
+
]
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
level: "4",
|
|
1116
|
+
maxBitrateMainTier: 12000,
|
|
1117
|
+
maxBitrateHighTier: 30000,
|
|
1118
|
+
maxResolutionsAndFrameRates: [
|
|
1119
|
+
{
|
|
1120
|
+
width: 1280,
|
|
1121
|
+
height: 720,
|
|
1122
|
+
fps: 68
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
width: 1920,
|
|
1126
|
+
height: 1080,
|
|
1127
|
+
fps: 32
|
|
1128
|
+
},
|
|
1129
|
+
{
|
|
1130
|
+
width: 2048,
|
|
1131
|
+
height: 1080,
|
|
1132
|
+
fps: 30
|
|
1133
|
+
}
|
|
1134
|
+
]
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
level: "4.1",
|
|
1138
|
+
maxBitrateMainTier: 20000,
|
|
1139
|
+
maxBitrateHighTier: 50000,
|
|
1140
|
+
maxResolutionsAndFrameRates: [
|
|
1141
|
+
{
|
|
1142
|
+
width: 1280,
|
|
1143
|
+
height: 720,
|
|
1144
|
+
fps: 136
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
width: 1920,
|
|
1148
|
+
height: 1080,
|
|
1149
|
+
fps: 64
|
|
1150
|
+
},
|
|
1151
|
+
{
|
|
1152
|
+
width: 2048,
|
|
1153
|
+
height: 1080,
|
|
1154
|
+
fps: 60
|
|
1155
|
+
}
|
|
1156
|
+
]
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
level: "5",
|
|
1160
|
+
maxBitrateMainTier: 25000,
|
|
1161
|
+
maxBitrateHighTier: 1e5,
|
|
1162
|
+
maxResolutionsAndFrameRates: [
|
|
1163
|
+
{
|
|
1164
|
+
width: 1920,
|
|
1165
|
+
height: 1080,
|
|
1166
|
+
fps: 128
|
|
1167
|
+
},
|
|
1168
|
+
{
|
|
1169
|
+
width: 2048,
|
|
1170
|
+
height: 1080,
|
|
1171
|
+
fps: 120
|
|
1172
|
+
},
|
|
1173
|
+
{
|
|
1174
|
+
width: 3840,
|
|
1175
|
+
height: 2160,
|
|
1176
|
+
fps: 32
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
width: 4096,
|
|
1180
|
+
height: 2160,
|
|
1181
|
+
fps: 30
|
|
1182
|
+
}
|
|
1183
|
+
]
|
|
1184
|
+
},
|
|
1185
|
+
{
|
|
1186
|
+
level: "5.1",
|
|
1187
|
+
maxBitrateMainTier: 40000,
|
|
1188
|
+
maxBitrateHighTier: 160000,
|
|
1189
|
+
maxResolutionsAndFrameRates: [
|
|
1190
|
+
{
|
|
1191
|
+
width: 1920,
|
|
1192
|
+
height: 1080,
|
|
1193
|
+
fps: 256
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
width: 2048,
|
|
1197
|
+
height: 1080,
|
|
1198
|
+
fps: 240
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
width: 3840,
|
|
1202
|
+
height: 2160,
|
|
1203
|
+
fps: 64
|
|
1204
|
+
},
|
|
1205
|
+
{
|
|
1206
|
+
width: 4096,
|
|
1207
|
+
height: 2160,
|
|
1208
|
+
fps: 60
|
|
1209
|
+
}
|
|
1210
|
+
]
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
level: "5.2",
|
|
1214
|
+
maxBitrateMainTier: 60000,
|
|
1215
|
+
maxBitrateHighTier: 240000,
|
|
1216
|
+
maxResolutionsAndFrameRates: [
|
|
1217
|
+
{
|
|
1218
|
+
width: 2048,
|
|
1219
|
+
height: 1080,
|
|
1220
|
+
fps: 300
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
width: 3840,
|
|
1224
|
+
height: 2160,
|
|
1225
|
+
fps: 128
|
|
1226
|
+
},
|
|
1227
|
+
{
|
|
1228
|
+
width: 4096,
|
|
1229
|
+
height: 2160,
|
|
1230
|
+
fps: 120
|
|
1231
|
+
}
|
|
1232
|
+
]
|
|
1233
|
+
},
|
|
1234
|
+
{
|
|
1235
|
+
level: "6",
|
|
1236
|
+
maxBitrateMainTier: 60000,
|
|
1237
|
+
maxBitrateHighTier: 240000,
|
|
1238
|
+
maxResolutionsAndFrameRates: [
|
|
1239
|
+
{
|
|
1240
|
+
width: 3840,
|
|
1241
|
+
height: 2160,
|
|
1242
|
+
fps: 128
|
|
1243
|
+
},
|
|
1244
|
+
{
|
|
1245
|
+
width: 4096,
|
|
1246
|
+
height: 2160,
|
|
1247
|
+
fps: 120
|
|
1248
|
+
},
|
|
1249
|
+
{
|
|
1250
|
+
width: 7680,
|
|
1251
|
+
height: 4320,
|
|
1252
|
+
fps: 32
|
|
1253
|
+
},
|
|
1254
|
+
{
|
|
1255
|
+
width: 8192,
|
|
1256
|
+
height: 4320,
|
|
1257
|
+
fps: 30
|
|
1258
|
+
}
|
|
1259
|
+
]
|
|
1260
|
+
},
|
|
1261
|
+
{
|
|
1262
|
+
level: "6.1",
|
|
1263
|
+
maxBitrateMainTier: 120000,
|
|
1264
|
+
maxBitrateHighTier: 480000,
|
|
1265
|
+
maxResolutionsAndFrameRates: [
|
|
1266
|
+
{
|
|
1267
|
+
width: 3840,
|
|
1268
|
+
height: 2160,
|
|
1269
|
+
fps: 256
|
|
1270
|
+
},
|
|
1271
|
+
{
|
|
1272
|
+
width: 4096,
|
|
1273
|
+
height: 2160,
|
|
1274
|
+
fps: 240
|
|
1275
|
+
},
|
|
1276
|
+
{
|
|
1277
|
+
width: 7680,
|
|
1278
|
+
height: 4320,
|
|
1279
|
+
fps: 64
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
width: 8192,
|
|
1283
|
+
height: 4320,
|
|
1284
|
+
fps: 60
|
|
1285
|
+
}
|
|
1286
|
+
]
|
|
1287
|
+
},
|
|
1288
|
+
{
|
|
1289
|
+
level: "6.2",
|
|
1290
|
+
maxBitrateMainTier: 240000,
|
|
1291
|
+
maxBitrateHighTier: 800000,
|
|
1292
|
+
maxResolutionsAndFrameRates: [
|
|
1293
|
+
{
|
|
1294
|
+
width: 3840,
|
|
1295
|
+
height: 2160,
|
|
1296
|
+
fps: 512
|
|
1297
|
+
},
|
|
1298
|
+
{
|
|
1299
|
+
width: 4096,
|
|
1300
|
+
height: 2160,
|
|
1301
|
+
fps: 480
|
|
1302
|
+
},
|
|
1303
|
+
{
|
|
1304
|
+
width: 7680,
|
|
1305
|
+
height: 4320,
|
|
1306
|
+
fps: 128
|
|
1307
|
+
},
|
|
1308
|
+
{
|
|
1309
|
+
width: 8192,
|
|
1310
|
+
height: 4320,
|
|
1311
|
+
fps: 120
|
|
1312
|
+
}
|
|
1313
|
+
]
|
|
1314
|
+
}
|
|
1315
|
+
];
|
|
1316
|
+
|
|
1317
|
+
// src/choose-correct-hevc-profile.ts
|
|
1318
|
+
var chooseCorrectHevcProfile = ({
|
|
1319
|
+
width,
|
|
1320
|
+
height,
|
|
1321
|
+
fps
|
|
1322
|
+
}) => {
|
|
1323
|
+
const profile = hevcLevels.find((p) => {
|
|
1324
|
+
return p.maxResolutionsAndFrameRates.some((max) => {
|
|
1325
|
+
if (width > max.width) {
|
|
1326
|
+
return false;
|
|
1327
|
+
}
|
|
1328
|
+
if (height > max.height) {
|
|
1329
|
+
return false;
|
|
1330
|
+
}
|
|
1331
|
+
const fallbackFps = fps ?? 60;
|
|
1332
|
+
return fallbackFps <= max.fps;
|
|
1333
|
+
});
|
|
1334
|
+
});
|
|
1335
|
+
if (!profile) {
|
|
1336
|
+
throw new Error(`No suitable HEVC profile found for ${width}x${height}@${fps}fps`);
|
|
1337
|
+
}
|
|
1338
|
+
return `hvc1.${1}.${0}.${"L"}${Math.round(Number(profile.level) * 30)}.${"b0"}`;
|
|
1339
|
+
};
|
|
1340
|
+
|
|
1341
|
+
// src/get-codec-string.ts
|
|
1342
|
+
var getCodecStringForEncoder = ({
|
|
1343
|
+
codec,
|
|
1344
|
+
fps,
|
|
1345
|
+
height,
|
|
1346
|
+
width
|
|
1347
|
+
}) => {
|
|
1348
|
+
if (codec === "h264") {
|
|
1349
|
+
return chooseCorrectAvc1Profile({ fps, height, width });
|
|
1350
|
+
}
|
|
1351
|
+
if (codec === "h265") {
|
|
1352
|
+
return chooseCorrectHevcProfile({ fps, height, width });
|
|
1353
|
+
}
|
|
1354
|
+
if (codec === "vp8") {
|
|
1355
|
+
return "vp8";
|
|
1356
|
+
}
|
|
1357
|
+
if (codec === "vp9") {
|
|
1358
|
+
return "vp09.00.10.08";
|
|
1359
|
+
}
|
|
1360
|
+
throw new Error(`Unknown codec: ${codec}`);
|
|
1361
|
+
};
|
|
1362
|
+
|
|
1052
1363
|
// src/video-encoder-config.ts
|
|
1053
1364
|
var getVideoEncoderConfig = async ({
|
|
1054
1365
|
codec,
|
|
@@ -1060,10 +1371,12 @@ var getVideoEncoderConfig = async ({
|
|
|
1060
1371
|
return null;
|
|
1061
1372
|
}
|
|
1062
1373
|
const config = {
|
|
1063
|
-
codec:
|
|
1374
|
+
codec: getCodecStringForEncoder({ codec, fps, height, width }),
|
|
1064
1375
|
height,
|
|
1065
1376
|
width,
|
|
1066
|
-
bitrate: isSafari() ? 3000000 : undefined
|
|
1377
|
+
bitrate: isSafari() ? 3000000 : undefined,
|
|
1378
|
+
bitrateMode: codec === "vp9" && !isSafari() ? "quantizer" : undefined,
|
|
1379
|
+
framerate: fps ?? undefined
|
|
1067
1380
|
};
|
|
1068
1381
|
const hardware = {
|
|
1069
1382
|
...config,
|
|
@@ -1106,7 +1419,11 @@ var canReencodeVideoTrack = async ({
|
|
|
1106
1419
|
return Boolean(videoDecoderConfig && videoEncoderConfig);
|
|
1107
1420
|
};
|
|
1108
1421
|
// src/convert-media.ts
|
|
1109
|
-
import {
|
|
1422
|
+
import {
|
|
1423
|
+
MediaParserAbortError as MediaParserAbortError3,
|
|
1424
|
+
MediaParserInternals as MediaParserInternals9
|
|
1425
|
+
} from "@remotion/media-parser";
|
|
1426
|
+
import { fetchReader } from "@remotion/media-parser/fetch";
|
|
1110
1427
|
|
|
1111
1428
|
// src/auto-select-writer.ts
|
|
1112
1429
|
var autoSelectWriter = async (writer, logLevel) => {
|
|
@@ -1211,9 +1528,6 @@ var makeProgressTracker = () => {
|
|
|
1211
1528
|
};
|
|
1212
1529
|
};
|
|
1213
1530
|
|
|
1214
|
-
// src/error-cause.ts
|
|
1215
|
-
var error_cause_default = Error;
|
|
1216
|
-
|
|
1217
1531
|
// src/generate-output-filename.ts
|
|
1218
1532
|
var generateOutputFilename = (source, container) => {
|
|
1219
1533
|
const filename = typeof source === "string" ? source : source instanceof File ? source.name : "converted";
|
|
@@ -1222,6 +1536,29 @@ var generateOutputFilename = (source, container) => {
|
|
|
1222
1536
|
return `${withoutExtension}.${container}`;
|
|
1223
1537
|
};
|
|
1224
1538
|
|
|
1539
|
+
// src/get-available-containers.ts
|
|
1540
|
+
var availableContainers = ["webm", "mp4", "wav"];
|
|
1541
|
+
var getAvailableContainers = () => {
|
|
1542
|
+
return availableContainers;
|
|
1543
|
+
};
|
|
1544
|
+
|
|
1545
|
+
// src/get-available-video-codecs.ts
|
|
1546
|
+
var availableVideoCodecs = ["vp8", "vp9", "h264", "h265"];
|
|
1547
|
+
var getAvailableVideoCodecs = ({
|
|
1548
|
+
container
|
|
1549
|
+
}) => {
|
|
1550
|
+
if (container === "mp4") {
|
|
1551
|
+
return ["h264", "h265"];
|
|
1552
|
+
}
|
|
1553
|
+
if (container === "webm") {
|
|
1554
|
+
return ["vp8", "vp9"];
|
|
1555
|
+
}
|
|
1556
|
+
if (container === "wav") {
|
|
1557
|
+
return [];
|
|
1558
|
+
}
|
|
1559
|
+
throw new Error(`Unsupported container: ${container}`);
|
|
1560
|
+
};
|
|
1561
|
+
|
|
1225
1562
|
// src/on-audio-track.ts
|
|
1226
1563
|
import {
|
|
1227
1564
|
MediaParserInternals as MediaParserInternals3
|
|
@@ -1325,7 +1662,7 @@ var makeAudioTrackHandler = ({
|
|
|
1325
1662
|
return null;
|
|
1326
1663
|
}
|
|
1327
1664
|
if (audioOperation.type === "fail") {
|
|
1328
|
-
throw new
|
|
1665
|
+
throw new Error(`Audio track with ID ${track.trackId} resolved with {"type": "fail"}. This could mean that this audio track could neither be copied to the output container or re-encoded. You have the option to drop the track instead of failing it: https://remotion.dev/docs/webcodecs/track-transformation`);
|
|
1329
1666
|
}
|
|
1330
1667
|
if (audioOperation.type === "copy") {
|
|
1331
1668
|
const addedTrack = await state.addTrack({
|
|
@@ -1365,17 +1702,18 @@ var makeAudioTrackHandler = ({
|
|
|
1365
1702
|
description: track.description
|
|
1366
1703
|
});
|
|
1367
1704
|
if (!audioEncoderConfig) {
|
|
1368
|
-
abortConversion(new
|
|
1705
|
+
abortConversion(new Error(`Could not configure audio encoder of track ${track.trackId}`));
|
|
1369
1706
|
return null;
|
|
1370
1707
|
}
|
|
1371
1708
|
if (!audioDecoderConfig) {
|
|
1372
|
-
abortConversion(new
|
|
1709
|
+
abortConversion(new Error(`Could not configure audio decoder of track ${track.trackId}`));
|
|
1373
1710
|
return null;
|
|
1374
1711
|
}
|
|
1375
1712
|
const codecPrivate = audioOperation.audioCodec === "aac" ? MediaParserInternals3.createAacCodecPrivate({
|
|
1376
1713
|
audioObjectType: 2,
|
|
1377
1714
|
sampleRate: track.sampleRate,
|
|
1378
|
-
channelConfiguration: track.numberOfChannels
|
|
1715
|
+
channelConfiguration: track.numberOfChannels,
|
|
1716
|
+
codecPrivate: null
|
|
1379
1717
|
}) : null;
|
|
1380
1718
|
const { trackNumber } = await state.addTrack({
|
|
1381
1719
|
type: "audio",
|
|
@@ -1404,12 +1742,12 @@ var makeAudioTrackHandler = ({
|
|
|
1404
1742
|
});
|
|
1405
1743
|
},
|
|
1406
1744
|
onError: (err) => {
|
|
1407
|
-
abortConversion(new
|
|
1745
|
+
abortConversion(new Error(`Audio encoder of ${track.trackId} failed (see .cause of this error)`, {
|
|
1408
1746
|
cause: err
|
|
1409
1747
|
}));
|
|
1410
1748
|
},
|
|
1411
1749
|
codec: audioOperation.audioCodec,
|
|
1412
|
-
|
|
1750
|
+
controller,
|
|
1413
1751
|
config: audioEncoderConfig,
|
|
1414
1752
|
logLevel,
|
|
1415
1753
|
progressTracker
|
|
@@ -1419,19 +1757,19 @@ var makeAudioTrackHandler = ({
|
|
|
1419
1757
|
const newAudioData = onAudioData ? await onAudioData?.({ audioData, track }) : audioData;
|
|
1420
1758
|
if (newAudioData !== audioData) {
|
|
1421
1759
|
if (newAudioData.duration !== audioData.duration) {
|
|
1422
|
-
throw new
|
|
1760
|
+
throw new Error(`onAudioData returned a different duration than the input audio data. Original duration: ${audioData.duration}, new duration: ${newAudioData.duration}`);
|
|
1423
1761
|
}
|
|
1424
1762
|
if (newAudioData.numberOfChannels !== audioData.numberOfChannels) {
|
|
1425
|
-
throw new
|
|
1763
|
+
throw new Error(`onAudioData returned a different number of channels than the input audio data. Original channels: ${audioData.numberOfChannels}, new channels: ${newAudioData.numberOfChannels}`);
|
|
1426
1764
|
}
|
|
1427
1765
|
if (newAudioData.sampleRate !== audioData.sampleRate) {
|
|
1428
|
-
throw new
|
|
1766
|
+
throw new Error(`onAudioData returned a different sample rate than the input audio data. Original sample rate: ${audioData.sampleRate}, new sample rate: ${newAudioData.sampleRate}`);
|
|
1429
1767
|
}
|
|
1430
1768
|
if (newAudioData.format !== audioData.format) {
|
|
1431
|
-
throw new
|
|
1769
|
+
throw new Error(`onAudioData returned a different format than the input audio data. Original format: ${audioData.format}, new format: ${newAudioData.format}`);
|
|
1432
1770
|
}
|
|
1433
1771
|
if (newAudioData.timestamp !== audioData.timestamp) {
|
|
1434
|
-
throw new
|
|
1772
|
+
throw new Error(`onAudioData returned a different timestamp than the input audio data. Original timestamp: ${audioData.timestamp}, new timestamp: ${newAudioData.timestamp}`);
|
|
1435
1773
|
}
|
|
1436
1774
|
audioData.close();
|
|
1437
1775
|
}
|
|
@@ -1445,11 +1783,11 @@ var makeAudioTrackHandler = ({
|
|
|
1445
1783
|
newAudioData.close();
|
|
1446
1784
|
},
|
|
1447
1785
|
onError(error) {
|
|
1448
|
-
abortConversion(new
|
|
1786
|
+
abortConversion(new Error(`Audio decoder of track ${track.trackId} failed. Config: ${JSON.stringify(audioDecoderConfig)} (see .cause of this error)`, {
|
|
1449
1787
|
cause: error
|
|
1450
1788
|
}));
|
|
1451
1789
|
},
|
|
1452
|
-
|
|
1790
|
+
controller,
|
|
1453
1791
|
config: audioDecoderConfig,
|
|
1454
1792
|
logLevel,
|
|
1455
1793
|
track,
|
|
@@ -1610,7 +1948,7 @@ var onFrame = async ({
|
|
|
1610
1948
|
var createVideoDecoder = ({
|
|
1611
1949
|
onFrame: onFrame2,
|
|
1612
1950
|
onError,
|
|
1613
|
-
|
|
1951
|
+
controller,
|
|
1614
1952
|
config,
|
|
1615
1953
|
logLevel,
|
|
1616
1954
|
progress
|
|
@@ -1627,15 +1965,17 @@ var createVideoDecoder = ({
|
|
|
1627
1965
|
const abortHandler = () => {
|
|
1628
1966
|
inputFrame.close();
|
|
1629
1967
|
};
|
|
1630
|
-
signal.addEventListener("abort", abortHandler, {
|
|
1968
|
+
controller._internals.signal.addEventListener("abort", abortHandler, {
|
|
1969
|
+
once: true
|
|
1970
|
+
});
|
|
1631
1971
|
outputQueue = outputQueue.then(() => {
|
|
1632
|
-
if (signal.aborted) {
|
|
1972
|
+
if (controller._internals.signal.aborted) {
|
|
1633
1973
|
return;
|
|
1634
1974
|
}
|
|
1635
1975
|
return onFrame2(inputFrame);
|
|
1636
1976
|
}).then(() => {
|
|
1637
1977
|
ioSynchronizer.onProcessed();
|
|
1638
|
-
signal.removeEventListener("abort", abortHandler);
|
|
1978
|
+
controller._internals.signal.removeEventListener("abort", abortHandler);
|
|
1639
1979
|
return Promise.resolve();
|
|
1640
1980
|
}).catch((err) => {
|
|
1641
1981
|
inputFrame.close();
|
|
@@ -1647,7 +1987,7 @@ var createVideoDecoder = ({
|
|
|
1647
1987
|
}
|
|
1648
1988
|
});
|
|
1649
1989
|
const close = () => {
|
|
1650
|
-
signal.removeEventListener("abort", onAbort);
|
|
1990
|
+
controller._internals.signal.removeEventListener("abort", onAbort);
|
|
1651
1991
|
if (videoDecoder.state === "closed") {
|
|
1652
1992
|
return;
|
|
1653
1993
|
}
|
|
@@ -1656,7 +1996,7 @@ var createVideoDecoder = ({
|
|
|
1656
1996
|
const onAbort = () => {
|
|
1657
1997
|
close();
|
|
1658
1998
|
};
|
|
1659
|
-
signal.addEventListener("abort", onAbort);
|
|
1999
|
+
controller._internals.signal.addEventListener("abort", onAbort);
|
|
1660
2000
|
videoDecoder.configure(config);
|
|
1661
2001
|
const processSample = async (sample) => {
|
|
1662
2002
|
if (videoDecoder.state === "closed") {
|
|
@@ -1670,7 +2010,7 @@ var createVideoDecoder = ({
|
|
|
1670
2010
|
unemitted: 20,
|
|
1671
2011
|
unprocessed: 2,
|
|
1672
2012
|
minimumProgress: sample.timestamp - 1e7,
|
|
1673
|
-
|
|
2013
|
+
controller
|
|
1674
2014
|
});
|
|
1675
2015
|
if (sample.type === "key") {
|
|
1676
2016
|
await videoDecoder.flush();
|
|
@@ -1687,7 +2027,7 @@ var createVideoDecoder = ({
|
|
|
1687
2027
|
waitForFinish: async () => {
|
|
1688
2028
|
await videoDecoder.flush();
|
|
1689
2029
|
Log.verbose(logLevel, "Flushed video decoder");
|
|
1690
|
-
await ioSynchronizer.waitForFinish(
|
|
2030
|
+
await ioSynchronizer.waitForFinish(controller);
|
|
1691
2031
|
Log.verbose(logLevel, "IO synchro finished");
|
|
1692
2032
|
await outputQueue;
|
|
1693
2033
|
Log.verbose(logLevel, "Output queue finished");
|
|
@@ -1702,17 +2042,18 @@ var createVideoDecoder = ({
|
|
|
1702
2042
|
};
|
|
1703
2043
|
|
|
1704
2044
|
// src/video-encoder.ts
|
|
2045
|
+
import { MediaParserAbortError as MediaParserAbortError2 } from "@remotion/media-parser";
|
|
1705
2046
|
var createVideoEncoder = ({
|
|
1706
2047
|
onChunk,
|
|
1707
2048
|
onError,
|
|
1708
|
-
|
|
2049
|
+
controller,
|
|
1709
2050
|
config,
|
|
1710
2051
|
logLevel,
|
|
1711
2052
|
outputCodec,
|
|
1712
2053
|
progress
|
|
1713
2054
|
}) => {
|
|
1714
|
-
if (signal.aborted) {
|
|
1715
|
-
throw new
|
|
2055
|
+
if (controller._internals.signal.aborted) {
|
|
2056
|
+
throw new MediaParserAbortError2("Not creating video encoder, already aborted");
|
|
1716
2057
|
}
|
|
1717
2058
|
const ioSynchronizer = makeIoSynchronizer({
|
|
1718
2059
|
logLevel,
|
|
@@ -1728,7 +2069,7 @@ var createVideoEncoder = ({
|
|
|
1728
2069
|
const timestamp = chunk.timestamp + (chunk.duration ?? 0);
|
|
1729
2070
|
ioSynchronizer.onOutput(timestamp);
|
|
1730
2071
|
outputQueue = outputQueue.then(() => {
|
|
1731
|
-
if (signal.aborted) {
|
|
2072
|
+
if (controller._internals.signal.aborted) {
|
|
1732
2073
|
return;
|
|
1733
2074
|
}
|
|
1734
2075
|
return onChunk(chunk, metadata ?? null);
|
|
@@ -1741,7 +2082,7 @@ var createVideoEncoder = ({
|
|
|
1741
2082
|
}
|
|
1742
2083
|
});
|
|
1743
2084
|
const close = () => {
|
|
1744
|
-
signal.removeEventListener("abort", onAbort);
|
|
2085
|
+
controller._internals.signal.removeEventListener("abort", onAbort);
|
|
1745
2086
|
if (encoder.state === "closed") {
|
|
1746
2087
|
return;
|
|
1747
2088
|
}
|
|
@@ -1750,7 +2091,7 @@ var createVideoEncoder = ({
|
|
|
1750
2091
|
const onAbort = () => {
|
|
1751
2092
|
close();
|
|
1752
2093
|
};
|
|
1753
|
-
signal.addEventListener("abort", onAbort);
|
|
2094
|
+
controller._internals.signal.addEventListener("abort", onAbort);
|
|
1754
2095
|
Log.verbose(logLevel, "Configuring video encoder", config);
|
|
1755
2096
|
encoder.configure(config);
|
|
1756
2097
|
let framesProcessed = 0;
|
|
@@ -1763,14 +2104,17 @@ var createVideoEncoder = ({
|
|
|
1763
2104
|
unemitted: 10,
|
|
1764
2105
|
unprocessed: 10,
|
|
1765
2106
|
minimumProgress: frame.timestamp - 1e7,
|
|
1766
|
-
|
|
2107
|
+
controller
|
|
1767
2108
|
});
|
|
1768
2109
|
if (encoder.state === "closed") {
|
|
1769
2110
|
return;
|
|
1770
2111
|
}
|
|
1771
2112
|
const keyFrame = framesProcessed % 40 === 0;
|
|
1772
2113
|
encoder.encode(convertToCorrectVideoFrame({ videoFrame: frame, outputCodec }), {
|
|
1773
|
-
keyFrame
|
|
2114
|
+
keyFrame,
|
|
2115
|
+
vp9: {
|
|
2116
|
+
quantizer: 36
|
|
2117
|
+
}
|
|
1774
2118
|
});
|
|
1775
2119
|
ioSynchronizer.inputItem(frame.timestamp, keyFrame);
|
|
1776
2120
|
framesProcessed++;
|
|
@@ -1784,7 +2128,7 @@ var createVideoEncoder = ({
|
|
|
1784
2128
|
waitForFinish: async () => {
|
|
1785
2129
|
await encoder.flush();
|
|
1786
2130
|
await outputQueue;
|
|
1787
|
-
await ioSynchronizer.waitForFinish(
|
|
2131
|
+
await ioSynchronizer.waitForFinish(controller);
|
|
1788
2132
|
},
|
|
1789
2133
|
close,
|
|
1790
2134
|
flush: async () => {
|
|
@@ -1808,8 +2152,8 @@ var makeVideoTrackHandler = ({
|
|
|
1808
2152
|
progress,
|
|
1809
2153
|
resizeOperation
|
|
1810
2154
|
}) => async ({ track, container: inputContainer }) => {
|
|
1811
|
-
if (controller.signal.aborted) {
|
|
1812
|
-
throw new
|
|
2155
|
+
if (controller._internals.signal.aborted) {
|
|
2156
|
+
throw new Error("Aborted");
|
|
1813
2157
|
}
|
|
1814
2158
|
const canCopyTrack = canCopyVideoTrack({
|
|
1815
2159
|
inputContainer,
|
|
@@ -1832,7 +2176,7 @@ var makeVideoTrackHandler = ({
|
|
|
1832
2176
|
return null;
|
|
1833
2177
|
}
|
|
1834
2178
|
if (videoOperation.type === "fail") {
|
|
1835
|
-
throw new
|
|
2179
|
+
throw new Error(`Video track with ID ${track.trackId} resolved with {"type": "fail"}. This could mean that this video track could neither be copied to the output container or re-encoded. You have the option to drop the track instead of failing it: https://remotion.dev/docs/webcodecs/track-transformation`);
|
|
1836
2180
|
}
|
|
1837
2181
|
if (videoOperation.type === "copy") {
|
|
1838
2182
|
Log.verbose(logLevel, `Copying video track with codec ${track.codec} and timescale ${track.timescale}`);
|
|
@@ -1861,7 +2205,7 @@ var makeVideoTrackHandler = ({
|
|
|
1861
2205
|
};
|
|
1862
2206
|
}
|
|
1863
2207
|
if (videoOperation.type !== "reencode") {
|
|
1864
|
-
throw new
|
|
2208
|
+
throw new Error(`Video track with ID ${track.trackId} could not be resolved with a valid operation. Received ${JSON.stringify(videoOperation)}, but must be either "copy", "reencode", "drop" or "fail"`);
|
|
1865
2209
|
}
|
|
1866
2210
|
const rotation = (videoOperation.rotate ?? rotate) - track.rotation;
|
|
1867
2211
|
const { height: newHeight, width: newWidth } = calculateNewDimensionsFromRotateAndScale({
|
|
@@ -1879,11 +2223,11 @@ var makeVideoTrackHandler = ({
|
|
|
1879
2223
|
});
|
|
1880
2224
|
const videoDecoderConfig = await getVideoDecoderConfigWithHardwareAcceleration(track);
|
|
1881
2225
|
if (videoEncoderConfig === null) {
|
|
1882
|
-
abortConversion(new
|
|
2226
|
+
abortConversion(new Error(`Could not configure video encoder of track ${track.trackId}`));
|
|
1883
2227
|
return null;
|
|
1884
2228
|
}
|
|
1885
2229
|
if (videoDecoderConfig === null) {
|
|
1886
|
-
abortConversion(new
|
|
2230
|
+
abortConversion(new Error(`Could not configure video decoder of track ${track.trackId}`));
|
|
1887
2231
|
return null;
|
|
1888
2232
|
}
|
|
1889
2233
|
const { trackNumber } = await state.addTrack({
|
|
@@ -1912,11 +2256,11 @@ var makeVideoTrackHandler = ({
|
|
|
1912
2256
|
});
|
|
1913
2257
|
},
|
|
1914
2258
|
onError: (err) => {
|
|
1915
|
-
abortConversion(new
|
|
2259
|
+
abortConversion(new Error(`Video encoder of track ${track.trackId} failed (see .cause of this error)`, {
|
|
1916
2260
|
cause: err
|
|
1917
2261
|
}));
|
|
1918
2262
|
},
|
|
1919
|
-
|
|
2263
|
+
controller,
|
|
1920
2264
|
config: videoEncoderConfig,
|
|
1921
2265
|
logLevel,
|
|
1922
2266
|
outputCodec: videoOperation.videoCodec,
|
|
@@ -1936,11 +2280,11 @@ var makeVideoTrackHandler = ({
|
|
|
1936
2280
|
});
|
|
1937
2281
|
},
|
|
1938
2282
|
onError: (err) => {
|
|
1939
|
-
abortConversion(new
|
|
2283
|
+
abortConversion(new Error(`Video decoder of track ${track.trackId} failed (see .cause of this error)`, {
|
|
1940
2284
|
cause: err
|
|
1941
2285
|
}));
|
|
1942
2286
|
},
|
|
1943
|
-
|
|
2287
|
+
controller,
|
|
1944
2288
|
logLevel,
|
|
1945
2289
|
progress
|
|
1946
2290
|
});
|
|
@@ -2479,6 +2823,17 @@ var createAvccBox = (privateData) => {
|
|
|
2479
2823
|
]));
|
|
2480
2824
|
};
|
|
2481
2825
|
|
|
2826
|
+
// src/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-hvcc.ts
|
|
2827
|
+
var createHvccBox = (privateData) => {
|
|
2828
|
+
if (!privateData) {
|
|
2829
|
+
throw new Error("privateData is required");
|
|
2830
|
+
}
|
|
2831
|
+
return addSize(combineUint8Arrays([
|
|
2832
|
+
stringsToUint8Array("hvcC"),
|
|
2833
|
+
privateData
|
|
2834
|
+
]));
|
|
2835
|
+
};
|
|
2836
|
+
|
|
2482
2837
|
// src/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp.ts
|
|
2483
2838
|
var createPasp = (x, y) => {
|
|
2484
2839
|
return addSize(combineUint8Arrays([
|
|
@@ -2522,6 +2877,40 @@ var createAvc1Data = ({
|
|
|
2522
2877
|
]));
|
|
2523
2878
|
};
|
|
2524
2879
|
|
|
2880
|
+
// src/create/iso-base-media/codec-specific/hvc1.ts
|
|
2881
|
+
var createHvc1Data = ({
|
|
2882
|
+
compressorName,
|
|
2883
|
+
depth,
|
|
2884
|
+
height,
|
|
2885
|
+
horizontalResolution,
|
|
2886
|
+
hvccBox,
|
|
2887
|
+
pasp,
|
|
2888
|
+
verticalResolution,
|
|
2889
|
+
width
|
|
2890
|
+
}) => {
|
|
2891
|
+
return addSize(combineUint8Arrays([
|
|
2892
|
+
stringsToUint8Array("hvc1"),
|
|
2893
|
+
new Uint8Array([0, 0, 0, 0, 0, 0]),
|
|
2894
|
+
new Uint8Array([0, 1]),
|
|
2895
|
+
new Uint8Array([0, 0]),
|
|
2896
|
+
new Uint8Array([0, 0]),
|
|
2897
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
2898
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
2899
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
2900
|
+
numberTo16BitUIntOrInt(width),
|
|
2901
|
+
numberTo16BitUIntOrInt(height),
|
|
2902
|
+
setFixedPointSignedOrUnsigned1616Number(horizontalResolution),
|
|
2903
|
+
setFixedPointSignedOrUnsigned1616Number(verticalResolution),
|
|
2904
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
2905
|
+
numberTo16BitUIntOrInt(1),
|
|
2906
|
+
stringToPascalString(compressorName),
|
|
2907
|
+
numberTo16BitUIntOrInt(depth),
|
|
2908
|
+
numberTo16BitUIntOrInt(-1),
|
|
2909
|
+
hvccBox,
|
|
2910
|
+
pasp
|
|
2911
|
+
]));
|
|
2912
|
+
};
|
|
2913
|
+
|
|
2525
2914
|
// src/create/iso-base-media/codec-specific/mp4a.ts
|
|
2526
2915
|
var createMp4a = ({
|
|
2527
2916
|
sampleRate,
|
|
@@ -2574,17 +2963,33 @@ var createMp4a = ({
|
|
|
2574
2963
|
// src/create/iso-base-media/codec-specific/create-codec-specific-data.ts
|
|
2575
2964
|
var createCodecSpecificData = (track) => {
|
|
2576
2965
|
if (track.type === "video") {
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2966
|
+
if (track.codec === "h264") {
|
|
2967
|
+
return createAvc1Data({
|
|
2968
|
+
avccBox: createAvccBox(track.codecPrivate),
|
|
2969
|
+
compressorName: "WebCodecs",
|
|
2970
|
+
depth: 24,
|
|
2971
|
+
horizontalResolution: 72,
|
|
2972
|
+
verticalResolution: 72,
|
|
2973
|
+
height: track.height,
|
|
2974
|
+
width: track.width,
|
|
2975
|
+
pasp: createPasp(1, 1),
|
|
2976
|
+
type: "avc1-data"
|
|
2977
|
+
});
|
|
2978
|
+
}
|
|
2979
|
+
if (track.codec === "h265") {
|
|
2980
|
+
return createHvc1Data({
|
|
2981
|
+
hvccBox: createHvccBox(track.codecPrivate),
|
|
2982
|
+
compressorName: "WebCodecs",
|
|
2983
|
+
depth: 24,
|
|
2984
|
+
horizontalResolution: 72,
|
|
2985
|
+
verticalResolution: 72,
|
|
2986
|
+
height: track.height,
|
|
2987
|
+
width: track.width,
|
|
2988
|
+
pasp: createPasp(1, 1),
|
|
2989
|
+
type: "hvc1-data"
|
|
2990
|
+
});
|
|
2991
|
+
}
|
|
2992
|
+
throw new Error("Unsupported codec specific data " + track.codec);
|
|
2588
2993
|
}
|
|
2589
2994
|
if (track.type === "audio") {
|
|
2590
2995
|
return createMp4a({
|
|
@@ -3041,7 +3446,7 @@ var serializeTrack = ({
|
|
|
3041
3446
|
samplePositions,
|
|
3042
3447
|
timescale
|
|
3043
3448
|
}) => {
|
|
3044
|
-
if (track.codec !== "h264" && track.codec !== "aac") {
|
|
3449
|
+
if (track.codec !== "h264" && track.codec !== "h265" && track.codec !== "aac") {
|
|
3045
3450
|
throw new Error("Currently only H.264 and AAC is supported");
|
|
3046
3451
|
}
|
|
3047
3452
|
return createTrak({
|
|
@@ -3150,7 +3555,11 @@ var createIsoBaseMedia = async ({
|
|
|
3150
3555
|
majorBrand: "isom",
|
|
3151
3556
|
minorBrand: 512
|
|
3152
3557
|
});
|
|
3153
|
-
const w = await writer.createContent({
|
|
3558
|
+
const w = await writer.createContent({
|
|
3559
|
+
filename,
|
|
3560
|
+
mimeType: "video/mp4",
|
|
3561
|
+
logLevel
|
|
3562
|
+
});
|
|
3154
3563
|
await w.write(header);
|
|
3155
3564
|
let globalDurationInUnits = 0;
|
|
3156
3565
|
const lowestTrackTimestamps = {};
|
|
@@ -3266,8 +3675,8 @@ var createIsoBaseMedia = async ({
|
|
|
3266
3675
|
};
|
|
3267
3676
|
const waitForFinishPromises = [];
|
|
3268
3677
|
return {
|
|
3269
|
-
|
|
3270
|
-
return w.
|
|
3678
|
+
getBlob: () => {
|
|
3679
|
+
return w.getBlob();
|
|
3271
3680
|
},
|
|
3272
3681
|
remove: async () => {
|
|
3273
3682
|
await w.remove();
|
|
@@ -3308,7 +3717,7 @@ var createIsoBaseMedia = async ({
|
|
|
3308
3717
|
await updateMoov();
|
|
3309
3718
|
await updateMdatSize();
|
|
3310
3719
|
MediaParserInternals6.Log.verbose(logLevel, "All write operations done. Waiting for finish...");
|
|
3311
|
-
await w.
|
|
3720
|
+
await w.finish();
|
|
3312
3721
|
}
|
|
3313
3722
|
};
|
|
3314
3723
|
};
|
|
@@ -3743,6 +4152,9 @@ var makeAudioCodecId = (codecId) => {
|
|
|
3743
4152
|
if (codecId === "aac") {
|
|
3744
4153
|
return "A_AAC";
|
|
3745
4154
|
}
|
|
4155
|
+
if (codecId === "ac3") {
|
|
4156
|
+
return "A_AC3";
|
|
4157
|
+
}
|
|
3746
4158
|
if (codecId === "mp3") {
|
|
3747
4159
|
return "A_MPEG/L3";
|
|
3748
4160
|
}
|
|
@@ -3943,7 +4355,11 @@ var createMatroskaMedia = async ({
|
|
|
3943
4355
|
progressTracker
|
|
3944
4356
|
}) => {
|
|
3945
4357
|
const header = makeMatroskaHeader();
|
|
3946
|
-
const w = await writer.createContent({
|
|
4358
|
+
const w = await writer.createContent({
|
|
4359
|
+
filename,
|
|
4360
|
+
mimeType: "video/webm",
|
|
4361
|
+
logLevel
|
|
4362
|
+
});
|
|
3947
4363
|
await w.write(header.bytes);
|
|
3948
4364
|
const matroskaInfo = makeMatroskaInfo({
|
|
3949
4365
|
timescale
|
|
@@ -4076,8 +4492,8 @@ var createMatroskaMedia = async ({
|
|
|
4076
4492
|
}
|
|
4077
4493
|
});
|
|
4078
4494
|
},
|
|
4079
|
-
|
|
4080
|
-
return w.
|
|
4495
|
+
getBlob: async () => {
|
|
4496
|
+
return w.getBlob();
|
|
4081
4497
|
},
|
|
4082
4498
|
remove: async () => {
|
|
4083
4499
|
await w.remove();
|
|
@@ -4104,9 +4520,9 @@ var createMatroskaMedia = async ({
|
|
|
4104
4520
|
});
|
|
4105
4521
|
await updateSeekWrite();
|
|
4106
4522
|
await w.write(createMatroskaCues(cues).bytes);
|
|
4107
|
-
await w.waitForFinish();
|
|
4108
4523
|
const segmentSize = w.getWrittenByteCount() - segmentOffset - matroskaToHex(matroskaElements.Segment).byteLength - MATROSKA_SEGMENT_MIN_VINT_WIDTH;
|
|
4109
4524
|
await updateSegmentSize(segmentSize);
|
|
4525
|
+
await w.finish();
|
|
4110
4526
|
}
|
|
4111
4527
|
};
|
|
4112
4528
|
};
|
|
@@ -4133,7 +4549,11 @@ var createWav = async ({
|
|
|
4133
4549
|
writer,
|
|
4134
4550
|
progressTracker
|
|
4135
4551
|
}) => {
|
|
4136
|
-
const w = await writer.createContent({
|
|
4552
|
+
const w = await writer.createContent({
|
|
4553
|
+
filename,
|
|
4554
|
+
mimeType: "audio/wav",
|
|
4555
|
+
logLevel
|
|
4556
|
+
});
|
|
4137
4557
|
await w.write(new Uint8Array([82, 73, 70, 70]));
|
|
4138
4558
|
const sizePosition = w.getWrittenByteCount();
|
|
4139
4559
|
await w.write(new Uint8Array([0, 0, 0, 0]));
|
|
@@ -4183,8 +4603,8 @@ var createWav = async ({
|
|
|
4183
4603
|
};
|
|
4184
4604
|
const waitForFinishPromises = [];
|
|
4185
4605
|
return {
|
|
4186
|
-
|
|
4187
|
-
return w.
|
|
4606
|
+
getBlob: () => {
|
|
4607
|
+
return w.getBlob();
|
|
4188
4608
|
},
|
|
4189
4609
|
remove: () => {
|
|
4190
4610
|
return w.remove();
|
|
@@ -4208,7 +4628,7 @@ var createWav = async ({
|
|
|
4208
4628
|
await Promise.all(waitForFinishPromises.map((p) => p()));
|
|
4209
4629
|
await operationProm.current;
|
|
4210
4630
|
await updateSize();
|
|
4211
|
-
await w.
|
|
4631
|
+
await w.finish();
|
|
4212
4632
|
},
|
|
4213
4633
|
addTrack: async (track) => {
|
|
4214
4634
|
if (track.type !== "audio") {
|
|
@@ -4297,7 +4717,7 @@ var throttledStateUpdate = ({
|
|
|
4297
4717
|
const onAbort = () => {
|
|
4298
4718
|
clearInterval(interval);
|
|
4299
4719
|
};
|
|
4300
|
-
signal
|
|
4720
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
4301
4721
|
return {
|
|
4302
4722
|
get: () => currentState,
|
|
4303
4723
|
update: (fn) => {
|
|
@@ -4305,12 +4725,26 @@ var throttledStateUpdate = ({
|
|
|
4305
4725
|
},
|
|
4306
4726
|
stopAndGetLastProgress: () => {
|
|
4307
4727
|
clearInterval(interval);
|
|
4308
|
-
signal
|
|
4728
|
+
signal?.removeEventListener("abort", onAbort);
|
|
4309
4729
|
return currentState;
|
|
4310
4730
|
}
|
|
4311
4731
|
};
|
|
4312
4732
|
};
|
|
4313
4733
|
|
|
4734
|
+
// src/webcodecs-controller.ts
|
|
4735
|
+
import { mediaParserController } from "@remotion/media-parser";
|
|
4736
|
+
var webcodecsController = () => {
|
|
4737
|
+
const controller = mediaParserController();
|
|
4738
|
+
return {
|
|
4739
|
+
abort: controller.abort,
|
|
4740
|
+
pause: controller.pause,
|
|
4741
|
+
resume: controller.resume,
|
|
4742
|
+
addEventListener: controller.addEventListener,
|
|
4743
|
+
removeEventListener: controller.removeEventListener,
|
|
4744
|
+
_internals: controller._internals
|
|
4745
|
+
};
|
|
4746
|
+
};
|
|
4747
|
+
|
|
4314
4748
|
// src/convert-media.ts
|
|
4315
4749
|
var convertMedia = async function({
|
|
4316
4750
|
src,
|
|
@@ -4320,7 +4754,7 @@ var convertMedia = async function({
|
|
|
4320
4754
|
audioCodec,
|
|
4321
4755
|
container,
|
|
4322
4756
|
videoCodec,
|
|
4323
|
-
|
|
4757
|
+
controller = webcodecsController(),
|
|
4324
4758
|
onAudioTrack: userAudioResolver,
|
|
4325
4759
|
onVideoTrack: userVideoResolver,
|
|
4326
4760
|
reader,
|
|
@@ -4331,34 +4765,60 @@ var convertMedia = async function({
|
|
|
4331
4765
|
rotate,
|
|
4332
4766
|
apiKey,
|
|
4333
4767
|
resize,
|
|
4768
|
+
onAudioCodec,
|
|
4769
|
+
onContainer,
|
|
4770
|
+
onDimensions,
|
|
4771
|
+
onDurationInSeconds,
|
|
4772
|
+
onFps,
|
|
4773
|
+
onImages,
|
|
4774
|
+
onInternalStats,
|
|
4775
|
+
onIsHdr,
|
|
4776
|
+
onKeyframes,
|
|
4777
|
+
onLocation,
|
|
4778
|
+
onMetadata,
|
|
4779
|
+
onMimeType,
|
|
4780
|
+
onName,
|
|
4781
|
+
onNumberOfAudioChannels,
|
|
4782
|
+
onRotation,
|
|
4783
|
+
onSampleRate,
|
|
4784
|
+
onSize,
|
|
4785
|
+
onSlowAudioBitrate,
|
|
4786
|
+
onSlowDurationInSeconds,
|
|
4787
|
+
onSlowFps,
|
|
4788
|
+
onSlowKeyframes,
|
|
4789
|
+
onSlowNumberOfFrames,
|
|
4790
|
+
onSlowVideoBitrate,
|
|
4791
|
+
onStructure,
|
|
4792
|
+
onTracks,
|
|
4793
|
+
onUnrotatedDimensions,
|
|
4794
|
+
onVideoCodec,
|
|
4334
4795
|
...more
|
|
4335
4796
|
}) {
|
|
4336
|
-
if (
|
|
4337
|
-
return Promise.reject(new
|
|
4797
|
+
if (controller._internals.signal.aborted) {
|
|
4798
|
+
return Promise.reject(new MediaParserAbortError3("Aborted"));
|
|
4338
4799
|
}
|
|
4339
|
-
if (container
|
|
4340
|
-
return Promise.reject(new TypeError(
|
|
4800
|
+
if (availableContainers.indexOf(container) === -1) {
|
|
4801
|
+
return Promise.reject(new TypeError(`Only the following values for "container" are supported currently: ${JSON.stringify(availableContainers)}`));
|
|
4341
4802
|
}
|
|
4342
|
-
if (videoCodec && videoCodec
|
|
4343
|
-
return Promise.reject(new TypeError(
|
|
4803
|
+
if (videoCodec && availableVideoCodecs.indexOf(videoCodec) === -1) {
|
|
4804
|
+
return Promise.reject(new TypeError(`Only the following values for "videoCodec" are supported currently: ${JSON.stringify(availableVideoCodecs)}`));
|
|
4344
4805
|
}
|
|
4345
4806
|
const { resolve, reject, getPromiseToImmediatelyReturn } = withResolversAndWaitForReturn();
|
|
4346
|
-
const controller = new AbortController;
|
|
4347
4807
|
const abortConversion = (errCause) => {
|
|
4348
4808
|
reject(errCause);
|
|
4349
|
-
if (!controller.signal.aborted) {
|
|
4809
|
+
if (!controller._internals.signal.aborted) {
|
|
4350
4810
|
controller.abort();
|
|
4351
4811
|
}
|
|
4352
4812
|
};
|
|
4353
4813
|
const onUserAbort = () => {
|
|
4354
|
-
abortConversion(new
|
|
4814
|
+
abortConversion(new MediaParserAbortError3("Conversion aborted by user"));
|
|
4355
4815
|
};
|
|
4356
|
-
|
|
4816
|
+
controller._internals.signal.addEventListener("abort", onUserAbort);
|
|
4357
4817
|
const creator = selectContainerCreator(container);
|
|
4358
4818
|
const throttledState = throttledStateUpdate({
|
|
4359
4819
|
updateFn: onProgressDoNotCallDirectly ?? null,
|
|
4360
4820
|
everyMilliseconds: progressIntervalInMs ?? 100,
|
|
4361
|
-
signal: controller.signal
|
|
4821
|
+
signal: controller._internals.signal
|
|
4362
4822
|
});
|
|
4363
4823
|
const progressTracker = makeProgressTracker();
|
|
4364
4824
|
const state = await creator({
|
|
@@ -4416,17 +4876,17 @@ var convertMedia = async function({
|
|
|
4416
4876
|
progressTracker,
|
|
4417
4877
|
onAudioData: onAudioData ?? null
|
|
4418
4878
|
});
|
|
4419
|
-
|
|
4879
|
+
MediaParserInternals9.internalParseMedia({
|
|
4420
4880
|
logLevel,
|
|
4421
4881
|
src,
|
|
4422
4882
|
onVideoTrack,
|
|
4423
4883
|
onAudioTrack,
|
|
4424
|
-
|
|
4884
|
+
controller,
|
|
4425
4885
|
fields: {
|
|
4426
4886
|
...fields,
|
|
4427
4887
|
durationInSeconds: true
|
|
4428
4888
|
},
|
|
4429
|
-
reader,
|
|
4889
|
+
reader: reader ?? fetchReader,
|
|
4430
4890
|
...more,
|
|
4431
4891
|
onDurationInSeconds: (durationInSeconds) => {
|
|
4432
4892
|
if (durationInSeconds === null) {
|
|
@@ -4447,12 +4907,45 @@ var convertMedia = async function({
|
|
|
4447
4907
|
})
|
|
4448
4908
|
};
|
|
4449
4909
|
});
|
|
4450
|
-
}
|
|
4910
|
+
},
|
|
4911
|
+
acknowledgeRemotionLicense: true,
|
|
4912
|
+
mode: "query",
|
|
4913
|
+
onDiscardedData: null,
|
|
4914
|
+
onError: () => ({ action: "fail" }),
|
|
4915
|
+
onParseProgress: null,
|
|
4916
|
+
progressIntervalInMs: null,
|
|
4917
|
+
onAudioCodec: onAudioCodec ?? null,
|
|
4918
|
+
onContainer: onContainer ?? null,
|
|
4919
|
+
onDimensions: onDimensions ?? null,
|
|
4920
|
+
onFps: onFps ?? null,
|
|
4921
|
+
onImages: onImages ?? null,
|
|
4922
|
+
onInternalStats: onInternalStats ?? null,
|
|
4923
|
+
onIsHdr: onIsHdr ?? null,
|
|
4924
|
+
onKeyframes: onKeyframes ?? null,
|
|
4925
|
+
onLocation: onLocation ?? null,
|
|
4926
|
+
onMetadata: onMetadata ?? null,
|
|
4927
|
+
onMimeType: onMimeType ?? null,
|
|
4928
|
+
onName: onName ?? null,
|
|
4929
|
+
onNumberOfAudioChannels: onNumberOfAudioChannels ?? null,
|
|
4930
|
+
onRotation: onRotation ?? null,
|
|
4931
|
+
onSampleRate: onSampleRate ?? null,
|
|
4932
|
+
onSize: onSize ?? null,
|
|
4933
|
+
onSlowAudioBitrate: onSlowAudioBitrate ?? null,
|
|
4934
|
+
onSlowDurationInSeconds: onSlowDurationInSeconds ?? null,
|
|
4935
|
+
onSlowFps: onSlowFps ?? null,
|
|
4936
|
+
onSlowKeyframes: onSlowKeyframes ?? null,
|
|
4937
|
+
onSlowNumberOfFrames: onSlowNumberOfFrames ?? null,
|
|
4938
|
+
onSlowVideoBitrate: onSlowVideoBitrate ?? null,
|
|
4939
|
+
onStructure: onStructure ?? null,
|
|
4940
|
+
onTracks: onTracks ?? null,
|
|
4941
|
+
onUnrotatedDimensions: onUnrotatedDimensions ?? null,
|
|
4942
|
+
onVideoCodec: onVideoCodec ?? null,
|
|
4943
|
+
apiName: "convertMedia()"
|
|
4451
4944
|
}).then(() => {
|
|
4452
4945
|
return state.waitForFinish();
|
|
4453
4946
|
}).then(() => {
|
|
4454
4947
|
resolve({
|
|
4455
|
-
save: state.
|
|
4948
|
+
save: state.getBlob,
|
|
4456
4949
|
remove: state.remove,
|
|
4457
4950
|
finalState: throttledState.get()
|
|
4458
4951
|
});
|
|
@@ -4469,7 +4962,7 @@ var convertMedia = async function({
|
|
|
4469
4962
|
throttledState.stopAndGetLastProgress();
|
|
4470
4963
|
});
|
|
4471
4964
|
return getPromiseToImmediatelyReturn().finally(() => {
|
|
4472
|
-
|
|
4965
|
+
controller._internals.signal.removeEventListener("abort", onUserAbort);
|
|
4473
4966
|
});
|
|
4474
4967
|
};
|
|
4475
4968
|
// src/get-available-audio-codecs.ts
|
|
@@ -4487,26 +4980,6 @@ var getAvailableAudioCodecs = ({
|
|
|
4487
4980
|
}
|
|
4488
4981
|
throw new Error(`Unsupported container: ${container}`);
|
|
4489
4982
|
};
|
|
4490
|
-
// src/get-available-containers.ts
|
|
4491
|
-
var availableContainers = ["webm", "mp4", "wav"];
|
|
4492
|
-
var getAvailableContainers = () => {
|
|
4493
|
-
return availableContainers;
|
|
4494
|
-
};
|
|
4495
|
-
// src/get-available-video-codecs.ts
|
|
4496
|
-
var getAvailableVideoCodecs = ({
|
|
4497
|
-
container
|
|
4498
|
-
}) => {
|
|
4499
|
-
if (container === "mp4") {
|
|
4500
|
-
return ["h264"];
|
|
4501
|
-
}
|
|
4502
|
-
if (container === "webm") {
|
|
4503
|
-
return ["vp8", "vp9"];
|
|
4504
|
-
}
|
|
4505
|
-
if (container === "wav") {
|
|
4506
|
-
return [];
|
|
4507
|
-
}
|
|
4508
|
-
throw new Error(`Unsupported container: ${container}`);
|
|
4509
|
-
};
|
|
4510
4983
|
// src/index.ts
|
|
4511
4984
|
var WebCodecsInternals = {
|
|
4512
4985
|
rotateAndResizeVideoFrame,
|
|
@@ -4515,6 +4988,7 @@ var WebCodecsInternals = {
|
|
|
4515
4988
|
};
|
|
4516
4989
|
setRemotionImported();
|
|
4517
4990
|
export {
|
|
4991
|
+
webcodecsController,
|
|
4518
4992
|
getDefaultVideoCodec,
|
|
4519
4993
|
getDefaultAudioCodec,
|
|
4520
4994
|
getAvailableVideoCodecs,
|