@remotion/web-renderer 4.0.485 → 4.0.487
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/LICENSE.md +49 -0
- package/dist/compose.d.ts +2 -1
- package/dist/drawing/process-node.d.ts +2 -1
- package/dist/drawing/text/handle-text-node.d.ts +2 -1
- package/dist/drawing/text/text-decoration.d.ts +1 -1
- package/dist/esm/index.mjs +193 -35
- package/dist/index.d.ts +1 -0
- package/dist/page-responsiveness.d.ts +9 -0
- package/dist/render-media-on-web.d.ts +2 -0
- package/dist/take-screenshot.d.ts +2 -1
- package/dist/walk-over-node.d.ts +2 -1
- package/package.json +14 -14
package/LICENSE.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Remotion License
|
|
2
|
+
|
|
3
|
+
In Remotion 5.0, the license will slightly change. [View the changes here](https://github.com/remotion-dev/remotion/pull/3750).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Depending on the type of your legal entity, you are granted permission to use Remotion for your project. Individuals and small companies are allowed to use Remotion to create videos for free (even commercial), while a company license is required for for-profit organizations of a certain size. This two-tier system was designed to ensure funding for this project while still allowing the source code to be available and the program to be free for most. Read below for the exact terms of use.
|
|
8
|
+
|
|
9
|
+
- [Free License](#free-license)
|
|
10
|
+
- [Company License](#company-license)
|
|
11
|
+
|
|
12
|
+
## Free License
|
|
13
|
+
|
|
14
|
+
Copyright © 2026 [Remotion](https://www.remotion.dev)
|
|
15
|
+
|
|
16
|
+
### Eligibility
|
|
17
|
+
|
|
18
|
+
You are eligible to use Remotion for free if you are:
|
|
19
|
+
|
|
20
|
+
- an individual
|
|
21
|
+
- a for-profit organization with up to 3 employees
|
|
22
|
+
- a non-profit or not-for-profit organization
|
|
23
|
+
- evaluating whether Remotion is a good fit, and are not yet using it in a commercial way
|
|
24
|
+
|
|
25
|
+
### Allowed use cases
|
|
26
|
+
|
|
27
|
+
Permission is hereby granted, free of charge, to any person eligible for the "Free License", to use the software non-commercially or commercially for the purpose of creating videos and images and to modify the software to their own liking, for the purpose of fulfilling their custom use case or to contribute bug fixes or improvements back to Remotion.
|
|
28
|
+
|
|
29
|
+
### Disallowed use cases
|
|
30
|
+
|
|
31
|
+
It is not allowed to copy or modify Remotion code for the purpose of selling, renting, licensing, relicensing, or sublicensing your own derivate of Remotion.
|
|
32
|
+
|
|
33
|
+
### Warranty notice
|
|
34
|
+
|
|
35
|
+
The software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
|
|
36
|
+
|
|
37
|
+
### Support
|
|
38
|
+
|
|
39
|
+
Support is provided on a best-we-can-do basis via GitHub Issues and Discord.
|
|
40
|
+
|
|
41
|
+
## Company License
|
|
42
|
+
|
|
43
|
+
You are required to obtain a Company License to use Remotion if you are not within the group of entities eligible for a Free License. This license will enable you to use Remotion for the allowed use cases specified in the Free License, and give you access to prioritized support (read the [Support Policy](https://www.remotion.dev/docs/support)).
|
|
44
|
+
|
|
45
|
+
Visit [remotion.pro](https://www.remotion.pro/license) for pricing and to buy a license.
|
|
46
|
+
|
|
47
|
+
### FAQs
|
|
48
|
+
|
|
49
|
+
Are you not sure whether you need a Company License because of an edge case? Here are some [frequently asked questions](https://www.remotion.pro/faq).
|
package/dist/compose.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const compose: ({ element, context, logLevel, parentRect, internalState, onlyBackgroundClipText, scale, }: {
|
|
1
|
+
export declare const compose: ({ element, context, logLevel, parentRect, internalState, onlyBackgroundClipText, scale, waitForPageResponsiveness, }: {
|
|
2
2
|
element: HTMLElement | SVGElement;
|
|
3
3
|
context: OffscreenCanvasRenderingContext2D;
|
|
4
4
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
@@ -23,4 +23,5 @@ export declare const compose: ({ element, context, logLevel, parentRect, interna
|
|
|
23
23
|
};
|
|
24
24
|
onlyBackgroundClipText: boolean;
|
|
25
25
|
scale: number;
|
|
26
|
+
waitForPageResponsiveness: (() => Promise<void>) | null;
|
|
26
27
|
}) => Promise<void>;
|
|
@@ -5,7 +5,7 @@ export type ProcessNodeReturnValue = {
|
|
|
5
5
|
} | {
|
|
6
6
|
type: 'skip-children';
|
|
7
7
|
};
|
|
8
|
-
export declare const processNode: ({ element, context, draw, logLevel, parentRect, internalState, rootElement, scale, }: {
|
|
8
|
+
export declare const processNode: ({ element, context, draw, logLevel, parentRect, internalState, rootElement, scale, waitForPageResponsiveness, }: {
|
|
9
9
|
element: HTMLElement | SVGElement;
|
|
10
10
|
context: OffscreenCanvasRenderingContext2D;
|
|
11
11
|
draw: DrawFn;
|
|
@@ -31,4 +31,5 @@ export declare const processNode: ({ element, context, draw, logLevel, parentRec
|
|
|
31
31
|
};
|
|
32
32
|
rootElement: HTMLElement | SVGElement;
|
|
33
33
|
scale: number;
|
|
34
|
+
waitForPageResponsiveness: (() => Promise<void>) | null;
|
|
34
35
|
}) => Promise<ProcessNodeReturnValue>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ProcessNodeReturnValue } from '../process-node';
|
|
2
|
-
export declare const handleTextNode: ({ node, context, logLevel, parentRect, internalState, rootElement, onlyBackgroundClipText, scale, }: {
|
|
2
|
+
export declare const handleTextNode: ({ node, context, logLevel, parentRect, internalState, rootElement, onlyBackgroundClipText, scale, waitForPageResponsiveness, }: {
|
|
3
3
|
node: Text;
|
|
4
4
|
context: OffscreenCanvasRenderingContext2D;
|
|
5
5
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
@@ -25,4 +25,5 @@ export declare const handleTextNode: ({ node, context, logLevel, parentRect, int
|
|
|
25
25
|
rootElement: HTMLElement | SVGElement;
|
|
26
26
|
onlyBackgroundClipText: boolean;
|
|
27
27
|
scale: number;
|
|
28
|
+
waitForPageResponsiveness: (() => Promise<void>) | null;
|
|
28
29
|
}) => Promise<ProcessNodeReturnValue>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
type TextDecorationLine = 'underline' | 'overline' | 'line-through';
|
|
2
|
-
export type TextDecorationStyle = 'solid' | 'double' | 'dotted' | 'dashed';
|
|
2
|
+
export type TextDecorationStyle = 'solid' | 'double' | 'dotted' | 'dashed' | 'wavy';
|
|
3
3
|
export type TextDecoration = {
|
|
4
4
|
lines: TextDecorationLine[];
|
|
5
5
|
color: string;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1248,6 +1248,53 @@ var makeVideoSampleSourceCleanup = (encodingConfig) => {
|
|
|
1248
1248
|
};
|
|
1249
1249
|
};
|
|
1250
1250
|
|
|
1251
|
+
// src/page-responsiveness.ts
|
|
1252
|
+
var PRESET_INTERVALS = {
|
|
1253
|
+
low: 100,
|
|
1254
|
+
medium: 33,
|
|
1255
|
+
high: 16
|
|
1256
|
+
};
|
|
1257
|
+
var resolvePageResponsivenessInterval = (pageResponsiveness) => {
|
|
1258
|
+
if (pageResponsiveness === "disabled") {
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
if (pageResponsiveness === "low" || pageResponsiveness === "medium" || pageResponsiveness === "high") {
|
|
1262
|
+
return PRESET_INTERVALS[pageResponsiveness];
|
|
1263
|
+
}
|
|
1264
|
+
if (typeof pageResponsiveness === "number") {
|
|
1265
|
+
if (Number.isNaN(pageResponsiveness)) {
|
|
1266
|
+
throw new Error("`pageResponsiveness` should not be NaN, but is NaN");
|
|
1267
|
+
}
|
|
1268
|
+
if (!Number.isFinite(pageResponsiveness)) {
|
|
1269
|
+
throw new Error(`"pageResponsiveness" must be finite, but is ${pageResponsiveness}`);
|
|
1270
|
+
}
|
|
1271
|
+
if (pageResponsiveness <= 0) {
|
|
1272
|
+
throw new Error(`"pageResponsiveness" must be greater than 0, but is ${pageResponsiveness}`);
|
|
1273
|
+
}
|
|
1274
|
+
return pageResponsiveness;
|
|
1275
|
+
}
|
|
1276
|
+
throw new Error(`"pageResponsiveness" must be one of "disabled", "low", "medium", "high", or a number, but got ${JSON.stringify(pageResponsiveness)}`);
|
|
1277
|
+
};
|
|
1278
|
+
var createPageResponsivenessController = ({
|
|
1279
|
+
intervalInMilliseconds,
|
|
1280
|
+
now,
|
|
1281
|
+
wait
|
|
1282
|
+
}) => {
|
|
1283
|
+
let lastYieldAt = now();
|
|
1284
|
+
return {
|
|
1285
|
+
waitIfNeeded: async () => {
|
|
1286
|
+
if (intervalInMilliseconds === null) {
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
if (now() - lastYieldAt < intervalInMilliseconds) {
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
await wait();
|
|
1293
|
+
lastYieldAt = now();
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
};
|
|
1297
|
+
|
|
1251
1298
|
// src/render-operations-queue.ts
|
|
1252
1299
|
var onlyOneRenderAtATimeQueue = {
|
|
1253
1300
|
ref: Promise.resolve()
|
|
@@ -2045,6 +2092,38 @@ var filterRequiresPrecompositing = (filter) => {
|
|
|
2045
2092
|
}
|
|
2046
2093
|
return null;
|
|
2047
2094
|
};
|
|
2095
|
+
var isReplacedElement = (element) => {
|
|
2096
|
+
return element instanceof HTMLImageElement || element instanceof HTMLVideoElement || element instanceof HTMLCanvasElement || element instanceof HTMLIFrameElement || element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement || element instanceof HTMLObjectElement || element instanceof HTMLEmbedElement;
|
|
2097
|
+
};
|
|
2098
|
+
var canApplyCssTransforms = ({
|
|
2099
|
+
element,
|
|
2100
|
+
computedStyle
|
|
2101
|
+
}) => {
|
|
2102
|
+
if (element instanceof SVGElement) {
|
|
2103
|
+
return true;
|
|
2104
|
+
}
|
|
2105
|
+
if (computedStyle.display !== "inline") {
|
|
2106
|
+
return true;
|
|
2107
|
+
}
|
|
2108
|
+
return isReplacedElement(element);
|
|
2109
|
+
};
|
|
2110
|
+
var makeTransformResetter = (element) => {
|
|
2111
|
+
const { transform, scale, rotate } = element.style;
|
|
2112
|
+
return (hasApplicableTransformCssValue) => {
|
|
2113
|
+
if (hasApplicableTransformCssValue) {
|
|
2114
|
+
element.style.transform = "none";
|
|
2115
|
+
element.style.scale = "none";
|
|
2116
|
+
element.style.rotate = "none";
|
|
2117
|
+
}
|
|
2118
|
+
return () => {
|
|
2119
|
+
if (hasApplicableTransformCssValue) {
|
|
2120
|
+
element.style.transform = transform;
|
|
2121
|
+
element.style.scale = scale;
|
|
2122
|
+
element.style.rotate = rotate;
|
|
2123
|
+
}
|
|
2124
|
+
};
|
|
2125
|
+
};
|
|
2126
|
+
};
|
|
2048
2127
|
var getInternalTransformOrigin = (transform) => {
|
|
2049
2128
|
const centerX = transform.boundingClientRect.width / 2;
|
|
2050
2129
|
const centerY = transform.boundingClientRect.height / 2;
|
|
@@ -2099,21 +2178,21 @@ var calculateTransforms = ({
|
|
|
2099
2178
|
}
|
|
2100
2179
|
});
|
|
2101
2180
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2181
|
+
const hasApplicableTransformCssValue = canApplyCssTransforms({ computedStyle, element: parent }) && hasAnyTransformCssValue(computedStyle);
|
|
2182
|
+
if (hasApplicableTransformCssValue || parent === element) {
|
|
2183
|
+
const toParse = hasApplicableTransformCssValue && hasTransformCssValue(computedStyle) ? computedStyle.transform : undefined;
|
|
2104
2184
|
const matrix = new DOMMatrix(toParse);
|
|
2105
|
-
const
|
|
2185
|
+
const resetTransforms = makeTransformResetter(parent);
|
|
2186
|
+
const { scale, rotate } = parent.style;
|
|
2106
2187
|
const additionalMatrices = [];
|
|
2107
|
-
if (rotate !== "" && rotate !== "none") {
|
|
2188
|
+
if (hasApplicableTransformCssValue && rotate !== "" && rotate !== "none") {
|
|
2108
2189
|
additionalMatrices.push(new DOMMatrix(`rotate(${rotate})`));
|
|
2109
2190
|
}
|
|
2110
|
-
if (scale !== "" && scale !== "none") {
|
|
2191
|
+
if (hasApplicableTransformCssValue && scale !== "" && scale !== "none") {
|
|
2111
2192
|
additionalMatrices.push(new DOMMatrix(`scale(${scale})`));
|
|
2112
2193
|
}
|
|
2113
2194
|
additionalMatrices.push(matrix);
|
|
2114
|
-
|
|
2115
|
-
parent.style.scale = "none";
|
|
2116
|
-
parent.style.rotate = "none";
|
|
2195
|
+
const cleanup = resetTransforms(hasApplicableTransformCssValue);
|
|
2117
2196
|
transforms.push({
|
|
2118
2197
|
element: parent,
|
|
2119
2198
|
transformOrigin: computedStyle.transformOrigin,
|
|
@@ -2122,9 +2201,7 @@ var calculateTransforms = ({
|
|
|
2122
2201
|
});
|
|
2123
2202
|
const parentRef = parent;
|
|
2124
2203
|
toReset.push(() => {
|
|
2125
|
-
|
|
2126
|
-
parentRef.style.scale = scale;
|
|
2127
|
-
parentRef.style.rotate = rotate;
|
|
2204
|
+
cleanup();
|
|
2128
2205
|
parentRef.style.transition = originalTransition;
|
|
2129
2206
|
});
|
|
2130
2207
|
} else {
|
|
@@ -2727,7 +2804,8 @@ var drawBackground = async ({
|
|
|
2727
2804
|
logLevel,
|
|
2728
2805
|
internalState,
|
|
2729
2806
|
scale,
|
|
2730
|
-
onlyBackgroundClipText: true
|
|
2807
|
+
onlyBackgroundClipText: true,
|
|
2808
|
+
waitForPageResponsiveness: null
|
|
2731
2809
|
});
|
|
2732
2810
|
onlyBackgroundClipText.setTransform(new DOMMatrix().scale(scale, scale));
|
|
2733
2811
|
element.style.backgroundClip = originalBackgroundClip;
|
|
@@ -3921,7 +3999,8 @@ var processNode = async ({
|
|
|
3921
3999
|
parentRect,
|
|
3922
4000
|
internalState,
|
|
3923
4001
|
rootElement,
|
|
3924
|
-
scale
|
|
4002
|
+
scale,
|
|
4003
|
+
waitForPageResponsiveness
|
|
3925
4004
|
}) => {
|
|
3926
4005
|
let __stack = [];
|
|
3927
4006
|
try {
|
|
@@ -3985,8 +4064,12 @@ var processNode = async ({
|
|
|
3985
4064
|
logLevel,
|
|
3986
4065
|
internalState,
|
|
3987
4066
|
scale,
|
|
3988
|
-
onlyBackgroundClipText: false
|
|
4067
|
+
onlyBackgroundClipText: false,
|
|
4068
|
+
waitForPageResponsiveness
|
|
3989
4069
|
});
|
|
4070
|
+
if (waitForPageResponsiveness !== null) {
|
|
4071
|
+
await waitForPageResponsiveness();
|
|
4072
|
+
}
|
|
3990
4073
|
let drawable = tempContext.canvas;
|
|
3991
4074
|
const rectAfterTransforms = roundToExpandRect(scaleRect({
|
|
3992
4075
|
scale,
|
|
@@ -4003,6 +4086,9 @@ var processNode = async ({
|
|
|
4003
4086
|
tempContext,
|
|
4004
4087
|
scale
|
|
4005
4088
|
});
|
|
4089
|
+
if (waitForPageResponsiveness !== null) {
|
|
4090
|
+
await waitForPageResponsiveness();
|
|
4091
|
+
}
|
|
4006
4092
|
}
|
|
4007
4093
|
if (precompositing.needs3DTransformViaWebGL) {
|
|
4008
4094
|
const t = handle3dTransform({
|
|
@@ -4016,6 +4102,9 @@ var processNode = async ({
|
|
|
4016
4102
|
if (t) {
|
|
4017
4103
|
drawable = t;
|
|
4018
4104
|
}
|
|
4105
|
+
if (waitForPageResponsiveness !== null) {
|
|
4106
|
+
await waitForPageResponsiveness();
|
|
4107
|
+
}
|
|
4019
4108
|
}
|
|
4020
4109
|
const previousTransform = context.getTransform();
|
|
4021
4110
|
context.setTransform(new DOMMatrix);
|
|
@@ -4032,6 +4121,9 @@ var processNode = async ({
|
|
|
4032
4121
|
drawPrecomposedCanvas();
|
|
4033
4122
|
}
|
|
4034
4123
|
context.setTransform(previousTransform);
|
|
4124
|
+
if (waitForPageResponsiveness !== null) {
|
|
4125
|
+
await waitForPageResponsiveness();
|
|
4126
|
+
}
|
|
4035
4127
|
Internals6.Log.trace({
|
|
4036
4128
|
logLevel,
|
|
4037
4129
|
tag: "@remotion/web-renderer"
|
|
@@ -4134,10 +4226,7 @@ var getDefaultTextDecorationThickness = (fontSizePx) => {
|
|
|
4134
4226
|
return Math.max(1, Number.isFinite(fontSizePx) ? fontSizePx / 16 : 1);
|
|
4135
4227
|
};
|
|
4136
4228
|
var getTextDecorationStyle = (style) => {
|
|
4137
|
-
if (style === "wavy") {
|
|
4138
|
-
return null;
|
|
4139
|
-
}
|
|
4140
|
-
if (style === "double" || style === "dotted" || style === "dashed") {
|
|
4229
|
+
if (style === "double" || style === "dotted" || style === "dashed" || style === "wavy") {
|
|
4141
4230
|
return style;
|
|
4142
4231
|
}
|
|
4143
4232
|
return "solid";
|
|
@@ -4147,9 +4236,6 @@ var parseTextDecoration = ({
|
|
|
4147
4236
|
style
|
|
4148
4237
|
}) => {
|
|
4149
4238
|
const textDecorationStyle = getTextDecorationStyle(style.getPropertyValue("text-decoration-style").trim());
|
|
4150
|
-
if (textDecorationStyle === null) {
|
|
4151
|
-
return null;
|
|
4152
|
-
}
|
|
4153
4239
|
const textDecorationLine = style.getPropertyValue("text-decoration-line");
|
|
4154
4240
|
const lineParts = textDecorationLine.split(/\s+/);
|
|
4155
4241
|
const lines = textDecorationLines.filter((line) => lineParts.includes(line));
|
|
@@ -4223,6 +4309,34 @@ var getTextDecorationLineDashPattern = (style, thickness) => {
|
|
|
4223
4309
|
}
|
|
4224
4310
|
return [];
|
|
4225
4311
|
};
|
|
4312
|
+
var drawWavyTextDecorationLine = ({
|
|
4313
|
+
contextToDraw,
|
|
4314
|
+
endX,
|
|
4315
|
+
lineY,
|
|
4316
|
+
startX,
|
|
4317
|
+
thickness
|
|
4318
|
+
}) => {
|
|
4319
|
+
const step = Math.max(2, thickness);
|
|
4320
|
+
const amplitude = step;
|
|
4321
|
+
const halfWavelength = step * 2;
|
|
4322
|
+
const wavelength = halfWavelength * 2;
|
|
4323
|
+
const phaseStartX = Math.floor(startX / wavelength) * wavelength;
|
|
4324
|
+
contextToDraw.save();
|
|
4325
|
+
contextToDraw.beginPath();
|
|
4326
|
+
contextToDraw.rect(startX, lineY - amplitude - thickness, endX - startX, (amplitude + thickness) * 2);
|
|
4327
|
+
contextToDraw.clip();
|
|
4328
|
+
contextToDraw.beginPath();
|
|
4329
|
+
contextToDraw.moveTo(phaseStartX, lineY);
|
|
4330
|
+
let x = phaseStartX;
|
|
4331
|
+
let direction = 1;
|
|
4332
|
+
while (x < endX) {
|
|
4333
|
+
contextToDraw.quadraticCurveTo(x + halfWavelength / 2, lineY + direction * amplitude * 2, x + halfWavelength, lineY);
|
|
4334
|
+
x += halfWavelength;
|
|
4335
|
+
direction = -direction;
|
|
4336
|
+
}
|
|
4337
|
+
contextToDraw.stroke();
|
|
4338
|
+
contextToDraw.restore();
|
|
4339
|
+
};
|
|
4226
4340
|
var strokeTextDecorationLine = ({
|
|
4227
4341
|
contextToDraw,
|
|
4228
4342
|
endX,
|
|
@@ -4264,6 +4378,17 @@ var drawTextDecoration = ({
|
|
|
4264
4378
|
thickness: textDecoration.thickness,
|
|
4265
4379
|
fontSizePx
|
|
4266
4380
|
});
|
|
4381
|
+
if (textDecoration.style === "wavy") {
|
|
4382
|
+
contextToDraw.setLineDash([]);
|
|
4383
|
+
drawWavyTextDecorationLine({
|
|
4384
|
+
contextToDraw,
|
|
4385
|
+
endX,
|
|
4386
|
+
lineY,
|
|
4387
|
+
startX,
|
|
4388
|
+
thickness: textDecoration.thickness
|
|
4389
|
+
});
|
|
4390
|
+
continue;
|
|
4391
|
+
}
|
|
4267
4392
|
if (textDecoration.style === "double") {
|
|
4268
4393
|
contextToDraw.setLineDash([]);
|
|
4269
4394
|
strokeTextDecorationLine({
|
|
@@ -4426,7 +4551,8 @@ var handleTextNode = async ({
|
|
|
4426
4551
|
internalState,
|
|
4427
4552
|
rootElement,
|
|
4428
4553
|
onlyBackgroundClipText,
|
|
4429
|
-
scale
|
|
4554
|
+
scale,
|
|
4555
|
+
waitForPageResponsiveness
|
|
4430
4556
|
}) => {
|
|
4431
4557
|
const span = document.createElement("span");
|
|
4432
4558
|
const parent = node.parentNode;
|
|
@@ -4443,7 +4569,8 @@ var handleTextNode = async ({
|
|
|
4443
4569
|
parentRect,
|
|
4444
4570
|
internalState,
|
|
4445
4571
|
rootElement,
|
|
4446
|
-
scale
|
|
4572
|
+
scale,
|
|
4573
|
+
waitForPageResponsiveness
|
|
4447
4574
|
});
|
|
4448
4575
|
parent.insertBefore(node, span);
|
|
4449
4576
|
parent.removeChild(span);
|
|
@@ -4459,7 +4586,8 @@ var walkOverNode = ({
|
|
|
4459
4586
|
internalState,
|
|
4460
4587
|
rootElement,
|
|
4461
4588
|
onlyBackgroundClipText,
|
|
4462
|
-
scale
|
|
4589
|
+
scale,
|
|
4590
|
+
waitForPageResponsiveness
|
|
4463
4591
|
}) => {
|
|
4464
4592
|
if (node instanceof HTMLElement || node instanceof SVGElement) {
|
|
4465
4593
|
return processNode({
|
|
@@ -4470,7 +4598,8 @@ var walkOverNode = ({
|
|
|
4470
4598
|
parentRect,
|
|
4471
4599
|
internalState,
|
|
4472
4600
|
rootElement,
|
|
4473
|
-
scale
|
|
4601
|
+
scale,
|
|
4602
|
+
waitForPageResponsiveness
|
|
4474
4603
|
});
|
|
4475
4604
|
}
|
|
4476
4605
|
if (node instanceof Text) {
|
|
@@ -4482,7 +4611,8 @@ var walkOverNode = ({
|
|
|
4482
4611
|
internalState,
|
|
4483
4612
|
rootElement,
|
|
4484
4613
|
onlyBackgroundClipText,
|
|
4485
|
-
scale
|
|
4614
|
+
scale,
|
|
4615
|
+
waitForPageResponsiveness
|
|
4486
4616
|
});
|
|
4487
4617
|
}
|
|
4488
4618
|
throw new Error("Unknown node type");
|
|
@@ -4509,7 +4639,8 @@ var compose = async ({
|
|
|
4509
4639
|
parentRect,
|
|
4510
4640
|
internalState,
|
|
4511
4641
|
onlyBackgroundClipText,
|
|
4512
|
-
scale
|
|
4642
|
+
scale,
|
|
4643
|
+
waitForPageResponsiveness
|
|
4513
4644
|
}) => {
|
|
4514
4645
|
let __stack = [];
|
|
4515
4646
|
try {
|
|
@@ -4532,7 +4663,8 @@ var compose = async ({
|
|
|
4532
4663
|
internalState,
|
|
4533
4664
|
rootElement: element,
|
|
4534
4665
|
onlyBackgroundClipText,
|
|
4535
|
-
scale
|
|
4666
|
+
scale,
|
|
4667
|
+
waitForPageResponsiveness
|
|
4536
4668
|
});
|
|
4537
4669
|
if (val.type === "skip-children") {
|
|
4538
4670
|
if (!skipToNextNonDescendant(treeWalker)) {
|
|
@@ -4546,6 +4678,9 @@ var compose = async ({
|
|
|
4546
4678
|
break;
|
|
4547
4679
|
}
|
|
4548
4680
|
}
|
|
4681
|
+
if (waitForPageResponsiveness !== null) {
|
|
4682
|
+
await waitForPageResponsiveness();
|
|
4683
|
+
}
|
|
4549
4684
|
}
|
|
4550
4685
|
} catch (_catch) {
|
|
4551
4686
|
var _err = _catch, _hasErr = 1;
|
|
@@ -4563,7 +4698,8 @@ var createLayer = async ({
|
|
|
4563
4698
|
onlyBackgroundClipText,
|
|
4564
4699
|
cutout,
|
|
4565
4700
|
htmlInCanvasContext,
|
|
4566
|
-
onHtmlInCanvasLayerOutcome
|
|
4701
|
+
onHtmlInCanvasLayerOutcome,
|
|
4702
|
+
waitForPageResponsiveness
|
|
4567
4703
|
}) => {
|
|
4568
4704
|
const scaledWidth = Math.ceil(cutout.width * scale);
|
|
4569
4705
|
const scaledHeight = Math.ceil(cutout.height * scale);
|
|
@@ -4599,7 +4735,8 @@ var createLayer = async ({
|
|
|
4599
4735
|
parentRect: cutout,
|
|
4600
4736
|
internalState,
|
|
4601
4737
|
onlyBackgroundClipText,
|
|
4602
|
-
scale
|
|
4738
|
+
scale,
|
|
4739
|
+
waitForPageResponsiveness
|
|
4603
4740
|
});
|
|
4604
4741
|
return context;
|
|
4605
4742
|
};
|
|
@@ -4827,6 +4964,7 @@ var internalRenderMediaOnWeb = async ({
|
|
|
4827
4964
|
transparent,
|
|
4828
4965
|
onArtifact,
|
|
4829
4966
|
onFrame,
|
|
4967
|
+
pageResponsiveness,
|
|
4830
4968
|
outputTarget: userDesiredOutputTarget,
|
|
4831
4969
|
licenseKey,
|
|
4832
4970
|
muted,
|
|
@@ -4838,6 +4976,7 @@ var internalRenderMediaOnWeb = async ({
|
|
|
4838
4976
|
let __stack2 = [];
|
|
4839
4977
|
try {
|
|
4840
4978
|
validateScale(scale);
|
|
4979
|
+
const pageResponsivenessIntervalInMilliseconds = resolvePageResponsivenessInterval(pageResponsiveness);
|
|
4841
4980
|
let htmlInCanvasLayerOutcomeReported = false;
|
|
4842
4981
|
const onHtmlInCanvasLayerOutcome = (outcome) => {
|
|
4843
4982
|
if (htmlInCanvasLayerOutcomeReported) {
|
|
@@ -4949,6 +5088,19 @@ var internalRenderMediaOnWeb = async ({
|
|
|
4949
5088
|
});
|
|
4950
5089
|
}
|
|
4951
5090
|
const internalState = __using(__stack2, makeInternalState(), 0);
|
|
5091
|
+
const pageResponsivenessController = createPageResponsivenessController({
|
|
5092
|
+
intervalInMilliseconds: pageResponsivenessIntervalInMilliseconds,
|
|
5093
|
+
now: () => performance.now(),
|
|
5094
|
+
wait: () => new Promise((resolve) => {
|
|
5095
|
+
setTimeout(resolve, 0);
|
|
5096
|
+
})
|
|
5097
|
+
});
|
|
5098
|
+
const waitForPageResponsiveness = async () => {
|
|
5099
|
+
await pageResponsivenessController.waitIfNeeded();
|
|
5100
|
+
if (signal?.aborted) {
|
|
5101
|
+
throw new Error("renderMediaOnWeb() was cancelled");
|
|
5102
|
+
}
|
|
5103
|
+
};
|
|
4952
5104
|
const keepalive = __using(__stack2, createBackgroundKeepalive({
|
|
4953
5105
|
fps: resolved.fps,
|
|
4954
5106
|
logLevel
|
|
@@ -5062,13 +5214,15 @@ var internalRenderMediaOnWeb = async ({
|
|
|
5062
5214
|
onlyBackgroundClipText: false,
|
|
5063
5215
|
cutout: new DOMRect(0, 0, resolved.width, resolved.height),
|
|
5064
5216
|
htmlInCanvasContext,
|
|
5065
|
-
onHtmlInCanvasLayerOutcome: htmlInCanvasContext ? onHtmlInCanvasLayerOutcome : undefined
|
|
5217
|
+
onHtmlInCanvasLayerOutcome: htmlInCanvasContext ? onHtmlInCanvasLayerOutcome : undefined,
|
|
5218
|
+
waitForPageResponsiveness
|
|
5066
5219
|
});
|
|
5067
5220
|
internalState.addCreateFrameTime(performance.now() - createFrameStart);
|
|
5068
5221
|
layerCanvas = layer.canvas;
|
|
5069
5222
|
if (signal?.aborted) {
|
|
5070
5223
|
throw new Error("renderMediaOnWeb() was cancelled");
|
|
5071
5224
|
}
|
|
5225
|
+
await waitForPageResponsiveness();
|
|
5072
5226
|
const videoFrame = new VideoFrame(layer.canvas, {
|
|
5073
5227
|
timestamp
|
|
5074
5228
|
});
|
|
@@ -5085,6 +5239,7 @@ var internalRenderMediaOnWeb = async ({
|
|
|
5085
5239
|
expectedHeight: Math.round(resolved.height * scale),
|
|
5086
5240
|
expectedTimestamp: timestamp
|
|
5087
5241
|
});
|
|
5242
|
+
await waitForPageResponsiveness();
|
|
5088
5243
|
}
|
|
5089
5244
|
}
|
|
5090
5245
|
const now = Date.now();
|
|
@@ -5110,11 +5265,10 @@ var internalRenderMediaOnWeb = async ({
|
|
|
5110
5265
|
onArtifact
|
|
5111
5266
|
});
|
|
5112
5267
|
}
|
|
5113
|
-
|
|
5114
|
-
throw new Error("renderMediaOnWeb() was cancelled");
|
|
5115
|
-
}
|
|
5268
|
+
await waitForPageResponsiveness();
|
|
5116
5269
|
const audio = muted ? null : onlyInlineAudio({ assets, fps: resolved.fps, timestamp, sampleRate });
|
|
5117
5270
|
internalState.addAudioMixingTime(performance.now() - audioCombineStart);
|
|
5271
|
+
await waitForPageResponsiveness();
|
|
5118
5272
|
const addSampleStart = performance.now();
|
|
5119
5273
|
const encodingPromises = [];
|
|
5120
5274
|
if (frameToEncode && videoSampleSource) {
|
|
@@ -5133,8 +5287,10 @@ var internalRenderMediaOnWeb = async ({
|
|
|
5133
5287
|
if (signal?.aborted) {
|
|
5134
5288
|
throw new Error("renderMediaOnWeb() was cancelled");
|
|
5135
5289
|
}
|
|
5290
|
+
await waitForPageResponsiveness();
|
|
5136
5291
|
}
|
|
5137
5292
|
onProgress?.(getProgressPayload());
|
|
5293
|
+
await waitForPageResponsiveness();
|
|
5138
5294
|
videoSampleSource?.videoSampleSource.close();
|
|
5139
5295
|
audioSampleSource?.audioSampleSource.close();
|
|
5140
5296
|
await outputWithCleanup.output.finalize();
|
|
@@ -5222,6 +5378,7 @@ var renderMediaOnWeb = (options) => {
|
|
|
5222
5378
|
transparent: options.transparent ?? false,
|
|
5223
5379
|
onArtifact: options.onArtifact ?? null,
|
|
5224
5380
|
onFrame: options.onFrame ?? null,
|
|
5381
|
+
pageResponsiveness: options.pageResponsiveness ?? "medium",
|
|
5225
5382
|
outputTarget: options.outputTarget ?? null,
|
|
5226
5383
|
licenseKey: options.licenseKey ?? null,
|
|
5227
5384
|
muted: options.muted ?? false,
|
|
@@ -5387,7 +5544,8 @@ async function internalRenderStillOnWeb({
|
|
|
5387
5544
|
onlyBackgroundClipText: false,
|
|
5388
5545
|
cutout: new DOMRect(0, 0, resolved.width, resolved.height),
|
|
5389
5546
|
htmlInCanvasContext,
|
|
5390
|
-
onHtmlInCanvasLayerOutcome: htmlInCanvasContext ? onHtmlInCanvasLayerOutcome : undefined
|
|
5547
|
+
onHtmlInCanvasLayerOutcome: htmlInCanvasContext ? onHtmlInCanvasLayerOutcome : undefined,
|
|
5548
|
+
waitForPageResponsiveness: null
|
|
5391
5549
|
});
|
|
5392
5550
|
const { canvas } = capturedFrame;
|
|
5393
5551
|
const assets = collectAssets.current.collectAssets();
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { getEncodableAudioCodecs, getEncodableVideoCodecs, type GetEncodableAudi
|
|
|
7
7
|
export { getDefaultAudioCodecForContainer, getDefaultContainerForCodec, getDefaultVideoCodecForContainer, getSupportedAudioCodecsForContainer, getSupportedVideoCodecsForContainer, isAudioOnlyContainer, } from './mediabunny-mappings';
|
|
8
8
|
export type { WebRendererAudioCodec, WebRendererContainer, WebRendererQuality, WebRendererVideoCodec, } from './mediabunny-mappings';
|
|
9
9
|
export type { WebRendererOutputTarget } from './output-target';
|
|
10
|
+
export type { WebRendererPageResponsiveness } from './page-responsiveness';
|
|
10
11
|
export { renderMediaOnWeb } from './render-media-on-web';
|
|
11
12
|
export type { RenderMediaOnWebOptions, RenderMediaOnWebProgress, RenderMediaOnWebProgressCallback, RenderMediaOnWebResult, WebRendererHardwareAcceleration, } from './render-media-on-web';
|
|
12
13
|
export { renderStillOnWeb } from './render-still-on-web';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type WebRendererPageResponsiveness = 'disabled' | 'low' | 'medium' | 'high' | number;
|
|
2
|
+
export declare const resolvePageResponsivenessInterval: (pageResponsiveness: unknown) => number | null;
|
|
3
|
+
export declare const createPageResponsivenessController: ({ intervalInMilliseconds, now, wait, }: {
|
|
4
|
+
intervalInMilliseconds: number | null;
|
|
5
|
+
now: () => number;
|
|
6
|
+
wait: () => Promise<void>;
|
|
7
|
+
}) => {
|
|
8
|
+
waitIfNeeded: () => Promise<void>;
|
|
9
|
+
};
|
|
@@ -7,6 +7,7 @@ import type { InternalState } from './internal-state';
|
|
|
7
7
|
import type { WebRendererAudioCodec, WebRendererContainer, WebRendererQuality } from './mediabunny-mappings';
|
|
8
8
|
import { type WebRendererVideoCodec } from './mediabunny-mappings';
|
|
9
9
|
import type { WebRendererOutputTarget } from './output-target';
|
|
10
|
+
import { type WebRendererPageResponsiveness } from './page-responsiveness';
|
|
10
11
|
import type { CompositionCalculateMetadataOrExplicit } from './props-if-has-props';
|
|
11
12
|
import { type OnFrameCallback } from './validate-video-frame';
|
|
12
13
|
export type InputPropsIfHasProps<Schema extends $ZodObject, Props> = $ZodObject extends Schema ? {} extends Props ? {
|
|
@@ -60,6 +61,7 @@ type OptionalRenderMediaOnWebOptions<Schema extends $ZodObject> = {
|
|
|
60
61
|
transparent: boolean;
|
|
61
62
|
onArtifact: WebRendererOnArtifact | null;
|
|
62
63
|
onFrame: OnFrameCallback | null;
|
|
64
|
+
pageResponsiveness: WebRendererPageResponsiveness;
|
|
63
65
|
outputTarget: WebRendererOutputTarget | null;
|
|
64
66
|
licenseKey: string | null;
|
|
65
67
|
isProduction: boolean;
|
|
@@ -6,7 +6,7 @@ export type HtmlInCanvasLayerOutcome = {
|
|
|
6
6
|
reason: string;
|
|
7
7
|
shouldWarn: boolean;
|
|
8
8
|
};
|
|
9
|
-
export declare const createLayer: ({ element, scale, logLevel, internalState, onlyBackgroundClipText, cutout, htmlInCanvasContext, onHtmlInCanvasLayerOutcome, }: {
|
|
9
|
+
export declare const createLayer: ({ element, scale, logLevel, internalState, onlyBackgroundClipText, cutout, htmlInCanvasContext, onHtmlInCanvasLayerOutcome, waitForPageResponsiveness, }: {
|
|
10
10
|
element: HTMLElement | SVGElement;
|
|
11
11
|
scale: number;
|
|
12
12
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
@@ -32,4 +32,5 @@ export declare const createLayer: ({ element, scale, logLevel, internalState, on
|
|
|
32
32
|
cutout: DOMRect;
|
|
33
33
|
htmlInCanvasContext?: HtmlInCanvasContext | null | undefined;
|
|
34
34
|
onHtmlInCanvasLayerOutcome?: ((outcome: HtmlInCanvasLayerOutcome) => void) | undefined;
|
|
35
|
+
waitForPageResponsiveness: (() => Promise<void>) | null;
|
|
35
36
|
}) => Promise<OffscreenCanvasRenderingContext2D>;
|
package/dist/walk-over-node.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ProcessNodeReturnValue } from './drawing/process-node';
|
|
2
|
-
export declare const walkOverNode: ({ node, context, logLevel, parentRect, internalState, rootElement, onlyBackgroundClipText, scale, }: {
|
|
2
|
+
export declare const walkOverNode: ({ node, context, logLevel, parentRect, internalState, rootElement, onlyBackgroundClipText, scale, waitForPageResponsiveness, }: {
|
|
3
3
|
node: Node;
|
|
4
4
|
context: OffscreenCanvasRenderingContext2D;
|
|
5
5
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
@@ -25,4 +25,5 @@ export declare const walkOverNode: ({ node, context, logLevel, parentRect, inter
|
|
|
25
25
|
rootElement: HTMLElement | SVGElement;
|
|
26
26
|
onlyBackgroundClipText: boolean;
|
|
27
27
|
scale: number;
|
|
28
|
+
waitForPageResponsiveness: (() => Promise<void>) | null;
|
|
28
29
|
}) => Promise<ProcessNodeReturnValue>;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/web-renderer"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/web-renderer",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.487",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"scripts": {
|
|
@@ -19,22 +19,22 @@
|
|
|
19
19
|
"author": "Remotion <jonny@remotion.dev>",
|
|
20
20
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@mediabunny/mp3-encoder": "1.50.
|
|
23
|
-
"@mediabunny/aac-encoder": "1.50.
|
|
24
|
-
"@mediabunny/flac-encoder": "1.50.
|
|
25
|
-
"@remotion/licensing": "4.0.
|
|
26
|
-
"remotion": "4.0.
|
|
27
|
-
"mediabunny": "1.50.
|
|
22
|
+
"@mediabunny/mp3-encoder": "1.50.7",
|
|
23
|
+
"@mediabunny/aac-encoder": "1.50.7",
|
|
24
|
+
"@mediabunny/flac-encoder": "1.50.7",
|
|
25
|
+
"@remotion/licensing": "4.0.487",
|
|
26
|
+
"remotion": "4.0.487",
|
|
27
|
+
"mediabunny": "1.50.7"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@react-three/fiber": "9.2.0",
|
|
31
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
32
|
-
"@remotion/paths": "4.0.
|
|
33
|
-
"@remotion/player": "4.0.
|
|
34
|
-
"@remotion/media": "4.0.
|
|
35
|
-
"@remotion/shapes": "4.0.
|
|
36
|
-
"@remotion/three": "4.0.
|
|
37
|
-
"@remotion/transitions": "4.0.
|
|
31
|
+
"@remotion/eslint-config-internal": "4.0.487",
|
|
32
|
+
"@remotion/paths": "4.0.487",
|
|
33
|
+
"@remotion/player": "4.0.487",
|
|
34
|
+
"@remotion/media": "4.0.487",
|
|
35
|
+
"@remotion/shapes": "4.0.487",
|
|
36
|
+
"@remotion/three": "4.0.487",
|
|
37
|
+
"@remotion/transitions": "4.0.487",
|
|
38
38
|
"@types/three": "0.170.0",
|
|
39
39
|
"@typescript/native-preview": "7.0.0-dev.20260217.1",
|
|
40
40
|
"@vitejs/plugin-react": "4.3.4",
|