@remotion/player 3.3.55 → 3.3.56
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/esm/calculate-scale.d.ts +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/test/test-utils.d.ts +2 -2
- package/dist/esm/utils/delay.d.ts +1 -1
- package/dist/esm/utils/use-cancellable-promises.d.ts +1 -1
- package/dist/{tsconfig-cjs.tsbuildinfo → tsconfig-esm.tsbuildinfo} +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/dist/esm/MediaVolumeSlider.js +0 -114
- package/dist/esm/Player.js +0 -140
- package/dist/esm/PlayerControls.js +0 -146
- package/dist/esm/PlayerSeekBar.js +0 -142
- package/dist/esm/PlayerUI.js +0 -283
- package/dist/esm/SharedPlayerContext.js +0 -68
- package/dist/esm/Thumbnail.js +0 -39
- package/dist/esm/ThumbnailUI.js +0 -82
- package/dist/esm/calculate-next-frame.js +0 -24
- package/dist/esm/calculate-scale.js +0 -77
- package/dist/esm/emitter-context.js +0 -3
- package/dist/esm/error-boundary.js +0 -32
- package/dist/esm/event-emitter.js +0 -82
- package/dist/esm/format-time.js +0 -5
- package/dist/esm/icons.js +0 -42
- package/dist/esm/index.js +0 -20
- package/dist/esm/player-css-classname.js +0 -1
- package/dist/esm/player-methods.js +0 -1
- package/dist/esm/test/index.test.js +0 -7
- package/dist/esm/test/test-utils.js +0 -14
- package/dist/esm/test/validate-in-out-frames.test.js +0 -54
- package/dist/esm/test/validate-prop.test.js +0 -129
- package/dist/esm/use-hover-state.js +0 -23
- package/dist/esm/use-playback.js +0 -88
- package/dist/esm/use-player.js +0 -128
- package/dist/esm/use-thumbnail.js +0 -14
- package/dist/esm/use-video-controls-resize.js +0 -35
- package/dist/esm/utils/calculate-player-size.js +0 -24
- package/dist/esm/utils/cancellable-promise.js +0 -22
- package/dist/esm/utils/delay.js +0 -2
- package/dist/esm/utils/is-node.js +0 -1
- package/dist/esm/utils/preview-size.js +0 -1
- package/dist/esm/utils/props-if-has-props.js +0 -1
- package/dist/esm/utils/use-cancellable-promises.js +0 -18
- package/dist/esm/utils/use-click-prevention-on-double-click.js +0 -42
- package/dist/esm/utils/use-element-size.js +0 -93
- package/dist/esm/utils/validate-in-out-frame.js +0 -49
- package/dist/esm/utils/validate-initial-frame.js +0 -23
- package/dist/esm/utils/validate-playbackrate.js +0 -14
- package/dist/esm/volume-persistance.js +0 -14
package/dist/esm/PlayerUI.js
DELETED
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { forwardRef, Suspense, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
3
|
-
import { Internals } from 'remotion';
|
|
4
|
-
import { calculateCanvasTransformation, calculateContainerStyle, calculateOuter, calculateOuterStyle, } from './calculate-scale.js';
|
|
5
|
-
import { ErrorBoundary } from './error-boundary.js';
|
|
6
|
-
import { PLAYER_CSS_CLASSNAME } from './player-css-classname.js';
|
|
7
|
-
import { Controls } from './PlayerControls.js';
|
|
8
|
-
import { useHoverState } from './use-hover-state.js';
|
|
9
|
-
import { usePlayback } from './use-playback.js';
|
|
10
|
-
import { usePlayer } from './use-player.js';
|
|
11
|
-
import { IS_NODE } from './utils/is-node.js';
|
|
12
|
-
import { useClickPreventionOnDoubleClick } from './utils/use-click-prevention-on-double-click.js';
|
|
13
|
-
import { useElementSize } from './utils/use-element-size.js';
|
|
14
|
-
const reactVersion = React.version.split('.')[0];
|
|
15
|
-
if (reactVersion === '0') {
|
|
16
|
-
throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
|
|
17
|
-
}
|
|
18
|
-
const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
|
|
19
|
-
const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, doubleClickToFullscreen, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, renderPoster, className, moveToBeginningWhenEnded, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, inFrame, outFrame, initiallyShowControls, renderFullscreen: renderFullscreenButton, renderPlayPauseButton, alwaysShowControls, }, ref) => {
|
|
20
|
-
var _a, _b, _c, _d, _e;
|
|
21
|
-
const config = Internals.useUnsafeVideoConfig();
|
|
22
|
-
const video = Internals.useVideo();
|
|
23
|
-
const container = useRef(null);
|
|
24
|
-
const hovered = useHoverState(container);
|
|
25
|
-
const canvasSize = useElementSize(container, {
|
|
26
|
-
triggerOnWindowResize: false,
|
|
27
|
-
shouldApplyCssTransforms: false,
|
|
28
|
-
});
|
|
29
|
-
const [hasPausedToResume, setHasPausedToResume] = useState(false);
|
|
30
|
-
const [shouldAutoplay, setShouldAutoPlay] = useState(autoPlay);
|
|
31
|
-
const [isFullscreen, setIsFullscreen] = useState(() => false);
|
|
32
|
-
const [seeking, setSeeking] = useState(false);
|
|
33
|
-
usePlayback({
|
|
34
|
-
loop,
|
|
35
|
-
playbackRate,
|
|
36
|
-
moveToBeginningWhenEnded,
|
|
37
|
-
inFrame,
|
|
38
|
-
outFrame,
|
|
39
|
-
});
|
|
40
|
-
const player = usePlayer();
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
if (hasPausedToResume && !player.playing) {
|
|
43
|
-
setHasPausedToResume(false);
|
|
44
|
-
player.play();
|
|
45
|
-
}
|
|
46
|
-
}, [hasPausedToResume, player]);
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
const { current } = container;
|
|
49
|
-
if (!current) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
const onFullscreenChange = () => {
|
|
53
|
-
setIsFullscreen(document.fullscreenElement === current ||
|
|
54
|
-
document.webkitFullscreenElement === current);
|
|
55
|
-
};
|
|
56
|
-
document.addEventListener('fullscreenchange', onFullscreenChange);
|
|
57
|
-
document.addEventListener('webkitfullscreenchange', onFullscreenChange);
|
|
58
|
-
return () => {
|
|
59
|
-
document.removeEventListener('fullscreenchange', onFullscreenChange);
|
|
60
|
-
document.removeEventListener('webkitfullscreenchange', onFullscreenChange);
|
|
61
|
-
};
|
|
62
|
-
}, []);
|
|
63
|
-
const toggle = useCallback((e) => {
|
|
64
|
-
if (player.isPlaying()) {
|
|
65
|
-
player.pause();
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
player.play(e);
|
|
69
|
-
}
|
|
70
|
-
}, [player]);
|
|
71
|
-
const requestFullscreen = useCallback(() => {
|
|
72
|
-
if (!allowFullscreen) {
|
|
73
|
-
throw new Error('allowFullscreen is false');
|
|
74
|
-
}
|
|
75
|
-
const supportsFullScreen = document.fullscreenEnabled || document.webkitFullscreenEnabled;
|
|
76
|
-
if (!supportsFullScreen) {
|
|
77
|
-
throw new Error('Browser doesnt support fullscreen');
|
|
78
|
-
}
|
|
79
|
-
if (!container.current) {
|
|
80
|
-
throw new Error('No player ref found');
|
|
81
|
-
}
|
|
82
|
-
if (container.current.webkitRequestFullScreen) {
|
|
83
|
-
container.current.webkitRequestFullScreen();
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
container.current.requestFullscreen();
|
|
87
|
-
}
|
|
88
|
-
}, [allowFullscreen]);
|
|
89
|
-
const exitFullscreen = useCallback(() => {
|
|
90
|
-
if (document.webkitExitFullscreen) {
|
|
91
|
-
document.webkitExitFullscreen();
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
document.exitFullscreen();
|
|
95
|
-
}
|
|
96
|
-
}, []);
|
|
97
|
-
useEffect(() => {
|
|
98
|
-
const { current } = container;
|
|
99
|
-
if (!current) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const fullscreenChange = () => {
|
|
103
|
-
var _a;
|
|
104
|
-
const element = (_a = document.webkitFullscreenElement) !== null && _a !== void 0 ? _a : document.fullscreenElement;
|
|
105
|
-
if (element && element === container.current) {
|
|
106
|
-
player.emitter.dispatchFullscreenChangeUpdate({
|
|
107
|
-
isFullscreen: true,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
player.emitter.dispatchFullscreenChangeUpdate({
|
|
112
|
-
isFullscreen: false,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
current.addEventListener('webkitfullscreenchange', fullscreenChange);
|
|
117
|
-
current.addEventListener('fullscreenchange', fullscreenChange);
|
|
118
|
-
return () => {
|
|
119
|
-
current.removeEventListener('webkitfullscreenchange', fullscreenChange);
|
|
120
|
-
current.removeEventListener('fullscreenchange', fullscreenChange);
|
|
121
|
-
};
|
|
122
|
-
}, [player.emitter]);
|
|
123
|
-
const durationInFrames = (_a = config === null || config === void 0 ? void 0 : config.durationInFrames) !== null && _a !== void 0 ? _a : 1;
|
|
124
|
-
const layout = useMemo(() => {
|
|
125
|
-
if (!config || !canvasSize) {
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
return calculateCanvasTransformation({
|
|
129
|
-
canvasSize,
|
|
130
|
-
compositionHeight: config.height,
|
|
131
|
-
compositionWidth: config.width,
|
|
132
|
-
previewSize: 'auto',
|
|
133
|
-
});
|
|
134
|
-
}, [canvasSize, config]);
|
|
135
|
-
const scale = (_b = layout === null || layout === void 0 ? void 0 : layout.scale) !== null && _b !== void 0 ? _b : 1;
|
|
136
|
-
const { setMediaVolume, setMediaMuted } = useContext(Internals.SetMediaVolumeContext);
|
|
137
|
-
const { mediaMuted, mediaVolume } = useContext(Internals.MediaVolumeContext);
|
|
138
|
-
useImperativeHandle(ref, () => {
|
|
139
|
-
const methods = {
|
|
140
|
-
play: player.play,
|
|
141
|
-
pause: player.pause,
|
|
142
|
-
toggle,
|
|
143
|
-
getContainerNode: () => container.current,
|
|
144
|
-
getCurrentFrame: player.getCurrentFrame,
|
|
145
|
-
isPlaying: () => player.playing,
|
|
146
|
-
seekTo: (f) => {
|
|
147
|
-
const lastFrame = durationInFrames - 1;
|
|
148
|
-
const frameToSeekTo = Math.max(0, Math.min(lastFrame, f));
|
|
149
|
-
if (player.isPlaying()) {
|
|
150
|
-
const pauseToResume = frameToSeekTo !== lastFrame || loop;
|
|
151
|
-
setHasPausedToResume(pauseToResume);
|
|
152
|
-
player.pause();
|
|
153
|
-
}
|
|
154
|
-
if (frameToSeekTo === lastFrame && !loop) {
|
|
155
|
-
player.emitter.dispatchEnded();
|
|
156
|
-
}
|
|
157
|
-
player.seek(frameToSeekTo);
|
|
158
|
-
},
|
|
159
|
-
isFullscreen: () => isFullscreen,
|
|
160
|
-
requestFullscreen,
|
|
161
|
-
exitFullscreen,
|
|
162
|
-
getVolume: () => {
|
|
163
|
-
if (mediaMuted) {
|
|
164
|
-
return 0;
|
|
165
|
-
}
|
|
166
|
-
return mediaVolume;
|
|
167
|
-
},
|
|
168
|
-
setVolume: (vol) => {
|
|
169
|
-
if (typeof vol !== 'number') {
|
|
170
|
-
throw new TypeError(`setVolume() takes a number, got value of type ${typeof vol}`);
|
|
171
|
-
}
|
|
172
|
-
if (isNaN(vol)) {
|
|
173
|
-
throw new TypeError(`setVolume() got a number that is NaN. Volume must be between 0 and 1.`);
|
|
174
|
-
}
|
|
175
|
-
if (vol < 0 || vol > 1) {
|
|
176
|
-
throw new TypeError(`setVolume() got a number that is out of range. Must be between 0 and 1, got ${typeof vol}`);
|
|
177
|
-
}
|
|
178
|
-
setMediaVolume(vol);
|
|
179
|
-
},
|
|
180
|
-
isMuted: () => mediaMuted || mediaVolume === 0,
|
|
181
|
-
mute: () => {
|
|
182
|
-
setMediaMuted(true);
|
|
183
|
-
},
|
|
184
|
-
unmute: () => {
|
|
185
|
-
setMediaMuted(false);
|
|
186
|
-
},
|
|
187
|
-
getScale: () => scale,
|
|
188
|
-
};
|
|
189
|
-
return Object.assign(player.emitter, methods);
|
|
190
|
-
}, [
|
|
191
|
-
durationInFrames,
|
|
192
|
-
exitFullscreen,
|
|
193
|
-
isFullscreen,
|
|
194
|
-
loop,
|
|
195
|
-
mediaMuted,
|
|
196
|
-
mediaVolume,
|
|
197
|
-
player,
|
|
198
|
-
requestFullscreen,
|
|
199
|
-
setMediaMuted,
|
|
200
|
-
setMediaVolume,
|
|
201
|
-
toggle,
|
|
202
|
-
scale,
|
|
203
|
-
]);
|
|
204
|
-
const VideoComponent = video ? video.component : null;
|
|
205
|
-
const outerStyle = useMemo(() => {
|
|
206
|
-
return calculateOuterStyle({ canvasSize, config, style });
|
|
207
|
-
}, [canvasSize, config, style]);
|
|
208
|
-
const outer = useMemo(() => {
|
|
209
|
-
return calculateOuter({ config, layout, scale });
|
|
210
|
-
}, [config, layout, scale]);
|
|
211
|
-
const containerStyle = useMemo(() => {
|
|
212
|
-
return calculateContainerStyle({ canvasSize, config, layout, scale });
|
|
213
|
-
}, [canvasSize, config, layout, scale]);
|
|
214
|
-
const onError = useCallback((error) => {
|
|
215
|
-
player.pause();
|
|
216
|
-
// Pay attention to `this context`
|
|
217
|
-
player.emitter.dispatchError(error);
|
|
218
|
-
}, [player]);
|
|
219
|
-
const onFullscreenButtonClick = useCallback((e) => {
|
|
220
|
-
e.stopPropagation();
|
|
221
|
-
requestFullscreen();
|
|
222
|
-
}, [requestFullscreen]);
|
|
223
|
-
const onExitFullscreenButtonClick = useCallback((e) => {
|
|
224
|
-
e.stopPropagation();
|
|
225
|
-
exitFullscreen();
|
|
226
|
-
}, [exitFullscreen]);
|
|
227
|
-
const onSingleClick = useCallback((e) => {
|
|
228
|
-
toggle(e);
|
|
229
|
-
}, [toggle]);
|
|
230
|
-
const onSeekStart = useCallback(() => {
|
|
231
|
-
setSeeking(true);
|
|
232
|
-
}, []);
|
|
233
|
-
const onSeekEnd = useCallback(() => {
|
|
234
|
-
setSeeking(false);
|
|
235
|
-
}, []);
|
|
236
|
-
const onDoubleClick = useCallback(() => {
|
|
237
|
-
if (isFullscreen) {
|
|
238
|
-
exitFullscreen();
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
requestFullscreen();
|
|
242
|
-
}
|
|
243
|
-
}, [exitFullscreen, isFullscreen, requestFullscreen]);
|
|
244
|
-
const [handleClick, handleDoubleClick] = useClickPreventionOnDoubleClick(onSingleClick, onDoubleClick, doubleClickToFullscreen);
|
|
245
|
-
useEffect(() => {
|
|
246
|
-
if (shouldAutoplay) {
|
|
247
|
-
player.play();
|
|
248
|
-
setShouldAutoPlay(false);
|
|
249
|
-
}
|
|
250
|
-
}, [shouldAutoplay, player]);
|
|
251
|
-
const loadingMarkup = useMemo(() => {
|
|
252
|
-
return renderLoading
|
|
253
|
-
? renderLoading({
|
|
254
|
-
height: outerStyle.height,
|
|
255
|
-
width: outerStyle.width,
|
|
256
|
-
})
|
|
257
|
-
: null;
|
|
258
|
-
}, [outerStyle.height, outerStyle.width, renderLoading]);
|
|
259
|
-
if (!config) {
|
|
260
|
-
return null;
|
|
261
|
-
}
|
|
262
|
-
const poster = renderPoster
|
|
263
|
-
? renderPoster({
|
|
264
|
-
height: outerStyle.height,
|
|
265
|
-
width: outerStyle.width,
|
|
266
|
-
})
|
|
267
|
-
: null;
|
|
268
|
-
if (poster === undefined) {
|
|
269
|
-
throw new TypeError('renderPoster() must return a React element, but undefined was returned');
|
|
270
|
-
}
|
|
271
|
-
const shouldShowPoster = poster &&
|
|
272
|
-
[
|
|
273
|
-
showPosterWhenPaused && !player.isPlaying() && !seeking,
|
|
274
|
-
showPosterWhenEnded && player.isLastFrame && !player.isPlaying(),
|
|
275
|
-
showPosterWhenUnplayed && !player.hasPlayed && !player.isPlaying(),
|
|
276
|
-
].some(Boolean);
|
|
277
|
-
const content = (_jsxs(_Fragment, { children: [_jsx("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: _jsx("div", { style: containerStyle, className: PLAYER_CSS_CLASSNAME, children: VideoComponent ? (_jsx(ErrorBoundary, { onError: onError, errorFallback: errorFallback, children: _jsx(VideoComponent, { ...((_c = video === null || video === void 0 ? void 0 : video.defaultProps) !== null && _c !== void 0 ? _c : {}), ...((_d = inputProps) !== null && _d !== void 0 ? _d : {}) }) })) : null }) }), shouldShowPoster ? (_jsx("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null, controls ? (_jsx(Controls, { fps: config.fps, durationInFrames: config.durationInFrames, hovered: hovered, player: player, onFullscreenButtonClick: onFullscreenButtonClick, isFullscreen: isFullscreen, allowFullscreen: allowFullscreen, showVolumeControls: showVolumeControls, onExitFullscreenButtonClick: onExitFullscreenButtonClick, spaceKeyToPlayOrPause: spaceKeyToPlayOrPause, onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, inFrame: inFrame, outFrame: outFrame, initiallyShowControls: initiallyShowControls, playerWidth: (_e = canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.width) !== null && _e !== void 0 ? _e : 0, renderFullscreenButton: renderFullscreenButton, renderPlayPauseButton: renderPlayPauseButton, alwaysShowControls: alwaysShowControls })) : null] }));
|
|
278
|
-
if (IS_NODE && !doesReactVersionSupportSuspense) {
|
|
279
|
-
return (_jsx("div", { ref: container, style: outerStyle, className: className, children: content }));
|
|
280
|
-
}
|
|
281
|
-
return (_jsx("div", { ref: container, style: outerStyle, className: className, children: _jsx(Suspense, { fallback: loadingMarkup, children: content }) }));
|
|
282
|
-
};
|
|
283
|
-
export default forwardRef(PlayerUI);
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useMemo, useState } from 'react';
|
|
3
|
-
import { Internals } from 'remotion';
|
|
4
|
-
import { getPreferredVolume, persistVolume } from './volume-persistance.js';
|
|
5
|
-
export const SharedPlayerContexts = ({ children, timelineContext, inputProps, fps, compositionHeight, compositionWidth, durationInFrames, component, numberOfSharedAudioTags, }) => {
|
|
6
|
-
const compositionManagerContext = useMemo(() => {
|
|
7
|
-
return {
|
|
8
|
-
compositions: [
|
|
9
|
-
{
|
|
10
|
-
component: component,
|
|
11
|
-
durationInFrames,
|
|
12
|
-
height: compositionHeight,
|
|
13
|
-
width: compositionWidth,
|
|
14
|
-
fps,
|
|
15
|
-
id: 'player-comp',
|
|
16
|
-
props: inputProps,
|
|
17
|
-
nonce: 777,
|
|
18
|
-
scale: 1,
|
|
19
|
-
folderName: null,
|
|
20
|
-
defaultProps: undefined,
|
|
21
|
-
parentFolderName: null,
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
folders: [],
|
|
25
|
-
registerFolder: () => undefined,
|
|
26
|
-
unregisterFolder: () => undefined,
|
|
27
|
-
currentComposition: 'player-comp',
|
|
28
|
-
registerComposition: () => undefined,
|
|
29
|
-
registerSequence: () => undefined,
|
|
30
|
-
sequences: [],
|
|
31
|
-
setCurrentComposition: () => undefined,
|
|
32
|
-
unregisterComposition: () => undefined,
|
|
33
|
-
unregisterSequence: () => undefined,
|
|
34
|
-
registerAsset: () => undefined,
|
|
35
|
-
unregisterAsset: () => undefined,
|
|
36
|
-
currentCompositionMetadata: null,
|
|
37
|
-
setCurrentCompositionMetadata: () => undefined,
|
|
38
|
-
assets: [],
|
|
39
|
-
setClipRegion: () => undefined,
|
|
40
|
-
};
|
|
41
|
-
}, [
|
|
42
|
-
component,
|
|
43
|
-
durationInFrames,
|
|
44
|
-
compositionHeight,
|
|
45
|
-
compositionWidth,
|
|
46
|
-
fps,
|
|
47
|
-
inputProps,
|
|
48
|
-
]);
|
|
49
|
-
const [mediaMuted, setMediaMuted] = useState(false);
|
|
50
|
-
const [mediaVolume, setMediaVolume] = useState(getPreferredVolume());
|
|
51
|
-
const mediaVolumeContextValue = useMemo(() => {
|
|
52
|
-
return {
|
|
53
|
-
mediaMuted,
|
|
54
|
-
mediaVolume,
|
|
55
|
-
};
|
|
56
|
-
}, [mediaMuted, mediaVolume]);
|
|
57
|
-
const setMediaVolumeAndPersist = useCallback((vol) => {
|
|
58
|
-
setMediaVolume(vol);
|
|
59
|
-
persistVolume(vol);
|
|
60
|
-
}, []);
|
|
61
|
-
const setMediaVolumeContextValue = useMemo(() => {
|
|
62
|
-
return {
|
|
63
|
-
setMediaMuted,
|
|
64
|
-
setMediaVolume: setMediaVolumeAndPersist,
|
|
65
|
-
};
|
|
66
|
-
}, [setMediaVolumeAndPersist]);
|
|
67
|
-
return (_jsx(Internals.CanUseRemotionHooksProvider, { children: _jsx(Internals.Timeline.TimelineContext.Provider, { value: timelineContext, children: _jsx(Internals.CompositionManager.Provider, { value: compositionManagerContext, children: _jsx(Internals.PrefetchProvider, { children: _jsx(Internals.DurationsContextProvider, { children: _jsx(Internals.MediaVolumeContext.Provider, { value: mediaVolumeContextValue, children: _jsx(Internals.SetMediaVolumeContext.Provider, { value: setMediaVolumeContextValue, children: _jsx(Internals.SharedAudioContextProvider, { numberOfAudioTags: numberOfSharedAudioTags, children: children }) }) }) }) }) }) }) }));
|
|
68
|
-
};
|
package/dist/esm/Thumbnail.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
3
|
-
import { Internals, random } from 'remotion';
|
|
4
|
-
import { ThumbnailEmitterContext } from './emitter-context.js';
|
|
5
|
-
import { ThumbnailEmitter } from './event-emitter.js';
|
|
6
|
-
import { SharedPlayerContexts } from './SharedPlayerContext.js';
|
|
7
|
-
import ThumbnailUI from './ThumbnailUI.js';
|
|
8
|
-
export const ThumbnailFn = ({ frameToDisplay, style, inputProps, compositionHeight, compositionWidth, durationInFrames, fps, className, errorFallback = () => '⚠️', renderLoading, ...componentProps }, ref) => {
|
|
9
|
-
const [thumbnailId] = useState(() => String(random(null)));
|
|
10
|
-
const rootRef = useRef(null);
|
|
11
|
-
const timelineState = useMemo(() => {
|
|
12
|
-
return {
|
|
13
|
-
playing: false,
|
|
14
|
-
frame: frameToDisplay,
|
|
15
|
-
rootId: thumbnailId,
|
|
16
|
-
imperativePlaying: {
|
|
17
|
-
current: false,
|
|
18
|
-
},
|
|
19
|
-
playbackRate: 1,
|
|
20
|
-
setPlaybackRate: () => {
|
|
21
|
-
throw new Error('thumbnail');
|
|
22
|
-
},
|
|
23
|
-
audioAndVideoTags: { current: [] },
|
|
24
|
-
};
|
|
25
|
-
}, [frameToDisplay, thumbnailId]);
|
|
26
|
-
useImperativeHandle(ref, () => rootRef.current, []);
|
|
27
|
-
const Component = Internals.useLazyComponent(componentProps);
|
|
28
|
-
const [emitter] = useState(() => new ThumbnailEmitter());
|
|
29
|
-
const passedInputProps = useMemo(() => {
|
|
30
|
-
return inputProps !== null && inputProps !== void 0 ? inputProps : {};
|
|
31
|
-
}, [inputProps]);
|
|
32
|
-
return (_jsx(Internals.IsPlayerContextProvider, { children: _jsx(SharedPlayerContexts, { timelineContext: timelineState, component: Component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, inputProps: inputProps, numberOfSharedAudioTags: 0, children: _jsx(ThumbnailEmitterContext.Provider, { value: emitter, children: _jsx(ThumbnailUI, { className: className, errorFallback: errorFallback, inputProps: passedInputProps, renderLoading: renderLoading, style: style }) }) }) }));
|
|
33
|
-
};
|
|
34
|
-
const forward = forwardRef;
|
|
35
|
-
/**
|
|
36
|
-
* @description A component which can be rendered in a regular React App (for example: Create React App, Next.js) to display a single frame of a video.
|
|
37
|
-
* @see [Documentation](https://www.remotion.dev/docs/player/thumbnail)
|
|
38
|
-
*/
|
|
39
|
-
export const Thumbnail = forward(ThumbnailFn);
|
package/dist/esm/ThumbnailUI.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React, { forwardRef, Suspense, useCallback, useImperativeHandle, useMemo, useRef, } from 'react';
|
|
3
|
-
import { Internals } from 'remotion';
|
|
4
|
-
import { calculateCanvasTransformation, calculateContainerStyle, calculateOuter, calculateOuterStyle, } from './calculate-scale.js';
|
|
5
|
-
import { ErrorBoundary } from './error-boundary.js';
|
|
6
|
-
import { PLAYER_CSS_CLASSNAME } from './player-css-classname.js';
|
|
7
|
-
import { useThumbnail } from './use-thumbnail.js';
|
|
8
|
-
import { IS_NODE } from './utils/is-node.js';
|
|
9
|
-
import { useElementSize } from './utils/use-element-size.js';
|
|
10
|
-
const reactVersion = React.version.split('.')[0];
|
|
11
|
-
if (reactVersion === '0') {
|
|
12
|
-
throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
|
|
13
|
-
}
|
|
14
|
-
const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
|
|
15
|
-
const ThumbnailUI = ({ style, inputProps, errorFallback, renderLoading, className }, ref) => {
|
|
16
|
-
var _a, _b, _c;
|
|
17
|
-
const config = Internals.useUnsafeVideoConfig();
|
|
18
|
-
const video = Internals.useVideo();
|
|
19
|
-
const container = useRef(null);
|
|
20
|
-
const canvasSize = useElementSize(container, {
|
|
21
|
-
triggerOnWindowResize: false,
|
|
22
|
-
shouldApplyCssTransforms: false,
|
|
23
|
-
});
|
|
24
|
-
const layout = useMemo(() => {
|
|
25
|
-
if (!config || !canvasSize) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
return calculateCanvasTransformation({
|
|
29
|
-
canvasSize,
|
|
30
|
-
compositionHeight: config.height,
|
|
31
|
-
compositionWidth: config.width,
|
|
32
|
-
previewSize: 'auto',
|
|
33
|
-
});
|
|
34
|
-
}, [canvasSize, config]);
|
|
35
|
-
const scale = (_a = layout === null || layout === void 0 ? void 0 : layout.scale) !== null && _a !== void 0 ? _a : 1;
|
|
36
|
-
const thumbnail = useThumbnail();
|
|
37
|
-
useImperativeHandle(ref, () => {
|
|
38
|
-
const methods = {
|
|
39
|
-
getContainerNode: () => container.current,
|
|
40
|
-
getScale: () => scale,
|
|
41
|
-
};
|
|
42
|
-
return Object.assign(thumbnail.emitter, methods);
|
|
43
|
-
}, [scale, thumbnail.emitter]);
|
|
44
|
-
const VideoComponent = video ? video.component : null;
|
|
45
|
-
const outerStyle = useMemo(() => {
|
|
46
|
-
return calculateOuterStyle({ config, style, canvasSize });
|
|
47
|
-
}, [canvasSize, config, style]);
|
|
48
|
-
const outer = useMemo(() => {
|
|
49
|
-
return calculateOuter({ config, layout, scale });
|
|
50
|
-
}, [config, layout, scale]);
|
|
51
|
-
const containerStyle = useMemo(() => {
|
|
52
|
-
return calculateContainerStyle({
|
|
53
|
-
canvasSize,
|
|
54
|
-
config,
|
|
55
|
-
layout,
|
|
56
|
-
scale,
|
|
57
|
-
});
|
|
58
|
-
}, [canvasSize, config, layout, scale]);
|
|
59
|
-
const onError = useCallback((error) => {
|
|
60
|
-
// Pay attention to `this context`
|
|
61
|
-
thumbnail.emitter.dispatchError(error);
|
|
62
|
-
}, [thumbnail.emitter]);
|
|
63
|
-
const rootRef = useRef(null);
|
|
64
|
-
useImperativeHandle(ref, () => rootRef.current, []);
|
|
65
|
-
const loadingMarkup = useMemo(() => {
|
|
66
|
-
return renderLoading
|
|
67
|
-
? renderLoading({
|
|
68
|
-
height: outerStyle.height,
|
|
69
|
-
width: outerStyle.width,
|
|
70
|
-
})
|
|
71
|
-
: null;
|
|
72
|
-
}, [outerStyle.height, outerStyle.width, renderLoading]);
|
|
73
|
-
if (!config) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
const content = (_jsx("div", { style: outer, children: _jsx("div", { style: containerStyle, className: PLAYER_CSS_CLASSNAME, children: VideoComponent ? (_jsx(ErrorBoundary, { onError: onError, errorFallback: errorFallback, children: _jsx(VideoComponent, { ...((_b = video === null || video === void 0 ? void 0 : video.defaultProps) !== null && _b !== void 0 ? _b : {}), ...((_c = inputProps) !== null && _c !== void 0 ? _c : {}) }) })) : null }) }));
|
|
77
|
-
if (IS_NODE && !doesReactVersionSupportSuspense) {
|
|
78
|
-
return (_jsx("div", { ref: container, style: outerStyle, className: className, children: content }));
|
|
79
|
-
}
|
|
80
|
-
return (_jsx("div", { ref: container, style: outerStyle, className: className, children: _jsx(Suspense, { fallback: loadingMarkup, children: content }) }));
|
|
81
|
-
};
|
|
82
|
-
export default forwardRef(ThumbnailUI);
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export const calculateNextFrame = ({ time, currentFrame: startFrame, playbackSpeed, fps, actualLastFrame, actualFirstFrame, framesAdvanced, shouldLoop, }) => {
|
|
2
|
-
const op = playbackSpeed < 0 ? Math.ceil : Math.floor;
|
|
3
|
-
const framesToAdvance = op((time * playbackSpeed) / (1000 / fps)) - framesAdvanced;
|
|
4
|
-
const nextFrame = framesToAdvance + startFrame;
|
|
5
|
-
const isCurrentFrameOutside = startFrame > actualLastFrame || startFrame < actualFirstFrame;
|
|
6
|
-
const isNextFrameOutside = nextFrame > actualLastFrame || nextFrame < actualFirstFrame;
|
|
7
|
-
const hasEnded = !shouldLoop && isNextFrameOutside && !isCurrentFrameOutside;
|
|
8
|
-
if (playbackSpeed > 0) {
|
|
9
|
-
// Play forwards
|
|
10
|
-
if (isNextFrameOutside) {
|
|
11
|
-
return {
|
|
12
|
-
nextFrame: actualFirstFrame,
|
|
13
|
-
framesToAdvance,
|
|
14
|
-
hasEnded,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
return { nextFrame, framesToAdvance, hasEnded };
|
|
18
|
-
}
|
|
19
|
-
// Reverse playback
|
|
20
|
-
if (isNextFrameOutside) {
|
|
21
|
-
return { nextFrame: actualLastFrame, framesToAdvance, hasEnded };
|
|
22
|
-
}
|
|
23
|
-
return { nextFrame, framesToAdvance, hasEnded };
|
|
24
|
-
};
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { calculatePlayerSize } from './utils/calculate-player-size.js';
|
|
2
|
-
export const calculateScale = ({ canvasSize, compositionHeight, compositionWidth, previewSize, }) => {
|
|
3
|
-
const heightRatio = canvasSize.height / compositionHeight;
|
|
4
|
-
const widthRatio = canvasSize.width / compositionWidth;
|
|
5
|
-
const ratio = Math.min(heightRatio, widthRatio);
|
|
6
|
-
return previewSize === 'auto' ? ratio : Number(previewSize);
|
|
7
|
-
};
|
|
8
|
-
export const calculateCanvasTransformation = ({ previewSize, compositionWidth, compositionHeight, canvasSize, }) => {
|
|
9
|
-
const scale = calculateScale({
|
|
10
|
-
canvasSize,
|
|
11
|
-
compositionHeight,
|
|
12
|
-
compositionWidth,
|
|
13
|
-
previewSize,
|
|
14
|
-
});
|
|
15
|
-
const correction = 0 - (1 - scale) / 2;
|
|
16
|
-
const xCorrection = correction * compositionWidth;
|
|
17
|
-
const yCorrection = correction * compositionHeight;
|
|
18
|
-
const width = compositionWidth * scale;
|
|
19
|
-
const height = compositionHeight * scale;
|
|
20
|
-
const centerX = canvasSize.width / 2 - width / 2;
|
|
21
|
-
const centerY = canvasSize.height / 2 - height / 2;
|
|
22
|
-
return {
|
|
23
|
-
centerX,
|
|
24
|
-
centerY,
|
|
25
|
-
xCorrection,
|
|
26
|
-
yCorrection,
|
|
27
|
-
scale,
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
export const calculateOuterStyle = ({ config, style, canvasSize, }) => {
|
|
31
|
-
if (!config) {
|
|
32
|
-
return {};
|
|
33
|
-
}
|
|
34
|
-
return {
|
|
35
|
-
position: 'relative',
|
|
36
|
-
overflow: 'hidden',
|
|
37
|
-
...calculatePlayerSize({
|
|
38
|
-
compositionHeight: config.height,
|
|
39
|
-
compositionWidth: config.width,
|
|
40
|
-
currentSize: canvasSize,
|
|
41
|
-
height: style === null || style === void 0 ? void 0 : style.height,
|
|
42
|
-
width: style === null || style === void 0 ? void 0 : style.width,
|
|
43
|
-
}),
|
|
44
|
-
...style,
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
export const calculateContainerStyle = ({ config, canvasSize, layout, scale, }) => {
|
|
48
|
-
if (!config || !canvasSize || !layout) {
|
|
49
|
-
return {};
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
position: 'absolute',
|
|
53
|
-
width: config.width,
|
|
54
|
-
height: config.height,
|
|
55
|
-
display: 'flex',
|
|
56
|
-
transform: `scale(${scale})`,
|
|
57
|
-
marginLeft: layout.xCorrection,
|
|
58
|
-
marginTop: layout.yCorrection,
|
|
59
|
-
overflow: 'hidden',
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
export const calculateOuter = ({ layout, scale, config, }) => {
|
|
63
|
-
if (!layout || !config) {
|
|
64
|
-
return {};
|
|
65
|
-
}
|
|
66
|
-
const { centerX, centerY } = layout;
|
|
67
|
-
return {
|
|
68
|
-
width: config.width * scale,
|
|
69
|
-
height: config.height * scale,
|
|
70
|
-
display: 'flex',
|
|
71
|
-
flexDirection: 'column',
|
|
72
|
-
position: 'absolute',
|
|
73
|
-
left: centerX,
|
|
74
|
-
top: centerY,
|
|
75
|
-
overflow: 'hidden',
|
|
76
|
-
};
|
|
77
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React from 'react';
|
|
3
|
-
const errorStyle = {
|
|
4
|
-
display: 'flex',
|
|
5
|
-
justifyContent: 'center',
|
|
6
|
-
alignItems: 'center',
|
|
7
|
-
flex: 1,
|
|
8
|
-
height: '100%',
|
|
9
|
-
width: '100%',
|
|
10
|
-
};
|
|
11
|
-
export class ErrorBoundary extends React.Component {
|
|
12
|
-
constructor() {
|
|
13
|
-
super(...arguments);
|
|
14
|
-
this.state = { hasError: null };
|
|
15
|
-
}
|
|
16
|
-
static getDerivedStateFromError(error) {
|
|
17
|
-
// Update state so the next render will show the fallback UI.
|
|
18
|
-
return { hasError: error };
|
|
19
|
-
}
|
|
20
|
-
componentDidCatch(error) {
|
|
21
|
-
this.props.onError(error);
|
|
22
|
-
}
|
|
23
|
-
render() {
|
|
24
|
-
if (this.state.hasError) {
|
|
25
|
-
// You can render any custom fallback UI
|
|
26
|
-
return (_jsx("div", { style: errorStyle, children: this.props.errorFallback({
|
|
27
|
-
error: this.state.hasError,
|
|
28
|
-
}) }));
|
|
29
|
-
}
|
|
30
|
-
return this.props.children;
|
|
31
|
-
}
|
|
32
|
-
}
|