remotion 4.0.229 → 4.0.231
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/ResolveCompositionConfig.js +5 -1
- package/dist/cjs/multiple-versions-warning.js +15 -4
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/index.mjs +17 -6
- package/dist/esm/version.mjs +1 -1
- package/package.json +2 -2
- package/dist/cjs/NativeLayers.d.ts +0 -13
- package/dist/cjs/NativeLayers.js +0 -30
- package/dist/cjs/animated-image/AnimatedImage.d.ts +0 -2
- package/dist/cjs/animated-image/AnimatedImage.js +0 -62
- package/dist/cjs/animated-image/canvas.d.ts +0 -15
- package/dist/cjs/animated-image/canvas.js +0 -114
- package/dist/cjs/animated-image/decode-image.d.ts +0 -14
- package/dist/cjs/animated-image/decode-image.js +0 -117
- package/dist/cjs/animated-image/index.d.ts +0 -1
- package/dist/cjs/animated-image/index.js +0 -5
- package/dist/cjs/animated-image/props.d.ts +0 -19
- package/dist/cjs/animated-image/props.js +0 -2
- package/dist/cjs/animated-image/resolve-image-source.d.ts +0 -1
- package/dist/cjs/animated-image/resolve-image-source.js +0 -8
- package/dist/cjs/animated-image/use-element-size.d.ts +0 -6
- package/dist/cjs/animated-image/use-element-size.js +0 -73
|
@@ -237,7 +237,11 @@ const ResolveCompositionConfig = ({ children }) => {
|
|
|
237
237
|
// to the file
|
|
238
238
|
return;
|
|
239
239
|
}
|
|
240
|
-
window.dispatchEvent(new CustomEvent(
|
|
240
|
+
window.dispatchEvent(new CustomEvent(exports.PROPS_UPDATED_EXTERNALLY, {
|
|
241
|
+
detail: {
|
|
242
|
+
resetUnsaved: true,
|
|
243
|
+
},
|
|
244
|
+
}));
|
|
241
245
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
242
246
|
}, [fastRefreshes]);
|
|
243
247
|
(0, react_1.useEffect)(() => {
|
|
@@ -7,6 +7,12 @@ const checkMultipleRemotionVersions = () => {
|
|
|
7
7
|
if (typeof globalThis === 'undefined') {
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
|
+
const set = () => {
|
|
11
|
+
globalThis.remotion_imported = version_js_1.VERSION;
|
|
12
|
+
if (typeof window !== 'undefined') {
|
|
13
|
+
window.remotion_imported = version_js_1.VERSION;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
10
16
|
const alreadyImported = globalThis.remotion_imported ||
|
|
11
17
|
(typeof window !== 'undefined' && window.remotion_imported);
|
|
12
18
|
if (alreadyImported) {
|
|
@@ -15,6 +21,14 @@ const checkMultipleRemotionVersions = () => {
|
|
|
15
21
|
// It's okay if this happens during SSR in developement
|
|
16
22
|
return;
|
|
17
23
|
}
|
|
24
|
+
// @remotion/webcodecs will also set this variable for the purpose of
|
|
25
|
+
// being picked up by Wappalyzer.
|
|
26
|
+
// If so, we can just override it because it is not the same as Remotion
|
|
27
|
+
if (typeof alreadyImported === 'string' &&
|
|
28
|
+
alreadyImported.includes('webcodecs')) {
|
|
29
|
+
set();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
18
32
|
throw new TypeError(`🚨 Multiple versions of Remotion detected: ${[
|
|
19
33
|
version_js_1.VERSION,
|
|
20
34
|
typeof alreadyImported === 'string'
|
|
@@ -24,9 +38,6 @@ const checkMultipleRemotionVersions = () => {
|
|
|
24
38
|
.filter(truthy_js_1.truthy)
|
|
25
39
|
.join(' and ')}. This will cause things to break in an unexpected way.\nCheck that all your Remotion packages are on the same version. If your dependencies depend on Remotion, make them peer dependencies. You can also run \`npx remotion versions\` from your terminal to see which versions are mismatching.`);
|
|
26
40
|
}
|
|
27
|
-
|
|
28
|
-
if (typeof window !== 'undefined') {
|
|
29
|
-
window.remotion_imported = version_js_1.VERSION;
|
|
30
|
-
}
|
|
41
|
+
set();
|
|
31
42
|
};
|
|
32
43
|
exports.checkMultipleRemotionVersions = checkMultipleRemotionVersions;
|
package/dist/cjs/version.d.ts
CHANGED
package/dist/cjs/version.js
CHANGED
package/dist/esm/index.mjs
CHANGED
|
@@ -101,27 +101,34 @@ function truthy(value) {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
// src/version.ts
|
|
104
|
-
var VERSION = "4.0.
|
|
104
|
+
var VERSION = "4.0.231";
|
|
105
105
|
|
|
106
106
|
// src/multiple-versions-warning.ts
|
|
107
107
|
var checkMultipleRemotionVersions = () => {
|
|
108
108
|
if (typeof globalThis === "undefined") {
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
|
+
const set = () => {
|
|
112
|
+
globalThis.remotion_imported = VERSION;
|
|
113
|
+
if (typeof window !== "undefined") {
|
|
114
|
+
window.remotion_imported = VERSION;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
111
117
|
const alreadyImported = globalThis.remotion_imported || typeof window !== "undefined" && window.remotion_imported;
|
|
112
118
|
if (alreadyImported) {
|
|
113
119
|
if (alreadyImported === VERSION) {
|
|
114
120
|
return;
|
|
115
121
|
}
|
|
122
|
+
if (typeof alreadyImported === "string" && alreadyImported.includes("webcodecs")) {
|
|
123
|
+
set();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
116
126
|
throw new TypeError(`\uD83D\uDEA8 Multiple versions of Remotion detected: ${[
|
|
117
127
|
VERSION,
|
|
118
128
|
typeof alreadyImported === "string" ? alreadyImported : "an older version"
|
|
119
129
|
].filter(truthy).join(" and ")}. This will cause things to break in an unexpected way.\nCheck that all your Remotion packages are on the same version. If your dependencies depend on Remotion, make them peer dependencies. You can also run \`npx remotion versions\` from your terminal to see which versions are mismatching.`);
|
|
120
130
|
}
|
|
121
|
-
|
|
122
|
-
if (typeof window !== "undefined") {
|
|
123
|
-
window.remotion_imported = VERSION;
|
|
124
|
-
}
|
|
131
|
+
set();
|
|
125
132
|
};
|
|
126
133
|
|
|
127
134
|
// src/Null.tsx
|
|
@@ -928,7 +935,11 @@ var ResolveCompositionConfig = ({ children }) => {
|
|
|
928
935
|
if (shouldIgnoreUpdate) {
|
|
929
936
|
return;
|
|
930
937
|
}
|
|
931
|
-
window.dispatchEvent(new CustomEvent(
|
|
938
|
+
window.dispatchEvent(new CustomEvent(PROPS_UPDATED_EXTERNALLY, {
|
|
939
|
+
detail: {
|
|
940
|
+
resetUnsaved: true
|
|
941
|
+
}
|
|
942
|
+
}));
|
|
932
943
|
}, [fastRefreshes]);
|
|
933
944
|
useEffect2(() => {
|
|
934
945
|
if (renderModalComposition && !isTheSame) {
|
package/dist/esm/version.mjs
CHANGED
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/core"
|
|
4
4
|
},
|
|
5
5
|
"name": "remotion",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.231",
|
|
7
7
|
"description": "Make videos programmatically",
|
|
8
8
|
"main": "dist/cjs/index.js",
|
|
9
9
|
"types": "dist/cjs/index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"webpack": "5.96.1",
|
|
29
29
|
"zod": "3.22.3",
|
|
30
30
|
"eslint": "9.14.0",
|
|
31
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
31
|
+
"@remotion/eslint-config-internal": "4.0.231"
|
|
32
32
|
},
|
|
33
33
|
"keywords": [
|
|
34
34
|
"remotion",
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { PropsWithChildren } from 'react';
|
|
2
|
-
export type ClipRegion = {
|
|
3
|
-
x: number;
|
|
4
|
-
y: number;
|
|
5
|
-
width: number;
|
|
6
|
-
height: number;
|
|
7
|
-
} | 'hide';
|
|
8
|
-
export type TNativeLayersContext = {
|
|
9
|
-
clipRegion: ClipRegion | null;
|
|
10
|
-
setClipRegion: React.Dispatch<React.SetStateAction<ClipRegion | null>>;
|
|
11
|
-
};
|
|
12
|
-
export declare const NativeLayersContext: import("react").Context<TNativeLayersContext>;
|
|
13
|
-
export declare const NativeLayersProvider: React.FC<PropsWithChildren>;
|
package/dist/cjs/NativeLayers.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NativeLayersProvider = exports.NativeLayersContext = void 0;
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_1 = require("react");
|
|
6
|
-
exports.NativeLayersContext = (0, react_1.createContext)({
|
|
7
|
-
setClipRegion: () => {
|
|
8
|
-
throw new Error('NativeLayers not set');
|
|
9
|
-
},
|
|
10
|
-
clipRegion: null,
|
|
11
|
-
});
|
|
12
|
-
const NativeLayersProvider = ({ children, }) => {
|
|
13
|
-
const [clipRegion, setClipRegion] = (0, react_1.useState)(null);
|
|
14
|
-
const context = (0, react_1.useMemo)(() => {
|
|
15
|
-
return {
|
|
16
|
-
setClipRegion,
|
|
17
|
-
clipRegion,
|
|
18
|
-
};
|
|
19
|
-
}, [clipRegion, setClipRegion]);
|
|
20
|
-
if (typeof window !== 'undefined') {
|
|
21
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
22
|
-
(0, react_1.useLayoutEffect)(() => {
|
|
23
|
-
window.remotion_getClipRegion = () => {
|
|
24
|
-
return clipRegion;
|
|
25
|
-
};
|
|
26
|
-
}, [clipRegion, setClipRegion]);
|
|
27
|
-
}
|
|
28
|
-
return ((0, jsx_runtime_1.jsx)(exports.NativeLayersContext.Provider, { value: context, children: children }));
|
|
29
|
-
};
|
|
30
|
-
exports.NativeLayersProvider = NativeLayersProvider;
|
|
@@ -1,62 +0,0 @@
|
|
|
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
|
-
});
|
|
@@ -1,15 +0,0 @@
|
|
|
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 {};
|
|
@@ -1,114 +0,0 @@
|
|
|
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);
|
|
@@ -1,14 +0,0 @@
|
|
|
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>;
|
|
@@ -1,117 +0,0 @@
|
|
|
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;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { AnimatedImage } from './AnimatedImage';
|
|
@@ -1,5 +0,0 @@
|
|
|
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; } });
|
|
@@ -1,19 +0,0 @@
|
|
|
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';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const resolveAnimatedImageSource: (src: string) => string;
|
|
@@ -1,8 +0,0 @@
|
|
|
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;
|
|
@@ -1,73 +0,0 @@
|
|
|
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;
|