remotion 4.0.227 → 4.0.229

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 (39) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/Clipper.d.ts +4 -6
  3. package/dist/cjs/Clipper.js +5 -19
  4. package/dist/cjs/Composition.d.ts +1 -2
  5. package/dist/cjs/Composition.js +2 -19
  6. package/dist/cjs/Null.d.ts +3 -0
  7. package/dist/cjs/Null.js +4 -19
  8. package/dist/cjs/RemotionRoot.js +1 -2
  9. package/dist/cjs/animated-image/AnimatedImage.d.ts +2 -0
  10. package/dist/cjs/animated-image/AnimatedImage.js +62 -0
  11. package/dist/cjs/animated-image/canvas.d.ts +15 -0
  12. package/dist/cjs/animated-image/canvas.js +114 -0
  13. package/dist/cjs/animated-image/decode-image.d.ts +14 -0
  14. package/dist/cjs/animated-image/decode-image.js +117 -0
  15. package/dist/cjs/animated-image/index.d.ts +1 -0
  16. package/dist/cjs/animated-image/index.js +5 -0
  17. package/dist/cjs/animated-image/props.d.ts +19 -0
  18. package/dist/cjs/animated-image/props.js +2 -0
  19. package/dist/cjs/animated-image/resolve-image-source.d.ts +1 -0
  20. package/dist/cjs/animated-image/resolve-image-source.js +8 -0
  21. package/dist/cjs/animated-image/use-element-size.d.ts +6 -0
  22. package/dist/cjs/animated-image/use-element-size.js +73 -0
  23. package/dist/cjs/audio/Audio.js +3 -0
  24. package/dist/cjs/index.d.ts +1 -9
  25. package/dist/cjs/internals.d.ts +0 -6
  26. package/dist/cjs/internals.js +0 -4
  27. package/dist/cjs/no-react.d.ts +0 -1
  28. package/dist/cjs/prefetch.d.ts +1 -0
  29. package/dist/cjs/prefetch.js +2 -1
  30. package/dist/cjs/version.d.ts +1 -1
  31. package/dist/cjs/version.js +1 -1
  32. package/dist/cjs/video/Video.js +3 -0
  33. package/dist/cjs/video/VideoForRendering.js +1 -1
  34. package/dist/cjs/video/seek-until-right.js +7 -0
  35. package/dist/cjs/wrap-remotion-context.d.ts +0 -1
  36. package/dist/cjs/wrap-remotion-context.js +1 -5
  37. package/dist/esm/index.mjs +449 -520
  38. package/dist/esm/version.mjs +1 -1
  39. package/package.json +4 -4
package/README.md CHANGED
@@ -26,11 +26,11 @@ Remotion is a framework for **creating videos programmatically using React.**
26
26
  <table>
27
27
  <tr>
28
28
  <td align="center">
29
- <img style="width: 290px" src="packages/docs/static/img/fireship-quick.gif" />
29
+ <img style="width: 290px" src="https://remotion-assets.s3.eu-central-1.amazonaws.com/fireship-quick.gif" />
30
30
  <p>"This video was made with code" <em>- Fireship</em> <a href="https://youtu.be/deg8bOoziaE">Watch</a> • <a href="https://github.com/wcandillon/remotion-fireship">Source</a></p>
31
31
  </td>
32
32
  <td align="center">
33
- <img style="width: 240px" src="packages/docs/static/img/unwrapped-2023.gif" />
33
+ <img style="width: 240px" src="https://remotion-assets.s3.eu-central-1.amazonaws.com/unwrapped-2023.gif" />
34
34
  <p>GitHub Unwrapped - Personalized Year in Review <a href="https://www.githubunwrapped.com">Try</a> • <a href="https://github.com/remotion-dev/github-unwrapped-2023">Source</a></p>
35
35
  </td>
36
36
  <td align="center">
@@ -1,7 +1,5 @@
1
1
  import type React from 'react';
2
- export declare const Clipper: React.FC<{
3
- readonly width: number;
4
- readonly height: number;
5
- readonly x: number;
6
- readonly y: number;
7
- }>;
2
+ /**
3
+ * @deprecated <Clipper> has been removed as of Remotion v4.0.228. The native clipping APIs were experimental and subject to removal at any time. We removed them because they were sparingly used and made rendering often slower rather than faster.
4
+ */
5
+ export declare const Clipper: React.FC<{}>;
@@ -1,24 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Clipper = void 0;
4
- const react_1 = require("react");
5
- const NativeLayers_js_1 = require("./NativeLayers.js");
6
- const Clipper = ({ height, width, x, y }) => {
7
- const { setClipRegion } = (0, react_1.useContext)(NativeLayers_js_1.NativeLayersContext);
8
- (0, react_1.useEffect)(() => {
9
- setClipRegion((c) => {
10
- if (c === 'hide') {
11
- throw new Error('Cannot render <Clipper>, because another <Null> is already rendered');
12
- }
13
- if (c === null) {
14
- return { height, width, x, y };
15
- }
16
- throw new Error('Cannot render <Clipper>, because another component clipping the region was already rendered (most likely <Clipper>)');
17
- });
18
- return () => {
19
- setClipRegion(null);
20
- };
21
- }, [height, setClipRegion, width, x, y]);
22
- return null;
4
+ /**
5
+ * @deprecated <Clipper> has been removed as of Remotion v4.0.228. The native clipping APIs were experimental and subject to removal at any time. We removed them because they were sparingly used and made rendering often slower rather than faster.
6
+ */
7
+ const Clipper = () => {
8
+ throw new Error('<Clipper> has been removed as of Remotion v4.0.228. The native clipping APIs were experimental and subject to removal at any time. We removed them because they were sparingly used and made rendering often slower rather than faster.');
23
9
  };
24
10
  exports.Clipper = Clipper;
@@ -1,4 +1,4 @@
1
- import type { ComponentType, PropsWithChildren } from 'react';
1
+ import type { ComponentType } from 'react';
2
2
  import React from 'react';
3
3
  import type { AnyZodObject } from 'zod';
4
4
  import type { Codec } from './codec.js';
@@ -47,7 +47,6 @@ export type StillProps<Schema extends AnyZodObject, Props extends Record<string,
47
47
  id: string;
48
48
  schema?: Schema;
49
49
  } & StillCalculateMetadataOrExplicit<Schema, Props> & CompProps<Props> & PropsIfHasProps<Schema, Props>;
50
- export declare const ClipComposition: React.FC<PropsWithChildren>;
51
50
  export type CompositionProps<Schema extends AnyZodObject, Props extends Record<string, unknown>> = {
52
51
  readonly id: string;
53
52
  readonly schema?: Schema;
@@ -1,14 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Composition = exports.ClipComposition = void 0;
3
+ exports.Composition = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const react_dom_1 = require("react-dom");
7
- const AbsoluteFill_js_1 = require("./AbsoluteFill.js");
8
7
  const CanUseRemotionHooks_js_1 = require("./CanUseRemotionHooks.js");
9
8
  const CompositionManagerContext_js_1 = require("./CompositionManagerContext.js");
10
9
  const Folder_js_1 = require("./Folder.js");
11
- const NativeLayers_js_1 = require("./NativeLayers.js");
12
10
  const ResolveCompositionConfig_js_1 = require("./ResolveCompositionConfig.js");
13
11
  const delay_render_js_1 = require("./delay-render.js");
14
12
  const get_remotion_environment_js_1 = require("./get-remotion-environment.js");
@@ -21,21 +19,6 @@ const use_lazy_component_js_1 = require("./use-lazy-component.js");
21
19
  const use_video_js_1 = require("./use-video.js");
22
20
  const validate_composition_id_js_1 = require("./validation/validate-composition-id.js");
23
21
  const validate_default_props_js_1 = require("./validation/validate-default-props.js");
24
- const ClipComposition = ({ children }) => {
25
- const { clipRegion } = (0, react_1.useContext)(NativeLayers_js_1.NativeLayersContext);
26
- const style = (0, react_1.useMemo)(() => {
27
- return {
28
- display: 'flex',
29
- flexDirection: 'row',
30
- opacity: clipRegion === 'hide' ? 0 : 1,
31
- clipPath: clipRegion && clipRegion !== 'hide'
32
- ? `polygon(${clipRegion.x}px ${clipRegion.y}px, ${clipRegion.x}px ${clipRegion.height + clipRegion.y}px, ${clipRegion.width + clipRegion.x}px ${clipRegion.height + clipRegion.y}px, ${clipRegion.width + clipRegion.x}px ${clipRegion.y}px)`
33
- : undefined,
34
- };
35
- }, [clipRegion]);
36
- return (0, jsx_runtime_1.jsx)(AbsoluteFill_js_1.AbsoluteFill, { style: style, children: children });
37
- };
38
- exports.ClipComposition = ClipComposition;
39
22
  const Fallback = () => {
40
23
  (0, react_1.useEffect)(() => {
41
24
  const fallback = (0, delay_render_js_1.delayRender)('Waiting for Root component to unsuspend');
@@ -110,7 +93,7 @@ const Composition = ({ width, height, fps, durationInFrames, id, defaultProps, s
110
93
  if (resolved === null || resolved.type !== 'success') {
111
94
  return null;
112
95
  }
113
- return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(exports.ClipComposition, { children: (0, jsx_runtime_1.jsx)(CanUseRemotionHooks_js_1.CanUseRemotionHooksProvider, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(loading_indicator_js_1.Loading, {}), children: (0, jsx_runtime_1.jsx)(Comp, { ...((_a = resolved.result.props) !== null && _a !== void 0 ? _a : {}) }) }) }) }), (0, portal_node_js_1.portalNode)());
96
+ return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(CanUseRemotionHooks_js_1.CanUseRemotionHooksProvider, { children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)(loading_indicator_js_1.Loading, {}), children: (0, jsx_runtime_1.jsx)(Comp, { ...((_a = resolved.result.props) !== null && _a !== void 0 ? _a : {}) }) }) }), (0, portal_node_js_1.portalNode)());
114
97
  }
115
98
  if (environment.isRendering && video && video.component === lazy) {
116
99
  const Comp = lazy;
@@ -1 +1,4 @@
1
+ /**
2
+ * @deprecated <Null /> has been removed as of Remotion v4.0.228. The native clipping APIs were experimental and subject to removal at any time. We removed them because they were sparingly used and made rendering often slower rather than faster.
3
+ */
1
4
  export declare const Null: React.FC;
package/dist/cjs/Null.js CHANGED
@@ -1,25 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Null = void 0;
4
- const react_1 = require("react");
5
- const NativeLayers_js_1 = require("./NativeLayers.js");
4
+ /**
5
+ * @deprecated <Null /> has been removed as of Remotion v4.0.228. The native clipping APIs were experimental and subject to removal at any time. We removed them because they were sparingly used and made rendering often slower rather than faster.
6
+ */
6
7
  const Null = () => {
7
- const { setClipRegion } = (0, react_1.useContext)(NativeLayers_js_1.NativeLayersContext);
8
- (0, react_1.useEffect)(() => {
9
- setClipRegion((c) => {
10
- if (c === null) {
11
- return 'hide';
12
- }
13
- // Rendering multiple <Null> is fine, because they are all hidden
14
- if (c === 'hide') {
15
- return 'hide';
16
- }
17
- throw new Error('Cannot render <Null>, because another component clipping the region was already rendered (most likely <Clipper>)');
18
- });
19
- return () => {
20
- setClipRegion(null);
21
- };
22
- }, [setClipRegion]);
23
- return null;
8
+ throw new Error('<Null> has been removed as of Remotion v4.0.228. The native clipping APIs were experimental and subject to removal at any time. We removed them because they were sparingly used and made rendering often slower rather than faster.');
24
9
  };
25
10
  exports.Null = Null;
@@ -5,7 +5,6 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const CompositionManager_js_1 = require("./CompositionManager.js");
7
7
  const EditorProps_js_1 = require("./EditorProps.js");
8
- const NativeLayers_js_1 = require("./NativeLayers.js");
9
8
  const buffering_js_1 = require("./buffering.js");
10
9
  const delay_render_js_1 = require("./delay-render.js");
11
10
  const nonce_js_1 = require("./nonce.js");
@@ -87,6 +86,6 @@ const RemotionRoot = ({ children, numberOfAudioTags }) => {
87
86
  }
88
87
  }
89
88
  }, []);
90
- return ((0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(timeline_position_state_js_1.TimelineContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(timeline_position_state_js_1.SetTimelineContext.Provider, { value: setTimelineContextValue, children: (0, jsx_runtime_1.jsx)(EditorProps_js_1.EditorPropsProvider, { children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(NativeLayers_js_1.NativeLayersProvider, { children: (0, jsx_runtime_1.jsx)(CompositionManager_js_1.CompositionManagerProvider, { numberOfAudioTags: numberOfAudioTags, children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: (0, jsx_runtime_1.jsx)(buffering_js_1.BufferingProvider, { children: children }) }) }) }) }) }) }) }) }));
89
+ return ((0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(timeline_position_state_js_1.TimelineContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(timeline_position_state_js_1.SetTimelineContext.Provider, { value: setTimelineContextValue, children: (0, jsx_runtime_1.jsx)(EditorProps_js_1.EditorPropsProvider, { children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(CompositionManager_js_1.CompositionManagerProvider, { numberOfAudioTags: numberOfAudioTags, children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: (0, jsx_runtime_1.jsx)(buffering_js_1.BufferingProvider, { children: children }) }) }) }) }) }) }) }));
91
90
  };
92
91
  exports.RemotionRoot = RemotionRoot;
@@ -0,0 +1,2 @@
1
+ import type { RemotionAnimatedImageProps } from './props';
2
+ export declare const AnimatedImage: import("react").ForwardRefExoticComponent<RemotionAnimatedImageProps & import("react").RefAttributes<HTMLCanvasElement>>;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnimatedImage = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const cancel_render_js_1 = require("../cancel-render.js");
7
+ const delay_render_js_1 = require("../delay-render.js");
8
+ const use_current_frame_js_1 = require("../use-current-frame.js");
9
+ const use_video_config_js_1 = require("../use-video-config.js");
10
+ const canvas_1 = require("./canvas");
11
+ const decode_image_js_1 = require("./decode-image.js");
12
+ const resolve_image_source_1 = require("./resolve-image-source");
13
+ exports.AnimatedImage = (0, react_1.forwardRef)(({ src, width, height, onError, loopBehavior = 'loop', playbackRate = 1, onLoad, fit = 'fill', ...props }, canvasRef) => {
14
+ const resolvedSrc = (0, resolve_image_source_1.resolveAnimatedImageSource)(src);
15
+ const [imageDecoder, setImageDecoder] = (0, react_1.useState)(null);
16
+ const [id] = (0, react_1.useState)(() => (0, delay_render_js_1.delayRender)(`Rendering <AnimatedImage/> with src="${resolvedSrc}"`));
17
+ const frame = (0, use_current_frame_js_1.useCurrentFrame)();
18
+ const { fps } = (0, use_video_config_js_1.useVideoConfig)();
19
+ const currentTime = frame / fps;
20
+ const currentTimeRef = (0, react_1.useRef)(currentTime);
21
+ currentTimeRef.current = currentTime;
22
+ const ref = (0, react_1.useRef)(null);
23
+ (0, react_1.useImperativeHandle)(canvasRef, () => {
24
+ var _a;
25
+ const c = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.getCanvas();
26
+ if (!c) {
27
+ throw new Error('Canvas ref is not set');
28
+ }
29
+ return c;
30
+ }, []);
31
+ (0, react_1.useEffect)(() => {
32
+ const controller = new AbortController();
33
+ (0, decode_image_js_1.decodeImage)({
34
+ resolvedSrc,
35
+ signal: controller.signal,
36
+ currentTime: currentTimeRef.current,
37
+ })
38
+ .then((d) => {
39
+ setImageDecoder(d);
40
+ })
41
+ .catch((err) => {
42
+ if (err.name === 'AbortError') {
43
+ return;
44
+ }
45
+ // TODO: Allow to catch error
46
+ (0, cancel_render_js_1.cancelRender)(err);
47
+ });
48
+ return () => {
49
+ controller.abort();
50
+ };
51
+ }, [resolvedSrc, id, onLoad, onError]);
52
+ (0, react_1.useEffect)(() => {
53
+ if (!imageDecoder) {
54
+ return;
55
+ }
56
+ imageDecoder.getFrame(currentTime).then((videoFrame) => {
57
+ var _a;
58
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.draw(videoFrame.frame);
59
+ });
60
+ }, [currentTime, imageDecoder]);
61
+ return ((0, jsx_runtime_1.jsx)(canvas_1.Canvas, { ref: ref, width: width, height: height, fit: fit, ...props }));
62
+ });
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import type { AnimatedImageFillMode } from './props';
3
+ type Props = {
4
+ readonly width?: number;
5
+ readonly height?: number;
6
+ readonly fit: AnimatedImageFillMode;
7
+ readonly className?: string;
8
+ readonly style?: React.CSSProperties;
9
+ };
10
+ export type AnimatedImageCanvasRef = {
11
+ readonly draw: (imageData: VideoFrame) => void;
12
+ readonly getCanvas: () => HTMLCanvasElement | null;
13
+ };
14
+ export declare const Canvas: React.ForwardRefExoticComponent<Props & React.RefAttributes<AnimatedImageCanvasRef>>;
15
+ export {};
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.Canvas = void 0;
27
+ const jsx_runtime_1 = require("react/jsx-runtime");
28
+ const react_1 = __importStar(require("react"));
29
+ const calcArgs = (fit, frameSize, canvasSize) => {
30
+ switch (fit) {
31
+ case 'fill': {
32
+ return [
33
+ 0,
34
+ 0,
35
+ frameSize.width,
36
+ frameSize.height,
37
+ 0,
38
+ 0,
39
+ canvasSize.width,
40
+ canvasSize.height,
41
+ ];
42
+ }
43
+ case 'contain': {
44
+ const ratio = Math.min(canvasSize.width / frameSize.width, canvasSize.height / frameSize.height);
45
+ const centerX = (canvasSize.width - frameSize.width * ratio) / 2;
46
+ const centerY = (canvasSize.height - frameSize.height * ratio) / 2;
47
+ return [
48
+ 0,
49
+ 0,
50
+ frameSize.width,
51
+ frameSize.height,
52
+ centerX,
53
+ centerY,
54
+ frameSize.width * ratio,
55
+ frameSize.height * ratio,
56
+ ];
57
+ }
58
+ case 'cover': {
59
+ const ratio = Math.max(canvasSize.width / frameSize.width, canvasSize.height / frameSize.height);
60
+ const centerX = (canvasSize.width - frameSize.width * ratio) / 2;
61
+ const centerY = (canvasSize.height - frameSize.height * ratio) / 2;
62
+ return [
63
+ 0,
64
+ 0,
65
+ frameSize.width,
66
+ frameSize.height,
67
+ centerX,
68
+ centerY,
69
+ frameSize.width * ratio,
70
+ frameSize.height * ratio,
71
+ ];
72
+ }
73
+ default:
74
+ throw new Error('Unknown fit: ' + fit);
75
+ }
76
+ };
77
+ const CanvasRefForwardingFunction = ({ width, height, fit, className, style }, ref) => {
78
+ const canvasRef = (0, react_1.useRef)(null);
79
+ const draw = (0, react_1.useCallback)((imageData) => {
80
+ var _a;
81
+ const canvas = canvasRef.current;
82
+ const canvasWidth = width !== null && width !== void 0 ? width : imageData.displayWidth;
83
+ const canvasHeight = height !== null && height !== void 0 ? height : imageData.displayHeight;
84
+ if (!canvas) {
85
+ throw new Error('Canvas ref is not set');
86
+ }
87
+ const ctx = (_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.getContext('2d');
88
+ if (!ctx) {
89
+ throw new Error('Could not get 2d context');
90
+ }
91
+ canvas.width = canvasWidth;
92
+ canvas.height = canvasHeight;
93
+ ctx.drawImage(imageData, ...calcArgs(fit, {
94
+ height: imageData.displayHeight,
95
+ width: imageData.displayWidth,
96
+ }, {
97
+ width: canvasWidth,
98
+ height: canvasHeight,
99
+ }));
100
+ }, [fit, height, width]);
101
+ (0, react_1.useImperativeHandle)(ref, () => {
102
+ return {
103
+ draw,
104
+ getCanvas: () => {
105
+ if (!canvasRef.current) {
106
+ throw new Error('Canvas ref is not set');
107
+ }
108
+ return canvasRef.current;
109
+ },
110
+ };
111
+ }, [draw]);
112
+ return (0, jsx_runtime_1.jsx)("canvas", { ref: canvasRef, className: className, style: style });
113
+ };
114
+ exports.Canvas = react_1.default.forwardRef(CanvasRefForwardingFunction);
@@ -0,0 +1,14 @@
1
+ export type AnimatedImageCacheItem = {
2
+ timeInSeconds: number;
3
+ frameIndex: number;
4
+ frame: VideoFrame | null;
5
+ };
6
+ export type RemotionImageDecoder = {
7
+ getFrame: (i: number) => Promise<AnimatedImageCacheItem>;
8
+ frameCount: number;
9
+ };
10
+ export declare const decodeImage: ({ resolvedSrc, signal, currentTime, }: {
11
+ resolvedSrc: string;
12
+ signal: AbortSignal;
13
+ currentTime: number;
14
+ }) => Promise<RemotionImageDecoder>;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeImage = void 0;
4
+ const CACHE_SIZE = 5;
5
+ const decodeImage = async ({ resolvedSrc, signal, currentTime, }) => {
6
+ if (typeof ImageDecoder === 'undefined') {
7
+ throw new Error('Your browser does not support the WebCodecs ImageDecoder API.');
8
+ }
9
+ const res = await fetch(resolvedSrc, { signal });
10
+ const { body } = res;
11
+ if (!body) {
12
+ throw new Error('Got no body');
13
+ }
14
+ const decoder = new ImageDecoder({
15
+ data: body,
16
+ type: res.headers.get('Content-Type') || 'image/gif',
17
+ });
18
+ await decoder.completed;
19
+ const { selectedTrack } = decoder.tracks;
20
+ if (!selectedTrack) {
21
+ throw new Error('No selected track');
22
+ }
23
+ const cache = [];
24
+ let durationFound = null;
25
+ const getFrameByIndex = async (frameIndex) => {
26
+ const foundInCache = cache.find((c) => c.frameIndex === frameIndex);
27
+ if (foundInCache && foundInCache.frame) {
28
+ return foundInCache;
29
+ }
30
+ const frame = await decoder.decode({
31
+ frameIndex,
32
+ completeFramesOnly: true,
33
+ });
34
+ if (foundInCache) {
35
+ foundInCache.frame = frame.image;
36
+ }
37
+ else {
38
+ cache.push({
39
+ frame: frame.image,
40
+ frameIndex,
41
+ timeInSeconds: frame.image.timestamp / 1000000,
42
+ });
43
+ }
44
+ return {
45
+ frame: frame.image,
46
+ frameIndex,
47
+ timeInSeconds: frame.image.timestamp / 1000000,
48
+ };
49
+ };
50
+ const clearCache = (closeToTimeInSec) => {
51
+ const itemsInCache = cache.filter((c) => c.frame);
52
+ const sortByClosestToCurrentTime = itemsInCache.sort((a, b) => {
53
+ const aDiff = Math.abs(a.timeInSeconds - closeToTimeInSec);
54
+ const bDiff = Math.abs(b.timeInSeconds - closeToTimeInSec);
55
+ return aDiff - bDiff;
56
+ });
57
+ for (let i = 0; i < sortByClosestToCurrentTime.length; i++) {
58
+ if (i < CACHE_SIZE) {
59
+ continue;
60
+ }
61
+ const item = sortByClosestToCurrentTime[i];
62
+ item.frame = null;
63
+ }
64
+ };
65
+ const ensureFrameBeforeAndAfter = async (timeInSec) => {
66
+ const actualTimeInSec = durationFound
67
+ ? timeInSec % durationFound
68
+ : timeInSec;
69
+ const framesBefore = cache.filter((c) => c.timeInSeconds <= actualTimeInSec);
70
+ const biggestIndex = framesBefore
71
+ .map((c) => c.frameIndex)
72
+ .reduce((a, b) => Math.max(a, b), 0);
73
+ let i = biggestIndex;
74
+ while (true) {
75
+ const f = await getFrameByIndex(i);
76
+ i++;
77
+ if (!f.frame) {
78
+ throw new Error('No frame found');
79
+ }
80
+ if (!f.frame.duration) {
81
+ throw new Error('Frame has no duration');
82
+ }
83
+ if (i === selectedTrack.frameCount) {
84
+ const duration = (f.frame.timestamp + f.frame.duration) / 1000000;
85
+ durationFound = duration;
86
+ }
87
+ if (f.timeInSeconds > actualTimeInSec || i === selectedTrack.frameCount) {
88
+ break;
89
+ }
90
+ }
91
+ clearCache(actualTimeInSec);
92
+ };
93
+ // Twice because might be over total duration
94
+ await ensureFrameBeforeAndAfter(currentTime);
95
+ await ensureFrameBeforeAndAfter(currentTime);
96
+ const getFrame = async (timeInSec) => {
97
+ const actualTimeInSec = durationFound
98
+ ? timeInSec % durationFound
99
+ : timeInSec;
100
+ await ensureFrameBeforeAndAfter(actualTimeInSec);
101
+ const itemsInCache = cache.filter((c) => c.frame);
102
+ const closest = itemsInCache.reduce((a, b) => {
103
+ const aDiff = Math.abs(a.timeInSeconds - actualTimeInSec);
104
+ const bDiff = Math.abs(b.timeInSeconds - actualTimeInSec);
105
+ return aDiff < bDiff ? a : b;
106
+ });
107
+ if (!closest.frame) {
108
+ throw new Error('No frame found');
109
+ }
110
+ return closest;
111
+ };
112
+ return {
113
+ getFrame,
114
+ frameCount: selectedTrack.frameCount,
115
+ };
116
+ };
117
+ exports.decodeImage = decodeImage;
@@ -0,0 +1 @@
1
+ export { AnimatedImage } from './AnimatedImage';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnimatedImage = void 0;
4
+ var AnimatedImage_1 = require("./AnimatedImage");
5
+ Object.defineProperty(exports, "AnimatedImage", { enumerable: true, get: function () { return AnimatedImage_1.AnimatedImage; } });
@@ -0,0 +1,19 @@
1
+ export type RemotionAnimatedImageLoopBehavior = 'loop' | 'pause-after-finish' | 'unmount-after-finish';
2
+ export type RemotionAnimatedImageProps = {
3
+ src: string;
4
+ width?: number;
5
+ height?: number;
6
+ onLoad?: (info: {
7
+ width: number;
8
+ height: number;
9
+ delays: number[];
10
+ frames: ImageData[];
11
+ }) => void;
12
+ onError?: (error: Error) => void;
13
+ fit?: AnimatedImageFillMode;
14
+ playbackRate?: number;
15
+ style?: React.CSSProperties;
16
+ loopBehavior?: RemotionAnimatedImageLoopBehavior;
17
+ id?: string;
18
+ };
19
+ export type AnimatedImageFillMode = 'contain' | 'cover' | 'fill';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export declare const resolveAnimatedImageSource: (src: string) => string;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveAnimatedImageSource = void 0;
4
+ const resolveAnimatedImageSource = (src) => {
5
+ return new URL(src, typeof window === 'undefined' ? undefined : window.origin)
6
+ .href;
7
+ };
8
+ exports.resolveAnimatedImageSource = resolveAnimatedImageSource;
@@ -0,0 +1,6 @@
1
+ export type Size = {
2
+ width: number;
3
+ height: number;
4
+ };
5
+ export declare const updateAllElementsSizes: () => void;
6
+ export declare const useElementSize: (ref: React.RefObject<HTMLElement>) => Size | null;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useElementSize = exports.updateAllElementsSizes = void 0;
4
+ const react_1 = require("react");
5
+ let elementSizeHooks = [];
6
+ const updateAllElementsSizes = () => {
7
+ for (const listener of elementSizeHooks) {
8
+ listener();
9
+ }
10
+ };
11
+ exports.updateAllElementsSizes = updateAllElementsSizes;
12
+ const useElementSize = (ref) => {
13
+ const [size, setSize] = (0, react_1.useState)(null);
14
+ const observer = (0, react_1.useMemo)(() => {
15
+ if (typeof ResizeObserver === 'undefined') {
16
+ return null;
17
+ }
18
+ return new ResizeObserver((entries) => {
19
+ // The contentRect returns the width without any `scale()`'s being applied. The height is wrong
20
+ const { contentRect } = entries[0];
21
+ // The clientRect returns the size with `scale()` being applied.
22
+ const newSize = entries[0].target.getClientRects();
23
+ if (!(newSize === null || newSize === void 0 ? void 0 : newSize[0])) {
24
+ setSize(null);
25
+ return;
26
+ }
27
+ const probableCssParentScale = newSize[0].width / contentRect.width;
28
+ const width = newSize[0].width * (1 / probableCssParentScale);
29
+ const height = newSize[0].height * (1 / probableCssParentScale);
30
+ setSize({
31
+ width,
32
+ height,
33
+ });
34
+ });
35
+ }, []);
36
+ const updateSize = (0, react_1.useCallback)(() => {
37
+ if (!ref.current) {
38
+ return;
39
+ }
40
+ const rect = ref.current.getClientRects();
41
+ if (!rect[0]) {
42
+ setSize(null);
43
+ return;
44
+ }
45
+ setSize({
46
+ width: rect[0].width,
47
+ height: rect[0].height,
48
+ });
49
+ }, [ref]);
50
+ (0, react_1.useEffect)(() => {
51
+ if (!observer) {
52
+ return;
53
+ }
54
+ updateSize();
55
+ const { current } = ref;
56
+ if (ref.current) {
57
+ observer.observe(ref.current);
58
+ }
59
+ return () => {
60
+ if (current) {
61
+ observer.unobserve(current);
62
+ }
63
+ };
64
+ }, [observer, ref, updateSize]);
65
+ (0, react_1.useEffect)(() => {
66
+ elementSizeHooks.push(updateSize);
67
+ return () => {
68
+ elementSizeHooks = elementSizeHooks.filter((e) => e !== updateSize);
69
+ };
70
+ }, [updateSize]);
71
+ return size;
72
+ };
73
+ exports.useElementSize = useElementSize;
@@ -50,6 +50,9 @@ const AudioRefForwardingFunction = (props, ref) => {
50
50
  }, [setDurations]);
51
51
  const durationFetched = (_a = durations[(0, absolute_src_js_1.getAbsoluteSrc)(preloadedSrc)]) !== null && _a !== void 0 ? _a : durations[(0, absolute_src_js_1.getAbsoluteSrc)(props.src)];
52
52
  if (loop && durationFetched !== undefined) {
53
+ if (!Number.isFinite(durationFetched)) {
54
+ return ((0, jsx_runtime_1.jsx)(exports.Audio, { ...propsOtherThanLoop, ref: ref, _remotionInternalNativeLoopPassed: true }));
55
+ }
53
56
  const duration = durationFetched * fps;
54
57
  return ((0, jsx_runtime_1.jsx)(index_js_1.Loop, { layout: "none", durationInFrames: (0, calculate_loop_js_1.calculateLoopDuration)({
55
58
  endAt,