@remotion/gif 4.0.534 → 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.
package/dist/cjs/Gif.js CHANGED
@@ -30,7 +30,7 @@ exports.gifSchema = {
30
30
  ...remotion_1.Interactive.borderRadiusSchema,
31
31
  ...remotion_1.Interactive.cropSchema,
32
32
  };
33
- const GifInner = ({ src, width, height, onLoad, onError, fit, playbackRate, loopBehavior, id, delayRenderTimeoutInMilliseconds, requestInit, durationInFrames, from, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, style, cropLeft, cropRight, cropTop, cropBottom, controls, effects = [], ref, ...sequenceProps }) => {
33
+ const GifInner = ({ src, width, height, onLoad, onError, fit, playbackRate, loopBehavior, id, delayRenderTimeoutInMilliseconds, requestInit, durationInFrames, from, premountFor, postmountFor, styleWhilePremounted, styleWhilePostmounted, style, cropLeft, cropRight, cropTop, cropBottom, controls, effects = [], effectsOutputSize, ref, ...sequenceProps }) => {
34
34
  var _a, _b;
35
35
  const env = (0, remotion_1.useRemotionEnvironment)();
36
36
  const { effectivePostmountFor, effectivePremountFor, freezeFrame, isPremountingOrPostmounting, postmountingActive, premountingActive, premountingStyle, } = remotion_1.Internals.usePremounting({
@@ -74,6 +74,7 @@ const GifInner = ({ src, width, height, onLoad, onError, fit, playbackRate, loop
74
74
  requestInit,
75
75
  style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined,
76
76
  effects: memoizedEffects,
77
+ effectsOutputSize,
77
78
  };
78
79
  const inner = env.isRendering ? (jsx_runtime_1.jsx(GifForRendering_1.GifForRendering, { ...gifProps, ref: ref })) : (jsx_runtime_1.jsx(GifForDevelopment_1.GifForDevelopment, { ...gifProps, ref: ref }));
79
80
  return (jsx_runtime_1.jsx(remotion_1.Freeze, { frame: freezeFrame, active: isPremountingOrPostmounting, children: jsx_runtime_1.jsx(remotion_1.Sequence, { layout: "none", from: from !== null && from !== void 0 ? from : 0, playbackRate: playbackRate, durationInFrames: durationInFrames, name: "<Gif>", _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/gif/gif", controls: controls, _remotionInternalEffects: memoizedEffectDefinitions, _remotionInternalPremountDisplay: effectivePremountFor || null, _remotionInternalPostmountDisplay: effectivePostmountFor || null, _remotionInternalIsPremounting: premountingActive, _remotionInternalIsPostmounting: postmountingActive, ...sequenceProps, children: inner }) }));
@@ -86,17 +87,21 @@ const GifWithIntrinsicDuration = (props) => {
86
87
  onErrorRef.current = props.onError;
87
88
  const requestInitRef = (0, react_2.useRef)(requestInit);
88
89
  requestInitRef.current = requestInit;
89
- const [handle] = (0, react_2.useState)(() => delayRender(`Finding duration of <Gif src="${src}" />`, {
90
- timeoutInMilliseconds: props.delayRenderTimeoutInMilliseconds,
91
- }));
92
- const [durationInFrames, setDurationInFrames] = (0, react_2.useState)(null);
93
- const [failed, setFailed] = (0, react_2.useState)(false);
94
- (0, react_2.useEffect)(() => {
90
+ const [duration, setDuration] = (0, react_2.useState)(null);
91
+ const [failedHandle, setFailedHandle] = (0, react_2.useState)(null);
92
+ const { delayRenderTimeoutInMilliseconds } = props;
93
+ (0, react_2.useLayoutEffect)(() => {
94
+ const handle = delayRender(`Finding duration of <Gif src="${src}" />`, {
95
+ timeoutInMilliseconds: delayRenderTimeoutInMilliseconds,
96
+ });
95
97
  let cancelled = false;
96
98
  (0, get_gif_duration_in_seconds_1.getGifDurationInSeconds)(src, { requestInit: requestInitRef.current })
97
- .then((duration) => {
99
+ .then((durationInSeconds) => {
98
100
  if (!cancelled) {
99
- setDurationInFrames(Math.ceil(duration * fps) - (trimBefore !== null && trimBefore !== void 0 ? trimBefore : 0));
101
+ setDuration({
102
+ durationInFrames: Math.ceil(durationInSeconds * fps) - (trimBefore !== null && trimBefore !== void 0 ? trimBefore : 0),
103
+ handle,
104
+ });
100
105
  }
101
106
  })
102
107
  .catch((error) => {
@@ -105,7 +110,7 @@ const GifWithIntrinsicDuration = (props) => {
105
110
  }
106
111
  if (onErrorRef.current) {
107
112
  onErrorRef.current(error);
108
- setFailed(true);
113
+ setFailedHandle(handle);
109
114
  }
110
115
  else {
111
116
  cancelRender(error);
@@ -115,16 +120,27 @@ const GifWithIntrinsicDuration = (props) => {
115
120
  cancelled = true;
116
121
  continueRender(handle);
117
122
  };
118
- }, [cancelRender, continueRender, fps, handle, src, trimBefore]);
119
- (0, react_2.useEffect)(() => {
120
- if (durationInFrames !== null || failed) {
121
- continueRender(handle);
123
+ }, [
124
+ cancelRender,
125
+ continueRender,
126
+ delayRender,
127
+ delayRenderTimeoutInMilliseconds,
128
+ fps,
129
+ src,
130
+ trimBefore,
131
+ ]);
132
+ (0, react_2.useLayoutEffect)(() => {
133
+ if (duration !== null) {
134
+ continueRender(duration.handle);
135
+ }
136
+ if (failedHandle !== null) {
137
+ continueRender(failedHandle);
122
138
  }
123
- }, [continueRender, durationInFrames, failed, handle]);
124
- if (durationInFrames === null || failed) {
139
+ }, [continueRender, duration, failedHandle]);
140
+ if (duration === null || failedHandle !== null) {
125
141
  return null;
126
142
  }
127
- return jsx_runtime_1.jsx(GifInner, { ...props, durationInFrames: durationInFrames });
143
+ return jsx_runtime_1.jsx(GifInner, { ...props, durationInFrames: duration.durationInFrames });
128
144
  };
129
145
  const GifComponent = (props) => {
130
146
  var _a;
@@ -11,7 +11,7 @@ const react_tools_1 = require("./react-tools");
11
11
  const request_init_1 = require("./request-init");
12
12
  const resolve_gif_source_1 = require("./resolve-gif-source");
13
13
  const useCurrentGifIndex_1 = require("./useCurrentGifIndex");
14
- exports.GifForDevelopment = (0, react_1.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, onLoad, fit = 'fill', requestInit, effects, ...props }, ref) => {
14
+ exports.GifForDevelopment = (0, react_1.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, onLoad, fit = 'fill', requestInit, effects, effectsOutputSize = null, ...props }, ref) => {
15
15
  const resolvedSrc = (0, resolve_gif_source_1.resolveGifSource)(src);
16
16
  const requestInitRef = (0, react_1.useRef)(requestInit);
17
17
  requestInitRef.current = requestInit;
@@ -91,5 +91,5 @@ exports.GifForDevelopment = (0, react_1.forwardRef)(({ src, width, height, onErr
91
91
  if (index === -1) {
92
92
  return null;
93
93
  }
94
- return (jsx_runtime_1.jsx(canvas_1.Canvas, { fit: fit, index: index, frames: state.frames, width: width, height: height, effects: effects, ...props, ref: ref }));
94
+ return (jsx_runtime_1.jsx(canvas_1.Canvas, { fit: fit, index: index, frames: state.frames, width: width, height: height, effects: effects, effectsOutputSize: effectsOutputSize, ...props, ref: ref }));
95
95
  });
@@ -11,7 +11,7 @@ const react_tools_1 = require("./react-tools");
11
11
  const request_init_1 = require("./request-init");
12
12
  const resolve_gif_source_1 = require("./resolve-gif-source");
13
13
  const useCurrentGifIndex_1 = require("./useCurrentGifIndex");
14
- exports.GifForRendering = (0, react_1.forwardRef)(({ src, width, height, onLoad, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', delayRenderTimeoutInMilliseconds, requestInit, effects, ...props }, ref) => {
14
+ exports.GifForRendering = (0, react_1.forwardRef)(({ src, width, height, onLoad, onError, loopBehavior = 'loop', playbackRate = 1, fit = 'fill', delayRenderTimeoutInMilliseconds, requestInit, effects, effectsOutputSize = null, ...props }, ref) => {
15
15
  const resolvedSrc = (0, resolve_gif_source_1.resolveGifSource)(src);
16
16
  const requestInitRef = (0, react_1.useRef)(requestInit);
17
17
  requestInitRef.current = requestInit;
@@ -25,20 +25,13 @@ exports.GifForRendering = (0, react_1.forwardRef)(({ src, width, height, onLoad,
25
25
  frames: [],
26
26
  width: 0,
27
27
  height: 0,
28
+ handle: null,
28
29
  };
29
30
  }
30
- return parsedGif;
31
+ return { ...parsedGif, handle: null };
31
32
  });
32
33
  const [error, setError] = (0, react_1.useState)(null);
33
- const [renderHandle] = (0, react_1.useState)(() => delayRender(`Rendering <Gif/> with src="${resolvedSrc}"`, {
34
- timeoutInMilliseconds: delayRenderTimeoutInMilliseconds,
35
- }));
36
34
  const logLevel = remotion_1.Internals.useLogLevel();
37
- (0, react_1.useEffect)(() => {
38
- return () => {
39
- continueRender(renderHandle);
40
- };
41
- }, [renderHandle, continueRender]);
42
35
  const index = (0, useCurrentGifIndex_1.useCurrentGifIndex)({
43
36
  delays: state.delays,
44
37
  loopBehavior,
@@ -48,7 +41,7 @@ exports.GifForRendering = (0, react_1.forwardRef)(({ src, width, height, onLoad,
48
41
  const currentOnError = (0, react_1.useRef)(onError);
49
42
  currentOnLoad.current = onLoad;
50
43
  currentOnError.current = onError;
51
- (0, react_1.useEffect)(() => {
44
+ (0, react_1.useLayoutEffect)(() => {
52
45
  const controller = new AbortController();
53
46
  let done = false;
54
47
  let aborted = false;
@@ -64,13 +57,14 @@ exports.GifForRendering = (0, react_1.forwardRef)(({ src, width, height, onLoad,
64
57
  })
65
58
  .then((parsed) => {
66
59
  var _a;
60
+ if (aborted) {
61
+ return;
62
+ }
67
63
  remotion_1.Internals.Log.verbose({ logLevel, tag: null }, 'Parsed GIF in', Date.now() - time, 'ms');
68
64
  (_a = currentOnLoad.current) === null || _a === void 0 ? void 0 : _a.call(currentOnLoad, parsed);
69
- update(parsed);
65
+ update({ ...parsed, handle: newHandle });
70
66
  gif_cache_1.volatileGifCache.set(cacheKey, parsed);
71
67
  done = true;
72
- continueRender(newHandle);
73
- continueRender(renderHandle);
74
68
  })
75
69
  .catch((err) => {
76
70
  if (aborted) {
@@ -91,10 +85,8 @@ exports.GifForRendering = (0, react_1.forwardRef)(({ src, width, height, onLoad,
91
85
  controller.abort();
92
86
  }
93
87
  continueRender(newHandle);
94
- continueRender(renderHandle);
95
88
  };
96
89
  }, [
97
- renderHandle,
98
90
  logLevel,
99
91
  cacheKey,
100
92
  resolvedSrc,
@@ -102,6 +94,11 @@ exports.GifForRendering = (0, react_1.forwardRef)(({ src, width, height, onLoad,
102
94
  continueRender,
103
95
  delayRenderTimeoutInMilliseconds,
104
96
  ]);
97
+ (0, react_1.useLayoutEffect)(() => {
98
+ if (state.handle !== null) {
99
+ continueRender(state.handle);
100
+ }
101
+ }, [state, continueRender]);
105
102
  if (error) {
106
103
  remotion_1.Internals.Log.error({ logLevel, tag: null }, error.stack);
107
104
  if ((0, is_cors_error_1.isCorsError)(error)) {
@@ -112,5 +109,5 @@ exports.GifForRendering = (0, react_1.forwardRef)(({ src, width, height, onLoad,
112
109
  if (index === -1) {
113
110
  return null;
114
111
  }
115
- return (jsx_runtime_1.jsx(canvas_1.Canvas, { fit: fit, index: index, frames: state.frames, width: width, height: height, effects: effects, ...props, ref: ref }));
112
+ return (jsx_runtime_1.jsx(canvas_1.Canvas, { fit: fit, index: index, frames: state.frames, width: width, height: height, effects: effects, effectsOutputSize: effectsOutputSize, ...props, ref: ref }));
116
113
  });
@@ -1,4 +1,4 @@
1
- import type { EffectDefinitionAndStack } from 'remotion';
1
+ import type { EffectDefinitionAndStack, EffectsOutputSize } from 'remotion';
2
2
  import type { GifFillMode } from './props';
3
3
  type Props = {
4
4
  readonly index: number;
@@ -9,6 +9,7 @@ type Props = {
9
9
  readonly className?: string;
10
10
  readonly style?: React.CSSProperties;
11
11
  readonly effects: EffectDefinitionAndStack<unknown>[];
12
+ readonly effectsOutputSize: EffectsOutputSize | null;
12
13
  };
13
14
  export declare const Canvas: import("react").ForwardRefExoticComponent<Props & import("react").RefAttributes<unknown>>;
14
15
  export {};
@@ -65,7 +65,7 @@ const makeCanvas = () => {
65
65
  canvas.height = 0;
66
66
  return ctx;
67
67
  };
68
- exports.Canvas = (0, react_1.forwardRef)(({ index, frames, width, height, fit, className, style, effects }, ref) => {
68
+ exports.Canvas = (0, react_1.forwardRef)(({ index, frames, width, height, fit, className, style, effects, effectsOutputSize, }, ref) => {
69
69
  const canvasRef = (0, react_1.useRef)(null);
70
70
  const [tempCtx] = (0, react_1.useState)(() => {
71
71
  return makeCanvas();
@@ -82,13 +82,13 @@ exports.Canvas = (0, react_1.forwardRef)(({ index, frames, width, height, fit, c
82
82
  }
83
83
  return document.createElement('canvas');
84
84
  }, []);
85
- const chainState = useEffectChainState();
85
+ const chainState = useEffectChainState(effectsOutputSize);
86
86
  const { delayRender, continueRender, cancelRender } = (0, remotion_1.useDelayRender)();
87
87
  const size = (0, use_element_size_1.useElementSize)(canvasRef);
88
88
  (0, react_1.useImperativeHandle)(ref, () => {
89
89
  return canvasRef.current;
90
90
  }, []);
91
- (0, react_1.useEffect)(() => {
91
+ (0, react_1.useLayoutEffect)(() => {
92
92
  if (!size) {
93
93
  return;
94
94
  }
@@ -1,5 +1,7 @@
1
+ import type { EffectsOutputSize } from 'remotion';
1
2
  export type GifLoopBehavior = 'loop' | 'pause-after-finish' | 'unmount-after-finish';
2
3
  export type RemotionGifProps = {
4
+ effectsOutputSize?: EffectsOutputSize;
3
5
  src: string;
4
6
  width?: number;
5
7
  height?: number;
@@ -51,7 +51,7 @@ const useElementSize = (ref) => {
51
51
  height: rect[0].height,
52
52
  });
53
53
  }, [ref]);
54
- (0, react_1.useEffect)(() => {
54
+ (0, react_1.useLayoutEffect)(() => {
55
55
  if (!observer) {
56
56
  return;
57
57
  }
@@ -785,15 +785,15 @@ var makeWorker = () => {
785
785
 
786
786
  // src/react-tools.ts
787
787
  var parseGif = async ({
788
- src: src2,
788
+ src,
789
789
  controller,
790
790
  requestInit
791
791
  }) => {
792
- const raw = await parse2(src2, { signal: controller.signal, requestInit });
792
+ const raw = await parse2(src, { signal: controller.signal, requestInit });
793
793
  return generate(raw);
794
794
  };
795
795
  var parseWithWorker = ({
796
- src: src2,
796
+ src,
797
797
  cacheKey,
798
798
  requestInit
799
799
  }) => {
@@ -815,7 +815,7 @@ var parseWithWorker = ({
815
815
  };
816
816
  worker.addEventListener("message", handler);
817
817
  worker.postMessage({
818
- src: src2,
818
+ src,
819
819
  cacheKey,
820
820
  requestInit: workerRequestInit,
821
821
  type: "parse"
@@ -832,19 +832,19 @@ var parseWithWorker = ({
832
832
  };
833
833
 
834
834
  // src/resolve-gif-source.ts
835
- var resolveGifSource = (src2) => {
835
+ var resolveGifSource = (src) => {
836
836
  if (typeof window === "undefined") {
837
- return src2;
837
+ return src;
838
838
  }
839
- return new URL(src2, document.baseURI).href;
839
+ return new URL(src, document.baseURI).href;
840
840
  };
841
841
 
842
842
  // src/get-gif-duration-in-seconds.ts
843
843
  var calcDuration = (parsed) => {
844
844
  return parsed.delays.reduce((sum, delay) => sum + delay, 0) / 1000;
845
845
  };
846
- var getGifDurationInSeconds = async (src2, options) => {
847
- const resolvedSrc = resolveGifSource(src2);
846
+ var getGifDurationInSeconds = async (src, options) => {
847
+ const resolvedSrc = resolveGifSource(src);
848
848
  const cacheKey = getGifCacheKey({
849
849
  resolvedSrc,
850
850
  requestInit: options?.requestInit
@@ -872,7 +872,7 @@ var getGifDurationInSeconds = async (src2, options) => {
872
872
  return calcDuration(parsed);
873
873
  };
874
874
  // src/Gif.tsx
875
- import React, { useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "react";
875
+ import React, { useLayoutEffect as useLayoutEffect4, useRef as useRef4, useState as useState5 } from "react";
876
876
  import {
877
877
  Freeze,
878
878
  Internals as Internals3,
@@ -884,12 +884,12 @@ import {
884
884
  } from "remotion";
885
885
 
886
886
  // src/GifForDevelopment.tsx
887
- import { forwardRef as forwardRef2, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
887
+ import { forwardRef as forwardRef2, useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
888
888
 
889
889
  // src/canvas.tsx
890
890
  import {
891
891
  forwardRef,
892
- useEffect as useEffect2,
892
+ useLayoutEffect as useLayoutEffect2,
893
893
  useImperativeHandle,
894
894
  useMemo as useMemo2,
895
895
  useRef,
@@ -898,7 +898,13 @@ import {
898
898
  import { Internals, useDelayRender } from "remotion";
899
899
 
900
900
  // src/use-element-size.ts
901
- import { useCallback, useEffect, useMemo, useState } from "react";
901
+ import {
902
+ useCallback,
903
+ useEffect,
904
+ useLayoutEffect,
905
+ useMemo,
906
+ useState
907
+ } from "react";
902
908
  var elementSizeHooks = [];
903
909
  var useElementSize = (ref) => {
904
910
  const [size, setSize] = useState(null);
@@ -936,7 +942,7 @@ var useElementSize = (ref) => {
936
942
  height: rect[0].height
937
943
  });
938
944
  }, [ref]);
939
- useEffect(() => {
945
+ useLayoutEffect(() => {
940
946
  if (!observer) {
941
947
  return;
942
948
  }
@@ -1021,7 +1027,17 @@ var makeCanvas = () => {
1021
1027
  canvas.height = 0;
1022
1028
  return ctx;
1023
1029
  };
1024
- var Canvas = forwardRef(({ index, frames, width, height, fit, className, style, effects }, ref) => {
1030
+ var Canvas = forwardRef(({
1031
+ index,
1032
+ frames,
1033
+ width,
1034
+ height,
1035
+ fit,
1036
+ className,
1037
+ style,
1038
+ effects,
1039
+ effectsOutputSize
1040
+ }, ref) => {
1025
1041
  const canvasRef = useRef(null);
1026
1042
  const [tempCtx] = useState2(() => {
1027
1043
  return makeCanvas();
@@ -1038,13 +1054,13 @@ var Canvas = forwardRef(({ index, frames, width, height, fit, className, style,
1038
1054
  }
1039
1055
  return document.createElement("canvas");
1040
1056
  }, []);
1041
- const chainState = useEffectChainState();
1057
+ const chainState = useEffectChainState(effectsOutputSize);
1042
1058
  const { delayRender, continueRender, cancelRender } = useDelayRender();
1043
1059
  const size = useElementSize(canvasRef);
1044
1060
  useImperativeHandle(ref, () => {
1045
1061
  return canvasRef.current;
1046
1062
  }, []);
1047
- useEffect2(() => {
1063
+ useLayoutEffect2(() => {
1048
1064
  if (!size) {
1049
1065
  return;
1050
1066
  }
@@ -1199,7 +1215,7 @@ function useCurrentGifIndex({
1199
1215
  // src/GifForDevelopment.tsx
1200
1216
  import { jsx as jsx2 } from "react/jsx-runtime";
1201
1217
  var GifForDevelopment = forwardRef2(({
1202
- src: src2,
1218
+ src,
1203
1219
  width,
1204
1220
  height,
1205
1221
  onError,
@@ -1209,9 +1225,10 @@ var GifForDevelopment = forwardRef2(({
1209
1225
  fit = "fill",
1210
1226
  requestInit,
1211
1227
  effects,
1228
+ effectsOutputSize = null,
1212
1229
  ...props
1213
1230
  }, ref) => {
1214
- const resolvedSrc = resolveGifSource(src2);
1231
+ const resolvedSrc = resolveGifSource(src);
1215
1232
  const requestInitRef = useRef2(requestInit);
1216
1233
  requestInitRef.current = requestInit;
1217
1234
  const cacheKey = getGifCacheKey({ resolvedSrc, requestInit });
@@ -1232,7 +1249,7 @@ var GifForDevelopment = forwardRef2(({
1232
1249
  const currentOnError = useRef2(onError);
1233
1250
  currentOnLoad.current = onLoad;
1234
1251
  currentOnError.current = onError;
1235
- useEffect3(() => {
1252
+ useEffect2(() => {
1236
1253
  const parsedGif = volatileGifCache.get(cacheKey) ?? manuallyManagedGifCache.get(cacheKey);
1237
1254
  if (parsedGif !== undefined) {
1238
1255
  update(parsedGif);
@@ -1271,9 +1288,9 @@ var GifForDevelopment = forwardRef2(({
1271
1288
  if (error) {
1272
1289
  console.error(error.stack);
1273
1290
  if (isCorsError(error)) {
1274
- throw new Error(`Failed to render GIF with source ${src2}: "${error.message}". You must enable CORS for this URL. Open the Developer Tools to see exactly why this fetch failed.`);
1291
+ throw new Error(`Failed to render GIF with source ${src}: "${error.message}". You must enable CORS for this URL. Open the Developer Tools to see exactly why this fetch failed.`);
1275
1292
  }
1276
- throw new Error(`Failed to render GIF with source ${src2}: "${error.message}".`);
1293
+ throw new Error(`Failed to render GIF with source ${src}: "${error.message}".`);
1277
1294
  }
1278
1295
  const index = useCurrentGifIndex({
1279
1296
  delays: state.delays,
@@ -1290,17 +1307,18 @@ var GifForDevelopment = forwardRef2(({
1290
1307
  width,
1291
1308
  height,
1292
1309
  effects,
1310
+ effectsOutputSize,
1293
1311
  ...props,
1294
1312
  ref
1295
1313
  });
1296
1314
  });
1297
1315
 
1298
1316
  // src/GifForRendering.tsx
1299
- import { forwardRef as forwardRef3, useEffect as useEffect4, useRef as useRef3, useState as useState4 } from "react";
1317
+ import { forwardRef as forwardRef3, useLayoutEffect as useLayoutEffect3, useRef as useRef3, useState as useState4 } from "react";
1300
1318
  import { Internals as Internals2, useDelayRender as useDelayRender2 } from "remotion";
1301
1319
  import { jsx as jsx3 } from "react/jsx-runtime";
1302
1320
  var GifForRendering = forwardRef3(({
1303
- src: src2,
1321
+ src,
1304
1322
  width,
1305
1323
  height,
1306
1324
  onLoad,
@@ -1311,9 +1329,10 @@ var GifForRendering = forwardRef3(({
1311
1329
  delayRenderTimeoutInMilliseconds,
1312
1330
  requestInit,
1313
1331
  effects,
1332
+ effectsOutputSize = null,
1314
1333
  ...props
1315
1334
  }, ref) => {
1316
- const resolvedSrc = resolveGifSource(src2);
1335
+ const resolvedSrc = resolveGifSource(src);
1317
1336
  const requestInitRef = useRef3(requestInit);
1318
1337
  requestInitRef.current = requestInit;
1319
1338
  const cacheKey = getGifCacheKey({ resolvedSrc, requestInit });
@@ -1325,21 +1344,14 @@ var GifForRendering = forwardRef3(({
1325
1344
  delays: [],
1326
1345
  frames: [],
1327
1346
  width: 0,
1328
- height: 0
1347
+ height: 0,
1348
+ handle: null
1329
1349
  };
1330
1350
  }
1331
- return parsedGif;
1351
+ return { ...parsedGif, handle: null };
1332
1352
  });
1333
1353
  const [error, setError] = useState4(null);
1334
- const [renderHandle] = useState4(() => delayRender(`Rendering <Gif/> with src="${resolvedSrc}"`, {
1335
- timeoutInMilliseconds: delayRenderTimeoutInMilliseconds
1336
- }));
1337
1354
  const logLevel = Internals2.useLogLevel();
1338
- useEffect4(() => {
1339
- return () => {
1340
- continueRender(renderHandle);
1341
- };
1342
- }, [renderHandle, continueRender]);
1343
1355
  const index = useCurrentGifIndex({
1344
1356
  delays: state.delays,
1345
1357
  loopBehavior,
@@ -1349,7 +1361,7 @@ var GifForRendering = forwardRef3(({
1349
1361
  const currentOnError = useRef3(onError);
1350
1362
  currentOnLoad.current = onLoad;
1351
1363
  currentOnError.current = onError;
1352
- useEffect4(() => {
1364
+ useLayoutEffect3(() => {
1353
1365
  const controller = new AbortController;
1354
1366
  let done = false;
1355
1367
  let aborted = false;
@@ -1363,13 +1375,14 @@ var GifForRendering = forwardRef3(({
1363
1375
  src: resolvedSrc,
1364
1376
  requestInit: requestInitRef.current
1365
1377
  }).then((parsed) => {
1378
+ if (aborted) {
1379
+ return;
1380
+ }
1366
1381
  Internals2.Log.verbose({ logLevel, tag: null }, "Parsed GIF in", Date.now() - time, "ms");
1367
1382
  currentOnLoad.current?.(parsed);
1368
- update(parsed);
1383
+ update({ ...parsed, handle: newHandle });
1369
1384
  volatileGifCache.set(cacheKey, parsed);
1370
1385
  done = true;
1371
- continueRender(newHandle);
1372
- continueRender(renderHandle);
1373
1386
  }).catch((err) => {
1374
1387
  if (aborted) {
1375
1388
  continueRender(newHandle);
@@ -1388,10 +1401,8 @@ var GifForRendering = forwardRef3(({
1388
1401
  controller.abort();
1389
1402
  }
1390
1403
  continueRender(newHandle);
1391
- continueRender(renderHandle);
1392
1404
  };
1393
1405
  }, [
1394
- renderHandle,
1395
1406
  logLevel,
1396
1407
  cacheKey,
1397
1408
  resolvedSrc,
@@ -1399,12 +1410,17 @@ var GifForRendering = forwardRef3(({
1399
1410
  continueRender,
1400
1411
  delayRenderTimeoutInMilliseconds
1401
1412
  ]);
1413
+ useLayoutEffect3(() => {
1414
+ if (state.handle !== null) {
1415
+ continueRender(state.handle);
1416
+ }
1417
+ }, [state, continueRender]);
1402
1418
  if (error) {
1403
1419
  Internals2.Log.error({ logLevel, tag: null }, error.stack);
1404
1420
  if (isCorsError(error)) {
1405
- throw new Error(`Failed to render GIF with source ${src2}: "${error.message}". You must enable CORS for this URL.`);
1421
+ throw new Error(`Failed to render GIF with source ${src}: "${error.message}". You must enable CORS for this URL.`);
1406
1422
  }
1407
- throw new Error(`Failed to render GIF with source ${src2}: "${error.message}". Render with --log=verbose to see the full stack.`);
1423
+ throw new Error(`Failed to render GIF with source ${src}: "${error.message}". Render with --log=verbose to see the full stack.`);
1408
1424
  }
1409
1425
  if (index === -1) {
1410
1426
  return null;
@@ -1416,6 +1432,7 @@ var GifForRendering = forwardRef3(({
1416
1432
  width,
1417
1433
  height,
1418
1434
  effects,
1435
+ effectsOutputSize,
1419
1436
  ...props,
1420
1437
  ref
1421
1438
  });
@@ -1441,7 +1458,7 @@ var gifSchema = {
1441
1458
  ...Interactive.cropSchema
1442
1459
  };
1443
1460
  var GifInner = ({
1444
- src: src2,
1461
+ src,
1445
1462
  width,
1446
1463
  height,
1447
1464
  onLoad,
@@ -1465,6 +1482,7 @@ var GifInner = ({
1465
1482
  cropBottom,
1466
1483
  controls,
1467
1484
  effects = [],
1485
+ effectsOutputSize,
1468
1486
  ref,
1469
1487
  ...sequenceProps
1470
1488
  }) => {
@@ -1506,7 +1524,7 @@ var GifInner = ({
1506
1524
  videoConfigValues: controls?.videoConfigValues ?? null
1507
1525
  });
1508
1526
  const gifProps = {
1509
- src: src2,
1527
+ src,
1510
1528
  width,
1511
1529
  height,
1512
1530
  onLoad,
@@ -1517,7 +1535,8 @@ var GifInner = ({
1517
1535
  delayRenderTimeoutInMilliseconds,
1518
1536
  requestInit,
1519
1537
  style: croppedStyle ?? undefined,
1520
- effects: memoizedEffects
1538
+ effects: memoizedEffects,
1539
+ effectsOutputSize
1521
1540
  };
1522
1541
  const inner = env.isRendering ? /* @__PURE__ */ jsx4(GifForRendering, {
1523
1542
  ...gifProps,
@@ -1550,21 +1569,25 @@ var GifInner = ({
1550
1569
  var GifWithIntrinsicDuration = (props) => {
1551
1570
  const { fps } = useVideoConfig2();
1552
1571
  const { delayRender, continueRender, cancelRender } = useDelayRender3();
1553
- const { src: src2, requestInit, trimBefore } = props;
1572
+ const { src, requestInit, trimBefore } = props;
1554
1573
  const onErrorRef = useRef4(props.onError);
1555
1574
  onErrorRef.current = props.onError;
1556
1575
  const requestInitRef = useRef4(requestInit);
1557
1576
  requestInitRef.current = requestInit;
1558
- const [handle] = useState5(() => delayRender(`Finding duration of <Gif src="${src2}" />`, {
1559
- timeoutInMilliseconds: props.delayRenderTimeoutInMilliseconds
1560
- }));
1561
- const [durationInFrames, setDurationInFrames] = useState5(null);
1562
- const [failed, setFailed] = useState5(false);
1563
- useEffect5(() => {
1577
+ const [duration, setDuration] = useState5(null);
1578
+ const [failedHandle, setFailedHandle] = useState5(null);
1579
+ const { delayRenderTimeoutInMilliseconds } = props;
1580
+ useLayoutEffect4(() => {
1581
+ const handle = delayRender(`Finding duration of <Gif src="${src}" />`, {
1582
+ timeoutInMilliseconds: delayRenderTimeoutInMilliseconds
1583
+ });
1564
1584
  let cancelled = false;
1565
- getGifDurationInSeconds(src2, { requestInit: requestInitRef.current }).then((duration) => {
1585
+ getGifDurationInSeconds(src, { requestInit: requestInitRef.current }).then((durationInSeconds) => {
1566
1586
  if (!cancelled) {
1567
- setDurationInFrames(Math.ceil(duration * fps) - (trimBefore ?? 0));
1587
+ setDuration({
1588
+ durationInFrames: Math.ceil(durationInSeconds * fps) - (trimBefore ?? 0),
1589
+ handle
1590
+ });
1568
1591
  }
1569
1592
  }).catch((error) => {
1570
1593
  if (cancelled) {
@@ -1572,7 +1595,7 @@ var GifWithIntrinsicDuration = (props) => {
1572
1595
  }
1573
1596
  if (onErrorRef.current) {
1574
1597
  onErrorRef.current(error);
1575
- setFailed(true);
1598
+ setFailedHandle(handle);
1576
1599
  } else {
1577
1600
  cancelRender(error);
1578
1601
  }
@@ -1581,18 +1604,29 @@ var GifWithIntrinsicDuration = (props) => {
1581
1604
  cancelled = true;
1582
1605
  continueRender(handle);
1583
1606
  };
1584
- }, [cancelRender, continueRender, fps, handle, src2, trimBefore]);
1585
- useEffect5(() => {
1586
- if (durationInFrames !== null || failed) {
1587
- continueRender(handle);
1607
+ }, [
1608
+ cancelRender,
1609
+ continueRender,
1610
+ delayRender,
1611
+ delayRenderTimeoutInMilliseconds,
1612
+ fps,
1613
+ src,
1614
+ trimBefore
1615
+ ]);
1616
+ useLayoutEffect4(() => {
1617
+ if (duration !== null) {
1618
+ continueRender(duration.handle);
1619
+ }
1620
+ if (failedHandle !== null) {
1621
+ continueRender(failedHandle);
1588
1622
  }
1589
- }, [continueRender, durationInFrames, failed, handle]);
1590
- if (durationInFrames === null || failed) {
1623
+ }, [continueRender, duration, failedHandle]);
1624
+ if (duration === null || failedHandle !== null) {
1591
1625
  return null;
1592
1626
  }
1593
1627
  return /* @__PURE__ */ jsx4(GifInner, {
1594
1628
  ...props,
1595
- durationInFrames
1629
+ durationInFrames: duration.durationInFrames
1596
1630
  });
1597
1631
  };
1598
1632
  var GifComponent = (props) => {
@@ -1620,8 +1654,8 @@ var Gif = Interactive.withSchema({
1620
1654
  });
1621
1655
  Gif.displayName = "Gif";
1622
1656
  // src/preload-gif.ts
1623
- var preloadGif = (src2, options) => {
1624
- const resolvedSrc = resolveGifSource(src2);
1657
+ var preloadGif = (src, options) => {
1658
+ const resolvedSrc = resolveGifSource(src);
1625
1659
  const cacheKey = getGifCacheKey({
1626
1660
  resolvedSrc,
1627
1661
  requestInit: options?.requestInit
@@ -1661,7 +1695,7 @@ var preloadGif = (src2, options) => {
1661
1695
  };
1662
1696
  };
1663
1697
  export {
1664
- preloadGif,
1698
+ Gif,
1665
1699
  getGifDurationInSeconds,
1666
- Gif
1700
+ preloadGif
1667
1701
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/gif"
4
4
  },
5
5
  "name": "@remotion/gif",
6
- "version": "4.0.534",
6
+ "version": "4.0.536",
7
7
  "description": "Embed GIFs in a Remotion video",
8
8
  "bugs": {
9
9
  "url": "https://github.com/remotion-dev/remotion/issues"
@@ -30,7 +30,7 @@
30
30
  }
31
31
  },
32
32
  "dependencies": {
33
- "remotion": "4.0.534"
33
+ "remotion": "4.0.536"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@testing-library/react": "16.1.0",
@@ -38,7 +38,7 @@
38
38
  "react": "19.2.3",
39
39
  "react-dom": "19.2.3",
40
40
  "webpack": "5.105.0",
41
- "@remotion/eslint-config-internal": "4.0.534",
41
+ "@remotion/eslint-config-internal": "4.0.536",
42
42
  "eslint": "9.19.0",
43
43
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
44
44
  },