remotion 4.0.462 → 4.0.464

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.
Files changed (59) hide show
  1. package/dist/cjs/CompositionManager.d.ts +1 -1
  2. package/dist/cjs/HtmlInCanvas.d.ts +8 -4
  3. package/dist/cjs/HtmlInCanvas.js +55 -46
  4. package/dist/cjs/Img.js +32 -18
  5. package/dist/cjs/Sequence.d.ts +1 -0
  6. package/dist/cjs/Sequence.js +10 -9
  7. package/dist/cjs/SequenceManager.d.ts +0 -5
  8. package/dist/cjs/SequenceManager.js +2 -15
  9. package/dist/cjs/animated-image/AnimatedImage.d.ts +10 -1
  10. package/dist/cjs/animated-image/AnimatedImage.js +70 -19
  11. package/dist/cjs/animated-image/canvas.d.ts +3 -1
  12. package/dist/cjs/animated-image/canvas.js +31 -10
  13. package/dist/cjs/animated-image/index.d.ts +1 -0
  14. package/dist/cjs/animated-image/props.d.ts +6 -0
  15. package/dist/cjs/audio/AudioForPreview.js +22 -21
  16. package/dist/cjs/audio/AudioForRendering.js +1 -1
  17. package/dist/cjs/audio/html5-audio.d.ts +2 -0
  18. package/dist/cjs/audio/html5-audio.js +5 -1
  19. package/dist/cjs/audio/props.d.ts +1 -0
  20. package/dist/cjs/effects/Solid.d.ts +11 -7
  21. package/dist/cjs/effects/Solid.js +53 -13
  22. package/dist/cjs/effects/canvas-pool.js +2 -1
  23. package/dist/cjs/effects/create-effect.d.ts +3 -3
  24. package/dist/cjs/effects/create-effect.js +37 -10
  25. package/dist/cjs/effects/effect-types.d.ts +8 -2
  26. package/dist/cjs/effects/index.d.ts +1 -1
  27. package/dist/cjs/effects/run-effect-chain.d.ts +4 -3
  28. package/dist/cjs/effects/run-effect-chain.js +7 -3
  29. package/dist/cjs/effects/webgl2-context-error.d.ts +3 -0
  30. package/dist/cjs/effects/webgl2-context-error.js +13 -0
  31. package/dist/cjs/index.d.ts +6 -2
  32. package/dist/cjs/index.js +7 -3
  33. package/dist/cjs/internals.d.ts +76 -22
  34. package/dist/cjs/internals.js +9 -3
  35. package/dist/cjs/no-react.d.ts +17 -16
  36. package/dist/cjs/sequence-field-schema.d.ts +68 -18
  37. package/dist/cjs/sequence-field-schema.js +14 -2
  38. package/dist/cjs/series/index.d.ts +1 -1
  39. package/dist/cjs/use-media-in-timeline.d.ts +4 -4
  40. package/dist/cjs/use-media-in-timeline.js +6 -6
  41. package/dist/cjs/use-media-playback.d.ts +2 -1
  42. package/dist/cjs/use-media-playback.js +5 -2
  43. package/dist/cjs/validate-media-props.d.ts +1 -0
  44. package/dist/cjs/validate-media-props.js +4 -0
  45. package/dist/cjs/version.d.ts +1 -1
  46. package/dist/cjs/version.js +1 -1
  47. package/dist/cjs/video/OffthreadVideo.js +2 -2
  48. package/dist/cjs/video/OffthreadVideoForRendering.js +1 -1
  49. package/dist/cjs/video/VideoForPreview.js +13 -14
  50. package/dist/cjs/video/VideoForRendering.js +1 -1
  51. package/dist/cjs/video/html5-video.d.ts +2 -0
  52. package/dist/cjs/video/html5-video.js +5 -1
  53. package/dist/cjs/video/props.d.ts +2 -0
  54. package/dist/esm/index.mjs +1614 -1351
  55. package/dist/esm/no-react.mjs +14 -2
  56. package/dist/esm/version.mjs +1 -1
  57. package/package.json +2 -2
  58. package/dist/cjs/effects/define-effect.d.ts +0 -3
  59. package/dist/cjs/effects/define-effect.js +0 -31
@@ -65,7 +65,7 @@ export type TSequence = {
65
65
  showInTimeline: boolean;
66
66
  nonce: NonceHistory;
67
67
  loopDisplay: LoopDisplay | undefined;
68
- stack: string | null;
68
+ getStack: () => string | null;
69
69
  premountDisplay: number | null;
70
70
  postmountDisplay: number | null;
71
71
  controls: SequenceControls | null;
@@ -14,10 +14,10 @@ declare global {
14
14
  drawElementImage(element: Element | ElementImage, sx: number, sy: number, swidth: number, sheight: number, dx: number, dy: number, dwidth: number, dheight: number): DOMMatrix;
15
15
  }
16
16
  interface OffscreenCanvasRenderingContext2D {
17
- drawElementImage(element: ElementImage, dx: number, dy: number): DOMMatrix;
18
- drawElementImage(element: ElementImage, dx: number, dy: number, dwidth: number, dheight: number): DOMMatrix;
19
- drawElementImage(element: ElementImage, sx: number, sy: number, swidth: number, sheight: number, dx: number, dy: number): DOMMatrix;
20
- drawElementImage(element: ElementImage, sx: number, sy: number, swidth: number, sheight: number, dx: number, dy: number, dwidth: number, dheight: number): DOMMatrix;
17
+ drawElementImage(element: Element | ElementImage, dx: number, dy: number): DOMMatrix;
18
+ drawElementImage(element: Element | ElementImage, dx: number, dy: number, dwidth: number, dheight: number): DOMMatrix;
19
+ drawElementImage(element: Element | ElementImage, sx: number, sy: number, swidth: number, sheight: number, dx: number, dy: number): DOMMatrix;
20
+ drawElementImage(element: Element | ElementImage, sx: number, sy: number, swidth: number, sheight: number, dx: number, dy: number, dwidth: number, dheight: number): DOMMatrix;
21
21
  }
22
22
  interface WebGLRenderingContextBase {
23
23
  texElementImage2D(target: GLenum, level: GLint, internalformat: GLint, format: GLenum, type: GLenum, element: Element | ElementImage): void;
@@ -37,6 +37,10 @@ declare global {
37
37
  }
38
38
  }
39
39
  export type HtmlInCanvasOnPaintParams = {
40
+ /**
41
+ * The `OffscreenCanvas` from {@link HTMLCanvasElement.transferControlToOffscreen}
42
+ * on the layout `<canvas>` (same logical canvas as the forwarded ref).
43
+ */
40
44
  readonly canvas: OffscreenCanvas;
41
45
  readonly element: HTMLDivElement;
42
46
  readonly elementImage: ElementImage;
@@ -10,7 +10,6 @@ const use_memoized_effects_js_1 = require("./effects/use-memoized-effects.js");
10
10
  const enable_sequence_stack_traces_js_1 = require("./enable-sequence-stack-traces.js");
11
11
  const sequence_field_schema_js_1 = require("./sequence-field-schema.js");
12
12
  const Sequence_js_1 = require("./Sequence.js");
13
- const use_current_frame_js_1 = require("./use-current-frame.js");
14
13
  const use_delay_render_js_1 = require("./use-delay-render.js");
15
14
  const use_video_config_js_1 = require("./use-video-config.js");
16
15
  const wrap_in_schema_js_1 = require("./wrap-in-schema.js");
@@ -30,7 +29,8 @@ const isHtmlInCanvasSupported = () => {
30
29
  cachedSupport =
31
30
  typeof (ctx === null || ctx === void 0 ? void 0 : ctx.drawElementImage) === 'function' &&
32
31
  typeof canvas.requestPaint === 'function' &&
33
- typeof canvas.captureElementImage === 'function';
32
+ typeof canvas.captureElementImage === 'function' &&
33
+ 'transferControlToOffscreen' in HTMLCanvasElement.prototype;
34
34
  return cachedSupport;
35
35
  };
36
36
  exports.isHtmlInCanvasSupported = isHtmlInCanvasSupported;
@@ -58,7 +58,7 @@ const defaultOnPaint = ({ canvas, element, elementImage, }) => {
58
58
  };
59
59
  /* eslint-enable react/require-default-props */
60
60
  const HtmlInCanvasAncestorContext = (0, react_1.createContext)(false);
61
- const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimentalEffects: effects = [], children, onPaint, onInit, _experimentalControls: controls, style, durationInFrames, ...sequenceProps }, ref) => {
61
+ const HtmlInCanvasContent = (0, react_1.forwardRef)(({ width, height, effects, children, onPaint, onInit, controls, style }, ref) => {
62
62
  var _a;
63
63
  const isInsideAncestorHtmlInCanvas = (0, react_1.useContext)(HtmlInCanvasAncestorContext);
64
64
  assertHtmlInCanvasDimensions(width, height);
@@ -66,11 +66,10 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
66
66
  if (!(0, exports.isHtmlInCanvasSupported)()) {
67
67
  cancelRender(new Error(exports.HTML_IN_CANVAS_UNSUPPORTED_MESSAGE));
68
68
  }
69
- const { durationInFrames: videoDuration } = (0, use_video_config_js_1.useVideoConfig)();
70
- const resolvedDuration = durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : videoDuration;
71
- const frame = (0, use_current_frame_js_1.useCurrentFrame)();
72
69
  const canvas2dRef = (0, react_1.useRef)(null);
70
+ const offscreenRef = (0, react_1.useRef)(null);
73
71
  const divRef = (0, react_1.useRef)(null);
72
+ const canvasSizeKey = `${width}x${height}`;
74
73
  const setLayoutCanvasRef = (0, react_1.useCallback)((node) => {
75
74
  canvas2dRef.current = node;
76
75
  if (typeof ref === 'function') {
@@ -81,18 +80,14 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
81
80
  node;
82
81
  }
83
82
  }, [ref]);
84
- const [offscreenCanvas] = (0, react_1.useState)(() => new OffscreenCanvas(1, 1));
85
83
  const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)();
86
84
  const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
87
85
  effects,
88
86
  overrideId: (_a = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _a !== void 0 ? _a : null,
89
87
  });
90
- const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
91
88
  // Refs so the paint handler always reads fresh values.
92
89
  const effectsRef = (0, react_1.useRef)(memoizedEffects);
93
90
  effectsRef.current = memoizedEffects;
94
- const frameRef = (0, react_1.useRef)(frame);
95
- frameRef.current = frame;
96
91
  const onPaintRef = (0, react_1.useRef)(onPaint);
97
92
  onPaintRef.current = onPaint;
98
93
  const onInitRef = (0, react_1.useRef)(onInit);
@@ -106,19 +101,23 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
106
101
  if (!element) {
107
102
  throw new Error('Canvas or scene element not found');
108
103
  }
109
- offscreenCanvas.width = width;
110
- offscreenCanvas.height = height;
104
+ const offscreen = offscreenRef.current;
105
+ if (!offscreen) {
106
+ throw new Error('HtmlInCanvas: offscreen canvas not ready (transferControlToOffscreen failed or canvas is remounting)');
107
+ }
108
+ offscreen.width = width;
109
+ offscreen.height = height;
111
110
  try {
112
- const layoutCanvas = canvas2dRef.current;
113
- if (!layoutCanvas) {
111
+ const placeholderCanvas = canvas2dRef.current;
112
+ if (!placeholderCanvas) {
114
113
  throw new Error('Canvas not found');
115
114
  }
116
115
  // `GPUQueue.copyElementImageToTexture` / related paths validate the
117
- // layout canvas has a rendering context. `runEffectChain` only runs
118
- // after `onPaint`, so acquire `2d` here before any capture or handler.
119
- const layout2d = layoutCanvas.getContext('2d');
120
- if (!layout2d) {
121
- throw new Error('Failed to acquire 2D context for <HtmlInCanvas> layout canvas');
116
+ // linked offscreen surface has a rendering context. Acquire `2d` here
117
+ // before any capture or handler (must not call getContext on placeholder).
118
+ const offscreen2d = offscreen.getContext('2d');
119
+ if (!offscreen2d) {
120
+ throw new Error('Failed to acquire 2D context for <HtmlInCanvas> offscreen canvas');
122
121
  }
123
122
  const handle = (0, delay_render_js_1.delayRender)('onPaint');
124
123
  if (!initializedRef.current) {
@@ -129,11 +128,11 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
129
128
  // can invalidate the capture's paint context, leaving subsequent
130
129
  // uploads (e.g. `copyElementImageToTexture`) failing with
131
130
  // "No context found for ElementImage" on the very first paint.
132
- const initImage = layoutCanvas.captureElementImage(element);
131
+ const initImage = placeholderCanvas.captureElementImage(element);
133
132
  const currentOnInit = onInitRef.current;
134
133
  if (currentOnInit) {
135
134
  const cleanup = await currentOnInit({
136
- canvas: offscreenCanvas,
135
+ canvas: offscreen,
137
136
  element,
138
137
  elementImage: initImage,
139
138
  });
@@ -149,18 +148,17 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
149
148
  }
150
149
  }
151
150
  const handler = (_a = onPaintRef.current) !== null && _a !== void 0 ? _a : defaultOnPaint;
152
- const elImage = layoutCanvas.captureElementImage(element);
151
+ const elImage = placeholderCanvas.captureElementImage(element);
153
152
  await handler({
154
- canvas: offscreenCanvas,
153
+ canvas: offscreen,
155
154
  element,
156
155
  elementImage: elImage,
157
156
  });
158
157
  await (0, run_effect_chain_js_1.runEffectChain)({
159
158
  state: chainState.get(width, height),
160
- source: offscreenCanvas,
159
+ source: offscreen,
161
160
  effects: effectsRef.current,
162
- output: canvas2dRef.current,
163
- frame: frameRef.current,
161
+ output: offscreen,
164
162
  width,
165
163
  height,
166
164
  });
@@ -169,32 +167,32 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
169
167
  catch (error) {
170
168
  cancelRender(error);
171
169
  }
172
- }, [
173
- chainState,
174
- continueRender,
175
- cancelRender,
176
- width,
177
- height,
178
- offscreenCanvas,
179
- ]);
180
- // Set up layoutSubtree and persistent paint listener. Runs as a
181
- // layout effect so the listener is attached before the resize effect
182
- // below dispatches its first synthetic paint.
170
+ }, [chainState, continueRender, cancelRender, width, height]);
171
+ // Transfer control once per layout canvas instance, then listen for paint on
172
+ // the placeholder (capture) while drawing on the linked offscreen surface.
183
173
  (0, react_1.useLayoutEffect)(() => {
184
- const canvas = canvas2dRef.current;
185
- if (!canvas) {
174
+ const placeholder = canvas2dRef.current;
175
+ if (!placeholder) {
186
176
  throw new Error('Canvas not found');
187
177
  }
188
- canvas.layoutSubtree = true;
189
- canvas.addEventListener('paint', onPaintCb);
178
+ placeholder.layoutSubtree = true;
179
+ const offscreen = placeholder.transferControlToOffscreen();
180
+ offscreenRef.current = offscreen;
181
+ offscreen.width = width;
182
+ offscreen.height = height;
183
+ initializedRef.current = false;
184
+ unmountedRef.current = false;
185
+ placeholder.addEventListener('paint', onPaintCb);
190
186
  return () => {
191
187
  var _a;
192
- canvas.removeEventListener('paint', onPaintCb);
188
+ placeholder.removeEventListener('paint', onPaintCb);
189
+ offscreenRef.current = null;
190
+ initializedRef.current = false;
193
191
  unmountedRef.current = true;
194
192
  (_a = onInitCleanupRef.current) === null || _a === void 0 ? void 0 : _a.call(onInitCleanupRef);
195
193
  onInitCleanupRef.current = null;
196
194
  };
197
- }, [onPaintCb, cancelRender]);
195
+ }, [onPaintCb, cancelRender, width, height]);
198
196
  const onPaintChangedRef = (0, react_1.useRef)(false);
199
197
  (0, react_1.useLayoutEffect)(() => {
200
198
  var _a;
@@ -220,7 +218,7 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
220
218
  return () => {
221
219
  continueRender(handle);
222
220
  };
223
- }, [width, height, continueRender]);
221
+ }, [width, height, continueRender, canvasSizeKey]);
224
222
  const innerStyle = (0, react_1.useMemo)(() => {
225
223
  return {
226
224
  width,
@@ -230,10 +228,21 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
230
228
  if (isInsideAncestorHtmlInCanvas) {
231
229
  throw new Error('<HtmlInCanvas> effects cannot be nested together. Chrome will only display the outer effect. Consider merging the effects into one if you can.');
232
230
  }
233
- return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { durationInFrames: resolvedDuration, name: "<HtmlInCanvas>", _experimentalControls: controls, _experimentalEffects: memoizedEffectDefinitions, layout: "none", ...sequenceProps, children: (0, jsx_runtime_1.jsx)(HtmlInCanvasAncestorContext.Provider, { value: true, children: (0, jsx_runtime_1.jsx)("canvas", { ref: setLayoutCanvasRef, width: width, height: height, style: style, children: (0, jsx_runtime_1.jsx)("div", { ref: divRef, style: innerStyle, children: children }) }) }) }));
231
+ return ((0, jsx_runtime_1.jsx)(HtmlInCanvasAncestorContext.Provider, { value: true, children: (0, jsx_runtime_1.jsx)("canvas", { ref: setLayoutCanvasRef, width: width, height: height, style: style, children: (0, jsx_runtime_1.jsx)("div", { ref: divRef, style: innerStyle, children: children }) }, canvasSizeKey) }));
232
+ });
233
+ HtmlInCanvasContent.displayName = 'HtmlInCanvasContent';
234
+ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimentalEffects: effects = [], children, onPaint, onInit, _experimentalControls: controls, style, durationInFrames, name, ...sequenceProps }, ref) => {
235
+ const { durationInFrames: videoDuration } = (0, use_video_config_js_1.useVideoConfig)();
236
+ const resolvedDuration = durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : videoDuration;
237
+ const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
238
+ return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { durationInFrames: resolvedDuration, name: name !== null && name !== void 0 ? name : '<HtmlInCanvas>', _experimentalControls: controls, _experimentalEffects: memoizedEffectDefinitions, layout: "none", ...sequenceProps, children: (0, jsx_runtime_1.jsx)(HtmlInCanvasContent, { ref: ref, width: width, height: height, effects: effects, onPaint: onPaint, onInit: onInit, controls: controls, style: style, children: children }) }));
234
239
  });
235
240
  HtmlInCanvasInner.displayName = 'HtmlInCanvas';
236
- const HtmlInCanvasWrapped = (0, wrap_in_schema_js_1.wrapInSchema)(HtmlInCanvasInner, sequence_field_schema_js_1.sequenceStyleSchema);
241
+ const htmlInCanvasSchema = {
242
+ ...sequence_field_schema_js_1.sequenceVisualStyleSchema,
243
+ hidden: sequence_field_schema_js_1.hiddenField,
244
+ };
245
+ const HtmlInCanvasWrapped = (0, wrap_in_schema_js_1.wrapInSchema)(HtmlInCanvasInner, htmlInCanvasSchema);
237
246
  exports.HtmlInCanvas = Object.assign(HtmlInCanvasWrapped, {
238
247
  isSupported: exports.isHtmlInCanvasSupported,
239
248
  });
package/dist/cjs/Img.js CHANGED
@@ -25,16 +25,11 @@ function truncateSrcForLabel(src) {
25
25
  }
26
26
  return src;
27
27
  }
28
- const ImgInner = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRenderRetries, delayRenderTimeoutInMilliseconds, onImageFrame, crossOrigin, showInTimeline, name, stack, ref, _experimentalControls: controls, ...props }) => {
29
- var _a, _b;
28
+ const ImgContent = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRenderRetries, delayRenderTimeoutInMilliseconds, onImageFrame, crossOrigin, ref, ...props }) => {
30
29
  const imageRef = (0, react_1.useRef)(null);
31
30
  const errors = (0, react_1.useRef)({});
32
31
  const { delayPlayback } = (0, use_buffer_state_js_1.useBufferState)();
33
32
  const sequenceContext = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
34
- const [timelineId] = (0, react_1.useState)(() => String(Math.random()));
35
- if (!src) {
36
- throw new Error('No "src" prop was passed to <Img>.');
37
- }
38
33
  const _propsValid = true;
39
34
  if (!_propsValid) {
40
35
  throw new Error('typecheck error');
@@ -42,17 +37,6 @@ const ImgInner = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRenderR
42
37
  (0, react_1.useImperativeHandle)(ref, () => {
43
38
  return imageRef.current;
44
39
  }, []);
45
- (0, use_media_in_timeline_js_1.useImageInTimeline)({
46
- src,
47
- displayName: name !== null && name !== void 0 ? name : null,
48
- id: timelineId,
49
- stack: stack !== null && stack !== void 0 ? stack : null,
50
- showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true,
51
- premountDisplay: (_a = sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premountDisplay) !== null && _a !== void 0 ? _a : null,
52
- postmountDisplay: (_b = sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmountDisplay) !== null && _b !== void 0 ? _b : null,
53
- loopDisplay: undefined,
54
- controls: controls !== null && controls !== void 0 ? controls : null,
55
- });
56
40
  const actualSrc = (0, prefetch_js_1.usePreload)(src);
57
41
  const retryIn = (0, react_1.useCallback)((timeout) => {
58
42
  if (!imageRef.current) {
@@ -197,9 +181,39 @@ const ImgInner = ({ onError, maxRetries = 2, src, pauseWhenLoading, delayRenderR
197
181
  // src gets set once we've loaded and decoded the image.
198
182
  return ((0, jsx_runtime_1.jsx)("img", { ...props, ref: imageRef, crossOrigin: crossOriginValue, onError: didGetError, decoding: "sync" }));
199
183
  };
184
+ const ImgInner = ({ hidden, name, stack, showInTimeline, src, _experimentalControls: controls, ...props }) => {
185
+ var _a, _b;
186
+ const sequenceContext = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
187
+ const [timelineId] = (0, react_1.useState)(() => String(Math.random()));
188
+ if (!src) {
189
+ throw new Error('No "src" prop was passed to <Img>.');
190
+ }
191
+ const stackRef = (0, react_1.useRef)(null);
192
+ stackRef.current = stack !== null && stack !== void 0 ? stack : null;
193
+ const getStack = (0, react_1.useCallback)(() => stackRef.current, []);
194
+ (0, use_media_in_timeline_js_1.useImageInTimeline)({
195
+ src,
196
+ displayName: name !== null && name !== void 0 ? name : null,
197
+ id: timelineId,
198
+ getStack,
199
+ showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true,
200
+ premountDisplay: (_a = sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premountDisplay) !== null && _a !== void 0 ? _a : null,
201
+ postmountDisplay: (_b = sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmountDisplay) !== null && _b !== void 0 ? _b : null,
202
+ loopDisplay: undefined,
203
+ controls: controls !== null && controls !== void 0 ? controls : null,
204
+ });
205
+ if (hidden) {
206
+ return null;
207
+ }
208
+ return (0, jsx_runtime_1.jsx)(ImgContent, { src: src, ...props });
209
+ };
210
+ const imgSchema = {
211
+ ...sequence_field_schema_js_1.sequenceVisualStyleSchema,
212
+ hidden: sequence_field_schema_js_1.hiddenField,
213
+ };
200
214
  /*
201
215
  * @description Works just like a regular HTML img tag. When you use the <Img> tag, Remotion will ensure that the image is loaded before rendering the frame.
202
216
  * @see [Documentation](https://remotion.dev/docs/img)
203
217
  */
204
- exports.Img = (0, wrap_in_schema_js_1.wrapInSchema)(ImgInner, sequence_field_schema_js_1.sequenceStyleSchema);
218
+ exports.Img = (0, wrap_in_schema_js_1.wrapInSchema)(ImgInner, imgSchema);
205
219
  (0, enable_sequence_stack_traces_js_1.addSequenceStackTraces)(exports.Img);
@@ -21,6 +21,7 @@ export type SequencePropsWithoutDuration = {
21
21
  readonly from?: number;
22
22
  readonly name?: string;
23
23
  readonly showInTimeline?: boolean;
24
+ readonly hidden?: boolean;
24
25
  readonly _experimentalControls?: SequenceControls;
25
26
  readonly _experimentalEffects?: readonly EffectDefinition<unknown>[];
26
27
  /**
@@ -4,6 +4,7 @@ exports.Sequence = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  /* eslint-disable @typescript-eslint/no-use-before-define */
6
6
  const react_1 = require("react");
7
+ const react_2 = require("react");
7
8
  const AbsoluteFill_js_1 = require("./AbsoluteFill.js");
8
9
  const freeze_js_1 = require("./freeze.js");
9
10
  const nonce_js_1 = require("./nonce.js");
@@ -17,8 +18,8 @@ const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
17
18
  const use_video_config_js_1 = require("./use-video-config.js");
18
19
  const v5_flag_js_1 = require("./v5-flag.js");
19
20
  const wrap_in_schema_js_1 = require("./wrap-in-schema.js");
20
- const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Infinity, children, name, height, width, showInTimeline = true, _experimentalControls: controls, _experimentalEffects, _remotionInternalLoopDisplay: loopDisplay, _remotionInternalStack: stack, _remotionInternalPremountDisplay: premountDisplay, _remotionInternalPostmountDisplay: postmountDisplay, _remotionInternalIsMedia: isMedia, ...other }, ref) => {
21
- var _a, _b;
21
+ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Infinity, children, name, height, width, showInTimeline = true, hidden = false, _experimentalControls: controls, _experimentalEffects, _remotionInternalLoopDisplay: loopDisplay, _remotionInternalStack: stack, _remotionInternalPremountDisplay: premountDisplay, _remotionInternalPostmountDisplay: postmountDisplay, _remotionInternalIsMedia: isMedia, ...other }, ref) => {
22
+ var _a;
22
23
  const { layout = 'absolute-fill' } = other;
23
24
  const [id] = (0, react_1.useState)(() => String(Math.random()));
24
25
  const parentSequence = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
@@ -55,7 +56,6 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
55
56
  : durationInFrames;
56
57
  const actualDurationInFrames = Math.max(0, Math.min(videoConfig.durationInFrames - from, parentSequenceDuration));
57
58
  const { registerSequence, unregisterSequence } = (0, react_1.useContext)(SequenceManager_js_1.SequenceManager);
58
- const { hidden } = (0, react_1.useContext)(SequenceManager_js_1.SequenceVisibilityToggleContext);
59
59
  const premounting = (0, react_1.useMemo)(() => {
60
60
  // || is intentional, ?? would not trigger on `false`
61
61
  return ((parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.premounting) ||
@@ -99,6 +99,10 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
99
99
  }, [name]);
100
100
  const env = (0, use_remotion_environment_js_1.useRemotionEnvironment)();
101
101
  const inheritedStack = (_a = other === null || other === void 0 ? void 0 : other.stack) !== null && _a !== void 0 ? _a : null;
102
+ // Our assumption: Stack doesnt' change. After we symbolicate we assign it a nodePath
103
+ // and if it changes, it would lead to-remounting of the sequence.
104
+ const stackRef = (0, react_2.useRef)(null);
105
+ stackRef.current = stack !== null && stack !== void 0 ? stack : inheritedStack;
102
106
  (0, react_1.useEffect)(() => {
103
107
  var _a, _b;
104
108
  if (!env.isStudio) {
@@ -123,7 +127,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
123
127
  rootId,
124
128
  showInTimeline,
125
129
  src: isMedia.data.src,
126
- stack: stack !== null && stack !== void 0 ? stack : inheritedStack,
130
+ getStack: () => stackRef.current,
127
131
  startMediaFrom: isMedia.data.startMediaFrom,
128
132
  volume: isMedia.data.volumes,
129
133
  });
@@ -142,7 +146,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
142
146
  showInTimeline,
143
147
  nonce: nonce.get(),
144
148
  loopDisplay,
145
- stack: stack !== null && stack !== void 0 ? stack : inheritedStack,
149
+ getStack: () => stackRef.current,
146
150
  premountDisplay: premountDisplay !== null && premountDisplay !== void 0 ? premountDisplay : null,
147
151
  postmountDisplay: postmountDisplay !== null && postmountDisplay !== void 0 ? postmountDisplay : null,
148
152
  controls: controls !== null && controls !== void 0 ? controls : null,
@@ -165,11 +169,9 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
165
169
  showInTimeline,
166
170
  nonce,
167
171
  loopDisplay,
168
- stack,
169
172
  premountDisplay,
170
173
  postmountDisplay,
171
174
  env.isStudio,
172
- inheritedStack,
173
175
  controls,
174
176
  _experimentalEffects,
175
177
  isMedia,
@@ -194,8 +196,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
194
196
  if (ref !== null && layout === 'none') {
195
197
  throw new TypeError('It is not supported to pass both a `ref` and `layout="none"` to <Sequence />.');
196
198
  }
197
- const isSequenceHidden = (_b = hidden[id]) !== null && _b !== void 0 ? _b : false;
198
- if (isSequenceHidden) {
199
+ if (hidden) {
199
200
  return null;
200
201
  }
201
202
  return ((0, jsx_runtime_1.jsx)(SequenceContext_js_1.SequenceContext.Provider, { value: contextValue, children: content === null ? null : other.layout === 'none' ? (content) : ((0, jsx_runtime_1.jsx)(AbsoluteFill_js_1.AbsoluteFill, { ref: ref, style: defaultStyle, className: other.className, children: content })) }));
@@ -8,11 +8,6 @@ export type SequenceManagerContext = {
8
8
  };
9
9
  export type SequenceNodePath = Array<string | number>;
10
10
  export declare const SequenceManager: React.Context<SequenceManagerContext>;
11
- export type SequenceVisibilityToggleState = {
12
- hidden: Record<string, boolean>;
13
- setHidden: React.Dispatch<React.SetStateAction<Record<string, boolean>>>;
14
- };
15
- export declare const SequenceVisibilityToggleContext: React.Context<SequenceVisibilityToggleState>;
16
11
  export type VisualModeCodeValues = {
17
12
  codeValues: CodeValues;
18
13
  };
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SequenceManagerProvider = exports.VisualModeSettersContext = exports.VisualModeDragOverridesContext = exports.VisualModeCodeValuesContext = exports.makeSequencePropsSubscriptionKey = exports.SequenceVisibilityToggleContext = exports.SequenceManager = void 0;
36
+ exports.SequenceManagerProvider = exports.VisualModeSettersContext = exports.VisualModeDragOverridesContext = exports.VisualModeCodeValuesContext = exports.makeSequencePropsSubscriptionKey = exports.SequenceManager = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  exports.SequenceManager = react_1.default.createContext({
@@ -45,12 +45,6 @@ exports.SequenceManager = react_1.default.createContext({
45
45
  },
46
46
  sequences: [],
47
47
  });
48
- exports.SequenceVisibilityToggleContext = react_1.default.createContext({
49
- hidden: {},
50
- setHidden: () => {
51
- throw new Error('SequenceVisibilityToggle not initialized');
52
- },
53
- });
54
48
  const makeSequencePropsSubscriptionKey = (key) => {
55
49
  return `${key.nodePath.join('.')}.${key.sequenceKeys.join('.')}.${key.effectKeys.map((keys) => keys.join('.')).join('.')}`;
56
50
  };
@@ -86,7 +80,6 @@ exports.VisualModeSettersContext = react_1.default.createContext({
86
80
  const effectDragOverridesKey = (nodePath, effectIndex) => `${(0, exports.makeSequencePropsSubscriptionKey)(nodePath)}.effects.${effectIndex}`;
87
81
  const SequenceManagerProvider = ({ children }) => {
88
82
  const [sequences, setSequences] = (0, react_1.useState)([]);
89
- const [hidden, setHidden] = (0, react_1.useState)({});
90
83
  const [dragOverrides, setControlOverrides] = (0, react_1.useState)({});
91
84
  const controlOverridesRef = (0, react_1.useRef)(dragOverrides);
92
85
  controlOverridesRef.current = dragOverrides;
@@ -161,12 +154,6 @@ const SequenceManagerProvider = ({ children }) => {
161
154
  unregisterSequence,
162
155
  };
163
156
  }, [registerSequence, sequences, unregisterSequence]);
164
- const hiddenContext = (0, react_1.useMemo)(() => {
165
- return {
166
- hidden,
167
- setHidden,
168
- };
169
- }, [hidden]);
170
157
  const getDragOverrides = (0, react_1.useCallback)((nodePath) => {
171
158
  var _a;
172
159
  return (_a = dragOverrides[(0, exports.makeSequencePropsSubscriptionKey)(nodePath)]) !== null && _a !== void 0 ? _a : {};
@@ -201,6 +188,6 @@ const SequenceManagerProvider = ({ children }) => {
201
188
  clearEffectDragOverrides,
202
189
  setCodeValues,
203
190
  ]);
204
- return ((0, jsx_runtime_1.jsx)(exports.SequenceManager.Provider, { value: sequenceContext, children: (0, jsx_runtime_1.jsx)(exports.SequenceVisibilityToggleContext.Provider, { value: hiddenContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeCodeValuesContext.Provider, { value: codeValuesContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeDragOverridesContext.Provider, { value: dragOverridesContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeSettersContext.Provider, { value: settersContext, children: children }) }) }) }) }));
191
+ return ((0, jsx_runtime_1.jsx)(exports.SequenceManager.Provider, { value: sequenceContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeCodeValuesContext.Provider, { value: codeValuesContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeDragOverridesContext.Provider, { value: dragOverridesContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeSettersContext.Provider, { value: settersContext, children: children }) }) }) }));
205
192
  };
206
193
  exports.SequenceManagerProvider = SequenceManagerProvider;
@@ -1,2 +1,11 @@
1
+ import type React from 'react';
2
+ import type { SequenceControls } from '../CompositionManager.js';
3
+ import type { EffectsProp } from '../effects/effect-types.js';
1
4
  import type { RemotionAnimatedImageProps } from './props';
2
- export declare const AnimatedImage: import("react").ForwardRefExoticComponent<RemotionAnimatedImageProps & import("react").RefAttributes<HTMLCanvasElement>>;
5
+ export declare const AnimatedImage: React.ComponentType<Omit<import("../Sequence.js").SequenceProps, "children" | "layout" | "durationInFrames" | "_experimentalEffects"> & RemotionAnimatedImageProps & {
6
+ readonly durationInFrames?: number;
7
+ readonly _experimentalEffects?: EffectsProp;
8
+ } & {
9
+ readonly _experimentalControls?: SequenceControls | undefined;
10
+ readonly ref?: React.Ref<HTMLCanvasElement>;
11
+ }>;
@@ -4,21 +4,31 @@ exports.AnimatedImage = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const cancel_render_js_1 = require("../cancel-render.js");
7
+ const use_memoized_effects_js_1 = require("../effects/use-memoized-effects.js");
8
+ const enable_sequence_stack_traces_js_1 = require("../enable-sequence-stack-traces.js");
9
+ const sequence_field_schema_js_1 = require("../sequence-field-schema.js");
10
+ const Sequence_js_1 = require("../Sequence.js");
7
11
  const use_current_frame_js_1 = require("../use-current-frame.js");
8
12
  const use_delay_render_js_1 = require("../use-delay-render.js");
9
13
  const use_video_config_js_1 = require("../use-video-config.js");
14
+ const wrap_in_schema_js_1 = require("../wrap-in-schema.js");
10
15
  const canvas_1 = require("./canvas");
11
16
  const decode_image_js_1 = require("./decode-image.js");
12
17
  const resolve_image_source_1 = require("./resolve-image-source");
13
- exports.AnimatedImage = (0, react_1.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', ...props }, canvasRef) => {
14
- const mountState = (0, react_1.useRef)({ isMounted: true });
15
- (0, react_1.useEffect)(() => {
16
- const { current } = mountState;
17
- current.isMounted = true;
18
- return () => {
19
- current.isMounted = false;
20
- };
21
- }, []);
18
+ const animatedImageSchema = {
19
+ playbackRate: {
20
+ type: 'number',
21
+ min: 0,
22
+ max: 10,
23
+ step: 0.1,
24
+ default: 1,
25
+ description: 'Playback Rate',
26
+ },
27
+ ...sequence_field_schema_js_1.sequenceVisualStyleSchema,
28
+ hidden: sequence_field_schema_js_1.hiddenField,
29
+ };
30
+ const AnimatedImageContent = (0, react_1.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', effects, controls, ...props }, canvasRef) => {
31
+ var _a;
22
32
  const resolvedSrc = (0, resolve_image_source_1.resolveAnimatedImageSource)(src);
23
33
  const [imageDecoder, setImageDecoder] = (0, react_1.useState)(null);
24
34
  const { delayRender, continueRender } = (0, use_delay_render_js_1.useDelayRender)();
@@ -29,6 +39,10 @@ exports.AnimatedImage = (0, react_1.forwardRef)(({ src, width, height, onError,
29
39
  const currentTimeRef = (0, react_1.useRef)(currentTime);
30
40
  currentTimeRef.current = currentTime;
31
41
  const ref = (0, react_1.useRef)(null);
42
+ const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
43
+ effects,
44
+ overrideId: (_a = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _a !== void 0 ? _a : null,
45
+ });
32
46
  (0, react_1.useImperativeHandle)(canvasRef, () => {
33
47
  var _a;
34
48
  const c = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.getCanvas();
@@ -78,21 +92,28 @@ exports.AnimatedImage = (0, react_1.forwardRef)(({ src, width, height, onError,
78
92
  return;
79
93
  }
80
94
  const delay = delayRender(`Rendering frame at ${currentTime} of <AnimatedImage src="${src}"/>`);
95
+ let cancelled = false;
81
96
  imageDecoder
82
97
  .getFrame(currentTime, loopBehavior)
83
- .then((videoFrame) => {
98
+ .then(async (videoFrame) => {
84
99
  var _a, _b;
85
- if (mountState.current.isMounted) {
86
- if (videoFrame === null) {
87
- (_a = ref.current) === null || _a === void 0 ? void 0 : _a.clear();
88
- }
89
- else {
90
- (_b = ref.current) === null || _b === void 0 ? void 0 : _b.draw(videoFrame.frame);
91
- }
100
+ if (cancelled) {
101
+ return;
102
+ }
103
+ if (videoFrame === null) {
104
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.clear();
105
+ continueRender(delay);
106
+ return;
107
+ }
108
+ const completed = await ((_b = ref.current) === null || _b === void 0 ? void 0 : _b.draw(videoFrame.frame));
109
+ if (completed && !cancelled) {
110
+ continueRender(delay);
92
111
  }
93
- continueRender(delay);
94
112
  })
95
113
  .catch((err) => {
114
+ if (cancelled) {
115
+ return;
116
+ }
96
117
  if (onError) {
97
118
  onError(err);
98
119
  continueRender(delay);
@@ -101,6 +122,10 @@ exports.AnimatedImage = (0, react_1.forwardRef)(({ src, width, height, onError,
101
122
  (0, cancel_render_js_1.cancelRender)(err);
102
123
  }
103
124
  });
125
+ return () => {
126
+ cancelled = true;
127
+ continueRender(delay);
128
+ };
104
129
  }, [
105
130
  currentTime,
106
131
  imageDecoder,
@@ -109,6 +134,32 @@ exports.AnimatedImage = (0, react_1.forwardRef)(({ src, width, height, onError,
109
134
  src,
110
135
  continueRender,
111
136
  delayRender,
137
+ memoizedEffects,
138
+ fit,
139
+ width,
140
+ height,
112
141
  ]);
113
- return ((0, jsx_runtime_1.jsx)(canvas_1.Canvas, { ref: ref, width: width, height: height, fit: fit, ...props }));
142
+ return ((0, jsx_runtime_1.jsx)(canvas_1.Canvas, { ref: ref, width: width, height: height, fit: fit, effects: memoizedEffects, ...props }));
114
143
  });
144
+ AnimatedImageContent.displayName = 'AnimatedImageContent';
145
+ const AnimatedImageInner = ({ src, width, height, onError, fit, playbackRate, loopBehavior, id, className, style, durationInFrames, _experimentalEffects: effects = [], _experimentalControls: controls, ref, ...sequenceProps }) => {
146
+ const { durationInFrames: videoDuration } = (0, use_video_config_js_1.useVideoConfig)();
147
+ const resolvedDuration = durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : videoDuration;
148
+ const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
149
+ const animatedImageProps = {
150
+ src,
151
+ width,
152
+ height,
153
+ onError,
154
+ fit,
155
+ playbackRate,
156
+ loopBehavior,
157
+ id,
158
+ className,
159
+ style,
160
+ };
161
+ return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { layout: "none", durationInFrames: resolvedDuration, name: "<AnimatedImage>", _experimentalControls: controls, _experimentalEffects: memoizedEffectDefinitions, ...sequenceProps, children: (0, jsx_runtime_1.jsx)(AnimatedImageContent, { ...animatedImageProps, ref: ref, effects: effects, controls: controls }) }));
162
+ };
163
+ exports.AnimatedImage = (0, wrap_in_schema_js_1.wrapInSchema)(AnimatedImageInner, animatedImageSchema);
164
+ exports.AnimatedImage.displayName = 'AnimatedImage';
165
+ (0, enable_sequence_stack_traces_js_1.addSequenceStackTraces)(exports.AnimatedImage);
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import type { EffectDefinitionAndStack } from '../effects/effect-types.js';
2
3
  import type { AnimatedImageFillMode } from './props';
3
4
  type Props = {
4
5
  readonly width?: number;
@@ -6,9 +7,10 @@ type Props = {
6
7
  readonly fit: AnimatedImageFillMode;
7
8
  readonly className?: string;
8
9
  readonly style?: React.CSSProperties;
10
+ readonly effects: EffectDefinitionAndStack<unknown>[];
9
11
  };
10
12
  export type AnimatedImageCanvasRef = {
11
- readonly draw: (imageData: VideoFrame) => void;
13
+ readonly draw: (imageData: VideoFrame) => Promise<boolean>;
12
14
  readonly getCanvas: () => HTMLCanvasElement | null;
13
15
  clear: () => void;
14
16
  };