@remotion/gif 4.0.529 → 4.0.530

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
@@ -1,14 +1,15 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.Gif = exports.gifSchema = void 0;
7
4
  const jsx_runtime_1 = require("react/jsx-runtime");
8
- const react_1 = __importDefault(require("react"));
5
+ const react_1 = require("react");
6
+ const react_2 = require("react");
9
7
  const remotion_1 = require("remotion");
8
+ const get_gif_duration_in_seconds_1 = require("./get-gif-duration-in-seconds");
10
9
  const GifForDevelopment_1 = require("./GifForDevelopment");
11
10
  const GifForRendering_1 = require("./GifForRendering");
11
+ const request_init_1 = require("./request-init");
12
+ const resolve_gif_source_1 = require("./resolve-gif-source");
12
13
  const { useMemoizedEffectDefinitions, useMemoizedEffects } = remotion_1.Internals;
13
14
  /*
14
15
  * @description Displays a GIF that synchronizes with Remotions useCurrentFrame().
@@ -26,10 +27,13 @@ exports.gifSchema = {
26
27
  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 }) => {
27
28
  var _a;
28
29
  const env = (0, remotion_1.useRemotionEnvironment)();
29
- const refForOutline = react_1.default.useRef(null);
30
30
  const { effectivePostmountFor, effectivePremountFor, freezeFrame, isPremountingOrPostmounting, postmountingActive, premountingActive, premountingStyle, } = remotion_1.Internals.usePremounting({
31
31
  from: from !== null && from !== void 0 ? from : 0,
32
- durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : Infinity,
32
+ durationInFrames: remotion_1.Internals.resolveSequenceDuration({
33
+ durationInFrames,
34
+ playbackRate,
35
+ loop: sequenceProps.loop,
36
+ }),
33
37
  premountFor: premountFor !== null && premountFor !== void 0 ? premountFor : null,
34
38
  postmountFor: postmountFor !== null && postmountFor !== void 0 ? postmountFor : null,
35
39
  style: style !== null && style !== void 0 ? style : null,
@@ -64,11 +68,71 @@ const GifInner = ({ src, width, height, onLoad, onError, fit, playbackRate, loop
64
68
  style: croppedStyle !== null && croppedStyle !== void 0 ? croppedStyle : undefined,
65
69
  effects: memoizedEffects,
66
70
  };
67
- const inner = env.isRendering ? (jsx_runtime_1.jsx(GifForRendering_1.GifForRendering, { ...gifProps, ref: ref })) : (jsx_runtime_1.jsx(GifForDevelopment_1.GifForDevelopment, { ...gifProps, ref: ref, refForOutline: refForOutline }));
68
- 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 !== null && durationInFrames !== void 0 ? durationInFrames : Infinity, 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, outlineRef: refForOutline, children: inner }) }));
71
+ const inner = env.isRendering ? (jsx_runtime_1.jsx(GifForRendering_1.GifForRendering, { ...gifProps, ref: ref })) : (jsx_runtime_1.jsx(GifForDevelopment_1.GifForDevelopment, { ...gifProps, ref: ref }));
72
+ 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 }) }));
73
+ };
74
+ const GifWithIntrinsicDuration = (props) => {
75
+ const { fps } = (0, remotion_1.useVideoConfig)();
76
+ const { delayRender, continueRender, cancelRender } = (0, remotion_1.useDelayRender)();
77
+ const { src, requestInit, trimBefore } = props;
78
+ const onErrorRef = (0, react_2.useRef)(props.onError);
79
+ onErrorRef.current = props.onError;
80
+ const requestInitRef = (0, react_2.useRef)(requestInit);
81
+ requestInitRef.current = requestInit;
82
+ const [handle] = (0, react_2.useState)(() => delayRender(`Finding duration of <Gif src="${src}" />`, {
83
+ timeoutInMilliseconds: props.delayRenderTimeoutInMilliseconds,
84
+ }));
85
+ const [durationInFrames, setDurationInFrames] = (0, react_2.useState)(null);
86
+ const [failed, setFailed] = (0, react_2.useState)(false);
87
+ (0, react_2.useEffect)(() => {
88
+ let cancelled = false;
89
+ (0, get_gif_duration_in_seconds_1.getGifDurationInSeconds)(src, { requestInit: requestInitRef.current })
90
+ .then((duration) => {
91
+ if (!cancelled) {
92
+ setDurationInFrames(Math.ceil(duration * fps) - (trimBefore !== null && trimBefore !== void 0 ? trimBefore : 0));
93
+ }
94
+ })
95
+ .catch((error) => {
96
+ if (cancelled) {
97
+ return;
98
+ }
99
+ if (onErrorRef.current) {
100
+ onErrorRef.current(error);
101
+ setFailed(true);
102
+ }
103
+ else {
104
+ cancelRender(error);
105
+ }
106
+ });
107
+ return () => {
108
+ cancelled = true;
109
+ continueRender(handle);
110
+ };
111
+ }, [cancelRender, continueRender, fps, handle, src, trimBefore]);
112
+ (0, react_2.useEffect)(() => {
113
+ if (durationInFrames !== null || failed) {
114
+ continueRender(handle);
115
+ }
116
+ }, [continueRender, durationInFrames, failed, handle]);
117
+ if (durationInFrames === null || failed) {
118
+ return null;
119
+ }
120
+ return jsx_runtime_1.jsx(GifInner, { ...props, durationInFrames: durationInFrames });
121
+ };
122
+ const GifComponent = (props) => {
123
+ var _a;
124
+ if (props.loop && props.durationInFrames === undefined) {
125
+ const resolvedSrc = (0, resolve_gif_source_1.resolveGifSource)(props.src);
126
+ const cacheKey = (0, request_init_1.getGifCacheKey)({
127
+ resolvedSrc,
128
+ requestInit: props.requestInit,
129
+ });
130
+ return (react_1.createElement(GifWithIntrinsicDuration, { ...props, key: `${cacheKey}-${(_a = props.trimBefore) !== null && _a !== void 0 ? _a : 0}` }));
131
+ }
132
+ return jsx_runtime_1.jsx(GifInner, { ...props });
69
133
  };
70
134
  exports.Gif = remotion_1.Interactive.withSchema({
71
- Component: GifInner,
135
+ Component: GifComponent,
72
136
  componentName: '<Gif>',
73
137
  componentIdentity: 'dev.remotion.gif.Gif',
74
138
  schema: exports.gifSchema,
@@ -1,7 +1,5 @@
1
- import { type RefObject } from 'react';
2
1
  import type { EffectDefinitionAndStack } from 'remotion';
3
2
  import type { RemotionGifProps } from './props';
4
3
  export declare const GifForDevelopment: import("react").ForwardRefExoticComponent<RemotionGifProps & {
5
4
  readonly effects: EffectDefinitionAndStack<unknown>[];
6
- readonly refForOutline: RefObject<HTMLElement | null>;
7
5
  } & import("react").RefAttributes<HTMLCanvasElement>>;
@@ -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, refForOutline, ...props }, ref) => {
14
+ exports.GifForDevelopment = (0, react_1.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, onLoad, fit = 'fill', requestInit, effects, ...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, refForOutline: refForOutline, ...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, ...props, ref: ref }));
95
95
  });
@@ -1,4 +1,3 @@
1
- import { type RefObject } from 'react';
2
1
  import type { EffectDefinitionAndStack } from 'remotion';
3
2
  import type { GifFillMode } from './props';
4
3
  type Props = {
@@ -10,7 +9,6 @@ type Props = {
10
9
  readonly className?: string;
11
10
  readonly style?: React.CSSProperties;
12
11
  readonly effects: EffectDefinitionAndStack<unknown>[];
13
- readonly refForOutline?: RefObject<HTMLElement | null>;
14
12
  };
15
13
  export declare const Canvas: import("react").ForwardRefExoticComponent<Props & import("react").RefAttributes<unknown>>;
16
14
  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, refForOutline, }, ref) => {
68
+ exports.Canvas = (0, react_1.forwardRef)(({ index, frames, width, height, fit, className, style, effects }, ref) => {
69
69
  const canvasRef = (0, react_1.useRef)(null);
70
70
  const [tempCtx] = (0, react_1.useState)(() => {
71
71
  return makeCanvas();
@@ -88,12 +88,6 @@ exports.Canvas = (0, react_1.forwardRef)(({ index, frames, width, height, fit, c
88
88
  (0, react_1.useImperativeHandle)(ref, () => {
89
89
  return canvasRef.current;
90
90
  }, []);
91
- const canvasCallbackRef = (0, react_1.useCallback)((canvas) => {
92
- canvasRef.current = canvas;
93
- if (refForOutline) {
94
- refForOutline.current = canvas;
95
- }
96
- }, [refForOutline]);
97
91
  (0, react_1.useEffect)(() => {
98
92
  if (!size) {
99
93
  return;
@@ -202,5 +196,5 @@ exports.Canvas = (0, react_1.forwardRef)(({ index, frames, width, height, fit, c
202
196
  continueRender,
203
197
  cancelRender,
204
198
  ]);
205
- return (jsx_runtime_1.jsx("canvas", { ref: canvasCallbackRef, className: className, style: style, width: width !== null && width !== void 0 ? width : size === null || size === void 0 ? void 0 : size.width, height: height !== null && height !== void 0 ? height : size === null || size === void 0 ? void 0 : size.height }));
199
+ return (jsx_runtime_1.jsx("canvas", { ref: canvasRef, className: className, style: style, width: width !== null && width !== void 0 ? width : size === null || size === void 0 ? void 0 : size.width, height: height !== null && height !== void 0 ? height : size === null || size === void 0 ? void 0 : size.height }));
206
200
  });
@@ -872,13 +872,15 @@ var getGifDurationInSeconds = async (src2, options) => {
872
872
  return calcDuration(parsed);
873
873
  };
874
874
  // src/Gif.tsx
875
- import React from "react";
875
+ import React, { useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "react";
876
876
  import {
877
877
  Freeze,
878
878
  Internals as Internals3,
879
879
  Interactive,
880
880
  Sequence,
881
- useRemotionEnvironment
881
+ useDelayRender as useDelayRender3,
882
+ useRemotionEnvironment,
883
+ useVideoConfig as useVideoConfig2
882
884
  } from "remotion";
883
885
 
884
886
  // src/GifForDevelopment.tsx
@@ -887,7 +889,6 @@ import { forwardRef as forwardRef2, useEffect as useEffect3, useRef as useRef2,
887
889
  // src/canvas.tsx
888
890
  import {
889
891
  forwardRef,
890
- useCallback as useCallback2,
891
892
  useEffect as useEffect2,
892
893
  useImperativeHandle,
893
894
  useMemo as useMemo2,
@@ -1020,17 +1021,7 @@ var makeCanvas = () => {
1020
1021
  canvas.height = 0;
1021
1022
  return ctx;
1022
1023
  };
1023
- var Canvas = forwardRef(({
1024
- index,
1025
- frames,
1026
- width,
1027
- height,
1028
- fit,
1029
- className,
1030
- style,
1031
- effects,
1032
- refForOutline
1033
- }, ref) => {
1024
+ var Canvas = forwardRef(({ index, frames, width, height, fit, className, style, effects }, ref) => {
1034
1025
  const canvasRef = useRef(null);
1035
1026
  const [tempCtx] = useState2(() => {
1036
1027
  return makeCanvas();
@@ -1053,12 +1044,6 @@ var Canvas = forwardRef(({
1053
1044
  useImperativeHandle(ref, () => {
1054
1045
  return canvasRef.current;
1055
1046
  }, []);
1056
- const canvasCallbackRef = useCallback2((canvas) => {
1057
- canvasRef.current = canvas;
1058
- if (refForOutline) {
1059
- refForOutline.current = canvas;
1060
- }
1061
- }, [refForOutline]);
1062
1047
  useEffect2(() => {
1063
1048
  if (!size) {
1064
1049
  return;
@@ -1160,7 +1145,7 @@ var Canvas = forwardRef(({
1160
1145
  cancelRender
1161
1146
  ]);
1162
1147
  return /* @__PURE__ */ jsx("canvas", {
1163
- ref: canvasCallbackRef,
1148
+ ref: canvasRef,
1164
1149
  className,
1165
1150
  style,
1166
1151
  width: width ?? size?.width,
@@ -1224,7 +1209,6 @@ var GifForDevelopment = forwardRef2(({
1224
1209
  fit = "fill",
1225
1210
  requestInit,
1226
1211
  effects,
1227
- refForOutline,
1228
1212
  ...props
1229
1213
  }, ref) => {
1230
1214
  const resolvedSrc = resolveGifSource(src2);
@@ -1306,7 +1290,6 @@ var GifForDevelopment = forwardRef2(({
1306
1290
  width,
1307
1291
  height,
1308
1292
  effects,
1309
- refForOutline,
1310
1293
  ...props,
1311
1294
  ref
1312
1295
  });
@@ -1440,6 +1423,7 @@ var GifForRendering = forwardRef3(({
1440
1423
 
1441
1424
  // src/Gif.tsx
1442
1425
  import { jsx as jsx4 } from "react/jsx-runtime";
1426
+ import { createElement } from "react";
1443
1427
  var { useMemoizedEffectDefinitions, useMemoizedEffects } = Internals3;
1444
1428
  var gifSchema = {
1445
1429
  ...Internals3.baseSchema,
@@ -1479,7 +1463,6 @@ var GifInner = ({
1479
1463
  ...sequenceProps
1480
1464
  }) => {
1481
1465
  const env = useRemotionEnvironment();
1482
- const refForOutline = React.useRef(null);
1483
1466
  const {
1484
1467
  effectivePostmountFor,
1485
1468
  effectivePremountFor,
@@ -1490,7 +1473,11 @@ var GifInner = ({
1490
1473
  premountingStyle
1491
1474
  } = Internals3.usePremounting({
1492
1475
  from: from ?? 0,
1493
- durationInFrames: durationInFrames ?? Infinity,
1476
+ durationInFrames: Internals3.resolveSequenceDuration({
1477
+ durationInFrames,
1478
+ playbackRate,
1479
+ loop: sequenceProps.loop
1480
+ }),
1494
1481
  premountFor: premountFor ?? null,
1495
1482
  postmountFor: postmountFor ?? null,
1496
1483
  style: style ?? null,
@@ -1530,8 +1517,7 @@ var GifInner = ({
1530
1517
  ref
1531
1518
  }) : /* @__PURE__ */ jsx4(GifForDevelopment, {
1532
1519
  ...gifProps,
1533
- ref,
1534
- refForOutline
1520
+ ref
1535
1521
  });
1536
1522
  return /* @__PURE__ */ jsx4(Freeze, {
1537
1523
  frame: freezeFrame,
@@ -1540,7 +1526,7 @@ var GifInner = ({
1540
1526
  layout: "none",
1541
1527
  from: from ?? 0,
1542
1528
  playbackRate,
1543
- durationInFrames: durationInFrames ?? Infinity,
1529
+ durationInFrames,
1544
1530
  name: "<Gif>",
1545
1531
  _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/gif/gif",
1546
1532
  controls,
@@ -1550,13 +1536,76 @@ var GifInner = ({
1550
1536
  _remotionInternalIsPremounting: premountingActive,
1551
1537
  _remotionInternalIsPostmounting: postmountingActive,
1552
1538
  ...sequenceProps,
1553
- outlineRef: refForOutline,
1554
1539
  children: inner
1555
1540
  })
1556
1541
  });
1557
1542
  };
1543
+ var GifWithIntrinsicDuration = (props) => {
1544
+ const { fps } = useVideoConfig2();
1545
+ const { delayRender, continueRender, cancelRender } = useDelayRender3();
1546
+ const { src: src2, requestInit, trimBefore } = props;
1547
+ const onErrorRef = useRef4(props.onError);
1548
+ onErrorRef.current = props.onError;
1549
+ const requestInitRef = useRef4(requestInit);
1550
+ requestInitRef.current = requestInit;
1551
+ const [handle] = useState5(() => delayRender(`Finding duration of <Gif src="${src2}" />`, {
1552
+ timeoutInMilliseconds: props.delayRenderTimeoutInMilliseconds
1553
+ }));
1554
+ const [durationInFrames, setDurationInFrames] = useState5(null);
1555
+ const [failed, setFailed] = useState5(false);
1556
+ useEffect5(() => {
1557
+ let cancelled = false;
1558
+ getGifDurationInSeconds(src2, { requestInit: requestInitRef.current }).then((duration) => {
1559
+ if (!cancelled) {
1560
+ setDurationInFrames(Math.ceil(duration * fps) - (trimBefore ?? 0));
1561
+ }
1562
+ }).catch((error) => {
1563
+ if (cancelled) {
1564
+ return;
1565
+ }
1566
+ if (onErrorRef.current) {
1567
+ onErrorRef.current(error);
1568
+ setFailed(true);
1569
+ } else {
1570
+ cancelRender(error);
1571
+ }
1572
+ });
1573
+ return () => {
1574
+ cancelled = true;
1575
+ continueRender(handle);
1576
+ };
1577
+ }, [cancelRender, continueRender, fps, handle, src2, trimBefore]);
1578
+ useEffect5(() => {
1579
+ if (durationInFrames !== null || failed) {
1580
+ continueRender(handle);
1581
+ }
1582
+ }, [continueRender, durationInFrames, failed, handle]);
1583
+ if (durationInFrames === null || failed) {
1584
+ return null;
1585
+ }
1586
+ return /* @__PURE__ */ jsx4(GifInner, {
1587
+ ...props,
1588
+ durationInFrames
1589
+ });
1590
+ };
1591
+ var GifComponent = (props) => {
1592
+ if (props.loop && props.durationInFrames === undefined) {
1593
+ const resolvedSrc = resolveGifSource(props.src);
1594
+ const cacheKey = getGifCacheKey({
1595
+ resolvedSrc,
1596
+ requestInit: props.requestInit
1597
+ });
1598
+ return /* @__PURE__ */ createElement(GifWithIntrinsicDuration, {
1599
+ ...props,
1600
+ key: `${cacheKey}-${props.trimBefore ?? 0}`
1601
+ });
1602
+ }
1603
+ return /* @__PURE__ */ jsx4(GifInner, {
1604
+ ...props
1605
+ });
1606
+ };
1558
1607
  var Gif = Interactive.withSchema({
1559
- Component: GifInner,
1608
+ Component: GifComponent,
1560
1609
  componentName: "<Gif>",
1561
1610
  componentIdentity: "dev.remotion.gif.Gif",
1562
1611
  schema: gifSchema,
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.529",
6
+ "version": "4.0.530",
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.529"
33
+ "remotion": "4.0.530"
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.529",
41
+ "@remotion/eslint-config-internal": "4.0.530",
42
42
  "eslint": "9.19.0",
43
43
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
44
44
  },