@remotion/player 4.0.225 → 4.0.227

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 (107) hide show
  1. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/BufferingIndicator.d.ts +5 -0
  2. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/BufferingIndicator.js +38 -0
  3. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/DefaultPlayPauseButton.d.ts +5 -0
  4. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/DefaultPlayPauseButton.js +12 -0
  5. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/EmitterProvider.d.ts +5 -0
  6. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/EmitterProvider.js +20 -0
  7. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/MediaVolumeSlider.d.ts +5 -0
  8. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/MediaVolumeSlider.js +129 -0
  9. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlaybackrateControl.d.ts +8 -0
  10. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlaybackrateControl.js +156 -0
  11. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/Player.d.ts +56 -0
  12. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/Player.js +143 -0
  13. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerControls.d.ts +47 -0
  14. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerControls.js +176 -0
  15. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerSeekBar.d.ts +8 -0
  16. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerSeekBar.js +145 -0
  17. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerUI.d.ts +46 -0
  18. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerUI.js +369 -0
  19. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/SharedPlayerContext.d.ts +15 -0
  20. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/SharedPlayerContext.js +55 -0
  21. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/Thumbnail.d.ts +23 -0
  22. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/Thumbnail.js +48 -0
  23. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/ThumbnailUI.d.ts +11 -0
  24. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/ThumbnailUI.js +89 -0
  25. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/calculate-next-frame.d.ts +14 -0
  26. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/calculate-next-frame.js +24 -0
  27. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/calculate-scale.d.ts +50 -0
  28. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/calculate-scale.js +72 -0
  29. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/emitter-context.d.ts +4 -0
  30. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/emitter-context.js +3 -0
  31. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/error-boundary.d.ts +19 -0
  32. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/error-boundary.js +32 -0
  33. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/event-emitter.d.ts +91 -0
  34. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/event-emitter.js +114 -0
  35. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/format-time.d.ts +1 -0
  36. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/format-time.js +5 -0
  37. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/icons.d.ts +10 -0
  38. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/icons.js +39 -0
  39. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/index.d.ts +64 -0
  40. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/index.js +23 -0
  41. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/is-backgrounded.d.ts +2 -0
  42. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/is-backgrounded.js +20 -0
  43. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/player-css-classname.d.ts +1 -0
  44. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/player-css-classname.js +1 -0
  45. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/player-methods.d.ts +25 -0
  46. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/player-methods.js +1 -0
  47. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/test/index.test.d.ts +1 -0
  48. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/test/index.test.js +7 -0
  49. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/test/test-utils.d.ts +6 -0
  50. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/test/test-utils.js +14 -0
  51. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/test/validate-in-out-frames.test.d.ts +1 -0
  52. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/test/validate-in-out-frames.test.js +54 -0
  53. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/test/validate-prop.test.d.ts +1 -0
  54. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/test/validate-prop.test.js +129 -0
  55. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-buffer-state-emitter.d.ts +2 -0
  56. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-buffer-state-emitter.js +22 -0
  57. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-hover-state.d.ts +1 -0
  58. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-hover-state.js +43 -0
  59. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-playback.d.ts +8 -0
  60. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-playback.js +157 -0
  61. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-player.d.ts +24 -0
  62. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-player.js +157 -0
  63. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-thumbnail.d.ts +6 -0
  64. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-thumbnail.js +14 -0
  65. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-video-controls-resize.d.ts +11 -0
  66. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-video-controls-resize.js +35 -0
  67. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/calculate-player-size.d.ts +9 -0
  68. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/calculate-player-size.js +24 -0
  69. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/cancellable-promise.d.ts +5 -0
  70. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/cancellable-promise.js +22 -0
  71. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/delay.d.ts +1 -0
  72. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/delay.js +2 -0
  73. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/is-node.d.ts +1 -0
  74. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/is-node.js +1 -0
  75. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/props-if-has-props.d.ts +10 -0
  76. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/props-if-has-props.js +1 -0
  77. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/use-cancellable-promises.d.ts +7 -0
  78. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/use-cancellable-promises.js +18 -0
  79. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/use-click-prevention-on-double-click.d.ts +3 -0
  80. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/use-click-prevention-on-double-click.js +41 -0
  81. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/use-component-visible.d.ts +6 -0
  82. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/use-component-visible.js +18 -0
  83. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/use-element-size.d.ts +16 -0
  84. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/use-element-size.js +127 -0
  85. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/validate-in-out-frame.d.ts +6 -0
  86. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/validate-in-out-frame.js +49 -0
  87. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/validate-initial-frame.d.ts +4 -0
  88. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/validate-initial-frame.js +23 -0
  89. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/validate-playbackrate.d.ts +1 -0
  90. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/utils/validate-playbackrate.js +14 -0
  91. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/validate.d.ts +5 -0
  92. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/validate.js +6 -0
  93. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/volume-persistance.d.ts +2 -0
  94. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/volume-persistance.js +29 -0
  95. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/tsconfig-esm.tsbuildinfo +1 -0
  96. package/dist/cjs/BufferingIndicator.d.ts +1 -1
  97. package/dist/cjs/EmitterProvider.d.ts +2 -2
  98. package/dist/cjs/PlaybackrateControl.d.ts +2 -2
  99. package/dist/cjs/ThumbnailUI.d.ts +6 -6
  100. package/dist/cjs/error-boundary.d.ts +1 -1
  101. package/dist/cjs/icons.d.ts +1 -1
  102. package/dist/cjs/index.d.ts +3 -3
  103. package/dist/cjs/test/test-utils.js +0 -1
  104. package/dist/cjs/volume-persistance.js +1 -1
  105. package/dist/esm/index.mjs +1 -1
  106. package/eslint.config.mjs +23 -0
  107. package/package.json +7 -5
@@ -0,0 +1,369 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } 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 { usePlayback } from './use-playback.js';
9
+ import { usePlayer } from './use-player.js';
10
+ import { IS_NODE } from './utils/is-node.js';
11
+ import { useClickPreventionOnDoubleClick } from './utils/use-click-prevention-on-double-click.js';
12
+ import { useElementSize } from './utils/use-element-size.js';
13
+ const reactVersion = React.version.split('.')[0];
14
+ if (reactVersion === '0') {
15
+ throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
16
+ }
17
+ const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
18
+ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, doubleClickToFullscreen, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, renderPoster, className, moveToBeginningWhenEnded, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, inFrame, outFrame, initiallyShowControls, renderFullscreen: renderFullscreenButton, renderPlayPauseButton, alwaysShowControls, showPlaybackRateControl, posterFillMode, bufferStateDelayInMilliseconds, hideControlsWhenPointerDoesntMove, }, ref) => {
19
+ var _a, _b, _c;
20
+ const config = Internals.useUnsafeVideoConfig();
21
+ const video = Internals.useVideo();
22
+ const container = useRef(null);
23
+ const canvasSize = useElementSize(container, {
24
+ triggerOnWindowResize: false,
25
+ shouldApplyCssTransforms: false,
26
+ });
27
+ const [hasPausedToResume, setHasPausedToResume] = useState(false);
28
+ const [shouldAutoplay, setShouldAutoPlay] = useState(autoPlay);
29
+ const [isFullscreen, setIsFullscreen] = useState(() => false);
30
+ const [seeking, setSeeking] = useState(false);
31
+ const supportsFullScreen = useMemo(() => {
32
+ if (typeof document === 'undefined') {
33
+ return false;
34
+ }
35
+ return Boolean(document.fullscreenEnabled || document.webkitFullscreenEnabled);
36
+ }, []);
37
+ const player = usePlayer();
38
+ usePlayback({
39
+ loop,
40
+ playbackRate,
41
+ moveToBeginningWhenEnded,
42
+ inFrame,
43
+ outFrame,
44
+ frameRef: player.remotionInternal_currentFrameRef,
45
+ });
46
+ useEffect(() => {
47
+ if (hasPausedToResume && !player.playing) {
48
+ setHasPausedToResume(false);
49
+ player.play();
50
+ }
51
+ }, [hasPausedToResume, player]);
52
+ useEffect(() => {
53
+ const { current } = container;
54
+ if (!current) {
55
+ return;
56
+ }
57
+ const onFullscreenChange = () => {
58
+ setIsFullscreen(document.fullscreenElement === current ||
59
+ document.webkitFullscreenElement === current);
60
+ };
61
+ document.addEventListener('fullscreenchange', onFullscreenChange);
62
+ document.addEventListener('webkitfullscreenchange', onFullscreenChange);
63
+ return () => {
64
+ document.removeEventListener('fullscreenchange', onFullscreenChange);
65
+ document.removeEventListener('webkitfullscreenchange', onFullscreenChange);
66
+ };
67
+ }, []);
68
+ const toggle = useCallback((e) => {
69
+ if (player.isPlaying()) {
70
+ player.pause();
71
+ }
72
+ else {
73
+ player.play(e);
74
+ }
75
+ }, [player]);
76
+ const requestFullscreen = useCallback(() => {
77
+ if (!allowFullscreen) {
78
+ throw new Error('allowFullscreen is false');
79
+ }
80
+ if (!supportsFullScreen) {
81
+ throw new Error('Browser doesnt support fullscreen');
82
+ }
83
+ if (!container.current) {
84
+ throw new Error('No player ref found');
85
+ }
86
+ if (container.current.webkitRequestFullScreen) {
87
+ container.current.webkitRequestFullScreen();
88
+ }
89
+ else {
90
+ container.current.requestFullscreen();
91
+ }
92
+ }, [allowFullscreen, supportsFullScreen]);
93
+ const exitFullscreen = useCallback(() => {
94
+ if (document.webkitExitFullscreen) {
95
+ document.webkitExitFullscreen();
96
+ }
97
+ else {
98
+ document.exitFullscreen();
99
+ }
100
+ }, []);
101
+ useEffect(() => {
102
+ const { current } = container;
103
+ if (!current) {
104
+ return;
105
+ }
106
+ const fullscreenChange = () => {
107
+ var _a;
108
+ const element = (_a = document.webkitFullscreenElement) !== null && _a !== void 0 ? _a : document.fullscreenElement;
109
+ if (element && element === container.current) {
110
+ player.emitter.dispatchFullscreenChange({
111
+ isFullscreen: true,
112
+ });
113
+ }
114
+ else {
115
+ player.emitter.dispatchFullscreenChange({
116
+ isFullscreen: false,
117
+ });
118
+ }
119
+ };
120
+ current.addEventListener('webkitfullscreenchange', fullscreenChange);
121
+ current.addEventListener('fullscreenchange', fullscreenChange);
122
+ return () => {
123
+ current.removeEventListener('webkitfullscreenchange', fullscreenChange);
124
+ current.removeEventListener('fullscreenchange', fullscreenChange);
125
+ };
126
+ }, [player.emitter]);
127
+ const durationInFrames = (_a = config === null || config === void 0 ? void 0 : config.durationInFrames) !== null && _a !== void 0 ? _a : 1;
128
+ const layout = useMemo(() => {
129
+ if (!config || !canvasSize) {
130
+ return null;
131
+ }
132
+ return calculateCanvasTransformation({
133
+ canvasSize,
134
+ compositionHeight: config.height,
135
+ compositionWidth: config.width,
136
+ previewSize: 'auto',
137
+ });
138
+ }, [canvasSize, config]);
139
+ const scale = (_b = layout === null || layout === void 0 ? void 0 : layout.scale) !== null && _b !== void 0 ? _b : 1;
140
+ const initialScaleIgnored = useRef(false);
141
+ useEffect(() => {
142
+ if (!initialScaleIgnored.current) {
143
+ initialScaleIgnored.current = true;
144
+ return;
145
+ }
146
+ player.emitter.dispatchScaleChange(scale);
147
+ }, [player.emitter, scale]);
148
+ const { setMediaVolume, setMediaMuted } = useContext(Internals.SetMediaVolumeContext);
149
+ const { mediaMuted, mediaVolume } = useContext(Internals.MediaVolumeContext);
150
+ useEffect(() => {
151
+ player.emitter.dispatchVolumeChange(mediaVolume);
152
+ }, [player.emitter, mediaVolume]);
153
+ const isMuted = mediaMuted || mediaVolume === 0;
154
+ useEffect(() => {
155
+ player.emitter.dispatchMuteChange({
156
+ isMuted,
157
+ });
158
+ }, [player.emitter, isMuted]);
159
+ const [showBufferIndicator, setShowBufferState] = useState(false);
160
+ useEffect(() => {
161
+ let timeout = null;
162
+ let stopped = false;
163
+ const onBuffer = () => {
164
+ requestAnimationFrame(() => {
165
+ if (bufferStateDelayInMilliseconds === 0) {
166
+ setShowBufferState(true);
167
+ }
168
+ else {
169
+ timeout = setTimeout(() => {
170
+ if (!stopped) {
171
+ setShowBufferState(true);
172
+ }
173
+ }, bufferStateDelayInMilliseconds);
174
+ }
175
+ });
176
+ };
177
+ const onResume = () => {
178
+ requestAnimationFrame(() => {
179
+ setShowBufferState(false);
180
+ if (timeout) {
181
+ clearTimeout(timeout);
182
+ }
183
+ });
184
+ };
185
+ player.emitter.addEventListener('waiting', onBuffer);
186
+ player.emitter.addEventListener('resume', onResume);
187
+ return () => {
188
+ player.emitter.removeEventListener('waiting', onBuffer);
189
+ player.emitter.removeEventListener('resume', onResume);
190
+ setShowBufferState(false);
191
+ if (timeout) {
192
+ clearTimeout(timeout);
193
+ }
194
+ stopped = true;
195
+ };
196
+ }, [bufferStateDelayInMilliseconds, player.emitter]);
197
+ useImperativeHandle(ref, () => {
198
+ const methods = {
199
+ play: player.play,
200
+ pause: () => {
201
+ // If, after .seek()-ing, the player was explicitly paused, we don't resume
202
+ setHasPausedToResume(false);
203
+ player.pause();
204
+ },
205
+ toggle,
206
+ getContainerNode: () => container.current,
207
+ getCurrentFrame: player.getCurrentFrame,
208
+ isPlaying: () => player.playing,
209
+ seekTo: (f) => {
210
+ const lastFrame = durationInFrames - 1;
211
+ const frameToSeekTo = Math.max(0, Math.min(lastFrame, f));
212
+ // continue playing after seeking if the player was playing before
213
+ if (player.isPlaying()) {
214
+ const pauseToResume = frameToSeekTo !== lastFrame || loop;
215
+ setHasPausedToResume(pauseToResume);
216
+ player.pause();
217
+ }
218
+ if (frameToSeekTo === lastFrame && !loop) {
219
+ player.emitter.dispatchEnded();
220
+ }
221
+ player.seek(frameToSeekTo);
222
+ },
223
+ isFullscreen: () => isFullscreen,
224
+ requestFullscreen,
225
+ exitFullscreen,
226
+ getVolume: () => {
227
+ if (mediaMuted) {
228
+ return 0;
229
+ }
230
+ return mediaVolume;
231
+ },
232
+ setVolume: (vol) => {
233
+ if (typeof vol !== 'number') {
234
+ throw new TypeError(`setVolume() takes a number, got value of type ${typeof vol}`);
235
+ }
236
+ if (isNaN(vol)) {
237
+ throw new TypeError(`setVolume() got a number that is NaN. Volume must be between 0 and 1.`);
238
+ }
239
+ if (vol < 0 || vol > 1) {
240
+ throw new TypeError(`setVolume() got a number that is out of range. Must be between 0 and 1, got ${typeof vol}`);
241
+ }
242
+ setMediaVolume(vol);
243
+ },
244
+ isMuted: () => isMuted,
245
+ mute: () => {
246
+ setMediaMuted(true);
247
+ },
248
+ unmute: () => {
249
+ setMediaMuted(false);
250
+ },
251
+ getScale: () => scale,
252
+ pauseAndReturnToPlayStart: () => {
253
+ player.pauseAndReturnToPlayStart();
254
+ },
255
+ };
256
+ return Object.assign(player.emitter, methods);
257
+ }, [
258
+ durationInFrames,
259
+ exitFullscreen,
260
+ isFullscreen,
261
+ loop,
262
+ mediaMuted,
263
+ isMuted,
264
+ mediaVolume,
265
+ player,
266
+ requestFullscreen,
267
+ setMediaMuted,
268
+ setMediaVolume,
269
+ toggle,
270
+ scale,
271
+ ]);
272
+ const VideoComponent = video ? video.component : null;
273
+ const outerStyle = useMemo(() => {
274
+ return calculateOuterStyle({ canvasSize, config, style });
275
+ }, [canvasSize, config, style]);
276
+ const outer = useMemo(() => {
277
+ return calculateOuter({ config, layout, scale });
278
+ }, [config, layout, scale]);
279
+ const containerStyle = useMemo(() => {
280
+ return calculateContainerStyle({ canvasSize, config, layout, scale });
281
+ }, [canvasSize, config, layout, scale]);
282
+ const onError = useCallback((error) => {
283
+ player.pause();
284
+ // Pay attention to `this context`
285
+ player.emitter.dispatchError(error);
286
+ }, [player]);
287
+ const onFullscreenButtonClick = useCallback((e) => {
288
+ e.stopPropagation();
289
+ requestFullscreen();
290
+ }, [requestFullscreen]);
291
+ const onExitFullscreenButtonClick = useCallback((e) => {
292
+ e.stopPropagation();
293
+ exitFullscreen();
294
+ }, [exitFullscreen]);
295
+ const onSingleClick = useCallback((e) => {
296
+ toggle(e);
297
+ }, [toggle]);
298
+ const onSeekStart = useCallback(() => {
299
+ setSeeking(true);
300
+ }, []);
301
+ const onSeekEnd = useCallback(() => {
302
+ setSeeking(false);
303
+ }, []);
304
+ const onDoubleClick = useCallback(() => {
305
+ if (isFullscreen) {
306
+ exitFullscreen();
307
+ }
308
+ else {
309
+ requestFullscreen();
310
+ }
311
+ }, [exitFullscreen, isFullscreen, requestFullscreen]);
312
+ const [handleClick, handleDoubleClick] = useClickPreventionOnDoubleClick(onSingleClick, onDoubleClick, doubleClickToFullscreen && allowFullscreen && supportsFullScreen);
313
+ useEffect(() => {
314
+ if (shouldAutoplay) {
315
+ player.play();
316
+ setShouldAutoPlay(false);
317
+ }
318
+ }, [shouldAutoplay, player]);
319
+ const loadingMarkup = useMemo(() => {
320
+ return renderLoading
321
+ ? renderLoading({
322
+ height: outerStyle.height,
323
+ width: outerStyle.width,
324
+ isBuffering: showBufferIndicator,
325
+ })
326
+ : null;
327
+ }, [outerStyle.height, outerStyle.width, renderLoading, showBufferIndicator]);
328
+ const currentScale = useMemo(() => {
329
+ return {
330
+ type: 'scale',
331
+ scale,
332
+ };
333
+ }, [scale]);
334
+ if (!config) {
335
+ return null;
336
+ }
337
+ const poster = renderPoster
338
+ ? renderPoster({
339
+ height: posterFillMode === 'player-size'
340
+ ? outerStyle.height
341
+ : config.height,
342
+ width: posterFillMode === 'player-size'
343
+ ? outerStyle.width
344
+ : config.width,
345
+ isBuffering: showBufferIndicator,
346
+ })
347
+ : null;
348
+ if (poster === undefined) {
349
+ throw new TypeError('renderPoster() must return a React element, but undefined was returned');
350
+ }
351
+ const shouldShowPoster = poster &&
352
+ [
353
+ showPosterWhenPaused && !player.isPlaying() && !seeking,
354
+ showPosterWhenEnded && player.isLastFrame && !player.isPlaying(),
355
+ showPosterWhenUnplayed && !player.hasPlayed && !player.isPlaying(),
356
+ showPosterWhenBuffering && showBufferIndicator && player.isPlaying(),
357
+ ].some(Boolean);
358
+ const { left, top, width, height, ...outerWithoutScale } = outer;
359
+ const content = (_jsxs(_Fragment, { children: [_jsx("div", { style: outer, onPointerUp: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: _jsxs("div", { style: containerStyle, className: PLAYER_CSS_CLASSNAME, children: [VideoComponent ? (_jsx(ErrorBoundary, { onError: onError, errorFallback: errorFallback, children: _jsx(Internals.ClipComposition, { children: _jsx(Internals.CurrentScaleContext.Provider, { value: currentScale, children: _jsx(VideoComponent, { ...((_c = video === null || video === void 0 ? void 0 : video.props) !== null && _c !== void 0 ? _c : {}), ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}) }) }) }) })) : null, shouldShowPoster && posterFillMode === 'composition-size' ? (_jsx("div", { style: {
360
+ ...outerWithoutScale,
361
+ width: config.width,
362
+ height: config.height,
363
+ }, onPointerUp: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null] }) }), shouldShowPoster && posterFillMode === 'player-size' ? (_jsx("div", { style: outer, onPointerUp: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null, controls ? (_jsx(Controls, { fps: config.fps, durationInFrames: config.durationInFrames, player: player, containerRef: container, onFullscreenButtonClick: onFullscreenButtonClick, isFullscreen: isFullscreen, allowFullscreen: allowFullscreen, showVolumeControls: showVolumeControls, onExitFullscreenButtonClick: onExitFullscreenButtonClick, spaceKeyToPlayOrPause: spaceKeyToPlayOrPause, onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, inFrame: inFrame, outFrame: outFrame, initiallyShowControls: initiallyShowControls, canvasSize: canvasSize, renderFullscreenButton: renderFullscreenButton, renderPlayPauseButton: renderPlayPauseButton, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl, buffering: showBufferIndicator, hideControlsWhenPointerDoesntMove: hideControlsWhenPointerDoesntMove, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, onPointerUp: clickToPlay ? handleClick : undefined })) : null] }));
364
+ if (IS_NODE && !doesReactVersionSupportSuspense) {
365
+ return (_jsx("div", { ref: container, style: outerStyle, className: className, children: content }));
366
+ }
367
+ return (_jsx("div", { ref: container, style: outerStyle, className: className, children: _jsx(Suspense, { fallback: loadingMarkup, children: content }) }));
368
+ };
369
+ export default forwardRef(PlayerUI);
@@ -0,0 +1,15 @@
1
+ import type { ComponentType, LazyExoticComponent } from 'react';
2
+ import React from 'react';
3
+ import type { TimelineContextValue } from 'remotion';
4
+ export declare const PLAYER_COMP_ID = "player-comp";
5
+ export declare const SharedPlayerContexts: React.FC<{
6
+ children: React.ReactNode;
7
+ timelineContext: TimelineContextValue;
8
+ fps: number;
9
+ compositionWidth: number;
10
+ compositionHeight: number;
11
+ durationInFrames: number;
12
+ component: LazyExoticComponent<ComponentType<unknown>>;
13
+ numberOfSharedAudioTags: number;
14
+ initiallyMuted: boolean;
15
+ }>;
@@ -0,0 +1,55 @@
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 PLAYER_COMP_ID = 'player-comp';
6
+ export const SharedPlayerContexts = ({ children, timelineContext, fps, compositionHeight, compositionWidth, durationInFrames, component, numberOfSharedAudioTags, initiallyMuted, }) => {
7
+ const compositionManagerContext = useMemo(() => {
8
+ const context = {
9
+ compositions: [
10
+ {
11
+ component: component,
12
+ durationInFrames,
13
+ height: compositionHeight,
14
+ width: compositionWidth,
15
+ fps,
16
+ id: PLAYER_COMP_ID,
17
+ nonce: 777,
18
+ folderName: null,
19
+ parentFolderName: null,
20
+ schema: null,
21
+ calculateMetadata: null,
22
+ },
23
+ ],
24
+ folders: [],
25
+ registerFolder: () => undefined,
26
+ unregisterFolder: () => undefined,
27
+ registerComposition: () => undefined,
28
+ unregisterComposition: () => undefined,
29
+ currentCompositionMetadata: null,
30
+ setCurrentCompositionMetadata: () => undefined,
31
+ canvasContent: { type: 'composition', compositionId: 'player-comp' },
32
+ setCanvasContent: () => undefined,
33
+ };
34
+ return context;
35
+ }, [component, durationInFrames, compositionHeight, compositionWidth, fps]);
36
+ const [mediaMuted, setMediaMuted] = useState(() => initiallyMuted);
37
+ const [mediaVolume, setMediaVolume] = useState(() => getPreferredVolume());
38
+ const mediaVolumeContextValue = useMemo(() => {
39
+ return {
40
+ mediaMuted,
41
+ mediaVolume,
42
+ };
43
+ }, [mediaMuted, mediaVolume]);
44
+ const setMediaVolumeAndPersist = useCallback((vol) => {
45
+ setMediaVolume(vol);
46
+ persistVolume(vol);
47
+ }, []);
48
+ const setMediaVolumeContextValue = useMemo(() => {
49
+ return {
50
+ setMediaMuted,
51
+ setMediaVolume: setMediaVolumeAndPersist,
52
+ };
53
+ }, [setMediaVolumeAndPersist]);
54
+ return (_jsx(Internals.CanUseRemotionHooksProvider, { children: _jsx(Internals.Timeline.TimelineContext.Provider, { value: timelineContext, children: _jsx(Internals.CompositionManager.Provider, { value: compositionManagerContext, children: _jsx(Internals.ResolveCompositionConfig, { children: _jsx(Internals.PrefetchProvider, { children: _jsx(Internals.DurationsContextProvider, { children: _jsx(Internals.MediaVolumeContext.Provider, { value: mediaVolumeContextValue, children: _jsx(Internals.NativeLayersProvider, { children: _jsx(Internals.SetMediaVolumeContext.Provider, { value: setMediaVolumeContextValue, children: _jsx(Internals.SharedAudioContextProvider, { numberOfAudioTags: numberOfSharedAudioTags, component: component, children: _jsx(Internals.BufferingProvider, { children: children }) }) }) }) }) }) }) }) }) }) }));
55
+ };
@@ -0,0 +1,23 @@
1
+ import type { CSSProperties } from 'react';
2
+ import type { CompProps } from 'remotion';
3
+ import type { AnyZodObject } from 'zod';
4
+ import type { ThumbnailMethods } from './player-methods.js';
5
+ import type { ErrorFallback, RenderLoading } from './PlayerUI.js';
6
+ import type { PropsIfHasProps } from './utils/props-if-has-props.js';
7
+ type ThumbnailProps<Schema extends AnyZodObject, Props extends Record<string, unknown>> = PropsIfHasProps<Schema, Props> & CompProps<Props> & {
8
+ frameToDisplay: number;
9
+ style?: CSSProperties;
10
+ durationInFrames: number;
11
+ compositionWidth: number;
12
+ compositionHeight: number;
13
+ fps: number;
14
+ errorFallback?: ErrorFallback;
15
+ renderLoading?: RenderLoading;
16
+ className?: string;
17
+ };
18
+ /**
19
+ * @description A component which can be rendered in a regular React App (for example: Next.js, Vite) to display a single frame of a video.
20
+ * @see [Documentation](https://www.remotion.dev/docs/player/thumbnail)
21
+ */
22
+ export declare const Thumbnail: <Schema extends AnyZodObject, Props extends Record<string, unknown>>(props: ThumbnailProps<Schema, Props> & import("react").RefAttributes<ThumbnailMethods>) => React.ReactElement | null;
23
+ export {};
@@ -0,0 +1,48 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useImperativeHandle, useLayoutEffect, 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 { PLAYER_COMP_ID, SharedPlayerContexts } from './SharedPlayerContext.js';
7
+ import ThumbnailUI from './ThumbnailUI.js';
8
+ const ThumbnailFn = ({ frameToDisplay, style, inputProps, compositionHeight, compositionWidth, durationInFrames, fps, className, errorFallback = () => '⚠️', renderLoading, ...componentProps }, ref) => {
9
+ if (typeof window !== 'undefined') {
10
+ // eslint-disable-next-line react-hooks/rules-of-hooks
11
+ useLayoutEffect(() => {
12
+ window.remotion_isPlayer = true;
13
+ }, []);
14
+ }
15
+ const [thumbnailId] = useState(() => String(random(null)));
16
+ const rootRef = useRef(null);
17
+ const timelineState = useMemo(() => {
18
+ const value = {
19
+ playing: false,
20
+ frame: {
21
+ [PLAYER_COMP_ID]: frameToDisplay,
22
+ },
23
+ rootId: thumbnailId,
24
+ imperativePlaying: {
25
+ current: false,
26
+ },
27
+ playbackRate: 1,
28
+ setPlaybackRate: () => {
29
+ throw new Error('thumbnail');
30
+ },
31
+ audioAndVideoTags: { current: [] },
32
+ };
33
+ return value;
34
+ }, [frameToDisplay, thumbnailId]);
35
+ useImperativeHandle(ref, () => rootRef.current, []);
36
+ const Component = Internals.useLazyComponent(componentProps);
37
+ const [emitter] = useState(() => new ThumbnailEmitter());
38
+ const passedInputProps = useMemo(() => {
39
+ return inputProps !== null && inputProps !== void 0 ? inputProps : {};
40
+ }, [inputProps]);
41
+ return (_jsx(Internals.IsPlayerContextProvider, { children: _jsx(SharedPlayerContexts, { timelineContext: timelineState, component: Component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, numberOfSharedAudioTags: 0, initiallyMuted: true, children: _jsx(ThumbnailEmitterContext.Provider, { value: emitter, children: _jsx(ThumbnailUI, { ref: rootRef, className: className, errorFallback: errorFallback, inputProps: passedInputProps, renderLoading: renderLoading, style: style }) }) }) }));
42
+ };
43
+ const forward = forwardRef;
44
+ /**
45
+ * @description A component which can be rendered in a regular React App (for example: Next.js, Vite) to display a single frame of a video.
46
+ * @see [Documentation](https://www.remotion.dev/docs/player/thumbnail)
47
+ */
48
+ export const Thumbnail = forward(ThumbnailFn);
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import type { ThumbnailMethods } from './player-methods.js';
3
+ import type { ErrorFallback, RenderLoading } from './PlayerUI.js';
4
+ declare const _default: React.ForwardRefExoticComponent<{
5
+ inputProps: Record<string, unknown>;
6
+ style?: React.CSSProperties | undefined;
7
+ errorFallback: ErrorFallback;
8
+ renderLoading: RenderLoading | undefined;
9
+ className: string | undefined;
10
+ } & React.RefAttributes<ThumbnailMethods>>;
11
+ export default _default;
@@ -0,0 +1,89 @@
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 { useBufferStateEmitter } from './use-buffer-state-emitter.js';
8
+ import { useThumbnail } from './use-thumbnail.js';
9
+ import { IS_NODE } from './utils/is-node.js';
10
+ import { useElementSize } from './utils/use-element-size.js';
11
+ const reactVersion = React.version.split('.')[0];
12
+ if (reactVersion === '0') {
13
+ throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
14
+ }
15
+ const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
16
+ const ThumbnailUI = ({ style, inputProps, errorFallback, renderLoading, className }, ref) => {
17
+ var _a, _b;
18
+ const config = Internals.useUnsafeVideoConfig();
19
+ const video = Internals.useVideo();
20
+ const container = useRef(null);
21
+ const canvasSize = useElementSize(container, {
22
+ triggerOnWindowResize: false,
23
+ shouldApplyCssTransforms: false,
24
+ });
25
+ const layout = useMemo(() => {
26
+ if (!config || !canvasSize) {
27
+ return null;
28
+ }
29
+ return calculateCanvasTransformation({
30
+ canvasSize,
31
+ compositionHeight: config.height,
32
+ compositionWidth: config.width,
33
+ previewSize: 'auto',
34
+ });
35
+ }, [canvasSize, config]);
36
+ const scale = (_a = layout === null || layout === void 0 ? void 0 : layout.scale) !== null && _a !== void 0 ? _a : 1;
37
+ const thumbnail = useThumbnail();
38
+ useBufferStateEmitter(thumbnail.emitter);
39
+ useImperativeHandle(ref, () => {
40
+ const methods = {
41
+ getContainerNode: () => container.current,
42
+ getScale: () => scale,
43
+ };
44
+ return Object.assign(thumbnail.emitter, methods);
45
+ }, [scale, thumbnail.emitter]);
46
+ const VideoComponent = video ? video.component : null;
47
+ const outerStyle = useMemo(() => {
48
+ return calculateOuterStyle({ config, style, canvasSize });
49
+ }, [canvasSize, config, style]);
50
+ const outer = useMemo(() => {
51
+ return calculateOuter({ config, layout, scale });
52
+ }, [config, layout, scale]);
53
+ const containerStyle = useMemo(() => {
54
+ return calculateContainerStyle({
55
+ canvasSize,
56
+ config,
57
+ layout,
58
+ scale,
59
+ });
60
+ }, [canvasSize, config, layout, scale]);
61
+ const onError = useCallback((error) => {
62
+ // Pay attention to `this context`
63
+ thumbnail.emitter.dispatchError(error);
64
+ }, [thumbnail.emitter]);
65
+ const loadingMarkup = useMemo(() => {
66
+ return renderLoading
67
+ ? renderLoading({
68
+ height: outerStyle.height,
69
+ width: outerStyle.width,
70
+ isBuffering: false,
71
+ })
72
+ : null;
73
+ }, [outerStyle.height, outerStyle.width, renderLoading]);
74
+ const currentScaleContext = useMemo(() => {
75
+ return {
76
+ type: 'scale',
77
+ scale,
78
+ };
79
+ }, [scale]);
80
+ if (!config) {
81
+ return null;
82
+ }
83
+ 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(Internals.CurrentScaleContext.Provider, { value: currentScaleContext, children: _jsx(VideoComponent, { ...((_b = video === null || video === void 0 ? void 0 : video.props) !== null && _b !== void 0 ? _b : {}), ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}) }) }) })) : null }) }));
84
+ if (IS_NODE && !doesReactVersionSupportSuspense) {
85
+ return (_jsx("div", { ref: container, style: outerStyle, className: className, children: content }));
86
+ }
87
+ return (_jsx("div", { ref: container, style: outerStyle, className: className, children: _jsx(Suspense, { fallback: loadingMarkup, children: content }) }));
88
+ };
89
+ export default forwardRef(ThumbnailUI);
@@ -0,0 +1,14 @@
1
+ export declare const calculateNextFrame: ({ time, currentFrame: startFrame, playbackSpeed, fps, actualLastFrame, actualFirstFrame, framesAdvanced, shouldLoop, }: {
2
+ time: number;
3
+ currentFrame: number;
4
+ playbackSpeed: number;
5
+ fps: number;
6
+ actualFirstFrame: number;
7
+ actualLastFrame: number;
8
+ framesAdvanced: number;
9
+ shouldLoop: boolean;
10
+ }) => {
11
+ nextFrame: number;
12
+ framesToAdvance: number;
13
+ hasEnded: boolean;
14
+ };
@@ -0,0 +1,24 @@
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
+ };