@remotion/web-renderer 4.0.403 → 4.0.404
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/background-keepalive.d.ts +9 -0
- package/dist/drawing/elements-and-bounds.d.ts +9 -0
- package/dist/drawing/get-pretransform-rect.d.ts +1 -1
- package/dist/drawing/handle-3d-transform.d.ts +3 -3
- package/dist/drawing/precompose-and-draw.d.ts +33 -0
- package/dist/drawing/precompose-element.d.ts +0 -0
- package/dist/drawing/renoun.d.ts +125 -0
- package/dist/drawing/transform-in-3d.d.ts +4 -7
- package/dist/drawing/transform-origin.d.ts +21 -0
- package/dist/drawing/transform-perspective-origin.d.ts +17 -0
- package/dist/esm/index.mjs +310 -174
- package/dist/internal-state.d.ts +2 -1
- package/dist/wait-for-ready.d.ts +3 -1
- package/package.json +6 -6
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type LogLevel } from 'remotion';
|
|
2
|
+
export type BackgroundKeepalive = {
|
|
3
|
+
waitForTick: () => Promise<void>;
|
|
4
|
+
[Symbol.dispose]: () => void;
|
|
5
|
+
};
|
|
6
|
+
export declare function createBackgroundKeepalive({ fps, logLevel }: {
|
|
7
|
+
fps: number;
|
|
8
|
+
logLevel: LogLevel;
|
|
9
|
+
}): BackgroundKeepalive;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Precompositing } from './calculate-transforms';
|
|
2
|
+
export type ElementAndBounds = {
|
|
3
|
+
element: Element;
|
|
4
|
+
bounds: DOMRect;
|
|
5
|
+
transform: DOMMatrix;
|
|
6
|
+
parentRect: DOMRect;
|
|
7
|
+
precompositing: Precompositing;
|
|
8
|
+
establishes3DRenderingContext: DOMMatrix | null;
|
|
9
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function getPreTransformRect(targetRect: DOMRect, matrix: DOMMatrix): DOMRect;
|
|
1
|
+
export declare function getPreTransformRect(targetRect: DOMRect, matrix: DOMMatrix): DOMRect | null;
|
|
@@ -2,10 +2,10 @@ export declare const getPrecomposeRectFor3DTransform: ({ element, parentRect, ma
|
|
|
2
2
|
element: HTMLElement | SVGElement;
|
|
3
3
|
parentRect: DOMRect;
|
|
4
4
|
matrix: DOMMatrix;
|
|
5
|
-
}) => DOMRect;
|
|
6
|
-
export declare const handle3dTransform: ({ matrix,
|
|
5
|
+
}) => DOMRect | null;
|
|
6
|
+
export declare const handle3dTransform: ({ matrix, sourceRect, tempCanvas, rectAfterTransforms, internalState, }: {
|
|
7
7
|
matrix: DOMMatrix;
|
|
8
|
-
|
|
8
|
+
sourceRect: DOMRect;
|
|
9
9
|
tempCanvas: OffscreenCanvas;
|
|
10
10
|
rectAfterTransforms: DOMRect;
|
|
11
11
|
internalState: {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Precompositing } from './calculate-transforms';
|
|
2
|
+
import type { ElementAndBounds } from './elements-and-bounds';
|
|
3
|
+
export declare const precompose: ({ element, logLevel, parentRect, internalState, precompositing, totalMatrix, rect, isIn3dRenderingContext, }: {
|
|
4
|
+
element: HTMLElement | SVGElement;
|
|
5
|
+
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
6
|
+
parentRect: DOMRect;
|
|
7
|
+
internalState: {
|
|
8
|
+
getDrawn3dPixels: () => number;
|
|
9
|
+
getPrecomposedTiles: () => number;
|
|
10
|
+
addPrecompose: ({ canvasWidth, canvasHeight, }: {
|
|
11
|
+
canvasWidth: number;
|
|
12
|
+
canvasHeight: number;
|
|
13
|
+
}) => void;
|
|
14
|
+
helperCanvasState: import("../internal-state").HelperCanvasState;
|
|
15
|
+
[Symbol.dispose]: () => void;
|
|
16
|
+
getWaitForReadyTime: () => number;
|
|
17
|
+
addWaitForReadyTime: (time: number) => void;
|
|
18
|
+
getAddSampleTime: () => number;
|
|
19
|
+
addAddSampleTime: (time: number) => void;
|
|
20
|
+
getCreateFrameTime: () => number;
|
|
21
|
+
addCreateFrameTime: (time: number) => void;
|
|
22
|
+
getAudioMixingTime: () => number;
|
|
23
|
+
addAudioMixingTime: (time: number) => void;
|
|
24
|
+
};
|
|
25
|
+
precompositing: Precompositing;
|
|
26
|
+
totalMatrix: DOMMatrix;
|
|
27
|
+
rect: DOMRect;
|
|
28
|
+
isIn3dRenderingContext: DOMMatrix | null;
|
|
29
|
+
}) => Promise<{
|
|
30
|
+
drawable: OffscreenCanvas;
|
|
31
|
+
rectAfterTransforms: DOMRect;
|
|
32
|
+
elementsToBeRenderedIndependently: ElementAndBounds[];
|
|
33
|
+
} | null>;
|
|
File without changes
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/** Image format for encoded screenshot output. */
|
|
2
|
+
export type ImageFormat = 'png' | 'jpeg' | 'webp';
|
|
3
|
+
/** Options for rendering a screenshot to canvas. */
|
|
4
|
+
export interface RenderOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Canvas background color. Set to `null` (or omit) for a transparent canvas.
|
|
7
|
+
* When provided, the string is passed directly to `fillStyle`.
|
|
8
|
+
*/
|
|
9
|
+
backgroundColor?: string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Optional existing canvas to render into.
|
|
12
|
+
* When omitted, a new canvas element is created.
|
|
13
|
+
*/
|
|
14
|
+
canvas?: HTMLCanvasElement;
|
|
15
|
+
/**
|
|
16
|
+
* Rendering scale factor. Defaults to `window.devicePixelRatio` (or `1`).
|
|
17
|
+
*/
|
|
18
|
+
scale?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Crop origin X (CSS pixels) relative to the element's left edge.
|
|
21
|
+
* Defaults to the element's left edge.
|
|
22
|
+
*/
|
|
23
|
+
x?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Crop origin Y (CSS pixels) relative to the element's top edge.
|
|
26
|
+
* Defaults to the element's top edge.
|
|
27
|
+
*/
|
|
28
|
+
y?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Output width in CSS pixels. Defaults to the element's width.
|
|
31
|
+
*/
|
|
32
|
+
width?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Output height in CSS pixels. Defaults to the element's height.
|
|
35
|
+
*/
|
|
36
|
+
height?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Controls how `position: fixed` elements outside the captured subtree are
|
|
39
|
+
* handled.
|
|
40
|
+
*
|
|
41
|
+
* - `none` – ignore all fixed elements outside `element`.
|
|
42
|
+
* - `intersecting` – include fixed elements whose bounding rect intersects the capture rect.
|
|
43
|
+
* - `all` – include all fixed elements that overlap the viewport.
|
|
44
|
+
*/
|
|
45
|
+
includeFixed?: 'none' | 'intersecting' | 'all';
|
|
46
|
+
/**
|
|
47
|
+
* CSS selector used to skip elements from rendering.
|
|
48
|
+
* Defaults to `[data-screenshot-ignore]`. Set to `null` or an empty string
|
|
49
|
+
* to disable selector-based skipping.
|
|
50
|
+
*/
|
|
51
|
+
ignoreSelector?: string | null;
|
|
52
|
+
}
|
|
53
|
+
/** Options for encoding a canvas to an image format. */
|
|
54
|
+
export interface EncodeOptions {
|
|
55
|
+
/**
|
|
56
|
+
* Image format to encode. Defaults to `'png'`.
|
|
57
|
+
*/
|
|
58
|
+
format?: ImageFormat;
|
|
59
|
+
/**
|
|
60
|
+
* Image quality for lossy formats (`jpeg`, `webp`). A number between `0` and `1`.
|
|
61
|
+
* Ignored for `png`. Defaults to `0.92`.
|
|
62
|
+
*/
|
|
63
|
+
quality?: number;
|
|
64
|
+
}
|
|
65
|
+
/** Combined options for one-shot screenshot methods that render and encode. */
|
|
66
|
+
export type ScreenshotOptions = RenderOptions & EncodeOptions;
|
|
67
|
+
/**
|
|
68
|
+
* A promise-like object representing a screenshot capture. The underlying
|
|
69
|
+
* render happens once; subsequent calls to `.canvas()`, `.blob()`, or `.url()`
|
|
70
|
+
* reuse the same rendered canvas.
|
|
71
|
+
*/
|
|
72
|
+
export interface ScreenshotTask extends Promise<HTMLCanvasElement> {
|
|
73
|
+
/** Returns the rendered canvas. */
|
|
74
|
+
canvas(): Promise<HTMLCanvasElement>;
|
|
75
|
+
/** Encodes the rendered canvas to a Blob. */
|
|
76
|
+
blob(options?: EncodeOptions): Promise<Blob>;
|
|
77
|
+
/**
|
|
78
|
+
* Encodes the rendered canvas to a Blob and creates an object URL.
|
|
79
|
+
* Remember to call `URL.revokeObjectURL(url)` when done to avoid memory leaks.
|
|
80
|
+
*/
|
|
81
|
+
url(options?: EncodeOptions): Promise<string>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Renders a DOM element into a canvas using modern browser features.
|
|
85
|
+
*
|
|
86
|
+
* Returns a `ScreenshotTask` that is both a Promise and provides methods
|
|
87
|
+
* to encode the rendered canvas. The underlying render happens once;
|
|
88
|
+
* subsequent calls to `.canvas()`, `.blob()`, or `.url()` reuse the same result.
|
|
89
|
+
*
|
|
90
|
+
* This implementation targets evergreen browsers only and assumes a real DOM +
|
|
91
|
+
* Canvas2D environment (not Node.js).
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* // Capture handle pattern - render once, encode multiple ways
|
|
95
|
+
* const shot = screenshot(element, { scale: 2 })
|
|
96
|
+
* const canvas = await shot.canvas()
|
|
97
|
+
* const pngBlob = await shot.blob({ format: 'png' })
|
|
98
|
+
* const webpUrl = await shot.url({ format: 'webp', quality: 0.9 })
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* // Direct await returns the canvas
|
|
102
|
+
* const canvas = await screenshot(element)
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* // One-shot convenience methods
|
|
106
|
+
* const canvas = await screenshot.canvas(element, { scale: 2 })
|
|
107
|
+
* const blob = await screenshot.blob(element, { format: 'jpeg', quality: 0.85 })
|
|
108
|
+
* const url = await screenshot.url(element, { format: 'png' })
|
|
109
|
+
*/
|
|
110
|
+
declare function screenshot(target: Element | string, options?: RenderOptions): ScreenshotTask;
|
|
111
|
+
declare namespace screenshot {
|
|
112
|
+
var canvas: (target: string | Element, options?: RenderOptions | undefined) => Promise<HTMLCanvasElement>;
|
|
113
|
+
}
|
|
114
|
+
declare namespace screenshot {
|
|
115
|
+
var blob: (target: string | Element, options?: ScreenshotOptions | undefined) => Promise<Blob>;
|
|
116
|
+
}
|
|
117
|
+
declare namespace screenshot {
|
|
118
|
+
var url: (target: string | Element, options?: ScreenshotOptions | undefined) => Promise<string>;
|
|
119
|
+
}
|
|
120
|
+
export { screenshot };
|
|
121
|
+
declare global {
|
|
122
|
+
interface CanvasRenderingContext2D {
|
|
123
|
+
_filterPolyfillValue?: string;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { HelperCanvasState } from '../internal-state';
|
|
2
|
-
export declare const transformIn3d: ({ matrix, sourceCanvas,
|
|
3
|
-
|
|
2
|
+
export declare const transformIn3d: ({ matrix, sourceCanvas, sourceRect, destRect, internalState, }: {
|
|
3
|
+
sourceRect: DOMRect;
|
|
4
4
|
matrix: DOMMatrix;
|
|
5
5
|
sourceCanvas: OffscreenCanvas;
|
|
6
|
-
|
|
6
|
+
destRect: DOMRect;
|
|
7
7
|
internalState: {
|
|
8
8
|
getDrawn3dPixels: () => number;
|
|
9
9
|
getPrecomposedTiles: () => number;
|
|
@@ -22,7 +22,4 @@ export declare const transformIn3d: ({ matrix, sourceCanvas, untransformedRect,
|
|
|
22
22
|
getAudioMixingTime: () => number;
|
|
23
23
|
addAudioMixingTime: (time: number) => void;
|
|
24
24
|
};
|
|
25
|
-
}) =>
|
|
26
|
-
canvas: OffscreenCanvas;
|
|
27
|
-
rect: DOMRect;
|
|
28
|
-
};
|
|
25
|
+
}) => OffscreenCanvas;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type Transform = {
|
|
2
|
+
matrices: DOMMatrix[];
|
|
3
|
+
element: Element;
|
|
4
|
+
transformOrigin: string;
|
|
5
|
+
boundingClientRect: DOMRect | null;
|
|
6
|
+
};
|
|
7
|
+
export declare const parseTransformOriginOrPerspectiveOrigin: (transformOrigin: string) => {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
} | null;
|
|
11
|
+
export declare const getInternalOrigin: (origin: string, boundingClientRect: DOMRect) => {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
};
|
|
15
|
+
export declare const getGlobalOrigin: ({ origin, boundingClientRect, }: {
|
|
16
|
+
origin: string;
|
|
17
|
+
boundingClientRect: DOMRect;
|
|
18
|
+
}) => {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type Transform = {
|
|
2
|
+
matrices: DOMMatrix[];
|
|
3
|
+
element: Element;
|
|
4
|
+
transformOrigin: string;
|
|
5
|
+
boundingClientRect: DOMRect | null;
|
|
6
|
+
};
|
|
7
|
+
export declare const parseTransformOriginOrPerspectiveOrigin: (transformOrigin: string) => {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
} | null;
|
|
11
|
+
export declare const getAbsoluteOrigin: ({ origin, boundingClientRect, }: {
|
|
12
|
+
origin: string;
|
|
13
|
+
boundingClientRect: DOMRect;
|
|
14
|
+
}) => {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
};
|
package/dist/esm/index.mjs
CHANGED
|
@@ -359,7 +359,7 @@ var getEncodableAudioCodecs = async (container, options) => {
|
|
|
359
359
|
};
|
|
360
360
|
// src/render-media-on-web.tsx
|
|
361
361
|
import { BufferTarget, StreamTarget } from "mediabunny";
|
|
362
|
-
import { Internals as
|
|
362
|
+
import { Internals as Internals8 } from "remotion";
|
|
363
363
|
|
|
364
364
|
// src/add-sample.ts
|
|
365
365
|
import { AudioSample, VideoSample } from "mediabunny";
|
|
@@ -488,6 +488,92 @@ var onlyInlineAudio = ({
|
|
|
488
488
|
});
|
|
489
489
|
};
|
|
490
490
|
|
|
491
|
+
// src/background-keepalive.ts
|
|
492
|
+
import { Internals } from "remotion";
|
|
493
|
+
var WORKER_CODE = `
|
|
494
|
+
let intervalId = null;
|
|
495
|
+
self.onmessage = (e) => {
|
|
496
|
+
if (e.data.type === 'start') {
|
|
497
|
+
if (intervalId !== null) {
|
|
498
|
+
clearInterval(intervalId);
|
|
499
|
+
}
|
|
500
|
+
intervalId = setInterval(() => self.postMessage('tick'), e.data.intervalMs);
|
|
501
|
+
} else if (e.data.type === 'stop') {
|
|
502
|
+
if (intervalId !== null) {
|
|
503
|
+
clearInterval(intervalId);
|
|
504
|
+
intervalId = null;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
`;
|
|
509
|
+
function createBackgroundKeepalive({
|
|
510
|
+
fps,
|
|
511
|
+
logLevel
|
|
512
|
+
}) {
|
|
513
|
+
const intervalMs = Math.round(1000 / fps);
|
|
514
|
+
let pendingResolvers = [];
|
|
515
|
+
let worker = null;
|
|
516
|
+
let disposed = false;
|
|
517
|
+
if (typeof Worker === "undefined") {
|
|
518
|
+
Internals.Log.warn({ logLevel, tag: "@remotion/web-renderer" }, "Web Workers not available. Rendering may pause when tab is backgrounded.");
|
|
519
|
+
return {
|
|
520
|
+
waitForTick: () => {
|
|
521
|
+
return new Promise((resolve) => {
|
|
522
|
+
setTimeout(resolve, intervalMs);
|
|
523
|
+
});
|
|
524
|
+
},
|
|
525
|
+
[Symbol.dispose]: () => {}
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
const blob = new Blob([WORKER_CODE], { type: "application/javascript" });
|
|
529
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
530
|
+
worker = new Worker(workerUrl);
|
|
531
|
+
worker.onmessage = () => {
|
|
532
|
+
const resolvers = pendingResolvers;
|
|
533
|
+
pendingResolvers = [];
|
|
534
|
+
for (const resolve of resolvers) {
|
|
535
|
+
resolve();
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
worker.onerror = (event) => {
|
|
539
|
+
Internals.Log.error({ logLevel, tag: "@remotion/web-renderer" }, "Background keepalive worker encountered an error and will be terminated.", event);
|
|
540
|
+
const resolvers = pendingResolvers;
|
|
541
|
+
pendingResolvers = [];
|
|
542
|
+
for (const resolve of resolvers) {
|
|
543
|
+
resolve();
|
|
544
|
+
}
|
|
545
|
+
if (!disposed) {
|
|
546
|
+
disposed = true;
|
|
547
|
+
worker?.terminate();
|
|
548
|
+
worker = null;
|
|
549
|
+
URL.revokeObjectURL(workerUrl);
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
worker.postMessage({ type: "start", intervalMs });
|
|
553
|
+
return {
|
|
554
|
+
waitForTick: () => {
|
|
555
|
+
return new Promise((resolve) => {
|
|
556
|
+
pendingResolvers.push(resolve);
|
|
557
|
+
});
|
|
558
|
+
},
|
|
559
|
+
[Symbol.dispose]: () => {
|
|
560
|
+
if (disposed) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
disposed = true;
|
|
564
|
+
worker?.postMessage({ type: "stop" });
|
|
565
|
+
worker?.terminate();
|
|
566
|
+
worker = null;
|
|
567
|
+
URL.revokeObjectURL(workerUrl);
|
|
568
|
+
const resolvers = pendingResolvers;
|
|
569
|
+
pendingResolvers = [];
|
|
570
|
+
for (const resolve of resolvers) {
|
|
571
|
+
resolve();
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
|
|
491
577
|
// src/create-audio-sample-source.ts
|
|
492
578
|
import { AudioSampleSource } from "mediabunny";
|
|
493
579
|
var createAudioSampleSource = ({
|
|
@@ -509,12 +595,12 @@ var createAudioSampleSource = ({
|
|
|
509
595
|
import { createRef } from "react";
|
|
510
596
|
import { flushSync as flushSync2 } from "react-dom";
|
|
511
597
|
import ReactDOM from "react-dom/client";
|
|
512
|
-
import { Internals as
|
|
598
|
+
import { Internals as Internals3 } from "remotion";
|
|
513
599
|
|
|
514
600
|
// src/update-time.tsx
|
|
515
601
|
import { useImperativeHandle, useState } from "react";
|
|
516
602
|
import { flushSync } from "react-dom";
|
|
517
|
-
import { Internals } from "remotion";
|
|
603
|
+
import { Internals as Internals2 } from "remotion";
|
|
518
604
|
import { jsx } from "react/jsx-runtime";
|
|
519
605
|
var UpdateTime = ({
|
|
520
606
|
children,
|
|
@@ -533,7 +619,7 @@ var UpdateTime = ({
|
|
|
533
619
|
});
|
|
534
620
|
}
|
|
535
621
|
}));
|
|
536
|
-
return /* @__PURE__ */ jsx(
|
|
622
|
+
return /* @__PURE__ */ jsx(Internals2.RemotionRootContexts, {
|
|
537
623
|
audioEnabled,
|
|
538
624
|
videoEnabled,
|
|
539
625
|
logLevel,
|
|
@@ -596,7 +682,7 @@ async function createScaffold({
|
|
|
596
682
|
div.style.pointerEvents = "none";
|
|
597
683
|
const scaffoldClassName = `remotion-scaffold-${Math.random().toString(36).substring(2, 15)}`;
|
|
598
684
|
div.className = scaffoldClassName;
|
|
599
|
-
const cleanupCSS =
|
|
685
|
+
const cleanupCSS = Internals3.CSSUtils.injectCSS(Internals3.CSSUtils.makeDefaultPreviewCSS(`.${scaffoldClassName}`, "white"));
|
|
600
686
|
document.body.appendChild(div);
|
|
601
687
|
const { promise, resolve, reject } = withResolvers();
|
|
602
688
|
const root = ReactDOM.createRoot(div, {
|
|
@@ -614,9 +700,9 @@ async function createScaffold({
|
|
|
614
700
|
const timeUpdater = createRef();
|
|
615
701
|
const collectAssets = createRef();
|
|
616
702
|
flushSync2(() => {
|
|
617
|
-
root.render(/* @__PURE__ */ jsx2(
|
|
703
|
+
root.render(/* @__PURE__ */ jsx2(Internals3.MaxMediaCacheSizeContext.Provider, {
|
|
618
704
|
value: mediaCacheSizeInBytes,
|
|
619
|
-
children: /* @__PURE__ */ jsx2(
|
|
705
|
+
children: /* @__PURE__ */ jsx2(Internals3.RemotionEnvironmentContext.Provider, {
|
|
620
706
|
value: {
|
|
621
707
|
isStudio: false,
|
|
622
708
|
isRendering: true,
|
|
@@ -624,9 +710,9 @@ async function createScaffold({
|
|
|
624
710
|
isReadOnlyStudio: false,
|
|
625
711
|
isClientSideRendering: true
|
|
626
712
|
},
|
|
627
|
-
children: /* @__PURE__ */ jsx2(
|
|
713
|
+
children: /* @__PURE__ */ jsx2(Internals3.DelayRenderContextType.Provider, {
|
|
628
714
|
value: delayRenderScope,
|
|
629
|
-
children: /* @__PURE__ */ jsx2(
|
|
715
|
+
children: /* @__PURE__ */ jsx2(Internals3.CompositionManager.Provider, {
|
|
630
716
|
value: {
|
|
631
717
|
compositions: [
|
|
632
718
|
{
|
|
@@ -662,7 +748,7 @@ async function createScaffold({
|
|
|
662
748
|
},
|
|
663
749
|
folders: []
|
|
664
750
|
},
|
|
665
|
-
children: /* @__PURE__ */ jsx2(
|
|
751
|
+
children: /* @__PURE__ */ jsx2(Internals3.RenderAssetManagerProvider, {
|
|
666
752
|
collectAssets,
|
|
667
753
|
children: /* @__PURE__ */ jsx2(UpdateTime, {
|
|
668
754
|
audioEnabled,
|
|
@@ -671,7 +757,7 @@ async function createScaffold({
|
|
|
671
757
|
compId: id,
|
|
672
758
|
initialFrame,
|
|
673
759
|
timeUpdater,
|
|
674
|
-
children: /* @__PURE__ */ jsx2(
|
|
760
|
+
children: /* @__PURE__ */ jsx2(Internals3.CanUseRemotionHooks.Provider, {
|
|
675
761
|
value: true,
|
|
676
762
|
children: /* @__PURE__ */ jsx2(Component, {
|
|
677
763
|
...resolvedProps
|
|
@@ -799,58 +885,77 @@ function isNetworkError(error) {
|
|
|
799
885
|
return false;
|
|
800
886
|
}
|
|
801
887
|
var HOST = "https://www.remotion.pro";
|
|
888
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
889
|
+
var exponentialBackoffMs = (attempt) => {
|
|
890
|
+
return 1000 * 2 ** (attempt - 1);
|
|
891
|
+
};
|
|
892
|
+
var sleep = (ms) => {
|
|
893
|
+
return new Promise((resolve) => {
|
|
894
|
+
setTimeout(resolve, ms);
|
|
895
|
+
});
|
|
896
|
+
};
|
|
802
897
|
var registerUsageEvent = async ({
|
|
803
898
|
host,
|
|
804
899
|
succeeded,
|
|
805
900
|
event,
|
|
806
901
|
...apiOrLicenseKey
|
|
807
902
|
}) => {
|
|
808
|
-
const abortController = new AbortController;
|
|
809
|
-
const timeout = setTimeout(() => {
|
|
810
|
-
abortController.abort();
|
|
811
|
-
}, 1e4);
|
|
812
903
|
const apiKey = "apiKey" in apiOrLicenseKey ? apiOrLicenseKey.apiKey : null;
|
|
813
904
|
const licenseKey = "licenseKey" in apiOrLicenseKey ? apiOrLicenseKey.licenseKey : null;
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
};
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
throw new Error(
|
|
905
|
+
let lastError;
|
|
906
|
+
const totalAttempts = DEFAULT_MAX_RETRIES + 1;
|
|
907
|
+
for (let attempt = 1;attempt <= totalAttempts; attempt++) {
|
|
908
|
+
const abortController = new AbortController;
|
|
909
|
+
const timeout = setTimeout(() => {
|
|
910
|
+
abortController.abort();
|
|
911
|
+
}, 1e4);
|
|
912
|
+
try {
|
|
913
|
+
const res = await fetch(`${HOST}/api/track/register-usage-point`, {
|
|
914
|
+
method: "POST",
|
|
915
|
+
body: JSON.stringify({
|
|
916
|
+
event,
|
|
917
|
+
apiKey: licenseKey ?? apiKey,
|
|
918
|
+
host,
|
|
919
|
+
succeeded
|
|
920
|
+
}),
|
|
921
|
+
headers: {
|
|
922
|
+
"Content-Type": "application/json"
|
|
923
|
+
},
|
|
924
|
+
signal: abortController.signal
|
|
925
|
+
});
|
|
926
|
+
clearTimeout(timeout);
|
|
927
|
+
const json = await res.json();
|
|
928
|
+
if (json.success) {
|
|
929
|
+
return {
|
|
930
|
+
billable: json.billable,
|
|
931
|
+
classification: json.classification
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
if (!res.ok) {
|
|
935
|
+
throw new Error(json.error);
|
|
936
|
+
}
|
|
937
|
+
throw new Error(`Unexpected response from server: ${JSON.stringify(json)}`);
|
|
938
|
+
} catch (err) {
|
|
939
|
+
clearTimeout(timeout);
|
|
940
|
+
const error = err;
|
|
941
|
+
const isTimeout = error.name === "AbortError";
|
|
942
|
+
const isRetryable = isNetworkError(error) || isTimeout;
|
|
943
|
+
if (!isRetryable) {
|
|
944
|
+
throw err;
|
|
945
|
+
}
|
|
946
|
+
lastError = isTimeout ? new Error("Request timed out after 10 seconds") : error;
|
|
947
|
+
if (attempt < totalAttempts) {
|
|
948
|
+
const backoffMs = exponentialBackoffMs(attempt);
|
|
949
|
+
console.log(`Failed to send usage event (attempt ${attempt}/${totalAttempts}), retrying in ${backoffMs}ms...`, err);
|
|
950
|
+
await sleep(backoffMs);
|
|
951
|
+
}
|
|
847
952
|
}
|
|
848
|
-
throw err;
|
|
849
953
|
}
|
|
954
|
+
throw lastError;
|
|
850
955
|
};
|
|
851
956
|
|
|
852
957
|
// src/send-telemetry-event.ts
|
|
853
|
-
import { Internals as
|
|
958
|
+
import { Internals as Internals4 } from "remotion";
|
|
854
959
|
var sendUsageEvent = async ({
|
|
855
960
|
licenseKey,
|
|
856
961
|
succeeded,
|
|
@@ -861,7 +966,7 @@ var sendUsageEvent = async ({
|
|
|
861
966
|
return;
|
|
862
967
|
}
|
|
863
968
|
if (licenseKey === null) {
|
|
864
|
-
|
|
969
|
+
Internals4.Log.warn({ logLevel: "warn", tag: "web-renderer" }, `Pass "licenseKey" to ${apiName}(). If you qualify for the Free License (https://remotion.dev/license), pass "free-license" instead.`);
|
|
865
970
|
}
|
|
866
971
|
await registerUsageEvent({
|
|
867
972
|
licenseKey: licenseKey === "free-license" ? null : licenseKey,
|
|
@@ -1207,7 +1312,7 @@ var drawDomElement = (node) => {
|
|
|
1207
1312
|
};
|
|
1208
1313
|
|
|
1209
1314
|
// src/drawing/process-node.ts
|
|
1210
|
-
import { Internals as
|
|
1315
|
+
import { Internals as Internals6 } from "remotion";
|
|
1211
1316
|
|
|
1212
1317
|
// src/drawing/has-transform.ts
|
|
1213
1318
|
var hasTransformCssValue = (style) => {
|
|
@@ -2256,7 +2361,7 @@ var drawBorder = ({
|
|
|
2256
2361
|
};
|
|
2257
2362
|
|
|
2258
2363
|
// src/drawing/draw-box-shadow.ts
|
|
2259
|
-
import { Internals as
|
|
2364
|
+
import { Internals as Internals5 } from "remotion";
|
|
2260
2365
|
var parseBoxShadow = (boxShadowValue) => {
|
|
2261
2366
|
if (!boxShadowValue || boxShadowValue === "none") {
|
|
2262
2367
|
return [];
|
|
@@ -2321,7 +2426,7 @@ var drawBorderRadius = ({
|
|
|
2321
2426
|
throw new Error("Failed to get context");
|
|
2322
2427
|
}
|
|
2323
2428
|
if (shadow.inset) {
|
|
2324
|
-
|
|
2429
|
+
Internals5.Log.warn({
|
|
2325
2430
|
logLevel,
|
|
2326
2431
|
tag: "@remotion/web-renderer"
|
|
2327
2432
|
}, 'Detected "box-shadow" with "inset". This is not yet supported in @remotion/web-renderer');
|
|
@@ -2619,55 +2724,81 @@ var getBiggestBoundingClientRect = (element) => {
|
|
|
2619
2724
|
|
|
2620
2725
|
// src/drawing/get-pretransform-rect.ts
|
|
2621
2726
|
var MAX_SCALE_FACTOR = 100;
|
|
2622
|
-
|
|
2727
|
+
var isScaleTooBig = (matrix) => {
|
|
2623
2728
|
const origin = new DOMPoint(0, 0).matrixTransform(matrix);
|
|
2624
2729
|
const unitX = new DOMPoint(1, 0).matrixTransform(matrix);
|
|
2625
2730
|
const unitY = new DOMPoint(0, 1).matrixTransform(matrix);
|
|
2626
2731
|
const basisX = { x: unitX.x - origin.x, y: unitX.y - origin.y };
|
|
2627
2732
|
const basisY = { x: unitY.x - origin.x, y: unitY.y - origin.y };
|
|
2628
|
-
const scaleX = Math.hypot(basisX.x, basisX.y);
|
|
2629
|
-
const scaleY = Math.hypot(basisY.x, basisY.y);
|
|
2630
|
-
const
|
|
2631
|
-
if (
|
|
2632
|
-
return
|
|
2633
|
-
}
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
const
|
|
2643
|
-
const
|
|
2644
|
-
if (
|
|
2645
|
-
return
|
|
2733
|
+
const scaleX = 1 / Math.hypot(basisX.x, basisX.y);
|
|
2734
|
+
const scaleY = 1 / Math.hypot(basisY.x, basisY.y);
|
|
2735
|
+
const maxScale = Math.max(scaleX, scaleY);
|
|
2736
|
+
if (maxScale > MAX_SCALE_FACTOR) {
|
|
2737
|
+
return true;
|
|
2738
|
+
}
|
|
2739
|
+
return false;
|
|
2740
|
+
};
|
|
2741
|
+
function invertProjectivePoint(xp, yp, matrix) {
|
|
2742
|
+
const A = matrix.m11 - xp * matrix.m14;
|
|
2743
|
+
const B = matrix.m21 - xp * matrix.m24;
|
|
2744
|
+
const C = xp * matrix.m44 - matrix.m41;
|
|
2745
|
+
const D = matrix.m12 - yp * matrix.m14;
|
|
2746
|
+
const E = matrix.m22 - yp * matrix.m24;
|
|
2747
|
+
const F = yp * matrix.m44 - matrix.m42;
|
|
2748
|
+
const det = A * E - B * D;
|
|
2749
|
+
if (Math.abs(det) < 0.0000000001) {
|
|
2750
|
+
return null;
|
|
2751
|
+
}
|
|
2752
|
+
const x = (C * E - B * F) / det;
|
|
2753
|
+
const y = (A * F - C * D) / det;
|
|
2754
|
+
return { x, y };
|
|
2755
|
+
}
|
|
2756
|
+
function getPreTransformRect(targetRect, matrix) {
|
|
2757
|
+
if (isScaleTooBig(matrix)) {
|
|
2758
|
+
return null;
|
|
2646
2759
|
}
|
|
2647
2760
|
const corners = [
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2761
|
+
{ x: targetRect.x, y: targetRect.y },
|
|
2762
|
+
{ x: targetRect.x + targetRect.width, y: targetRect.y },
|
|
2763
|
+
{ x: targetRect.x + targetRect.width, y: targetRect.y + targetRect.height },
|
|
2764
|
+
{ x: targetRect.x, y: targetRect.y + targetRect.height }
|
|
2652
2765
|
];
|
|
2653
|
-
const
|
|
2654
|
-
const
|
|
2655
|
-
|
|
2656
|
-
|
|
2766
|
+
const invertedCorners = [];
|
|
2767
|
+
for (const corner of corners) {
|
|
2768
|
+
const inverted = invertProjectivePoint(corner.x, corner.y, matrix);
|
|
2769
|
+
if (inverted === null) {
|
|
2770
|
+
return null;
|
|
2771
|
+
}
|
|
2772
|
+
invertedCorners.push(inverted);
|
|
2773
|
+
}
|
|
2774
|
+
const xCoords = invertedCorners.map((p) => p.x);
|
|
2775
|
+
const yCoords = invertedCorners.map((p) => p.y);
|
|
2776
|
+
return new DOMRect(Math.min(...xCoords), Math.min(...yCoords), Math.max(...xCoords) - Math.min(...xCoords), Math.max(...yCoords) - Math.min(...yCoords));
|
|
2657
2777
|
}
|
|
2658
2778
|
|
|
2659
2779
|
// src/drawing/transform-in-3d.ts
|
|
2660
2780
|
var vsSource = `
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2781
|
+
attribute vec2 aPosition;
|
|
2782
|
+
attribute vec2 aTexCoord;
|
|
2783
|
+
uniform mat4 uTransform;
|
|
2784
|
+
uniform vec2 uResolution;
|
|
2785
|
+
uniform vec2 uOffset;
|
|
2786
|
+
varying vec2 vTexCoord;
|
|
2666
2787
|
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2788
|
+
void main() {
|
|
2789
|
+
vec4 pos = uTransform * vec4(aPosition, 0.0, 1.0);
|
|
2790
|
+
pos.xy = pos.xy + uOffset * pos.w;
|
|
2791
|
+
|
|
2792
|
+
// Convert homogeneous coords to clip space
|
|
2793
|
+
gl_Position = vec4(
|
|
2794
|
+
(pos.x / uResolution.x) * 2.0 - pos.w, // x
|
|
2795
|
+
pos.w - (pos.y / uResolution.y) * 2.0, // y (flipped)
|
|
2796
|
+
0.0,
|
|
2797
|
+
pos.w
|
|
2798
|
+
);
|
|
2799
|
+
|
|
2800
|
+
vTexCoord = aTexCoord;
|
|
2801
|
+
}
|
|
2671
2802
|
`;
|
|
2672
2803
|
var fsSource = `
|
|
2673
2804
|
precision mediump float;
|
|
@@ -2730,7 +2861,8 @@ var createHelperCanvas = ({
|
|
|
2730
2861
|
aPosition: gl.getAttribLocation(program, "aPosition"),
|
|
2731
2862
|
aTexCoord: gl.getAttribLocation(program, "aTexCoord"),
|
|
2732
2863
|
uTransform: gl.getUniformLocation(program, "uTransform"),
|
|
2733
|
-
|
|
2864
|
+
uResolution: gl.getUniformLocation(program, "uResolution"),
|
|
2865
|
+
uOffset: gl.getUniformLocation(program, "uOffset"),
|
|
2734
2866
|
uTexture: gl.getUniformLocation(program, "uTexture")
|
|
2735
2867
|
};
|
|
2736
2868
|
gl.deleteShader(vertexShader);
|
|
@@ -2748,55 +2880,60 @@ var createHelperCanvas = ({
|
|
|
2748
2880
|
var transformIn3d = ({
|
|
2749
2881
|
matrix,
|
|
2750
2882
|
sourceCanvas,
|
|
2751
|
-
|
|
2752
|
-
|
|
2883
|
+
sourceRect,
|
|
2884
|
+
destRect,
|
|
2753
2885
|
internalState
|
|
2754
2886
|
}) => {
|
|
2755
2887
|
const { canvas, gl, program, locations } = createHelperCanvas({
|
|
2756
|
-
canvasWidth:
|
|
2757
|
-
canvasHeight:
|
|
2888
|
+
canvasWidth: destRect.width,
|
|
2889
|
+
canvasHeight: destRect.height,
|
|
2758
2890
|
helperCanvasState: internalState.helperCanvasState
|
|
2759
2891
|
});
|
|
2760
2892
|
gl.useProgram(program);
|
|
2761
|
-
gl.viewport(0, 0,
|
|
2893
|
+
gl.viewport(0, 0, destRect.width, destRect.height);
|
|
2762
2894
|
gl.clearColor(0, 0, 0, 0);
|
|
2763
2895
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
2764
2896
|
gl.enable(gl.BLEND);
|
|
2765
2897
|
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
|
2766
2898
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
2767
|
-
const
|
|
2768
|
-
gl.bindBuffer(gl.ARRAY_BUFFER,
|
|
2769
|
-
const
|
|
2770
|
-
|
|
2771
|
-
|
|
2899
|
+
const positionBuffer = gl.createBuffer();
|
|
2900
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
|
2901
|
+
const positions = new Float32Array([
|
|
2902
|
+
sourceRect.x,
|
|
2903
|
+
sourceRect.y,
|
|
2904
|
+
sourceRect.x + sourceRect.width,
|
|
2905
|
+
sourceRect.y,
|
|
2906
|
+
sourceRect.x,
|
|
2907
|
+
sourceRect.y + sourceRect.height,
|
|
2908
|
+
sourceRect.x,
|
|
2909
|
+
sourceRect.y + sourceRect.height,
|
|
2910
|
+
sourceRect.x + sourceRect.width,
|
|
2911
|
+
sourceRect.y,
|
|
2912
|
+
sourceRect.x + sourceRect.width,
|
|
2913
|
+
sourceRect.y + sourceRect.height
|
|
2914
|
+
]);
|
|
2915
|
+
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
|
|
2916
|
+
gl.enableVertexAttribArray(locations.aPosition);
|
|
2917
|
+
gl.vertexAttribPointer(locations.aPosition, 2, gl.FLOAT, false, 0, 0);
|
|
2918
|
+
const texCoordBuffer = gl.createBuffer();
|
|
2919
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
|
|
2920
|
+
const texCoords = new Float32Array([
|
|
2772
2921
|
0,
|
|
2773
2922
|
0,
|
|
2774
|
-
untransformedRect.x + untransformedRect.width,
|
|
2775
|
-
untransformedRect.y,
|
|
2776
2923
|
1,
|
|
2777
2924
|
0,
|
|
2778
|
-
untransformedRect.x,
|
|
2779
|
-
untransformedRect.y + untransformedRect.height,
|
|
2780
2925
|
0,
|
|
2781
2926
|
1,
|
|
2782
|
-
untransformedRect.x,
|
|
2783
|
-
untransformedRect.y + untransformedRect.height,
|
|
2784
2927
|
0,
|
|
2785
2928
|
1,
|
|
2786
|
-
untransformedRect.x + untransformedRect.width,
|
|
2787
|
-
untransformedRect.y,
|
|
2788
2929
|
1,
|
|
2789
2930
|
0,
|
|
2790
|
-
untransformedRect.x + untransformedRect.width,
|
|
2791
|
-
untransformedRect.y + untransformedRect.height,
|
|
2792
2931
|
1,
|
|
2793
2932
|
1
|
|
2794
2933
|
]);
|
|
2795
|
-
gl.bufferData(gl.ARRAY_BUFFER,
|
|
2796
|
-
gl.enableVertexAttribArray(locations.aPosition);
|
|
2797
|
-
gl.vertexAttribPointer(locations.aPosition, 2, gl.FLOAT, false, 4 * 4, 0);
|
|
2934
|
+
gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
|
|
2798
2935
|
gl.enableVertexAttribArray(locations.aTexCoord);
|
|
2799
|
-
gl.vertexAttribPointer(locations.aTexCoord, 2, gl.FLOAT, false,
|
|
2936
|
+
gl.vertexAttribPointer(locations.aTexCoord, 2, gl.FLOAT, false, 0, 0);
|
|
2800
2937
|
const texture = gl.createTexture();
|
|
2801
2938
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
2802
2939
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
@@ -2805,41 +2942,21 @@ var transformIn3d = ({
|
|
|
2805
2942
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
2806
2943
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, sourceCanvas);
|
|
2807
2944
|
const transformMatrix = matrix.toFloat32Array();
|
|
2808
|
-
const zScale = 1e9;
|
|
2809
|
-
const projectionMatrix = new Float32Array([
|
|
2810
|
-
2 / rectAfterTransforms.width,
|
|
2811
|
-
0,
|
|
2812
|
-
0,
|
|
2813
|
-
0,
|
|
2814
|
-
0,
|
|
2815
|
-
-2 / rectAfterTransforms.height,
|
|
2816
|
-
0,
|
|
2817
|
-
0,
|
|
2818
|
-
0,
|
|
2819
|
-
0,
|
|
2820
|
-
-2 / zScale,
|
|
2821
|
-
0,
|
|
2822
|
-
-1 + 2 * -rectAfterTransforms.x / rectAfterTransforms.width,
|
|
2823
|
-
1 - 2 * -rectAfterTransforms.y / rectAfterTransforms.height,
|
|
2824
|
-
0,
|
|
2825
|
-
1
|
|
2826
|
-
]);
|
|
2827
2945
|
gl.uniformMatrix4fv(locations.uTransform, false, transformMatrix);
|
|
2828
|
-
gl.
|
|
2946
|
+
gl.uniform2f(locations.uResolution, destRect.width, destRect.height);
|
|
2947
|
+
gl.uniform2f(locations.uOffset, -destRect.x, -destRect.y);
|
|
2829
2948
|
gl.uniform1i(locations.uTexture, 0);
|
|
2830
2949
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
2831
2950
|
gl.disableVertexAttribArray(locations.aPosition);
|
|
2832
2951
|
gl.disableVertexAttribArray(locations.aTexCoord);
|
|
2833
2952
|
gl.deleteTexture(texture);
|
|
2834
|
-
gl.deleteBuffer(
|
|
2953
|
+
gl.deleteBuffer(positionBuffer);
|
|
2954
|
+
gl.deleteBuffer(texCoordBuffer);
|
|
2835
2955
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
2836
2956
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
2837
2957
|
gl.disable(gl.BLEND);
|
|
2838
2958
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
2839
|
-
return
|
|
2840
|
-
canvas,
|
|
2841
|
-
rect: rectAfterTransforms
|
|
2842
|
-
};
|
|
2959
|
+
return canvas;
|
|
2843
2960
|
};
|
|
2844
2961
|
|
|
2845
2962
|
// src/drawing/handle-3d-transform.ts
|
|
@@ -2850,6 +2967,9 @@ var getPrecomposeRectFor3DTransform = ({
|
|
|
2850
2967
|
}) => {
|
|
2851
2968
|
const unclampedBiggestBoundingClientRect = getBiggestBoundingClientRect(element);
|
|
2852
2969
|
const biggestPossiblePretransformRect = getPreTransformRect(parentRect, matrix);
|
|
2970
|
+
if (!biggestPossiblePretransformRect) {
|
|
2971
|
+
return null;
|
|
2972
|
+
}
|
|
2853
2973
|
const preTransformRect = getNarrowerRect({
|
|
2854
2974
|
firstRect: unclampedBiggestBoundingClientRect,
|
|
2855
2975
|
secondRect: biggestPossiblePretransformRect
|
|
@@ -2858,21 +2978,21 @@ var getPrecomposeRectFor3DTransform = ({
|
|
|
2858
2978
|
};
|
|
2859
2979
|
var handle3dTransform = ({
|
|
2860
2980
|
matrix,
|
|
2861
|
-
|
|
2981
|
+
sourceRect,
|
|
2862
2982
|
tempCanvas,
|
|
2863
2983
|
rectAfterTransforms,
|
|
2864
2984
|
internalState
|
|
2865
2985
|
}) => {
|
|
2866
|
-
|
|
2867
|
-
|
|
2986
|
+
if (rectAfterTransforms.width <= 0 || rectAfterTransforms.height <= 0) {
|
|
2987
|
+
return null;
|
|
2988
|
+
}
|
|
2989
|
+
const transformed = transformIn3d({
|
|
2990
|
+
sourceRect,
|
|
2868
2991
|
matrix,
|
|
2869
2992
|
sourceCanvas: tempCanvas,
|
|
2870
|
-
rectAfterTransforms,
|
|
2993
|
+
destRect: rectAfterTransforms,
|
|
2871
2994
|
internalState
|
|
2872
2995
|
});
|
|
2873
|
-
if (transformedRect.width <= 0 || transformedRect.height <= 0) {
|
|
2874
|
-
return null;
|
|
2875
|
-
}
|
|
2876
2996
|
return transformed;
|
|
2877
2997
|
};
|
|
2878
2998
|
|
|
@@ -2973,20 +3093,21 @@ var processNode = async ({
|
|
|
2973
3093
|
const start = Date.now();
|
|
2974
3094
|
let precomposeRect = null;
|
|
2975
3095
|
if (precompositing.needsMaskImage) {
|
|
2976
|
-
precomposeRect =
|
|
2977
|
-
firstRect: precomposeRect,
|
|
2978
|
-
secondRect: getPrecomposeRectForMask(element)
|
|
2979
|
-
});
|
|
3096
|
+
precomposeRect = roundToExpandRect(getPrecomposeRectForMask(element));
|
|
2980
3097
|
}
|
|
2981
3098
|
if (precompositing.needs3DTransformViaWebGL) {
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
parentRect,
|
|
2987
|
-
matrix: totalMatrix
|
|
2988
|
-
})
|
|
3099
|
+
const tentativePrecomposeRect = getPrecomposeRectFor3DTransform({
|
|
3100
|
+
element,
|
|
3101
|
+
parentRect,
|
|
3102
|
+
matrix: totalMatrix
|
|
2989
3103
|
});
|
|
3104
|
+
if (!tentativePrecomposeRect) {
|
|
3105
|
+
return { type: "continue", cleanupAfterChildren: null };
|
|
3106
|
+
}
|
|
3107
|
+
precomposeRect = roundToExpandRect(getWiderRectAndExpand({
|
|
3108
|
+
firstRect: precomposeRect,
|
|
3109
|
+
secondRect: tentativePrecomposeRect
|
|
3110
|
+
}));
|
|
2990
3111
|
}
|
|
2991
3112
|
if (!precomposeRect) {
|
|
2992
3113
|
throw new Error("Precompose rect not found");
|
|
@@ -3019,7 +3140,7 @@ var processNode = async ({
|
|
|
3019
3140
|
if (precompositing.needs3DTransformViaWebGL) {
|
|
3020
3141
|
const t = handle3dTransform({
|
|
3021
3142
|
matrix: totalMatrix,
|
|
3022
|
-
precomposeRect,
|
|
3143
|
+
sourceRect: precomposeRect,
|
|
3023
3144
|
tempCanvas: drawable,
|
|
3024
3145
|
rectAfterTransforms,
|
|
3025
3146
|
internalState
|
|
@@ -3033,7 +3154,7 @@ var processNode = async ({
|
|
|
3033
3154
|
context.setTransform(new DOMMatrix);
|
|
3034
3155
|
context.drawImage(drawable, 0, drawable.height - rectAfterTransforms.height, rectAfterTransforms.width, rectAfterTransforms.height, rectAfterTransforms.left - parentRect.x, rectAfterTransforms.top - parentRect.y, rectAfterTransforms.width, rectAfterTransforms.height);
|
|
3035
3156
|
context.setTransform(previousTransform);
|
|
3036
|
-
|
|
3157
|
+
Internals6.Log.trace({
|
|
3037
3158
|
logLevel,
|
|
3038
3159
|
tag: "@remotion/web-renderer"
|
|
3039
3160
|
}, `Transforming element in 3D - canvas size: ${precomposeRect.width}x${precomposeRect.height} - compose: ${Date.now() - start}ms - helper canvas: ${drawable.width}x${drawable.height}`);
|
|
@@ -3065,7 +3186,7 @@ var processNode = async ({
|
|
|
3065
3186
|
};
|
|
3066
3187
|
|
|
3067
3188
|
// src/drawing/text/draw-text.ts
|
|
3068
|
-
import { Internals as
|
|
3189
|
+
import { Internals as Internals7 } from "remotion";
|
|
3069
3190
|
|
|
3070
3191
|
// src/drawing/text/apply-text-transform.ts
|
|
3071
3192
|
var applyTextTransform = (text, transform) => {
|
|
@@ -3238,7 +3359,7 @@ var drawText = ({
|
|
|
3238
3359
|
} = computedStyle;
|
|
3239
3360
|
const isVertical = writingMode !== "horizontal-tb";
|
|
3240
3361
|
if (isVertical) {
|
|
3241
|
-
|
|
3362
|
+
Internals7.Log.warn({
|
|
3242
3363
|
logLevel,
|
|
3243
3364
|
tag: "@remotion/web-renderer"
|
|
3244
3365
|
}, 'Detected "writing-mode" CSS property. Vertical text is not yet supported in @remotion/web-renderer');
|
|
@@ -3546,7 +3667,8 @@ var waitForReady = ({
|
|
|
3546
3667
|
scope,
|
|
3547
3668
|
signal,
|
|
3548
3669
|
apiName,
|
|
3549
|
-
internalState
|
|
3670
|
+
internalState,
|
|
3671
|
+
keepalive
|
|
3550
3672
|
}) => {
|
|
3551
3673
|
const start = performance.now();
|
|
3552
3674
|
const { promise, resolve, reject } = withResolvers();
|
|
@@ -3578,9 +3700,16 @@ var waitForReady = ({
|
|
|
3578
3700
|
reject(new Error(Object.values(scope.remotion_delayRenderTimeouts).map((d) => d.label).join(", ")));
|
|
3579
3701
|
return;
|
|
3580
3702
|
}
|
|
3581
|
-
|
|
3703
|
+
scheduleNextCheck();
|
|
3704
|
+
};
|
|
3705
|
+
const scheduleNextCheck = () => {
|
|
3706
|
+
const rafTick = new Promise((res) => {
|
|
3707
|
+
requestAnimationFrame(() => res());
|
|
3708
|
+
});
|
|
3709
|
+
const backgroundSafeTick = keepalive ? Promise.race([rafTick, keepalive.waitForTick()]) : rafTick;
|
|
3710
|
+
backgroundSafeTick.then(check);
|
|
3582
3711
|
};
|
|
3583
|
-
|
|
3712
|
+
scheduleNextCheck();
|
|
3584
3713
|
return promise;
|
|
3585
3714
|
};
|
|
3586
3715
|
|
|
@@ -3671,11 +3800,11 @@ var internalRenderMediaOnWeb = async ({
|
|
|
3671
3800
|
if (issue.severity === "error") {
|
|
3672
3801
|
return Promise.reject(new Error(issue.message));
|
|
3673
3802
|
}
|
|
3674
|
-
|
|
3803
|
+
Internals8.Log.warn({ logLevel, tag: "@remotion/web-renderer" }, issue.message);
|
|
3675
3804
|
}
|
|
3676
3805
|
finalAudioCodec = audioResult.codec;
|
|
3677
3806
|
}
|
|
3678
|
-
const resolved = await
|
|
3807
|
+
const resolved = await Internals8.resolveVideoConfig({
|
|
3679
3808
|
calculateMetadata: composition.calculateMetadata ?? null,
|
|
3680
3809
|
signal: signal ?? new AbortController().signal,
|
|
3681
3810
|
defaultProps: composition.defaultProps ?? {},
|
|
@@ -3710,6 +3839,10 @@ var internalRenderMediaOnWeb = async ({
|
|
|
3710
3839
|
}), 0);
|
|
3711
3840
|
const { delayRenderScope, div, timeUpdater, collectAssets } = scaffold;
|
|
3712
3841
|
const internalState = __using(__stack2, makeInternalState(), 0);
|
|
3842
|
+
const keepalive = __using(__stack2, createBackgroundKeepalive({
|
|
3843
|
+
fps: resolved.fps,
|
|
3844
|
+
logLevel
|
|
3845
|
+
}), 0);
|
|
3713
3846
|
const artifactsHandler = handleArtifacts();
|
|
3714
3847
|
const webFsTarget = outputTarget === "web-fs" ? await createWebFsTarget() : null;
|
|
3715
3848
|
const target = webFsTarget ? new StreamTarget(webFsTarget.stream) : new BufferTarget;
|
|
@@ -3728,7 +3861,8 @@ var internalRenderMediaOnWeb = async ({
|
|
|
3728
3861
|
scope: delayRenderScope,
|
|
3729
3862
|
signal,
|
|
3730
3863
|
apiName: "renderMediaOnWeb",
|
|
3731
|
-
internalState
|
|
3864
|
+
internalState,
|
|
3865
|
+
keepalive
|
|
3732
3866
|
});
|
|
3733
3867
|
if (signal?.aborted) {
|
|
3734
3868
|
throw new Error("renderMediaOnWeb() was cancelled");
|
|
@@ -3770,6 +3904,7 @@ var internalRenderMediaOnWeb = async ({
|
|
|
3770
3904
|
scope: delayRenderScope,
|
|
3771
3905
|
signal,
|
|
3772
3906
|
apiName: "renderMediaOnWeb",
|
|
3907
|
+
keepalive,
|
|
3773
3908
|
internalState
|
|
3774
3909
|
});
|
|
3775
3910
|
if (signal?.aborted) {
|
|
@@ -3838,7 +3973,7 @@ var internalRenderMediaOnWeb = async ({
|
|
|
3838
3973
|
videoSampleSource.videoSampleSource.close();
|
|
3839
3974
|
audioSampleSource?.audioSampleSource.close();
|
|
3840
3975
|
await outputWithCleanup.output.finalize();
|
|
3841
|
-
|
|
3976
|
+
Internals8.Log.verbose({ logLevel, tag: "web-renderer" }, `Render timings: waitForReady=${internalState.getWaitForReadyTime().toFixed(2)}ms, createFrame=${internalState.getCreateFrameTime().toFixed(2)}ms, addSample=${internalState.getAddSampleTime().toFixed(2)}ms, audioMixing=${internalState.getAudioMixingTime().toFixed(2)}ms`);
|
|
3842
3977
|
if (webFsTarget) {
|
|
3843
3978
|
sendUsageEvent({
|
|
3844
3979
|
licenseKey: licenseKey ?? null,
|
|
@@ -3882,7 +4017,7 @@ var internalRenderMediaOnWeb = async ({
|
|
|
3882
4017
|
licenseKey: licenseKey ?? null,
|
|
3883
4018
|
apiName: "renderMediaOnWeb"
|
|
3884
4019
|
}).catch((err2) => {
|
|
3885
|
-
|
|
4020
|
+
Internals8.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
|
|
3886
4021
|
});
|
|
3887
4022
|
}
|
|
3888
4023
|
throw err;
|
|
@@ -3923,7 +4058,7 @@ var renderMediaOnWeb = (options) => {
|
|
|
3923
4058
|
};
|
|
3924
4059
|
// src/render-still-on-web.tsx
|
|
3925
4060
|
import {
|
|
3926
|
-
Internals as
|
|
4061
|
+
Internals as Internals9
|
|
3927
4062
|
} from "remotion";
|
|
3928
4063
|
async function internalRenderStillOnWeb({
|
|
3929
4064
|
frame,
|
|
@@ -3940,7 +4075,7 @@ async function internalRenderStillOnWeb({
|
|
|
3940
4075
|
}) {
|
|
3941
4076
|
let __stack = [];
|
|
3942
4077
|
try {
|
|
3943
|
-
const resolved = await
|
|
4078
|
+
const resolved = await Internals9.resolveVideoConfig({
|
|
3944
4079
|
calculateMetadata: composition.calculateMetadata ?? null,
|
|
3945
4080
|
signal: signal ?? new AbortController().signal,
|
|
3946
4081
|
defaultProps: composition.defaultProps ?? {},
|
|
@@ -3984,7 +4119,8 @@ async function internalRenderStillOnWeb({
|
|
|
3984
4119
|
scope: delayRenderScope,
|
|
3985
4120
|
signal,
|
|
3986
4121
|
apiName: "renderStillOnWeb",
|
|
3987
|
-
internalState: null
|
|
4122
|
+
internalState: null,
|
|
4123
|
+
keepalive: null
|
|
3988
4124
|
});
|
|
3989
4125
|
if (signal?.aborted) {
|
|
3990
4126
|
throw new Error("renderStillOnWeb() was cancelled");
|
|
@@ -4014,7 +4150,7 @@ async function internalRenderStillOnWeb({
|
|
|
4014
4150
|
licenseKey: licenseKey ?? null,
|
|
4015
4151
|
apiName: "renderStillOnWeb"
|
|
4016
4152
|
}).catch((err2) => {
|
|
4017
|
-
|
|
4153
|
+
Internals9.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
|
|
4018
4154
|
});
|
|
4019
4155
|
}
|
|
4020
4156
|
throw err;
|
package/dist/internal-state.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ type HelperCanvas = {
|
|
|
6
6
|
aPosition: number;
|
|
7
7
|
aTexCoord: number;
|
|
8
8
|
uTransform: WebGLUniformLocation | null;
|
|
9
|
-
|
|
9
|
+
uResolution: WebGLUniformLocation | null;
|
|
10
|
+
uOffset: WebGLUniformLocation | null;
|
|
10
11
|
uTexture: WebGLUniformLocation | null;
|
|
11
12
|
};
|
|
12
13
|
cleanup: () => void;
|
package/dist/wait-for-ready.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DelayRenderScope } from 'remotion';
|
|
2
|
-
|
|
2
|
+
import type { BackgroundKeepalive } from './background-keepalive';
|
|
3
|
+
export declare const waitForReady: ({ timeoutInMilliseconds, scope, signal, apiName, internalState, keepalive, }: {
|
|
3
4
|
timeoutInMilliseconds: number;
|
|
4
5
|
scope: DelayRenderScope;
|
|
5
6
|
signal: AbortSignal | null;
|
|
@@ -22,4 +23,5 @@ export declare const waitForReady: ({ timeoutInMilliseconds, scope, signal, apiN
|
|
|
22
23
|
getAudioMixingTime: () => number;
|
|
23
24
|
addAudioMixingTime: (time: number) => void;
|
|
24
25
|
} | null;
|
|
26
|
+
keepalive: BackgroundKeepalive | null;
|
|
25
27
|
}) => Promise<void>;
|
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.404",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"sideEffects": false,
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
"author": "Remotion <jonny@remotion.dev>",
|
|
19
19
|
"license": "UNLICENSED",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@remotion/licensing": "4.0.
|
|
22
|
-
"remotion": "4.0.
|
|
21
|
+
"@remotion/licensing": "4.0.404",
|
|
22
|
+
"remotion": "4.0.404",
|
|
23
23
|
"mediabunny": "1.27.3"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
27
|
-
"@remotion/player": "4.0.
|
|
28
|
-
"@remotion/media": "4.0.
|
|
26
|
+
"@remotion/eslint-config-internal": "4.0.404",
|
|
27
|
+
"@remotion/player": "4.0.404",
|
|
28
|
+
"@remotion/media": "4.0.404",
|
|
29
29
|
"@typescript/native-preview": "7.0.0-dev.20260105.1",
|
|
30
30
|
"@vitejs/plugin-react": "4.1.0",
|
|
31
31
|
"@vitest/browser-playwright": "4.0.9",
|