@remotion/webcodecs 4.0.232 → 4.0.233
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/README.md +2 -2
- package/dist/audio-decoder-config.d.ts +2 -1
- package/dist/audio-decoder-config.js +44 -3
- package/dist/audio-decoder.d.ts +6 -3
- package/dist/audio-decoder.js +20 -4
- package/dist/audio-encoder.d.ts +3 -2
- package/dist/audio-encoder.js +11 -3
- package/dist/browser-quirks.d.ts +1 -0
- package/dist/browser-quirks.js +5 -1
- package/dist/can-copy-video-track.d.ts +3 -1
- package/dist/can-copy-video-track.js +6 -1
- package/dist/can-reencode-audio-track.d.ts +3 -2
- package/dist/can-reencode-audio-track.js +2 -2
- package/dist/convert-media.d.ts +2 -1
- package/dist/convert-media.js +7 -3
- package/dist/convert-to-correct-videoframe.js +4 -0
- package/dist/default-on-video-track-handler.js +8 -2
- package/dist/esm/index.mjs +351 -137
- package/dist/get-wave-audio-decoder.d.ts +2 -0
- package/dist/get-wave-audio-decoder.js +29 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -1
- package/dist/io-manager/event-emitter.d.ts +4 -0
- package/dist/io-manager/event-emitter.js +1 -0
- package/dist/io-manager/io-synchronizer.d.ts +8 -2
- package/dist/io-manager/io-synchronizer.js +31 -20
- package/dist/io-manager/make-timeout-promise.d.ts +4 -0
- package/dist/io-manager/make-timeout-promise.js +18 -0
- package/dist/on-audio-track.d.ts +3 -2
- package/dist/on-audio-track.js +6 -3
- package/dist/on-frame.d.ts +2 -1
- package/dist/on-frame.js +25 -14
- package/dist/on-video-track-handler.d.ts +2 -0
- package/dist/on-video-track.d.ts +4 -2
- package/dist/on-video-track.js +20 -5
- package/dist/rotate-video-frame.d.ts +5 -0
- package/dist/rotate-video-frame.js +48 -0
- package/dist/rotate-video.d.ts +4 -0
- package/dist/rotate-video.js +43 -0
- package/dist/rotation.d.ts +8 -0
- package/dist/rotation.js +10 -0
- package/dist/select-container-creator.d.ts +1 -1
- package/dist/test/avi-to-mp4.test.js +15 -0
- package/dist/video-decoder.d.ts +3 -2
- package/dist/video-decoder.js +11 -3
- package/dist/video-encoder.d.ts +3 -2
- package/dist/video-encoder.js +7 -2
- package/package.json +5 -3
package/dist/esm/index.mjs
CHANGED
|
@@ -1,3 +1,59 @@
|
|
|
1
|
+
// src/rotation.ts
|
|
2
|
+
var calculateNewDimensionsFromDimensions = ({
|
|
3
|
+
width,
|
|
4
|
+
height,
|
|
5
|
+
rotation
|
|
6
|
+
}) => {
|
|
7
|
+
const switchDimensions = rotation % 90 === 0 && rotation % 180 !== 0;
|
|
8
|
+
const newHeight = switchDimensions ? width : height;
|
|
9
|
+
const newWidth = switchDimensions ? height : width;
|
|
10
|
+
return { height: newHeight, width: newWidth };
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/rotate-video-frame.ts
|
|
14
|
+
var normalizeVideoRotation = (rotation) => {
|
|
15
|
+
return (rotation % 360 + 360) % 360;
|
|
16
|
+
};
|
|
17
|
+
var rotateVideoFrame = ({
|
|
18
|
+
frame,
|
|
19
|
+
rotation
|
|
20
|
+
}) => {
|
|
21
|
+
const normalized = (rotation % 360 + 360) % 360;
|
|
22
|
+
if (normalized % 360 === 0) {
|
|
23
|
+
return frame;
|
|
24
|
+
}
|
|
25
|
+
if (normalized % 90 !== 0) {
|
|
26
|
+
throw new Error("Only 90 degree rotations are supported");
|
|
27
|
+
}
|
|
28
|
+
const { height, width } = calculateNewDimensionsFromDimensions({
|
|
29
|
+
height: frame.displayHeight,
|
|
30
|
+
width: frame.displayWidth,
|
|
31
|
+
rotation
|
|
32
|
+
});
|
|
33
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
34
|
+
const ctx = canvas.getContext("2d");
|
|
35
|
+
if (!ctx) {
|
|
36
|
+
throw new Error("Could not get 2d context");
|
|
37
|
+
}
|
|
38
|
+
canvas.width = width;
|
|
39
|
+
canvas.height = height;
|
|
40
|
+
if (normalized === 90) {
|
|
41
|
+
ctx.translate(width, 0);
|
|
42
|
+
} else if (normalized === 180) {
|
|
43
|
+
ctx.translate(width, height);
|
|
44
|
+
} else if (normalized === 270) {
|
|
45
|
+
ctx.translate(0, height);
|
|
46
|
+
}
|
|
47
|
+
ctx.rotate(normalized * (Math.PI / 180));
|
|
48
|
+
ctx.drawImage(frame, 0, 0);
|
|
49
|
+
return new VideoFrame(canvas, {
|
|
50
|
+
displayHeight: height,
|
|
51
|
+
displayWidth: width,
|
|
52
|
+
duration: frame.duration ?? undefined,
|
|
53
|
+
timestamp: frame.timestamp
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
|
|
1
57
|
// src/set-remotion-imported.ts
|
|
2
58
|
import { VERSION } from "@remotion/media-parser";
|
|
3
59
|
var setRemotionImported = () => {
|
|
@@ -13,58 +69,65 @@ var setRemotionImported = () => {
|
|
|
13
69
|
}
|
|
14
70
|
};
|
|
15
71
|
|
|
16
|
-
// src/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const { promise: returnPromise, resolve: resolveReturn } = withResolvers();
|
|
72
|
+
// src/get-wave-audio-decoder.ts
|
|
73
|
+
var getWaveAudioDecoder = ({
|
|
74
|
+
onFrame,
|
|
75
|
+
track
|
|
76
|
+
}) => {
|
|
77
|
+
let queue = Promise.resolve();
|
|
78
|
+
const processSample = async (audioSample) => {
|
|
79
|
+
await onFrame(new AudioData({
|
|
80
|
+
data: audioSample.data,
|
|
81
|
+
format: "s16",
|
|
82
|
+
numberOfChannels: track.numberOfChannels,
|
|
83
|
+
numberOfFrames: audioSample.data.byteLength / 2,
|
|
84
|
+
sampleRate: track.sampleRate,
|
|
85
|
+
timestamp: audioSample.timestamp
|
|
86
|
+
}));
|
|
87
|
+
};
|
|
33
88
|
return {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return promise;
|
|
89
|
+
close() {
|
|
90
|
+
return Promise.resolve();
|
|
37
91
|
},
|
|
38
|
-
|
|
39
|
-
|
|
92
|
+
processSample(audioSample) {
|
|
93
|
+
queue = queue.then(() => processSample(audioSample));
|
|
94
|
+
return queue;
|
|
40
95
|
},
|
|
41
|
-
resolve
|
|
96
|
+
flush: () => Promise.resolve(),
|
|
97
|
+
waitForFinish: () => Promise.resolve()
|
|
42
98
|
};
|
|
43
99
|
};
|
|
44
100
|
|
|
45
|
-
// src/io-manager/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
101
|
+
// src/io-manager/io-synchronizer.ts
|
|
102
|
+
import { MediaParserInternals as MediaParserInternals3 } from "@remotion/media-parser";
|
|
103
|
+
|
|
104
|
+
// src/log.ts
|
|
105
|
+
import { MediaParserInternals } from "@remotion/media-parser";
|
|
106
|
+
var { Log } = MediaParserInternals;
|
|
107
|
+
|
|
108
|
+
// src/io-manager/make-timeout-promise.ts
|
|
109
|
+
import { MediaParserInternals as MediaParserInternals2 } from "@remotion/media-parser";
|
|
110
|
+
var makeTimeoutPromise = (label, ms) => {
|
|
111
|
+
const { promise, reject, resolve } = MediaParserInternals2.withResolvers();
|
|
112
|
+
const timeout = setTimeout(() => {
|
|
113
|
+
reject(new Error(`${label} (timed out after ${ms}ms)`));
|
|
114
|
+
}, ms);
|
|
115
|
+
return {
|
|
116
|
+
timeoutPromise: promise,
|
|
117
|
+
clear: () => {
|
|
118
|
+
clearTimeout(timeout);
|
|
119
|
+
resolve();
|
|
120
|
+
}
|
|
51
121
|
};
|
|
52
|
-
|
|
53
|
-
this.listeners[name].push(callback);
|
|
54
|
-
}
|
|
55
|
-
removeEventListener(name, callback) {
|
|
56
|
-
this.listeners[name] = this.listeners[name].filter((l) => l !== callback);
|
|
57
|
-
}
|
|
58
|
-
dispatchEvent(dispatchName, context) {
|
|
59
|
-
this.listeners[dispatchName].forEach((callback) => {
|
|
60
|
-
callback({ detail: context });
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
122
|
+
};
|
|
64
123
|
|
|
65
124
|
// src/io-manager/io-synchronizer.ts
|
|
66
|
-
var makeIoSynchronizer = (
|
|
67
|
-
|
|
125
|
+
var makeIoSynchronizer = ({
|
|
126
|
+
logLevel,
|
|
127
|
+
label,
|
|
128
|
+
progress
|
|
129
|
+
}) => {
|
|
130
|
+
const eventEmitter = new MediaParserInternals3.IoEventEmitter;
|
|
68
131
|
let lastInput = 0;
|
|
69
132
|
let lastInputKeyframe = 0;
|
|
70
133
|
let lastOutput = 0;
|
|
@@ -108,7 +171,7 @@ var makeIoSynchronizer = (logLevel, label) => {
|
|
|
108
171
|
printState("Got output");
|
|
109
172
|
};
|
|
110
173
|
const waitForOutput = () => {
|
|
111
|
-
const { promise, resolve } = withResolvers();
|
|
174
|
+
const { promise, resolve } = MediaParserInternals3.withResolvers();
|
|
112
175
|
const on = () => {
|
|
113
176
|
eventEmitter.removeEventListener("output", on);
|
|
114
177
|
resolve();
|
|
@@ -117,7 +180,7 @@ var makeIoSynchronizer = (logLevel, label) => {
|
|
|
117
180
|
return promise;
|
|
118
181
|
};
|
|
119
182
|
const waitForProcessed = () => {
|
|
120
|
-
const { promise, resolve } = withResolvers();
|
|
183
|
+
const { promise, resolve } = MediaParserInternals3.withResolvers();
|
|
121
184
|
const on = () => {
|
|
122
185
|
eventEmitter.removeEventListener("processed", on);
|
|
123
186
|
resolve();
|
|
@@ -127,23 +190,33 @@ var makeIoSynchronizer = (logLevel, label) => {
|
|
|
127
190
|
};
|
|
128
191
|
const waitFor = async ({
|
|
129
192
|
_unprocessed,
|
|
130
|
-
unemitted
|
|
193
|
+
unemitted,
|
|
194
|
+
minimumProgress
|
|
131
195
|
}) => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
196
|
+
const { timeoutPromise, clear } = makeTimeoutPromise(`Waited too long for ${label}`, 1e4);
|
|
197
|
+
await Promise.race([
|
|
198
|
+
timeoutPromise,
|
|
199
|
+
Promise.all([
|
|
200
|
+
(async () => {
|
|
201
|
+
while (getUnemittedItems() > unemitted) {
|
|
202
|
+
await waitForOutput();
|
|
203
|
+
}
|
|
204
|
+
})(),
|
|
205
|
+
(async () => {
|
|
206
|
+
while (getUnprocessed() > _unprocessed) {
|
|
207
|
+
await waitForProcessed();
|
|
208
|
+
}
|
|
209
|
+
})(),
|
|
210
|
+
minimumProgress === null ? Promise.resolve() : (async () => {
|
|
211
|
+
while (progress.getSmallestProgress() < minimumProgress) {
|
|
212
|
+
await progress.waitForProgress();
|
|
213
|
+
}
|
|
214
|
+
})()
|
|
215
|
+
])
|
|
216
|
+
]).finally(() => clear());
|
|
144
217
|
};
|
|
145
218
|
const waitForFinish = async () => {
|
|
146
|
-
await waitFor({ _unprocessed: 0, unemitted: 0 });
|
|
219
|
+
await waitFor({ _unprocessed: 0, unemitted: 0, minimumProgress: null });
|
|
147
220
|
};
|
|
148
221
|
const onProcessed = () => {
|
|
149
222
|
eventEmitter.dispatchEvent("processed", {});
|
|
@@ -165,12 +238,21 @@ var createAudioDecoder = ({
|
|
|
165
238
|
onError,
|
|
166
239
|
signal,
|
|
167
240
|
config,
|
|
168
|
-
logLevel
|
|
241
|
+
logLevel,
|
|
242
|
+
track,
|
|
243
|
+
progressTracker
|
|
169
244
|
}) => {
|
|
170
245
|
if (signal.aborted) {
|
|
171
246
|
throw new Error("Not creating audio decoder, already aborted");
|
|
172
247
|
}
|
|
173
|
-
|
|
248
|
+
if (config.codec === "pcm-s16") {
|
|
249
|
+
return getWaveAudioDecoder({ onFrame, track });
|
|
250
|
+
}
|
|
251
|
+
const ioSynchronizer = makeIoSynchronizer({
|
|
252
|
+
logLevel,
|
|
253
|
+
label: "Audio decoder",
|
|
254
|
+
progress: progressTracker
|
|
255
|
+
});
|
|
174
256
|
let outputQueue = Promise.resolve();
|
|
175
257
|
const audioDecoder = new AudioDecoder({
|
|
176
258
|
output(inputFrame) {
|
|
@@ -213,7 +295,11 @@ var createAudioDecoder = ({
|
|
|
213
295
|
if (audioDecoder.state === "closed") {
|
|
214
296
|
return;
|
|
215
297
|
}
|
|
216
|
-
await ioSynchronizer.waitFor({
|
|
298
|
+
await ioSynchronizer.waitFor({
|
|
299
|
+
unemitted: 20,
|
|
300
|
+
_unprocessed: 20,
|
|
301
|
+
minimumProgress: audioSample.timestamp - 1e7
|
|
302
|
+
});
|
|
217
303
|
const chunk = new EncodedAudioChunk(audioSample);
|
|
218
304
|
audioDecoder.decode(chunk);
|
|
219
305
|
ioSynchronizer.inputItem(chunk.timestamp, audioSample.type === "key");
|
|
@@ -228,7 +314,10 @@ var createAudioDecoder = ({
|
|
|
228
314
|
return queue;
|
|
229
315
|
},
|
|
230
316
|
waitForFinish: async () => {
|
|
231
|
-
|
|
317
|
+
try {
|
|
318
|
+
await audioDecoder.flush();
|
|
319
|
+
} catch {
|
|
320
|
+
}
|
|
232
321
|
await queue;
|
|
233
322
|
await ioSynchronizer.waitForFinish();
|
|
234
323
|
await outputQueue;
|
|
@@ -274,7 +363,8 @@ var createAudioEncoder = ({
|
|
|
274
363
|
signal,
|
|
275
364
|
config: audioEncoderConfig,
|
|
276
365
|
logLevel,
|
|
277
|
-
onNewAudioSampleRate
|
|
366
|
+
onNewAudioSampleRate,
|
|
367
|
+
progressTracker
|
|
278
368
|
}) => {
|
|
279
369
|
if (signal.aborted) {
|
|
280
370
|
throw new Error("Not creating audio encoder, already aborted");
|
|
@@ -282,7 +372,11 @@ var createAudioEncoder = ({
|
|
|
282
372
|
if (codec === "wav") {
|
|
283
373
|
return getWaveAudioEncoder({ onChunk, signal });
|
|
284
374
|
}
|
|
285
|
-
const ioSynchronizer = makeIoSynchronizer(
|
|
375
|
+
const ioSynchronizer = makeIoSynchronizer({
|
|
376
|
+
logLevel,
|
|
377
|
+
label: "Audio encoder",
|
|
378
|
+
progress: progressTracker
|
|
379
|
+
});
|
|
286
380
|
let prom = Promise.resolve();
|
|
287
381
|
const encoder = new AudioEncoder({
|
|
288
382
|
output: (chunk) => {
|
|
@@ -322,7 +416,11 @@ var createAudioEncoder = ({
|
|
|
322
416
|
if (encoder.state === "closed") {
|
|
323
417
|
return;
|
|
324
418
|
}
|
|
325
|
-
await ioSynchronizer.waitFor({
|
|
419
|
+
await ioSynchronizer.waitFor({
|
|
420
|
+
unemitted: 20,
|
|
421
|
+
_unprocessed: 20,
|
|
422
|
+
minimumProgress: audioData.timestamp - 1e7
|
|
423
|
+
});
|
|
326
424
|
if (encoder.state === "closed") {
|
|
327
425
|
return;
|
|
328
426
|
}
|
|
@@ -376,8 +474,13 @@ var canCopyAudioTrack = ({
|
|
|
376
474
|
// src/can-copy-video-track.ts
|
|
377
475
|
var canCopyVideoTrack = ({
|
|
378
476
|
inputCodec,
|
|
379
|
-
container
|
|
477
|
+
container,
|
|
478
|
+
inputRotation,
|
|
479
|
+
rotationToApply
|
|
380
480
|
}) => {
|
|
481
|
+
if (normalizeVideoRotation(inputRotation) !== normalizeVideoRotation(rotationToApply)) {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
381
484
|
if (container === "webm") {
|
|
382
485
|
return inputCodec === "vp8" || inputCodec === "vp9";
|
|
383
486
|
}
|
|
@@ -389,16 +492,68 @@ var canCopyVideoTrack = ({
|
|
|
389
492
|
}
|
|
390
493
|
throw new Error(`Unhandled codec: ${container}`);
|
|
391
494
|
};
|
|
495
|
+
// src/browser-quirks.ts
|
|
496
|
+
var isFirefox = () => {
|
|
497
|
+
return navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
|
|
498
|
+
};
|
|
499
|
+
var isSafari = () => {
|
|
500
|
+
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
501
|
+
};
|
|
502
|
+
var isChrome = () => {
|
|
503
|
+
return navigator.userAgent.toLowerCase().indexOf("chrome") > -1;
|
|
504
|
+
};
|
|
505
|
+
|
|
392
506
|
// src/audio-decoder-config.ts
|
|
393
|
-
var
|
|
507
|
+
var overrideBrowserQuirks = ({
|
|
508
|
+
config,
|
|
509
|
+
logLevel
|
|
510
|
+
}) => {
|
|
511
|
+
const bytes = config.description;
|
|
512
|
+
if (!bytes) {
|
|
513
|
+
return config;
|
|
514
|
+
}
|
|
515
|
+
if (bytes[0] === 18 && bytes[1] === 8) {
|
|
516
|
+
if (isFirefox()) {
|
|
517
|
+
return {
|
|
518
|
+
...config,
|
|
519
|
+
codec: "mp4a.40.2",
|
|
520
|
+
description: bytes
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
if (!isChrome()) {
|
|
524
|
+
return config;
|
|
525
|
+
}
|
|
526
|
+
Log.warn(logLevel, "Chrome has a bug and might not be able to decode this audio. It will be fixed, see: https://issues.chromium.org/issues/360083330");
|
|
527
|
+
return {
|
|
528
|
+
...config,
|
|
529
|
+
description: new Uint8Array([18, 16])
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
if (bytes.byteLength === 2 && bytes[0] === 17 && bytes[1] === 136) {
|
|
533
|
+
Log.warn(logLevel, "Chrome has a bug and might not be able to decode this audio. It will be fixed, see: https://issues.chromium.org/issues/360083330");
|
|
534
|
+
return {
|
|
535
|
+
...config,
|
|
536
|
+
description: new Uint8Array([18, 144])
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
return config;
|
|
540
|
+
};
|
|
541
|
+
var getAudioDecoderConfig = async (config, logLevel) => {
|
|
542
|
+
if (config.codec === "pcm-s16") {
|
|
543
|
+
return config;
|
|
544
|
+
}
|
|
394
545
|
if (typeof AudioDecoder === "undefined") {
|
|
395
546
|
return null;
|
|
396
547
|
}
|
|
397
548
|
if (typeof EncodedAudioChunk === "undefined") {
|
|
398
549
|
return null;
|
|
399
550
|
}
|
|
400
|
-
|
|
401
|
-
|
|
551
|
+
const realConfig = overrideBrowserQuirks({
|
|
552
|
+
config,
|
|
553
|
+
logLevel
|
|
554
|
+
});
|
|
555
|
+
if ((await AudioDecoder.isConfigSupported(realConfig)).supported) {
|
|
556
|
+
return realConfig;
|
|
402
557
|
}
|
|
403
558
|
return null;
|
|
404
559
|
};
|
|
@@ -437,9 +592,10 @@ var getAudioEncoderConfig = async (config) => {
|
|
|
437
592
|
var canReencodeAudioTrack = async ({
|
|
438
593
|
track,
|
|
439
594
|
audioCodec,
|
|
440
|
-
bitrate
|
|
595
|
+
bitrate,
|
|
596
|
+
logLevel = "info"
|
|
441
597
|
}) => {
|
|
442
|
-
const audioDecoderConfig = await getAudioDecoderConfig(track);
|
|
598
|
+
const audioDecoderConfig = await getAudioDecoderConfig(track, logLevel);
|
|
443
599
|
if (audioCodec === "wav" && audioDecoderConfig) {
|
|
444
600
|
return true;
|
|
445
601
|
}
|
|
@@ -473,14 +629,6 @@ var getVideoDecoderConfigWithHardwareAcceleration = async (config) => {
|
|
|
473
629
|
return null;
|
|
474
630
|
};
|
|
475
631
|
|
|
476
|
-
// src/browser-quirks.ts
|
|
477
|
-
var isFirefox = () => {
|
|
478
|
-
return navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
|
|
479
|
-
};
|
|
480
|
-
var isSafari = () => {
|
|
481
|
-
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
482
|
-
};
|
|
483
|
-
|
|
484
632
|
// src/choose-correct-avc1-profile.ts
|
|
485
633
|
var chooseCorrectAvc1Profile = ({
|
|
486
634
|
width,
|
|
@@ -564,7 +712,10 @@ var canReencodeVideoTrack = async ({
|
|
|
564
712
|
return Boolean(videoDecoderConfig && videoEncoderConfig);
|
|
565
713
|
};
|
|
566
714
|
// src/convert-media.ts
|
|
567
|
-
import {
|
|
715
|
+
import {
|
|
716
|
+
MediaParserInternals as MediaParserInternals7,
|
|
717
|
+
parseMedia
|
|
718
|
+
} from "@remotion/media-parser";
|
|
568
719
|
|
|
569
720
|
// src/auto-select-writer.ts
|
|
570
721
|
import { bufferWriter } from "@remotion/media-parser/buffer";
|
|
@@ -621,7 +772,7 @@ var convertEncodedChunk = (chunk, trackId) => {
|
|
|
621
772
|
};
|
|
622
773
|
|
|
623
774
|
// src/default-on-audio-track-handler.ts
|
|
624
|
-
import { MediaParserInternals as
|
|
775
|
+
import { MediaParserInternals as MediaParserInternals4 } from "@remotion/media-parser";
|
|
625
776
|
|
|
626
777
|
// src/get-default-audio-codec.ts
|
|
627
778
|
var getDefaultAudioCodec = ({
|
|
@@ -653,7 +804,7 @@ var defaultOnAudioTrackHandler = async ({
|
|
|
653
804
|
container
|
|
654
805
|
});
|
|
655
806
|
if (canCopy) {
|
|
656
|
-
|
|
807
|
+
MediaParserInternals4.Log.verbose(logLevel, `Track ${track.trackId} (audio): Can copy track, therefore copying`);
|
|
657
808
|
return Promise.resolve({ type: "copy" });
|
|
658
809
|
}
|
|
659
810
|
const audioCodec = defaultAudioCodec ?? getDefaultAudioCodec({ container });
|
|
@@ -663,14 +814,14 @@ var defaultOnAudioTrackHandler = async ({
|
|
|
663
814
|
bitrate
|
|
664
815
|
});
|
|
665
816
|
if (canReencode) {
|
|
666
|
-
|
|
817
|
+
MediaParserInternals4.Log.verbose(logLevel, `Track ${track.trackId} (audio): Cannot copy, but re-encode, therefore re-encoding`);
|
|
667
818
|
return Promise.resolve({
|
|
668
819
|
type: "reencode",
|
|
669
820
|
bitrate,
|
|
670
821
|
audioCodec
|
|
671
822
|
});
|
|
672
823
|
}
|
|
673
|
-
|
|
824
|
+
MediaParserInternals4.Log.verbose(logLevel, `Track ${track.trackId} (audio): Can neither re-encode nor copy, failing render`);
|
|
674
825
|
return Promise.resolve({ type: "fail" });
|
|
675
826
|
};
|
|
676
827
|
|
|
@@ -683,7 +834,8 @@ var makeAudioTrackHandler = ({
|
|
|
683
834
|
onMediaStateUpdate,
|
|
684
835
|
onAudioTrack,
|
|
685
836
|
logLevel,
|
|
686
|
-
container
|
|
837
|
+
container,
|
|
838
|
+
progressTracker
|
|
687
839
|
}) => async (track) => {
|
|
688
840
|
const audioOperation = await (onAudioTrack ?? defaultOnAudioTrackHandler)({
|
|
689
841
|
defaultAudioCodec: audioCodec,
|
|
@@ -734,7 +886,7 @@ var makeAudioTrackHandler = ({
|
|
|
734
886
|
numberOfChannels: track.numberOfChannels,
|
|
735
887
|
sampleRate: track.sampleRate,
|
|
736
888
|
description: track.description
|
|
737
|
-
});
|
|
889
|
+
}, logLevel);
|
|
738
890
|
if (!audioEncoderConfig) {
|
|
739
891
|
abortConversion(new error_cause_default(`Could not configure audio encoder of track ${track.trackId}`));
|
|
740
892
|
return null;
|
|
@@ -779,7 +931,8 @@ var makeAudioTrackHandler = ({
|
|
|
779
931
|
codec: audioOperation.audioCodec,
|
|
780
932
|
signal: controller.signal,
|
|
781
933
|
config: audioEncoderConfig,
|
|
782
|
-
logLevel
|
|
934
|
+
logLevel,
|
|
935
|
+
progressTracker
|
|
783
936
|
});
|
|
784
937
|
const audioDecoder = createAudioDecoder({
|
|
785
938
|
onFrame: async (frame) => {
|
|
@@ -793,13 +946,15 @@ var makeAudioTrackHandler = ({
|
|
|
793
946
|
frame.close();
|
|
794
947
|
},
|
|
795
948
|
onError(error) {
|
|
796
|
-
abortConversion(new error_cause_default(`Audio decoder of track ${track.trackId} failed (see .cause of this error)`, {
|
|
949
|
+
abortConversion(new error_cause_default(`Audio decoder of track ${track.trackId} failed. Config: ${JSON.stringify(audioDecoderConfig)} (see .cause of this error)`, {
|
|
797
950
|
cause: error
|
|
798
951
|
}));
|
|
799
952
|
},
|
|
800
953
|
signal: controller.signal,
|
|
801
954
|
config: audioDecoderConfig,
|
|
802
|
-
logLevel
|
|
955
|
+
logLevel,
|
|
956
|
+
track,
|
|
957
|
+
progressTracker
|
|
803
958
|
});
|
|
804
959
|
state.addWaitForFinishPromise(async () => {
|
|
805
960
|
await audioDecoder.waitForFinish();
|
|
@@ -818,7 +973,7 @@ var arrayBufferToUint8Array = (buffer) => {
|
|
|
818
973
|
};
|
|
819
974
|
|
|
820
975
|
// src/default-on-video-track-handler.ts
|
|
821
|
-
import { MediaParserInternals as
|
|
976
|
+
import { MediaParserInternals as MediaParserInternals5 } from "@remotion/media-parser";
|
|
822
977
|
|
|
823
978
|
// src/get-default-video-codec.ts
|
|
824
979
|
var getDefaultVideoCodec = ({
|
|
@@ -841,19 +996,22 @@ var defaultOnVideoTrackHandler = async ({
|
|
|
841
996
|
track,
|
|
842
997
|
defaultVideoCodec,
|
|
843
998
|
logLevel,
|
|
844
|
-
container
|
|
999
|
+
container,
|
|
1000
|
+
rotate
|
|
845
1001
|
}) => {
|
|
846
1002
|
const canCopy = canCopyVideoTrack({
|
|
847
1003
|
inputCodec: track.codecWithoutConfig,
|
|
848
|
-
container
|
|
1004
|
+
container,
|
|
1005
|
+
inputRotation: track.rotation,
|
|
1006
|
+
rotationToApply: rotate
|
|
849
1007
|
});
|
|
850
1008
|
if (canCopy) {
|
|
851
|
-
|
|
1009
|
+
MediaParserInternals5.Log.verbose(logLevel, `Track ${track.trackId} (video): Can copy, therefore copying`);
|
|
852
1010
|
return Promise.resolve({ type: "copy" });
|
|
853
1011
|
}
|
|
854
1012
|
const videoCodec = defaultVideoCodec ?? getDefaultVideoCodec({ container });
|
|
855
1013
|
if (videoCodec === null) {
|
|
856
|
-
|
|
1014
|
+
MediaParserInternals5.Log.verbose(logLevel, `Track ${track.trackId} (video): No default video codec, therefore dropping`);
|
|
857
1015
|
return Promise.resolve({ type: "drop" });
|
|
858
1016
|
}
|
|
859
1017
|
const canReencode = await canReencodeVideoTrack({
|
|
@@ -861,10 +1019,14 @@ var defaultOnVideoTrackHandler = async ({
|
|
|
861
1019
|
track
|
|
862
1020
|
});
|
|
863
1021
|
if (canReencode) {
|
|
864
|
-
|
|
865
|
-
return Promise.resolve({
|
|
1022
|
+
MediaParserInternals5.Log.verbose(logLevel, `Track ${track.trackId} (video): Cannot copy, but re-enconde, therefore re-encoding`);
|
|
1023
|
+
return Promise.resolve({
|
|
1024
|
+
type: "reencode",
|
|
1025
|
+
videoCodec,
|
|
1026
|
+
rotation: rotate - track.rotation
|
|
1027
|
+
});
|
|
866
1028
|
}
|
|
867
|
-
|
|
1029
|
+
MediaParserInternals5.Log.verbose(logLevel, `Track ${track.trackId} (video): Can neither copy nor re-encode, therefore failing`);
|
|
868
1030
|
return Promise.resolve({ type: "fail" });
|
|
869
1031
|
};
|
|
870
1032
|
|
|
@@ -876,6 +1038,9 @@ var needsToCorrectVideoFrame = ({
|
|
|
876
1038
|
if (videoFrame.format === null) {
|
|
877
1039
|
return true;
|
|
878
1040
|
}
|
|
1041
|
+
if (videoFrame.format === "I420P10") {
|
|
1042
|
+
return true;
|
|
1043
|
+
}
|
|
879
1044
|
return isFirefox() && videoFrame.format === "BGRX" && outputCodec === "h264";
|
|
880
1045
|
};
|
|
881
1046
|
var convertToCorrectVideoFrame = ({
|
|
@@ -903,35 +1068,43 @@ var convertToCorrectVideoFrame = ({
|
|
|
903
1068
|
|
|
904
1069
|
// src/on-frame.ts
|
|
905
1070
|
var onFrame = async ({
|
|
906
|
-
frame,
|
|
1071
|
+
frame: unrotatedFrame,
|
|
907
1072
|
onVideoFrame,
|
|
908
1073
|
videoEncoder,
|
|
909
1074
|
track,
|
|
910
|
-
outputCodec
|
|
1075
|
+
outputCodec,
|
|
1076
|
+
rotation
|
|
911
1077
|
}) => {
|
|
912
|
-
const
|
|
913
|
-
|
|
914
|
-
|
|
1078
|
+
const rotated = rotateVideoFrame({
|
|
1079
|
+
rotation,
|
|
1080
|
+
frame: unrotatedFrame
|
|
1081
|
+
});
|
|
1082
|
+
if (unrotatedFrame !== rotated) {
|
|
1083
|
+
unrotatedFrame.close();
|
|
1084
|
+
}
|
|
1085
|
+
const userProcessedFrame = onVideoFrame ? await onVideoFrame({ frame: rotated, track }) : rotated;
|
|
1086
|
+
if (userProcessedFrame.displayWidth !== rotated.displayWidth) {
|
|
1087
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different displayWidth (${userProcessedFrame.displayWidth}) than the input frame (${userProcessedFrame.displayHeight})`);
|
|
915
1088
|
}
|
|
916
|
-
if (
|
|
917
|
-
throw new Error(`Returned VideoFrame of track ${track.trackId} has different displayHeight (${
|
|
1089
|
+
if (userProcessedFrame.displayHeight !== rotated.displayHeight) {
|
|
1090
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different displayHeight (${userProcessedFrame.displayHeight}) than the input frame (${userProcessedFrame.displayHeight})`);
|
|
918
1091
|
}
|
|
919
|
-
if (
|
|
920
|
-
throw new Error(`Returned VideoFrame of track ${track.trackId} has different timestamp (${
|
|
1092
|
+
if (userProcessedFrame.timestamp !== rotated.timestamp) {
|
|
1093
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different timestamp (${userProcessedFrame.timestamp}) than the input frame (${rotated.timestamp}). When calling new VideoFrame(), pass {timestamp: frame.timestamp} as second argument`);
|
|
921
1094
|
}
|
|
922
|
-
if (
|
|
923
|
-
throw new Error(`Returned VideoFrame of track ${track.trackId} has different duration (${
|
|
1095
|
+
if ((userProcessedFrame.duration ?? 0) !== (rotated.duration ?? 0)) {
|
|
1096
|
+
throw new Error(`Returned VideoFrame of track ${track.trackId} has different duration (${userProcessedFrame.duration}) than the input frame (${rotated.duration}). When calling new VideoFrame(), pass {duration: frame.duration} as second argument`);
|
|
924
1097
|
}
|
|
925
1098
|
const fixedFrame = convertToCorrectVideoFrame({
|
|
926
|
-
videoFrame:
|
|
1099
|
+
videoFrame: userProcessedFrame,
|
|
927
1100
|
outputCodec
|
|
928
1101
|
});
|
|
929
1102
|
await videoEncoder.encodeFrame(fixedFrame, fixedFrame.timestamp);
|
|
930
1103
|
fixedFrame.close();
|
|
931
|
-
if (
|
|
932
|
-
|
|
1104
|
+
if (rotated !== userProcessedFrame) {
|
|
1105
|
+
rotated.close();
|
|
933
1106
|
}
|
|
934
|
-
if (fixedFrame !==
|
|
1107
|
+
if (fixedFrame !== userProcessedFrame) {
|
|
935
1108
|
fixedFrame.close();
|
|
936
1109
|
}
|
|
937
1110
|
};
|
|
@@ -942,9 +1115,14 @@ var createVideoDecoder = ({
|
|
|
942
1115
|
onError,
|
|
943
1116
|
signal,
|
|
944
1117
|
config,
|
|
945
|
-
logLevel
|
|
1118
|
+
logLevel,
|
|
1119
|
+
progress
|
|
946
1120
|
}) => {
|
|
947
|
-
const ioSynchronizer = makeIoSynchronizer(
|
|
1121
|
+
const ioSynchronizer = makeIoSynchronizer({
|
|
1122
|
+
logLevel,
|
|
1123
|
+
label: "Video decoder",
|
|
1124
|
+
progress
|
|
1125
|
+
});
|
|
948
1126
|
let outputQueue = Promise.resolve();
|
|
949
1127
|
const videoDecoder = new VideoDecoder({
|
|
950
1128
|
output(inputFrame) {
|
|
@@ -990,7 +1168,11 @@ var createVideoDecoder = ({
|
|
|
990
1168
|
if (videoDecoder.state === "closed") {
|
|
991
1169
|
return;
|
|
992
1170
|
}
|
|
993
|
-
await ioSynchronizer.waitFor({
|
|
1171
|
+
await ioSynchronizer.waitFor({
|
|
1172
|
+
unemitted: 20,
|
|
1173
|
+
_unprocessed: 2,
|
|
1174
|
+
minimumProgress: sample.timestamp - 5000000
|
|
1175
|
+
});
|
|
994
1176
|
if (sample.type === "key") {
|
|
995
1177
|
await videoDecoder.flush();
|
|
996
1178
|
}
|
|
@@ -1027,12 +1209,17 @@ var createVideoEncoder = ({
|
|
|
1027
1209
|
signal,
|
|
1028
1210
|
config,
|
|
1029
1211
|
logLevel,
|
|
1030
|
-
outputCodec
|
|
1212
|
+
outputCodec,
|
|
1213
|
+
progress
|
|
1031
1214
|
}) => {
|
|
1032
1215
|
if (signal.aborted) {
|
|
1033
1216
|
throw new Error("Not creating video encoder, already aborted");
|
|
1034
1217
|
}
|
|
1035
|
-
const ioSynchronizer = makeIoSynchronizer(
|
|
1218
|
+
const ioSynchronizer = makeIoSynchronizer({
|
|
1219
|
+
logLevel,
|
|
1220
|
+
label: "Video encoder",
|
|
1221
|
+
progress
|
|
1222
|
+
});
|
|
1036
1223
|
let outputQueue = Promise.resolve();
|
|
1037
1224
|
const encoder = new VideoEncoder({
|
|
1038
1225
|
error(error) {
|
|
@@ -1074,7 +1261,8 @@ var createVideoEncoder = ({
|
|
|
1074
1261
|
}
|
|
1075
1262
|
await ioSynchronizer.waitFor({
|
|
1076
1263
|
unemitted: 10,
|
|
1077
|
-
_unprocessed: 10
|
|
1264
|
+
_unprocessed: 10,
|
|
1265
|
+
minimumProgress: frame.timestamp - 5000000
|
|
1078
1266
|
});
|
|
1079
1267
|
if (encoder.state === "closed") {
|
|
1080
1268
|
return;
|
|
@@ -1114,7 +1302,9 @@ var makeVideoTrackHandler = ({
|
|
|
1114
1302
|
defaultVideoCodec,
|
|
1115
1303
|
onVideoTrack,
|
|
1116
1304
|
logLevel,
|
|
1117
|
-
container
|
|
1305
|
+
container,
|
|
1306
|
+
rotate,
|
|
1307
|
+
progress
|
|
1118
1308
|
}) => async (track) => {
|
|
1119
1309
|
if (controller.signal.aborted) {
|
|
1120
1310
|
throw new error_cause_default("Aborted");
|
|
@@ -1123,7 +1313,8 @@ var makeVideoTrackHandler = ({
|
|
|
1123
1313
|
track,
|
|
1124
1314
|
defaultVideoCodec,
|
|
1125
1315
|
logLevel,
|
|
1126
|
-
container
|
|
1316
|
+
container,
|
|
1317
|
+
rotate
|
|
1127
1318
|
});
|
|
1128
1319
|
if (videoOperation.type === "drop") {
|
|
1129
1320
|
return null;
|
|
@@ -1158,10 +1349,19 @@ var makeVideoTrackHandler = ({
|
|
|
1158
1349
|
});
|
|
1159
1350
|
};
|
|
1160
1351
|
}
|
|
1352
|
+
if (videoOperation.type !== "reencode") {
|
|
1353
|
+
throw new error_cause_default(`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"`);
|
|
1354
|
+
}
|
|
1355
|
+
const rotation = videoOperation.rotate ?? -track.rotation;
|
|
1356
|
+
const { height: newHeight, width: newWidth } = calculateNewDimensionsFromDimensions({
|
|
1357
|
+
width: track.codedWidth,
|
|
1358
|
+
height: track.codedHeight,
|
|
1359
|
+
rotation
|
|
1360
|
+
});
|
|
1161
1361
|
const videoEncoderConfig = await getVideoEncoderConfig({
|
|
1162
1362
|
codec: videoOperation.videoCodec,
|
|
1163
|
-
height:
|
|
1164
|
-
width:
|
|
1363
|
+
height: newHeight,
|
|
1364
|
+
width: newWidth,
|
|
1165
1365
|
fps: track.fps
|
|
1166
1366
|
});
|
|
1167
1367
|
const videoDecoderConfig = await getVideoDecoderConfigWithHardwareAcceleration(track);
|
|
@@ -1176,8 +1376,8 @@ var makeVideoTrackHandler = ({
|
|
|
1176
1376
|
const { trackNumber } = await state.addTrack({
|
|
1177
1377
|
type: "video",
|
|
1178
1378
|
color: track.color,
|
|
1179
|
-
width:
|
|
1180
|
-
height:
|
|
1379
|
+
width: newWidth,
|
|
1380
|
+
height: newHeight,
|
|
1181
1381
|
codec: videoOperation.videoCodec,
|
|
1182
1382
|
codecPrivate: null,
|
|
1183
1383
|
timescale: track.timescale
|
|
@@ -1207,7 +1407,8 @@ var makeVideoTrackHandler = ({
|
|
|
1207
1407
|
signal: controller.signal,
|
|
1208
1408
|
config: videoEncoderConfig,
|
|
1209
1409
|
logLevel,
|
|
1210
|
-
outputCodec: videoOperation.videoCodec
|
|
1410
|
+
outputCodec: videoOperation.videoCodec,
|
|
1411
|
+
progress
|
|
1211
1412
|
});
|
|
1212
1413
|
const videoDecoder = createVideoDecoder({
|
|
1213
1414
|
config: videoDecoderConfig,
|
|
@@ -1217,7 +1418,8 @@ var makeVideoTrackHandler = ({
|
|
|
1217
1418
|
track,
|
|
1218
1419
|
videoEncoder,
|
|
1219
1420
|
onVideoFrame,
|
|
1220
|
-
outputCodec: videoOperation.videoCodec
|
|
1421
|
+
outputCodec: videoOperation.videoCodec,
|
|
1422
|
+
rotation
|
|
1221
1423
|
});
|
|
1222
1424
|
},
|
|
1223
1425
|
onError: (err) => {
|
|
@@ -1226,7 +1428,8 @@ var makeVideoTrackHandler = ({
|
|
|
1226
1428
|
}));
|
|
1227
1429
|
},
|
|
1228
1430
|
signal: controller.signal,
|
|
1229
|
-
logLevel
|
|
1431
|
+
logLevel,
|
|
1432
|
+
progress
|
|
1230
1433
|
});
|
|
1231
1434
|
state.addWaitForFinishPromise(async () => {
|
|
1232
1435
|
Log.verbose(logLevel, "Waiting for video decoder to finish");
|
|
@@ -1243,16 +1446,16 @@ var makeVideoTrackHandler = ({
|
|
|
1243
1446
|
};
|
|
1244
1447
|
|
|
1245
1448
|
// src/select-container-creator.ts
|
|
1246
|
-
import { MediaParserInternals as
|
|
1449
|
+
import { MediaParserInternals as MediaParserInternals6 } from "@remotion/media-parser";
|
|
1247
1450
|
var selectContainerCreator = (container) => {
|
|
1248
1451
|
if (container === "mp4") {
|
|
1249
|
-
return
|
|
1452
|
+
return MediaParserInternals6.createIsoBaseMedia;
|
|
1250
1453
|
}
|
|
1251
1454
|
if (container === "wav") {
|
|
1252
|
-
return
|
|
1455
|
+
return MediaParserInternals6.createWav;
|
|
1253
1456
|
}
|
|
1254
1457
|
if (container === "webm") {
|
|
1255
|
-
return
|
|
1458
|
+
return MediaParserInternals6.createMatroskaMedia;
|
|
1256
1459
|
}
|
|
1257
1460
|
throw new Error(`Unsupported container: ${container}`);
|
|
1258
1461
|
};
|
|
@@ -1325,6 +1528,7 @@ var convertMedia = async function({
|
|
|
1325
1528
|
logLevel = "info",
|
|
1326
1529
|
writer,
|
|
1327
1530
|
progressIntervalInMs,
|
|
1531
|
+
rotate,
|
|
1328
1532
|
...more
|
|
1329
1533
|
}) {
|
|
1330
1534
|
if (userPassedAbortSignal?.aborted) {
|
|
@@ -1336,7 +1540,7 @@ var convertMedia = async function({
|
|
|
1336
1540
|
if (videoCodec && videoCodec !== "vp8" && videoCodec !== "vp9") {
|
|
1337
1541
|
return Promise.reject(new TypeError('Only `videoCodec: "vp8"` and `videoCodec: "vp9"` are supported currently'));
|
|
1338
1542
|
}
|
|
1339
|
-
const { resolve, reject, getPromiseToImmediatelyReturn } = withResolversAndWaitForReturn();
|
|
1543
|
+
const { resolve, reject, getPromiseToImmediatelyReturn } = MediaParserInternals7.withResolversAndWaitForReturn();
|
|
1340
1544
|
const controller = new AbortController;
|
|
1341
1545
|
const abortConversion = (errCause) => {
|
|
1342
1546
|
reject(errCause);
|
|
@@ -1354,6 +1558,7 @@ var convertMedia = async function({
|
|
|
1354
1558
|
everyMilliseconds: progressIntervalInMs ?? 100,
|
|
1355
1559
|
signal: controller.signal
|
|
1356
1560
|
});
|
|
1561
|
+
const progressTracker = MediaParserInternals7.makeProgressTracker();
|
|
1357
1562
|
const state = await creator({
|
|
1358
1563
|
filename: generateOutputFilename(src, container),
|
|
1359
1564
|
writer: await autoSelectWriter(writer, logLevel),
|
|
@@ -1380,7 +1585,8 @@ var convertMedia = async function({
|
|
|
1380
1585
|
return prevState;
|
|
1381
1586
|
});
|
|
1382
1587
|
},
|
|
1383
|
-
logLevel
|
|
1588
|
+
logLevel,
|
|
1589
|
+
progressTracker
|
|
1384
1590
|
});
|
|
1385
1591
|
const onVideoTrack = makeVideoTrackHandler({
|
|
1386
1592
|
state,
|
|
@@ -1391,7 +1597,9 @@ var convertMedia = async function({
|
|
|
1391
1597
|
defaultVideoCodec: videoCodec ?? null,
|
|
1392
1598
|
onVideoTrack: userVideoResolver ?? null,
|
|
1393
1599
|
logLevel,
|
|
1394
|
-
container
|
|
1600
|
+
container,
|
|
1601
|
+
rotate: rotate ?? 0,
|
|
1602
|
+
progress: progressTracker
|
|
1395
1603
|
});
|
|
1396
1604
|
const onAudioTrack = makeAudioTrackHandler({
|
|
1397
1605
|
abortConversion,
|
|
@@ -1401,7 +1609,8 @@ var convertMedia = async function({
|
|
|
1401
1609
|
state,
|
|
1402
1610
|
onAudioTrack: userAudioResolver ?? null,
|
|
1403
1611
|
logLevel,
|
|
1404
|
-
container
|
|
1612
|
+
container,
|
|
1613
|
+
progressTracker
|
|
1405
1614
|
});
|
|
1406
1615
|
parseMedia({
|
|
1407
1616
|
logLevel,
|
|
@@ -1488,6 +1697,10 @@ var getAvailableVideoCodecs = ({
|
|
|
1488
1697
|
throw new Error(`Unsupported container: ${container}`);
|
|
1489
1698
|
};
|
|
1490
1699
|
// src/index.ts
|
|
1700
|
+
var WebCodecsInternals = {
|
|
1701
|
+
rotateVideoFrame,
|
|
1702
|
+
normalizeVideoRotation
|
|
1703
|
+
};
|
|
1491
1704
|
setRemotionImported();
|
|
1492
1705
|
export {
|
|
1493
1706
|
getDefaultVideoCodec,
|
|
@@ -1505,5 +1718,6 @@ export {
|
|
|
1505
1718
|
canReencodeVideoTrack,
|
|
1506
1719
|
canReencodeAudioTrack,
|
|
1507
1720
|
canCopyVideoTrack,
|
|
1508
|
-
canCopyAudioTrack
|
|
1721
|
+
canCopyAudioTrack,
|
|
1722
|
+
WebCodecsInternals
|
|
1509
1723
|
};
|