@remotion/web-renderer 4.0.374 → 4.0.375

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.
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ export declare class ErrorBoundary extends React.Component<{
3
+ onError: (error: Error) => void;
4
+ children: React.ReactNode;
5
+ }, {
6
+ hasError: Error | null;
7
+ }> {
8
+ state: {
9
+ hasError: null;
10
+ };
11
+ static getDerivedStateFromError(): {
12
+ hasError: boolean;
13
+ };
14
+ componentDidCatch(error: Error): void;
15
+ render(): React.ReactNode;
16
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ export class ErrorBoundary extends React.Component {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.state = { hasError: null };
6
+ }
7
+ static getDerivedStateFromError() {
8
+ // Update state so the next render will show the fallback UI.
9
+ return { hasError: true };
10
+ }
11
+ componentDidCatch(error) {
12
+ this.props.onError(error);
13
+ }
14
+ render() {
15
+ if (this.state.hasError) {
16
+ return null;
17
+ }
18
+ return this.props.children;
19
+ }
20
+ }
@@ -1,4 +1,5 @@
1
1
  // src/render-still-on-web.tsx
2
+ import { flushSync } from "react-dom";
2
3
  import ReactDOM from "react-dom/client";
3
4
  import { Internals } from "remotion";
4
5
 
@@ -83,13 +84,29 @@ var findSvgElements = (element) => {
83
84
  return composables;
84
85
  };
85
86
 
87
+ // src/with-resolvers.ts
88
+ var withResolvers = function() {
89
+ let resolve;
90
+ let reject;
91
+ const promise = new Promise((res, rej) => {
92
+ resolve = res;
93
+ reject = rej;
94
+ });
95
+ return { promise, resolve, reject };
96
+ };
97
+
86
98
  // src/wait-for-ready.ts
87
99
  var waitForReady = (timeoutInMilliseconds, scope) => {
88
- const { promise, resolve, reject } = Promise.withResolvers();
100
+ if (scope.remotion_renderReady === true) {
101
+ return Promise.resolve();
102
+ }
89
103
  const start = Date.now();
104
+ const { promise, resolve, reject } = withResolvers();
90
105
  const interval = setInterval(() => {
91
106
  if (scope.remotion_renderReady === true) {
92
- resolve(true);
107
+ requestAnimationFrame(() => {
108
+ resolve();
109
+ });
93
110
  clearInterval(interval);
94
111
  return;
95
112
  }
@@ -109,7 +126,7 @@ var waitForReady = (timeoutInMilliseconds, scope) => {
109
126
  // src/render-still-on-web.tsx
110
127
  import { jsx } from "react/jsx-runtime";
111
128
  var COMP_ID = "markup";
112
- var internalRenderStillOnWeb = async ({
129
+ async function internalRenderStillOnWeb({
113
130
  Component,
114
131
  width,
115
132
  height,
@@ -117,8 +134,9 @@ var internalRenderStillOnWeb = async ({
117
134
  durationInFrames,
118
135
  frame,
119
136
  delayRenderTimeoutInMilliseconds,
120
- logLevel
121
- }) => {
137
+ logLevel,
138
+ inputProps
139
+ }) {
122
140
  const div = document.createElement("div");
123
141
  div.style.display = "flex";
124
142
  div.style.backgroundColor = "transparent";
@@ -130,74 +148,87 @@ var internalRenderStillOnWeb = async ({
130
148
  if (!ReactDOM.createRoot) {
131
149
  throw new Error("@remotion/web-renderer requires React 18 or higher");
132
150
  }
133
- const root = ReactDOM.createRoot(div);
151
+ const { promise, resolve, reject } = withResolvers();
152
+ const root = ReactDOM.createRoot(div, {
153
+ onUncaughtError: (err) => {
154
+ reject(err);
155
+ }
156
+ });
134
157
  const delayRenderScope = {
135
158
  remotion_renderReady: true,
136
159
  remotion_delayRenderTimeouts: {},
137
160
  remotion_puppeteerTimeout: delayRenderTimeoutInMilliseconds,
138
161
  remotion_attempt: 0
139
162
  };
140
- root.render(/* @__PURE__ */ jsx(Internals.RemotionEnvironmentContext, {
141
- value: {
142
- isStudio: false,
143
- isRendering: true,
144
- isPlayer: false,
145
- isReadOnlyStudio: false,
146
- isClientSideRendering: true
147
- },
148
- children: /* @__PURE__ */ jsx(Internals.DelayRenderContextType.Provider, {
149
- value: delayRenderScope,
150
- children: /* @__PURE__ */ jsx(Internals.CompositionManagerProvider, {
151
- initialCanvasContent: {
152
- type: "composition",
153
- compositionId: COMP_ID
154
- },
155
- onlyRenderComposition: null,
156
- currentCompositionMetadata: {
157
- props: {},
158
- durationInFrames,
159
- fps,
160
- height,
161
- width,
162
- defaultCodec: null,
163
- defaultOutName: null,
164
- defaultVideoImageFormat: null,
165
- defaultPixelFormat: null,
166
- defaultProResProfile: null
167
- },
168
- initialCompositions: [
169
- {
170
- id: COMP_ID,
171
- component: Component,
172
- nonce: 0,
173
- defaultProps: undefined,
174
- folderName: null,
175
- parentFolderName: null,
176
- schema: null,
177
- calculateMetadata: null,
178
- durationInFrames,
179
- fps,
180
- height,
181
- width
182
- }
183
- ],
184
- children: /* @__PURE__ */ jsx(Internals.RemotionRoot, {
185
- audioEnabled: false,
186
- videoEnabled: true,
187
- logLevel,
188
- numberOfAudioTags: 0,
189
- audioLatencyHint: "interactive",
190
- frameState: {
191
- [COMP_ID]: frame
163
+ flushSync(() => {
164
+ root.render(/* @__PURE__ */ jsx(Internals.RemotionEnvironmentContext, {
165
+ value: {
166
+ isStudio: false,
167
+ isRendering: true,
168
+ isPlayer: false,
169
+ isReadOnlyStudio: false,
170
+ isClientSideRendering: true
171
+ },
172
+ children: /* @__PURE__ */ jsx(Internals.DelayRenderContextType.Provider, {
173
+ value: delayRenderScope,
174
+ children: /* @__PURE__ */ jsx(Internals.CompositionManager.Provider, {
175
+ value: {
176
+ compositions: [
177
+ {
178
+ id: COMP_ID,
179
+ component: Component,
180
+ nonce: 0,
181
+ defaultProps: undefined,
182
+ folderName: null,
183
+ parentFolderName: null,
184
+ schema: null,
185
+ calculateMetadata: null,
186
+ durationInFrames,
187
+ fps,
188
+ height,
189
+ width
190
+ }
191
+ ],
192
+ canvasContent: {
193
+ type: "composition",
194
+ compositionId: COMP_ID
195
+ },
196
+ currentCompositionMetadata: {
197
+ props: inputProps,
198
+ durationInFrames,
199
+ fps,
200
+ height,
201
+ width,
202
+ defaultCodec: null,
203
+ defaultOutName: null,
204
+ defaultVideoImageFormat: null,
205
+ defaultPixelFormat: null,
206
+ defaultProResProfile: null
207
+ },
208
+ folders: []
192
209
  },
193
- children: /* @__PURE__ */ jsx(Internals.CanUseRemotionHooks, {
194
- value: true,
195
- children: /* @__PURE__ */ jsx(Component, {})
210
+ children: /* @__PURE__ */ jsx(Internals.RemotionRoot, {
211
+ audioEnabled: false,
212
+ videoEnabled: true,
213
+ logLevel,
214
+ numberOfAudioTags: 0,
215
+ audioLatencyHint: "interactive",
216
+ frameState: {
217
+ [COMP_ID]: frame
218
+ },
219
+ children: /* @__PURE__ */ jsx(Internals.CanUseRemotionHooks, {
220
+ value: true,
221
+ children: /* @__PURE__ */ jsx(Component, {
222
+ ...inputProps
223
+ })
224
+ })
196
225
  })
197
226
  })
198
227
  })
199
- })
200
- }));
228
+ }));
229
+ });
230
+ resolve();
231
+ await promise;
201
232
  await waitForReady(delayRenderTimeoutInMilliseconds, delayRenderScope);
202
233
  const canvasElements = findCanvasElements(div);
203
234
  const svgElements = findSvgElements(div);
@@ -212,7 +243,7 @@ var internalRenderStillOnWeb = async ({
212
243
  root.unmount();
213
244
  div.remove();
214
245
  return imageData;
215
- };
246
+ }
216
247
  var renderStillOnWeb = (options) => {
217
248
  return internalRenderStillOnWeb({
218
249
  ...options,
@@ -1,17 +1,18 @@
1
1
  import { type ComponentType, type LazyExoticComponent } from 'react';
2
2
  import type { LogLevel } from 'remotion';
3
- type MandatoryRenderStillOnWebOptions = {
4
- Component: LazyExoticComponent<ComponentType<Record<string, unknown>>> | ComponentType<Record<string, unknown>>;
3
+ type MandatoryRenderStillOnWebOptions<T extends Record<string, unknown>> = {
4
+ Component: LazyExoticComponent<ComponentType<T>> | ComponentType<T>;
5
5
  width: number;
6
6
  height: number;
7
7
  fps: number;
8
8
  durationInFrames: number;
9
9
  frame: number;
10
+ inputProps: T;
10
11
  };
11
12
  type OptionalRenderStillOnWebOptions = {
12
13
  delayRenderTimeoutInMilliseconds: number;
13
14
  logLevel: LogLevel;
14
15
  };
15
- type RenderStillOnWebOptions = MandatoryRenderStillOnWebOptions & Partial<OptionalRenderStillOnWebOptions>;
16
- export declare const renderStillOnWeb: (options: RenderStillOnWebOptions) => Promise<Blob>;
16
+ type RenderStillOnWebOptions<T extends Record<string, unknown>> = MandatoryRenderStillOnWebOptions<T> & Partial<OptionalRenderStillOnWebOptions>;
17
+ export declare const renderStillOnWeb: <T extends Record<string, unknown>>(options: RenderStillOnWebOptions<T>) => Promise<Blob>;
17
18
  export {};
@@ -1,12 +1,14 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { flushSync } from 'react-dom';
2
3
  import ReactDOM from 'react-dom/client';
3
4
  import { Internals } from 'remotion';
4
5
  import { compose } from './compose';
5
6
  import { findCanvasElements } from './find-canvas-elements';
6
7
  import { findSvgElements } from './find-svg-elements';
7
8
  import { waitForReady } from './wait-for-ready';
9
+ import { withResolvers } from './with-resolvers';
8
10
  const COMP_ID = 'markup';
9
- const internalRenderStillOnWeb = async ({ Component, width, height, fps, durationInFrames, frame, delayRenderTimeoutInMilliseconds, logLevel, }) => {
11
+ async function internalRenderStillOnWeb({ Component, width, height, fps, durationInFrames, frame, delayRenderTimeoutInMilliseconds, logLevel, inputProps, }) {
10
12
  const div = document.createElement('div');
11
13
  // Match same behavior as renderEntry.tsx
12
14
  div.style.display = 'flex';
@@ -22,69 +24,73 @@ const internalRenderStillOnWeb = async ({ Component, width, height, fps, duratio
22
24
  // TODO: Env variables
23
25
  // TODO: Input Props
24
26
  // TODO: Default props
27
+ // TODO: getInputProps()
25
28
  // TODO: calculateMetadata()
26
29
  // TODO: getRemotionEnvironment()
27
30
  // TODO: delayRender()
28
31
  // TODO: Video config
29
- // TODO: window.remotion_isPlayer
30
- const root = ReactDOM.createRoot(div);
32
+ const { promise, resolve, reject } = withResolvers();
33
+ // TODO: This might not work in React 18
34
+ const root = ReactDOM.createRoot(div, {
35
+ onUncaughtError: (err) => {
36
+ reject(err);
37
+ },
38
+ });
31
39
  const delayRenderScope = {
32
40
  remotion_renderReady: true,
33
41
  remotion_delayRenderTimeouts: {},
34
42
  remotion_puppeteerTimeout: delayRenderTimeoutInMilliseconds,
35
43
  remotion_attempt: 0,
36
44
  };
37
- root.render(_jsx(Internals.RemotionEnvironmentContext, { value: {
38
- isStudio: false,
39
- isRendering: true,
40
- isPlayer: false,
41
- isReadOnlyStudio: false,
42
- isClientSideRendering: true,
43
- }, children: _jsx(Internals.DelayRenderContextType.Provider, { value: delayRenderScope, children: _jsx(Internals.CompositionManagerProvider, { initialCanvasContent: {
44
- type: 'composition',
45
- compositionId: COMP_ID,
46
- }, onlyRenderComposition: null,
47
- // TODO: Hardcoded
48
- currentCompositionMetadata: {
49
- // TODO: Empty
50
- props: {},
51
- durationInFrames,
52
- fps,
53
- height,
54
- width,
55
- defaultCodec: null,
56
- defaultOutName: null,
57
- defaultVideoImageFormat: null,
58
- defaultPixelFormat: null,
59
- defaultProResProfile: null,
60
- }, initialCompositions: [
61
- {
62
- id: COMP_ID,
63
- component: Component,
64
- nonce: 0,
65
- // TODO: Do we need to allow to set this?
66
- defaultProps: undefined,
67
- folderName: null,
68
- parentFolderName: null,
69
- schema: null,
70
- calculateMetadata: null,
71
- durationInFrames,
72
- fps,
73
- height,
74
- width,
75
- },
76
- ], children: _jsx(Internals.RemotionRoot
77
- // TODO: Hardcoded
78
- , {
79
- // TODO: Hardcoded
80
- audioEnabled: false,
81
- // TODO: Hardcoded
82
- videoEnabled: true, logLevel: logLevel, numberOfAudioTags: 0,
83
- // TODO: Hardcoded
84
- audioLatencyHint: "interactive", frameState: {
85
- [COMP_ID]: frame,
86
- }, children: _jsx(Internals.CanUseRemotionHooks, { value: true, children: _jsx(Component, {}) }) }) }) }) }));
87
- // TODO: Scope cancelRender()
45
+ flushSync(() => {
46
+ root.render(_jsx(Internals.RemotionEnvironmentContext, { value: {
47
+ isStudio: false,
48
+ isRendering: true,
49
+ isPlayer: false,
50
+ isReadOnlyStudio: false,
51
+ isClientSideRendering: true,
52
+ }, children: _jsx(Internals.DelayRenderContextType.Provider, { value: delayRenderScope, children: _jsx(Internals.CompositionManager.Provider, { value: {
53
+ compositions: [
54
+ {
55
+ id: COMP_ID,
56
+ // @ts-expect-error
57
+ component: Component,
58
+ nonce: 0,
59
+ // TODO: Do we need to allow to set this?
60
+ defaultProps: undefined,
61
+ folderName: null,
62
+ parentFolderName: null,
63
+ schema: null,
64
+ calculateMetadata: null,
65
+ durationInFrames,
66
+ fps,
67
+ height,
68
+ width,
69
+ },
70
+ ],
71
+ canvasContent: {
72
+ type: 'composition',
73
+ compositionId: COMP_ID,
74
+ },
75
+ currentCompositionMetadata: {
76
+ props: inputProps,
77
+ durationInFrames,
78
+ fps,
79
+ height,
80
+ width,
81
+ defaultCodec: null,
82
+ defaultOutName: null,
83
+ defaultVideoImageFormat: null,
84
+ defaultPixelFormat: null,
85
+ defaultProResProfile: null,
86
+ },
87
+ folders: [],
88
+ }, children: _jsx(Internals.RemotionRoot, { audioEnabled: false, videoEnabled: true, logLevel: logLevel, numberOfAudioTags: 0, audioLatencyHint: "interactive", frameState: {
89
+ [COMP_ID]: frame,
90
+ }, children: _jsx(Internals.CanUseRemotionHooks, { value: true, children: _jsx(Component, { ...inputProps }) }) }) }) }) }));
91
+ });
92
+ resolve();
93
+ await promise;
88
94
  await waitForReady(delayRenderTimeoutInMilliseconds, delayRenderScope);
89
95
  const canvasElements = findCanvasElements(div);
90
96
  const svgElements = findSvgElements(div);
@@ -99,7 +105,7 @@ const internalRenderStillOnWeb = async ({ Component, width, height, fps, duratio
99
105
  root.unmount();
100
106
  div.remove();
101
107
  return imageData;
102
- };
108
+ }
103
109
  export const renderStillOnWeb = (options) => {
104
110
  var _a, _b;
105
111
  return internalRenderStillOnWeb({
@@ -1,2 +1,2 @@
1
1
  import type { _InternalTypes } from 'remotion';
2
- export declare const waitForReady: (timeoutInMilliseconds: number, scope: _InternalTypes["DelayRenderScope"]) => Promise<unknown>;
2
+ export declare const waitForReady: (timeoutInMilliseconds: number, scope: _InternalTypes["DelayRenderScope"]) => Promise<void>;
@@ -1,9 +1,16 @@
1
+ import { withResolvers } from './with-resolvers';
1
2
  export const waitForReady = (timeoutInMilliseconds, scope) => {
2
- const { promise, resolve, reject } = Promise.withResolvers();
3
+ if (scope.remotion_renderReady === true) {
4
+ return Promise.resolve();
5
+ }
3
6
  const start = Date.now();
7
+ const { promise, resolve, reject } = withResolvers();
4
8
  const interval = setInterval(() => {
5
9
  if (scope.remotion_renderReady === true) {
6
- resolve(true);
10
+ // Wait for useEffects() to apply
11
+ requestAnimationFrame(() => {
12
+ resolve();
13
+ });
7
14
  clearInterval(interval);
8
15
  return;
9
16
  }
@@ -0,0 +1,10 @@
1
+ export interface WithResolvers<T> {
2
+ promise: Promise<T>;
3
+ resolve: (value: T | PromiseLike<T>) => void;
4
+ reject: (reason?: any) => void;
5
+ }
6
+ export declare const withResolvers: <T>() => {
7
+ promise: Promise<T>;
8
+ resolve: (value: T | PromiseLike<T>) => void;
9
+ reject: (reason?: any) => void;
10
+ };
@@ -0,0 +1,9 @@
1
+ export const withResolvers = function () {
2
+ let resolve;
3
+ let reject;
4
+ const promise = new Promise((res, rej) => {
5
+ resolve = res;
6
+ reject = rej;
7
+ });
8
+ return { promise, resolve: resolve, reject: reject };
9
+ };
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.374",
6
+ "version": "4.0.375",
7
7
  "main": "dist/index.js",
8
8
  "sideEffects": false,
9
9
  "scripts": {
@@ -15,10 +15,11 @@
15
15
  "author": "Remotion <jonny@remotion.dev>",
16
16
  "license": "UNLICENSED",
17
17
  "dependencies": {
18
- "remotion": "4.0.374"
18
+ "remotion": "4.0.375"
19
19
  },
20
20
  "devDependencies": {
21
- "@remotion/eslint-config-internal": "4.0.374",
21
+ "@remotion/eslint-config-internal": "4.0.375",
22
+ "@remotion/player": "4.0.375",
22
23
  "@vitejs/plugin-react": "^5.1.0",
23
24
  "@vitest/browser-webdriverio": "4.0.7",
24
25
  "eslint": "9.19.0",