remotion 4.0.535 → 4.0.536

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 (63) hide show
  1. package/dist/cjs/AbsoluteFill.d.ts +1 -1
  2. package/dist/cjs/HtmlInCanvas.d.ts +4 -2
  3. package/dist/cjs/HtmlInCanvas.js +4 -4
  4. package/dist/cjs/Img.d.ts +4 -2
  5. package/dist/cjs/Img.js +2 -2
  6. package/dist/cjs/Interactive.d.ts +21 -7
  7. package/dist/cjs/Interactive.js +22 -1
  8. package/dist/cjs/Sequence.js +47 -3
  9. package/dist/cjs/SequenceActivityBoundary.js +14 -1
  10. package/dist/cjs/SequenceActivityBudget.js +26 -11
  11. package/dist/cjs/SequenceActivitySuspensionProvider.d.ts +4 -0
  12. package/dist/cjs/SequenceActivitySuspensionProvider.js +45 -0
  13. package/dist/cjs/SequenceManager.d.ts +5 -0
  14. package/dist/cjs/SequenceManager.js +22 -4
  15. package/dist/cjs/Track.js +1 -2
  16. package/dist/cjs/animated-image/AnimatedImage.d.ts +3 -2
  17. package/dist/cjs/animated-image/AnimatedImage.js +6 -4
  18. package/dist/cjs/animated-image/canvas.d.ts +2 -1
  19. package/dist/cjs/animated-image/canvas.js +2 -2
  20. package/dist/cjs/animated-image/props.d.ts +2 -1
  21. package/dist/cjs/asset-types.d.ts +4 -0
  22. package/dist/cjs/audio/shared-audio-tags.d.ts +1 -1
  23. package/dist/cjs/audio/shared-audio-tags.js +1 -1
  24. package/dist/cjs/canvas-image/CanvasImage.d.ts +3 -2
  25. package/dist/cjs/canvas-image/CanvasImage.js +4 -4
  26. package/dist/cjs/canvas-image/props.d.ts +2 -1
  27. package/dist/cjs/effects/Solid.d.ts +3 -2
  28. package/dist/cjs/effects/Solid.js +4 -4
  29. package/dist/cjs/effects/effect-types.d.ts +4 -0
  30. package/dist/cjs/effects/index.d.ts +1 -1
  31. package/dist/cjs/effects/run-effect-chain.d.ts +3 -1
  32. package/dist/cjs/effects/run-effect-chain.js +94 -56
  33. package/dist/cjs/effects/use-effect-chain-state.d.ts +2 -1
  34. package/dist/cjs/effects/use-effect-chain-state.js +11 -2
  35. package/dist/cjs/index.d.ts +1 -1
  36. package/dist/cjs/interactivity-schema.d.ts +5 -5
  37. package/dist/cjs/interactivity-schema.js +2 -1
  38. package/dist/cjs/internals.d.ts +8 -10
  39. package/dist/cjs/internals.js +0 -1
  40. package/dist/cjs/interpolate.js +8 -1
  41. package/dist/cjs/no-react.d.ts +1 -1
  42. package/dist/cjs/sequence-activity-context.d.ts +1 -1
  43. package/dist/cjs/sequence-activity-context.js +4 -3
  44. package/dist/cjs/sequence-activity-defaults.d.ts +1 -1
  45. package/dist/cjs/sequence-activity-defaults.js +1 -1
  46. package/dist/cjs/timeline-track-context.d.ts +0 -1
  47. package/dist/cjs/timeline-track-context.js +1 -2
  48. package/dist/cjs/use-schema.js +3 -1
  49. package/dist/cjs/use-timeline-seek.d.ts +1 -0
  50. package/dist/cjs/use-timeline-seek.js +10 -0
  51. package/dist/cjs/version.d.ts +1 -1
  52. package/dist/cjs/version.js +1 -1
  53. package/dist/cjs/video/seek-until-right.js +11 -7
  54. package/dist/cjs/wrap-remotion-context.d.ts +0 -1
  55. package/dist/cjs/wrap-remotion-context.js +1 -4
  56. package/dist/esm/index.mjs +704 -557
  57. package/dist/esm/no-react.mjs +4 -3
  58. package/dist/esm/version.mjs +1 -1
  59. package/package.json +2 -2
  60. package/dist/cjs/nonce.d.ts +0 -11
  61. package/dist/cjs/nonce.js +0 -42
  62. package/dist/cjs/sequence-order-marker.d.ts +0 -58
  63. package/dist/cjs/sequence-order-marker.js +0 -44
@@ -51,7 +51,7 @@ const getCanvasPropsFromSequenceProps = (props) => {
51
51
  }
52
52
  return canvasProps;
53
53
  };
54
- const AnimatedImageContent = (0, react_2.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', requestInit, effects, controls, ...props }, canvasRef) => {
54
+ const AnimatedImageContent = (0, react_2.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', requestInit, effects, effectsOutputSize, controls, ...props }, canvasRef) => {
55
55
  var _a, _b, _c;
56
56
  const resolvedSrc = (0, resolve_image_source_1.resolveAnimatedImageSource)(src);
57
57
  const [decodedImage, setDecodedImage] = (0, react_2.useState)(null);
@@ -196,11 +196,13 @@ const AnimatedImageContent = (0, react_2.forwardRef)(({ src, width, height, onEr
196
196
  width,
197
197
  height,
198
198
  cancelRender,
199
+ effectsOutputSize === null || effectsOutputSize === void 0 ? void 0 : effectsOutputSize.width,
200
+ effectsOutputSize === null || effectsOutputSize === void 0 ? void 0 : effectsOutputSize.height,
199
201
  ]);
200
- return (jsx_runtime_1.jsx(canvas_1.Canvas, { ref: ref, width: width, height: height, fit: fit, effects: memoizedEffects, ...props }));
202
+ return (jsx_runtime_1.jsx(canvas_1.Canvas, { ref: ref, width: width, height: height, fit: fit, effects: memoizedEffects, effectsOutputSize: effectsOutputSize !== null && effectsOutputSize !== void 0 ? effectsOutputSize : null, ...props }));
201
203
  });
202
204
  AnimatedImageContent.displayName = 'AnimatedImageContent';
203
- const AnimatedImageInner = ({ src, width, height, onError, fit, playbackRate, loopBehavior, id, className, style, durationInFrames, from, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, cropLeft, cropRight, cropTop, cropBottom, requestInit, effects = [], controls, ref, ...sequenceProps }) => {
205
+ const AnimatedImageInner = ({ src, width, height, onError, fit, playbackRate, loopBehavior, id, className, style, durationInFrames, from, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, cropLeft, cropRight, cropTop, cropBottom, requestInit, effects = [], effectsOutputSize, controls, ref, ...sequenceProps }) => {
204
206
  const actualRef = (0, react_2.useRef)(null);
205
207
  const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
206
208
  (0, react_2.useImperativeHandle)(ref, () => {
@@ -242,7 +244,7 @@ const AnimatedImageInner = ({ src, width, height, onError, fit, playbackRate, lo
242
244
  requestInit,
243
245
  ...canvasProps,
244
246
  };
245
- return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, _remotionInternalIsPremounting: premountingActive, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, playbackRate: playbackRate, durationInFrames: durationInFrames, name: "<AnimatedImage>", _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/animatedimage", controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, ...sequenceProps, children: jsx_runtime_1.jsx(sequence_activity_context_js_1.SequenceContent, { children: jsx_runtime_1.jsx(AnimatedImageContent, { ...animatedImageProps, ref: actualRef, effects: effects, controls: controls }) }) }) }));
247
+ return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, _remotionInternalIsPremounting: premountingActive, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, playbackRate: playbackRate, durationInFrames: durationInFrames, name: "<AnimatedImage>", _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/animatedimage", controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, ...sequenceProps, children: jsx_runtime_1.jsx(sequence_activity_context_js_1.SequenceContent, { children: jsx_runtime_1.jsx(AnimatedImageContent, { ...animatedImageProps, ref: actualRef, effects: effects, effectsOutputSize: effectsOutputSize !== null && effectsOutputSize !== void 0 ? effectsOutputSize : null, controls: controls }) }) }) }));
246
248
  };
247
249
  const AnimatedImageWithIntrinsicDuration = (props) => {
248
250
  const { fps } = (0, use_video_config_js_1.useVideoConfig)();
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { EffectDefinitionAndStack } from '../effects/effect-types.js';
2
+ import type { EffectDefinitionAndStack, EffectsOutputSize } from '../effects/effect-types.js';
3
3
  export type AnimatedImageCanvasRef = {
4
4
  readonly draw: (imageData: VideoFrame) => Promise<boolean>;
5
5
  readonly getCanvas: () => HTMLCanvasElement | null;
@@ -12,4 +12,5 @@ export declare const Canvas: React.ForwardRefExoticComponent<{
12
12
  readonly className?: string | undefined;
13
13
  readonly style?: React.CSSProperties | undefined;
14
14
  readonly effects: EffectDefinitionAndStack<unknown>[];
15
+ readonly effectsOutputSize: EffectsOutputSize | null;
15
16
  } & React.AriaAttributes & Record<`data-${string}`, string | undefined> & React.RefAttributes<AnimatedImageCanvasRef>>;
@@ -39,9 +39,9 @@ const react_1 = __importStar(require("react"));
39
39
  const calculate_image_fit_js_1 = require("../calculate-image-fit.js");
40
40
  const run_effect_chain_js_1 = require("../effects/run-effect-chain.js");
41
41
  const use_effect_chain_state_js_1 = require("../effects/use-effect-chain-state.js");
42
- const CanvasRefForwardingFunction = ({ width, height, fit, className, style, effects, ...props }, ref) => {
42
+ const CanvasRefForwardingFunction = ({ width, height, fit, className, style, effects, effectsOutputSize, ...props }, ref) => {
43
43
  const canvasRef = (0, react_1.useRef)(null);
44
- const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)();
44
+ const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)(effectsOutputSize);
45
45
  const sourceCanvas = (0, react_1.useMemo)(() => {
46
46
  if (typeof document === 'undefined') {
47
47
  return null;
@@ -1,5 +1,5 @@
1
1
  import type { ImageFit } from '../calculate-image-fit.js';
2
- import type { EffectsProp } from '../effects/effect-types.js';
2
+ import type { EffectsProp, EffectsOutputSize } from '../effects/effect-types.js';
3
3
  import type { InteractiveBaseProps, InteractiveCropProps, InteractivePremountProps } from '../Interactive.js';
4
4
  export type RemotionAnimatedImageLoopBehavior = 'loop' | 'pause-after-finish' | 'clear-after-finish';
5
5
  export type AnimatedImageCanvasProps = React.AriaAttributes & Record<`data-${string}`, string | undefined>;
@@ -18,5 +18,6 @@ export type RemotionAnimatedImageProps = {
18
18
  } & AnimatedImageCanvasProps;
19
19
  export type AnimatedImageProps = InteractiveBaseProps & InteractiveCropProps & InteractivePremountProps & RemotionAnimatedImageProps & {
20
20
  readonly effects?: EffectsProp;
21
+ readonly effectsOutputSize?: EffectsOutputSize;
21
22
  };
22
23
  export type AnimatedImageFillMode = ImageFit;
@@ -31,6 +31,10 @@ declare module '*.jpeg' {
31
31
  const src: string;
32
32
  export default src;
33
33
  }
34
+ declare module '*.jxl' {
35
+ const src: string;
36
+ export default src;
37
+ }
34
38
  declare module '*.bmp' {
35
39
  const src: string;
36
40
  export default src;
@@ -62,7 +62,7 @@ type SharedAudioContextValue = {
62
62
  resumeAsAutoPlay: () => Promise<void>;
63
63
  suspend: () => Promise<void>;
64
64
  getIsResumingAudioContext: () => Promise<AudioContextResumeResult> | null;
65
- unscheduleAudioNode: (node: AudioBufferSourceNode) => void;
65
+ unscheduleAudioNode: (node: AudioBufferSourceNode) => boolean;
66
66
  _experimentalKeepAudioContextAlive: boolean;
67
67
  };
68
68
  type SharedAudioTagsContextValue = {
@@ -127,7 +127,7 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
127
127
  const prevEndTimes = (0, react_1.useRef)({ scheduledEndTime: null, mediaEndTime: null });
128
128
  const nodesToResume = (0, react_1.useRef)(new Map());
129
129
  const unscheduleAudioNode = (0, react_1.useCallback)((node) => {
130
- nodesToResume.current.delete(node);
130
+ return nodesToResume.current.delete(node);
131
131
  }, []);
132
132
  const scheduleAudioNode = (0, react_1.useMemo)(() => {
133
133
  return ({ node, mediaTimestamp, sourceOffset, scheduledTime, duration, offset, originalUnloopedMediaTimestamp, }) => {
@@ -1,4 +1,4 @@
1
- import type { EffectsProp } from '../effects/effect-types.js';
1
+ import type { EffectsProp, EffectsOutputSize } from '../effects/effect-types.js';
2
2
  import type { CanvasImageCanvasProps } from './props.js';
3
3
  export declare const canvasImageSchema: {
4
4
  readonly 'style.transformOrigin': {
@@ -114,7 +114,7 @@ export declare const canvasImageSchema: {
114
114
  };
115
115
  readonly premountFor: {
116
116
  readonly type: "number";
117
- readonly default: 0;
117
+ readonly default: undefined;
118
118
  readonly description: "Premount For";
119
119
  readonly min: 0;
120
120
  readonly step: 1;
@@ -223,6 +223,7 @@ export declare const CanvasImage: import("react").ComponentType<Omit<import("../
223
223
  readonly height?: number | undefined;
224
224
  readonly fit?: import("../calculate-image-fit.js").ImageFit | undefined;
225
225
  readonly effects?: EffectsProp | undefined;
226
+ readonly effectsOutputSize?: EffectsOutputSize | undefined;
226
227
  readonly className?: string | undefined;
227
228
  readonly style?: import("react").CSSProperties | undefined;
228
229
  readonly id?: string | undefined;
@@ -111,14 +111,14 @@ const waitForNextFrame = ({ onFrame, }) => {
111
111
  const frame = requestAnimationFrame(onFrame);
112
112
  return () => cancelAnimationFrame(frame);
113
113
  };
114
- const CanvasImageContent = (0, react_1.forwardRef)(({ src, crossOrigin, width, height, fit = 'fill', effects, controls, onError, className, style, id, pauseWhenLoading, maxRetries = 2, delayRenderRetries, delayRenderTimeoutInMilliseconds, ...canvasProps }, ref) => {
114
+ const CanvasImageContent = (0, react_1.forwardRef)(({ src, crossOrigin, width, height, fit = 'fill', effects, effectsOutputSize, controls, onError, className, style, id, pauseWhenLoading, maxRetries = 2, delayRenderRetries, delayRenderTimeoutInMilliseconds, ...canvasProps }, ref) => {
115
115
  var _a, _b;
116
116
  const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
117
117
  const { delayPlayback } = (0, use_buffer_state_js_1.useBufferState)();
118
118
  const [outputCanvas, setOutputCanvas] = (0, react_1.useState)(null);
119
119
  const [loadedImage, setLoadedImage] = (0, react_1.useState)(null);
120
120
  const actualSrc = (0, prefetch_js_1.usePreload)(src);
121
- const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)();
121
+ const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)(effectsOutputSize);
122
122
  const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
123
123
  effects,
124
124
  overrideId: (_a = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _a !== void 0 ? _a : null,
@@ -330,7 +330,7 @@ const CanvasImageContent = (0, react_1.forwardRef)(({ src, crossOrigin, width, h
330
330
  return (jsx_runtime_1.jsx("canvas", { ...canvasProps, ref: canvasRef, width: width, height: height, className: className, style: style, id: id }));
331
331
  });
332
332
  CanvasImageContent.displayName = 'CanvasImageContent';
333
- const CanvasImageInner = (0, react_1.forwardRef)(({ src, crossOrigin, width, height, fit, effects = [], className, style, id, onError, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, durationInFrames, from, trimBefore, loop, freeze, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, hidden, name, showInTimeline, cropLeft, cropRight, cropTop, cropBottom, controls, _remotionInternalDocumentationLink, _remotionInternalCropComponentName, ...canvasProps }, ref) => {
333
+ const CanvasImageInner = (0, react_1.forwardRef)(({ src, crossOrigin, width, height, fit, effects = [], effectsOutputSize, className, style, id, onError, pauseWhenLoading, maxRetries, delayRenderRetries, delayRenderTimeoutInMilliseconds, durationInFrames, from, trimBefore, loop, freeze, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, hidden, name, showInTimeline, cropLeft, cropRight, cropTop, cropBottom, controls, _remotionInternalDocumentationLink, _remotionInternalCropComponentName, ...canvasProps }, ref) => {
334
334
  if (!src) {
335
335
  throw new Error('No "src" prop was passed to <CanvasImage>.');
336
336
  }
@@ -365,7 +365,7 @@ const CanvasImageInner = (0, react_1.forwardRef)(({ src, crossOrigin, width, hei
365
365
  style: premountingStyle,
366
366
  componentName: _remotionInternalCropComponentName !== null && _remotionInternalCropComponentName !== void 0 ? _remotionInternalCropComponentName : '<CanvasImage />',
367
367
  });
368
- return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, _remotionInternalIsPremounting: premountingActive, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, trimBefore: trimBefore, loop: loop, durationInFrames: durationInFrames, freeze: freeze, hidden: hidden, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, name: name !== null && name !== void 0 ? name : '<CanvasImage>', _remotionInternalDocumentationLink: _remotionInternalDocumentationLink !== null && _remotionInternalDocumentationLink !== void 0 ? _remotionInternalDocumentationLink : 'https://www.remotion.dev/docs/canvasimage', controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, _remotionInternalIsMedia: isMedia, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, children: jsx_runtime_1.jsx(sequence_activity_context_js_1.SequenceContent, { children: jsx_runtime_1.jsx(CanvasImageContent, { ref: actualRef, src: src, crossOrigin: crossOrigin, width: width, height: height, fit: fit, effects: effects, controls: controls, className: className, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, id: id, onError: onError, pauseWhenLoading: pauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, ...canvasProps }) }) }) }));
368
+ return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, _remotionInternalIsPremounting: premountingActive, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, trimBefore: trimBefore, loop: loop, durationInFrames: durationInFrames, freeze: freeze, hidden: hidden, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, name: name !== null && name !== void 0 ? name : '<CanvasImage>', _remotionInternalDocumentationLink: _remotionInternalDocumentationLink !== null && _remotionInternalDocumentationLink !== void 0 ? _remotionInternalDocumentationLink : 'https://www.remotion.dev/docs/canvasimage', controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, _remotionInternalIsMedia: isMedia, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, children: jsx_runtime_1.jsx(sequence_activity_context_js_1.SequenceContent, { children: jsx_runtime_1.jsx(CanvasImageContent, { ref: actualRef, src: src, crossOrigin: crossOrigin, width: width, height: height, fit: fit, effects: effects, effectsOutputSize: effectsOutputSize !== null && effectsOutputSize !== void 0 ? effectsOutputSize : null, controls: controls, className: className, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, id: id, onError: onError, pauseWhenLoading: pauseWhenLoading, maxRetries: maxRetries, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, ...canvasProps }) }) }) }));
369
369
  });
370
370
  /*
371
371
  * @description Renders a static image to a `<canvas>` and applies Remotion effects.
@@ -1,6 +1,6 @@
1
1
  import type React from 'react';
2
2
  import type { ImageFit } from '../calculate-image-fit.js';
3
- import type { EffectsProp } from '../effects/effect-types.js';
3
+ import type { EffectsProp, EffectsOutputSize } from '../effects/effect-types.js';
4
4
  import type { InteractiveBaseProps, InteractiveCropProps, InteractivePremountProps } from '../Interactive.js';
5
5
  type CanvasImageSequenceProps = Omit<InteractiveBaseProps, 'playbackRate'> & InteractiveCropProps & InteractivePremountProps;
6
6
  export type CanvasImageCanvasProps = Omit<React.CanvasHTMLAttributes<HTMLCanvasElement>, 'children' | 'height' | 'onError' | 'width'>;
@@ -11,6 +11,7 @@ export type CanvasImageProps = CanvasImageSequenceProps & CanvasImageCanvasProps
11
11
  readonly height?: number;
12
12
  readonly fit?: ImageFit;
13
13
  readonly effects?: EffectsProp;
14
+ readonly effectsOutputSize?: EffectsOutputSize;
14
15
  readonly className?: string;
15
16
  readonly style?: React.CSSProperties;
16
17
  readonly id?: string;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { InteractiveBaseProps, InteractivePremountProps, InteractiveCropProps } from '../Interactive.js';
3
- import type { EffectsProp } from './effect-types.js';
3
+ import type { EffectsProp, EffectsOutputSize } from './effect-types.js';
4
4
  type MandatoryProps = {
5
5
  readonly width: number;
6
6
  readonly height: number;
@@ -8,6 +8,7 @@ type MandatoryProps = {
8
8
  type OptionalProps = {
9
9
  readonly color: string | undefined;
10
10
  readonly effects: EffectsProp;
11
+ readonly effectsOutputSize: EffectsOutputSize | null;
11
12
  readonly className: string | undefined;
12
13
  readonly style: React.CSSProperties | undefined;
13
14
  readonly pixelDensity: number | undefined;
@@ -127,7 +128,7 @@ export declare const solidSchema: {
127
128
  };
128
129
  readonly premountFor: {
129
130
  readonly type: "number";
130
- readonly default: 0;
131
+ readonly default: undefined;
131
132
  readonly description: "Premount For";
132
133
  readonly min: 0;
133
134
  readonly step: 1;
@@ -66,7 +66,7 @@ exports.solidSchema = {
66
66
  ...interactivity_schema_js_1.borderRadiusSchema,
67
67
  ...interactivity_schema_js_1.cropSchema,
68
68
  };
69
- const SolidInner = ({ color, width, height, effects = [], className, style, pixelDensity, overrideId, videoConfigValues, reference, }) => {
69
+ const SolidInner = ({ color, width, height, effects = [], effectsOutputSize = null, className, style, pixelDensity, overrideId, videoConfigValues, reference, }) => {
70
70
  const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
71
71
  const resolvedPixelDensity = resolveSolidPixelDensity(pixelDensity);
72
72
  const canvasWidth = Math.ceil(width * resolvedPixelDensity);
@@ -86,7 +86,7 @@ const SolidInner = ({ color, width, height, effects = [], className, style, pixe
86
86
  canvas.height = 1;
87
87
  return canvas;
88
88
  }, []);
89
- const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)();
89
+ const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)(effectsOutputSize);
90
90
  const canvasRef = (0, react_1.useCallback)((canvas) => {
91
91
  setOutputCanvas(canvas);
92
92
  if (typeof reference === 'function') {
@@ -158,7 +158,7 @@ const SolidInner = ({ color, width, height, effects = [], className, style, pixe
158
158
  }, [height, style, width]);
159
159
  return (jsx_runtime_1.jsx("canvas", { ref: canvasRef, width: canvasWidth, height: canvasHeight, className: className, style: canvasStyle }));
160
160
  };
161
- const SolidOuter = (0, react_1.forwardRef)(({ effects = [], controls, color, height, width, className, durationInFrames, style, name, from, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, trimBefore, playbackRate, loop, freeze, hidden, showInTimeline, pixelDensity, cropLeft, cropRight, cropTop, cropBottom, ...props }, ref) => {
161
+ const SolidOuter = (0, react_1.forwardRef)(({ effects = [], effectsOutputSize = null, controls, color, height, width, className, durationInFrames, style, name, from, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, trimBefore, playbackRate, loop, freeze, hidden, showInTimeline, pixelDensity, cropLeft, cropRight, cropTop, cropBottom, ...props }, ref) => {
162
162
  var _a, _b;
163
163
  props;
164
164
  const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
@@ -188,7 +188,7 @@ const SolidOuter = (0, react_1.forwardRef)(({ effects = [], controls, color, hei
188
188
  style: premountingStyle,
189
189
  componentName: '<Solid />',
190
190
  });
191
- return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, _remotionInternalIsPremounting: premountingActive, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from, trimBefore: trimBefore, playbackRate: playbackRate, loop: loop, freeze: freeze, hidden: hidden, showInTimeline: showInTimeline, controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, durationInFrames: durationInFrames, name: name !== null && name !== void 0 ? name : '<Solid>', _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/solid", ...props, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, children: jsx_runtime_1.jsx(sequence_activity_context_js_1.SequenceContent, { children: jsx_runtime_1.jsx(SolidInner, { reference: actualRef, videoConfigValues: (_a = controls === null || controls === void 0 ? void 0 : controls.videoConfigValues) !== null && _a !== void 0 ? _a : null, overrideId: (_b = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _b !== void 0 ? _b : null, color: color, height: height, width: width, className: className, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, effects: effects, pixelDensity: pixelDensity }) }) }) }));
191
+ return (jsx_runtime_1.jsx(freeze_js_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, _remotionInternalIsPremounting: premountingActive, children: jsx_runtime_1.jsx(Sequence_js_1.Sequence, { layout: "none", from: from, trimBefore: trimBefore, playbackRate: playbackRate, loop: loop, freeze: freeze, hidden: hidden, showInTimeline: showInTimeline, controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, durationInFrames: durationInFrames, name: name !== null && name !== void 0 ? name : '<Solid>', _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/solid", ...props, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, children: jsx_runtime_1.jsx(sequence_activity_context_js_1.SequenceContent, { children: jsx_runtime_1.jsx(SolidInner, { reference: actualRef, videoConfigValues: (_a = controls === null || controls === void 0 ? void 0 : controls.videoConfigValues) !== null && _a !== void 0 ? _a : null, overrideId: (_b = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _b !== void 0 ? _b : null, color: color, height: height, width: width, className: className, style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined, effects: effects, effectsOutputSize: effectsOutputSize, pixelDensity: pixelDensity }) }) }) }));
192
192
  });
193
193
  exports.Solid = (0, with_interactivity_schema_js_1.withInteractivitySchema)({
194
194
  Component: SolidOuter,
@@ -52,4 +52,8 @@ export type EffectFactory<P> = {} extends P ? (params?: P & {
52
52
  }) => EffectDescriptor<unknown> : (params: P & {
53
53
  readonly disabled?: boolean;
54
54
  }) => EffectDescriptor<unknown>;
55
+ export type EffectsOutputSize = {
56
+ readonly width: number;
57
+ readonly height: number;
58
+ };
55
59
  export {};
@@ -1,2 +1,2 @@
1
1
  export { createEffect } from './create-effect.js';
2
- export type { Backend, EffectApplyParams, EffectDefinitionAndStack, EffectDescriptor, EffectsProp, EffectDefinition, EffectFactory, } from './effect-types.js';
2
+ export type { Backend, EffectApplyParams, EffectDefinitionAndStack, EffectDescriptor, EffectsProp, EffectsOutputSize, EffectDefinition, EffectFactory, } from './effect-types.js';
@@ -1,6 +1,8 @@
1
1
  import { CanvasPool } from './canvas-pool.js';
2
2
  import type { EffectDefinition, EffectDefinitionAndStack } from './effect-types.js';
3
3
  export type EffectChainState = {
4
+ readonly width: number;
5
+ readonly height: number;
4
6
  pool: CanvasPool;
5
7
  setupCache: WeakMap<EffectDefinition<unknown, unknown>, WeakMap<HTMLCanvasElement, unknown>>;
6
8
  cleanupRegistry: Array<{
@@ -22,4 +24,4 @@ export type RunEffectChainOptions = {
22
24
  readonly width: number;
23
25
  readonly height: number;
24
26
  };
25
- export declare const runEffectChain: ({ state, source, effects, output, width, height, }: RunEffectChainOptions) => Promise<boolean>;
27
+ export declare const runEffectChain: (options: RunEffectChainOptions) => Promise<boolean>;
@@ -6,6 +6,8 @@ const effect_internals_js_1 = require("./effect-internals.js");
6
6
  const gpu_device_js_1 = require("./gpu-device.js");
7
7
  const createEffectChainState = (width, height) => {
8
8
  const state = {
9
+ width,
10
+ height,
9
11
  pool: new canvas_pool_js_1.CanvasPool(width, height, (canvas) => {
10
12
  var _a;
11
13
  // The GL objects these setups hold died with the context and stay
@@ -62,9 +64,8 @@ const ensureSetup = (state, def, target) => {
62
64
  // Runs the effect pipeline imperatively. Returns `true` if the pipeline
63
65
  // completed and wrote to `output`, `false` if it was superseded by a newer
64
66
  // run (caller should not act on a stale result).
65
- const runEffectChain = async ({ state, source, effects, output, width, height, }) => {
67
+ const runEffectChainWithoutResize = async ({ state, source, effects, output, width, height }, initialFlipSourceY, runId) => {
66
68
  var _a;
67
- const runId = ++state.currentRunId;
68
69
  const isCancelled = () => state.currentRunId !== runId;
69
70
  // Bypass any effect with `disabled: true` before grouping by backend, so
70
71
  // disabled effects don't create empty runs or force unnecessary backend
@@ -102,66 +103,77 @@ const runEffectChain = async ({ state, source, effects, output, width, height, }
102
103
  // Canvas sources are DOM-oriented. Flip them when uploading into WebGL so
103
104
  // texture coordinates match clip-space output. `ImageBitmap` bridges below
104
105
  // opt out because they are already oriented for upload.
105
- let flipWebGLSourceY = true;
106
- for (let runIndex = 0; runIndex < runs.length; runIndex++) {
107
- const run = runs[runIndex];
108
- let canvasIndex = 0;
109
- for (const eff of run.effects) {
110
- const dst = state.pool.getCanvas(run.backend, canvasIndex);
111
- const def = eff.definition;
112
- if (run.backend === 'webgl2') {
113
- // Checked before `setup()`: a lost context cannot compile shaders,
114
- // and this surfaces the dedicated error instead of an effect's own.
115
- state.pool.assertContextNotLost(dst);
116
- }
117
- const setupState = ensureSetup(state, def, dst);
118
- def.apply({
119
- source: currentImage,
120
- target: dst,
121
- state: setupState,
122
- params: eff.params,
123
- width,
124
- height,
125
- gpuDevice,
126
- flipSourceY: run.backend === 'webgl2' ? flipWebGLSourceY : false,
127
- });
128
- if (run.backend === 'webgl2') {
129
- // Same-backend ping-pong passes feed the previous WebGL canvas back
130
- // through `texImage2D()`. That source is still a DOM canvas, so the
131
- // next upload also needs to be flipped.
132
- flipWebGLSourceY = true;
133
- }
134
- currentImage = dst;
135
- canvasIndex = canvasIndex === 0 ? 1 : 0;
136
- }
137
- lastTarget = (_a = currentImage) !== null && _a !== void 0 ? _a : lastTarget;
138
- const nextRun = runs[runIndex + 1];
139
- if (nextRun && nextRun.backend !== run.backend && lastTarget) {
140
- // 2D → WebGL: pass the 2D canvas directly so `texImage2D` + `UNPACK_FLIP_Y`
141
- // matches blur-only on a raw frame canvas. `createImageBitmap` here changes
142
- // upload orientation and produced upside-down stacks (wave + blur).
143
- if (run.backend === '2d' && nextRun.backend === 'webgl2') {
144
- currentImage = lastTarget;
145
- flipWebGLSourceY = true;
106
+ let flipWebGLSourceY = initialFlipSourceY;
107
+ // Only bridge bitmaps are owned here; the original source belongs to the caller.
108
+ let bridgeBitmap = null;
109
+ try {
110
+ for (let runIndex = 0; runIndex < runs.length; runIndex++) {
111
+ const run = runs[runIndex];
112
+ let canvasIndex = 0;
113
+ for (const eff of run.effects) {
114
+ const dst = state.pool.getCanvas(run.backend, canvasIndex);
115
+ const def = eff.definition;
116
+ if (run.backend === 'webgl2') {
117
+ // Checked before `setup()`: a lost context cannot compile shaders,
118
+ // and this surfaces the dedicated error instead of an effect's own.
119
+ state.pool.assertContextNotLost(dst);
120
+ }
121
+ const setupState = ensureSetup(state, def, dst);
122
+ def.apply({
123
+ source: currentImage,
124
+ target: dst,
125
+ state: setupState,
126
+ params: eff.params,
127
+ width: state.width,
128
+ height: state.height,
129
+ gpuDevice,
130
+ flipSourceY: run.backend === 'webgl2' ? flipWebGLSourceY : false,
131
+ });
132
+ // Effects consume their source synchronously. Release it before the
133
+ // next bridge so a run never retains multiple temporary bitmaps.
134
+ bridgeBitmap === null || bridgeBitmap === void 0 ? void 0 : bridgeBitmap.close();
135
+ bridgeBitmap = null;
136
+ if (run.backend === 'webgl2') {
137
+ // Same-backend ping-pong passes feed the previous WebGL canvas back
138
+ // through `texImage2D()`. That source is still a DOM canvas, so the
139
+ // next upload also needs to be flipped.
140
+ flipWebGLSourceY = true;
141
+ }
142
+ currentImage = dst;
143
+ canvasIndex = canvasIndex === 0 ? 1 : 0;
146
144
  }
147
- else {
148
- // Other bridges use `createImageBitmap` rather than passing the canvas
149
- // straight through. A direct `drawImage(webglCanvas)` in the next
150
- // backend's first effect forces an implicit GPU readback / finish on the
151
- // consuming context, which empirically blows the per-frame vsync budget and
152
- // halves the paint rate. `createImageBitmap` pipelines the GPU work.
153
- const bitmap = await createImageBitmap(lastTarget);
154
- if (isCancelled()) {
155
- bitmap.close();
156
- return false;
145
+ lastTarget = (_a = currentImage) !== null && _a !== void 0 ? _a : lastTarget;
146
+ const nextRun = runs[runIndex + 1];
147
+ if (nextRun && nextRun.backend !== run.backend && lastTarget) {
148
+ // 2D → WebGL: pass the 2D canvas directly so `texImage2D` + `UNPACK_FLIP_Y`
149
+ // matches blur-only on a raw frame canvas. `createImageBitmap` here changes
150
+ // upload orientation and produced upside-down stacks (wave + blur).
151
+ if (run.backend === '2d' && nextRun.backend === 'webgl2') {
152
+ currentImage = lastTarget;
153
+ flipWebGLSourceY = true;
157
154
  }
158
- currentImage = bitmap;
159
- if (nextRun.backend === 'webgl2') {
160
- flipWebGLSourceY = false;
155
+ else {
156
+ // Other bridges use `createImageBitmap` rather than passing the canvas
157
+ // straight through. A direct `drawImage(webglCanvas)` in the next
158
+ // backend's first effect forces an implicit GPU readback / finish on the
159
+ // consuming context, which empirically blows the per-frame vsync budget and
160
+ // halves the paint rate. `createImageBitmap` pipelines the GPU work.
161
+ bridgeBitmap = await createImageBitmap(lastTarget);
162
+ if (isCancelled()) {
163
+ return false;
164
+ }
165
+ currentImage = bridgeBitmap;
166
+ if (nextRun.backend === 'webgl2') {
167
+ flipWebGLSourceY = false;
168
+ }
161
169
  }
162
170
  }
163
171
  }
164
172
  }
173
+ finally {
174
+ // Also release a bridge if setup/apply throws or the run is cancelled.
175
+ bridgeBitmap === null || bridgeBitmap === void 0 ? void 0 : bridgeBitmap.close();
176
+ }
165
177
  if (!lastTarget) {
166
178
  return true;
167
179
  }
@@ -173,4 +185,30 @@ const runEffectChain = async ({ state, source, effects, output, width, height, }
173
185
  outCtx.drawImage(lastTarget, 0, 0, width, height);
174
186
  return true;
175
187
  };
188
+ // Keep ownership of the optional resized source until the existing chain settles.
189
+ const runEffectChain = async (options) => {
190
+ const { state, source, width, height, effects } = options;
191
+ // Keep one ID across resizing and effect passes so callers can cancel the run.
192
+ const runId = ++state.currentRunId;
193
+ if ((state.width === width && state.height === height) ||
194
+ !effects.some((effect) => !effect.params.disabled)) {
195
+ return runEffectChainWithoutResize(options, true, runId);
196
+ }
197
+ const firstEnabledEffect = effects.find((effect) => !effect.params.disabled);
198
+ const resized = await createImageBitmap(source, {
199
+ resizeWidth: state.width,
200
+ resizeHeight: state.height,
201
+ // WebGL ignores UNPACK_FLIP_Y_WEBGL for ImageBitmap uploads.
202
+ imageOrientation: firstEnabledEffect.definition.backend === 'webgl2' ? 'flipY' : 'none',
203
+ });
204
+ try {
205
+ if (state.currentRunId !== runId) {
206
+ return false;
207
+ }
208
+ return await runEffectChainWithoutResize({ ...options, source: resized }, false, runId);
209
+ }
210
+ finally {
211
+ resized.close();
212
+ }
213
+ };
176
214
  exports.runEffectChain = runEffectChain;
@@ -1,4 +1,5 @@
1
+ import type { EffectsOutputSize } from './effect-types.js';
1
2
  import type { EffectChainState } from './run-effect-chain.js';
2
- export declare const useEffectChainState: () => {
3
+ export declare const useEffectChainState: (effectsOutputSize?: EffectsOutputSize | null) => {
3
4
  get: (width: number, height: number) => EffectChainState | null;
4
5
  };
@@ -2,8 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useEffectChainState = void 0;
4
4
  const react_1 = require("react");
5
+ const validate_dimensions_js_1 = require("../validation/validate-dimensions.js");
5
6
  const run_effect_chain_js_1 = require("./run-effect-chain.js");
6
- const useEffectChainState = () => {
7
+ const useEffectChainState = (effectsOutputSize = null) => {
8
+ const effectWidth = effectsOutputSize === null || effectsOutputSize === void 0 ? void 0 : effectsOutputSize.width;
9
+ const effectHeight = effectsOutputSize === null || effectsOutputSize === void 0 ? void 0 : effectsOutputSize.height;
10
+ if (effectsOutputSize) {
11
+ (0, validate_dimensions_js_1.validateDimension)(effectWidth, 'effectsOutputSize.width', 'on an effect-capable component');
12
+ (0, validate_dimensions_js_1.validateDimension)(effectHeight, 'effectsOutputSize.height', 'on an effect-capable component');
13
+ }
7
14
  const chainStateRef = (0, react_1.useRef)(null);
8
15
  const sizeRef = (0, react_1.useRef)(null);
9
16
  const unmountedRef = (0, react_1.useRef)(false);
@@ -22,6 +29,8 @@ const useEffectChainState = () => {
22
29
  }, []);
23
30
  return (0, react_1.useMemo)(() => ({
24
31
  get: (width, height) => {
32
+ width = effectWidth !== null && effectWidth !== void 0 ? effectWidth : width;
33
+ height = effectHeight !== null && effectHeight !== void 0 ? effectHeight : height;
25
34
  // Async work such as a late decoded video frame can still get here
26
35
  // after unmount. Nothing would release a pool created at this point.
27
36
  if (unmountedRef.current) {
@@ -38,6 +47,6 @@ const useEffectChainState = () => {
38
47
  }
39
48
  return chainStateRef.current;
40
49
  },
41
- }), []);
50
+ }), [effectWidth, effectHeight]);
42
51
  };
43
52
  exports.useEffectChainState = useEffectChainState;
@@ -98,7 +98,7 @@ export type BundleEvaluationState = {
98
98
  export type BundleState = BundleIndexState | BundleEvaluationState | BundleCompositionState;
99
99
  export * from './AbsoluteFill.js';
100
100
  export * from './animated-image/index.js';
101
- export { createEffect, type Backend, type EffectApplyParams, type EffectDefinition, type EffectDefinitionAndStack, type EffectDescriptor, type EffectFactory, type EffectsProp, } from './effects/index.js';
101
+ export { createEffect, type Backend, type EffectApplyParams, type EffectDefinition, type EffectDefinitionAndStack, type EffectDescriptor, type EffectFactory, type EffectsProp, type EffectsOutputSize, } from './effects/index.js';
102
102
  /**
103
103
  * @description Renders a solid-color rectangle on a `<canvas>`.
104
104
  * @see [Documentation](https://www.remotion.dev/docs/solid)
@@ -450,7 +450,7 @@ export declare const textContentSchema: {
450
450
  export declare const premountSchema: {
451
451
  readonly premountFor: {
452
452
  readonly type: "number";
453
- readonly default: 0;
453
+ readonly default: undefined;
454
454
  readonly description: "Premount For";
455
455
  readonly min: 0;
456
456
  readonly step: 1;
@@ -469,7 +469,7 @@ export declare const premountSchema: {
469
469
  export declare const sequencePremountSchema: {
470
470
  readonly premountFor: {
471
471
  readonly type: "number";
472
- readonly default: 0;
472
+ readonly default: undefined;
473
473
  readonly description: "Premount For";
474
474
  readonly min: 0;
475
475
  readonly step: 1;
@@ -683,7 +683,7 @@ export declare const sequenceStyleSchema: {
683
683
  };
684
684
  readonly premountFor: {
685
685
  readonly type: "number";
686
- readonly default: 0;
686
+ readonly default: undefined;
687
687
  readonly description: "Premount For";
688
688
  readonly min: 0;
689
689
  readonly step: 1;
@@ -1040,7 +1040,7 @@ export declare const sequenceSchema: {
1040
1040
  };
1041
1041
  readonly premountFor: {
1042
1042
  readonly type: "number";
1043
- readonly default: 0;
1043
+ readonly default: undefined;
1044
1044
  readonly description: "Premount For";
1045
1045
  readonly min: 0;
1046
1046
  readonly step: 1;
@@ -1286,7 +1286,7 @@ export declare const sequenceSchemaWithoutFrom: {
1286
1286
  };
1287
1287
  readonly premountFor: {
1288
1288
  readonly type: "number";
1289
- readonly default: 0;
1289
+ readonly default: undefined;
1290
1290
  readonly description: "Premount For";
1291
1291
  readonly min: 0;
1292
1292
  readonly step: 1;
@@ -245,7 +245,8 @@ exports.textContentSchema = exports.childrenSchema;
245
245
  exports.premountSchema = {
246
246
  premountFor: {
247
247
  type: 'number',
248
- default: 0,
248
+ // Omission inherits the preview's default; zero explicitly disables it.
249
+ default: undefined,
249
250
  description: 'Premount For',
250
251
  min: 0,
251
252
  step: 1,