@remotion/player 4.0.109 → 4.0.111

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 (65) 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 +32 -0
  7. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/Player.d.ts +2 -0
  8. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/Player.js +4 -9
  9. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerControls.d.ts +3 -1
  10. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerControls.js +8 -5
  11. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerSeekBar.js +6 -7
  12. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerUI.d.ts +3 -0
  13. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerUI.js +51 -4
  14. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/SharedPlayerContext.js +1 -1
  15. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/ThumbnailUI.js +8 -1
  16. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/calculate-scale.d.ts +1 -8
  17. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/calculate-scale.js +2 -7
  18. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/error-boundary.d.ts +1 -1
  19. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/event-emitter.d.ts +6 -0
  20. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/event-emitter.js +8 -0
  21. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/icons.js +1 -1
  22. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/index.d.ts +8 -8
  23. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/index.js +5 -2
  24. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-playback.js +35 -3
  25. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-player.d.ts +1 -0
  26. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-player.js +8 -1
  27. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/tsconfig-esm.tsbuildinfo +1 -1
  28. package/dist/cjs/BufferingIndicator.d.ts +5 -0
  29. package/dist/cjs/BufferingIndicator.js +42 -0
  30. package/dist/cjs/DefaultPlayPauseButton.d.ts +5 -0
  31. package/dist/cjs/DefaultPlayPauseButton.js +16 -0
  32. package/dist/cjs/EmitterProvider.d.ts +5 -0
  33. package/dist/cjs/EmitterProvider.js +36 -0
  34. package/dist/cjs/Player.d.ts +2 -0
  35. package/dist/cjs/Player.js +4 -9
  36. package/dist/cjs/PlayerControls.d.ts +3 -1
  37. package/dist/cjs/PlayerControls.js +7 -4
  38. package/dist/cjs/PlayerSeekBar.js +6 -7
  39. package/dist/cjs/PlayerUI.d.ts +3 -0
  40. package/dist/cjs/PlayerUI.js +51 -4
  41. package/dist/cjs/SharedPlayerContext.js +1 -1
  42. package/dist/cjs/ThumbnailUI.js +8 -1
  43. package/dist/cjs/calculate-scale.d.ts +1 -8
  44. package/dist/cjs/calculate-scale.js +3 -9
  45. package/dist/cjs/event-emitter.d.ts +6 -0
  46. package/dist/cjs/event-emitter.js +8 -0
  47. package/dist/cjs/icons.js +1 -1
  48. package/dist/cjs/index.d.ts +8 -8
  49. package/dist/cjs/index.js +4 -1
  50. package/dist/cjs/use-playback.js +34 -2
  51. package/dist/cjs/use-player.d.ts +1 -0
  52. package/dist/cjs/use-player.js +8 -1
  53. package/dist/esm/BufferingIndicator.d.ts +5 -0
  54. package/dist/esm/DefaultPlayPauseButton.d.ts +5 -0
  55. package/dist/esm/EmitterProvider.d.ts +5 -0
  56. package/dist/esm/Player.d.ts +2 -0
  57. package/dist/esm/PlayerControls.d.ts +3 -1
  58. package/dist/esm/PlayerUI.d.ts +3 -0
  59. package/dist/esm/calculate-scale.d.ts +1 -8
  60. package/dist/esm/error-boundary.d.ts +1 -1
  61. package/dist/esm/event-emitter.d.ts +6 -0
  62. package/dist/esm/index.d.ts +8 -8
  63. package/dist/esm/index.mjs +243 -76
  64. package/dist/esm/use-player.d.ts +1 -0
  65. package/package.json +2 -2
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare const bufferingIndicatorStrokeWidth = 3;
3
+ export declare const BufferingIndicator: React.FC<{
4
+ type: 'player' | 'studio';
5
+ }>;
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ICON_SIZE } from './icons.js';
3
+ const className = '__remotion_buffering_indicator';
4
+ const remotionBufferingAnimation = '__remotion_buffering_animation';
5
+ export const bufferingIndicatorStrokeWidth = 3;
6
+ const playerStyle = {
7
+ width: ICON_SIZE,
8
+ height: ICON_SIZE,
9
+ overflow: 'hidden',
10
+ lineHeight: 'normal',
11
+ fontSize: 'inherit',
12
+ };
13
+ const studioStyle = {
14
+ width: 14,
15
+ height: 14,
16
+ overflow: 'hidden',
17
+ lineHeight: 'normal',
18
+ fontSize: 'inherit',
19
+ };
20
+ export const BufferingIndicator = ({ type }) => {
21
+ const style = type === 'player' ? playerStyle : studioStyle;
22
+ return (_jsxs(_Fragment, { children: [_jsx("style", { type: "text/css", children: `
23
+ @keyframes ${remotionBufferingAnimation} {
24
+ 0% {
25
+ rotate: 0deg;
26
+ }
27
+ 100% {
28
+ rotate: 360deg;
29
+ }
30
+ }
31
+
32
+ .${className} {
33
+ animation: ${remotionBufferingAnimation} 1s linear infinite;
34
+ }
35
+ ` }), _jsx("div", { style: style, children: _jsx("svg", { viewBox: type === 'player' ? '0 0 22 22' : '0 0 18 18', style: style, className: className, children: _jsx("path", { d: type === 'player'
36
+ ? 'M 11 4 A 7 7 0 0 1 15.1145 16.66312'
37
+ : 'M 9 2 A 7 7 0 0 1 13.1145 14.66312', stroke: "white", strokeLinecap: "round", fill: "none", strokeWidth: 3 }) }) })] }));
38
+ };
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ export declare const DefaultPlayPauseButton: React.FC<{
3
+ playing: boolean;
4
+ buffering: boolean;
5
+ }>;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { BufferingIndicator } from './BufferingIndicator.js';
3
+ import { PauseIcon, PlayIcon } from './icons.js';
4
+ export const DefaultPlayPauseButton = ({ playing, buffering }) => {
5
+ if (playing && buffering) {
6
+ return _jsx(BufferingIndicator, { type: "player" });
7
+ }
8
+ if (playing) {
9
+ return _jsx(PauseIcon, {});
10
+ }
11
+ return _jsx(PlayIcon, {});
12
+ };
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare const PlayerEmitterProvider: React.FC<{
3
+ children: React.ReactNode;
4
+ currentPlaybackRate: number | null;
5
+ }>;
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useContext, useEffect, useState } from 'react';
3
+ import { Internals } from 'remotion';
4
+ import { PlayerEventEmitterContext } from './emitter-context.js';
5
+ import { PlayerEmitter } from './event-emitter.js';
6
+ export const PlayerEmitterProvider = ({ children, currentPlaybackRate }) => {
7
+ const [emitter] = useState(() => new PlayerEmitter());
8
+ const bufferManager = useContext(Internals.BufferingContextReact);
9
+ if (!bufferManager) {
10
+ throw new Error('BufferingContextReact not found');
11
+ }
12
+ useEffect(() => {
13
+ if (currentPlaybackRate) {
14
+ emitter.dispatchRateChange(currentPlaybackRate);
15
+ }
16
+ }, [emitter, currentPlaybackRate]);
17
+ useEffect(() => {
18
+ const clear1 = bufferManager.listenForBuffering(() => {
19
+ bufferManager.buffering.current = true;
20
+ emitter.dispatchWaiting({});
21
+ });
22
+ const clear2 = bufferManager.listenForResume(() => {
23
+ bufferManager.buffering.current = false;
24
+ emitter.dispatchResume({});
25
+ });
26
+ return () => {
27
+ clear1.remove();
28
+ clear2.remove();
29
+ };
30
+ }, [bufferManager, emitter]);
31
+ return (_jsx(PlayerEventEmitterContext.Provider, { value: emitter, children: children }));
32
+ };
@@ -34,6 +34,7 @@ export type PlayerProps<Schema extends AnyZodObject, Props> = {
34
34
  showPosterWhenPaused?: boolean;
35
35
  showPosterWhenEnded?: boolean;
36
36
  showPosterWhenUnplayed?: boolean;
37
+ showPosterWhenBuffering?: boolean;
37
38
  inFrame?: number | null;
38
39
  outFrame?: number | null;
39
40
  initiallyShowControls?: number | boolean;
@@ -44,6 +45,7 @@ export type PlayerProps<Schema extends AnyZodObject, Props> = {
44
45
  initiallyMuted?: boolean;
45
46
  showPlaybackRateControl?: boolean | number[];
46
47
  posterFillMode?: PosterFillMode;
48
+ bufferStateDelayInMilliseconds?: number;
47
49
  } & CompProps<Props> & PropsIfHasProps<Schema, Props>;
48
50
  export declare const componentOrNullIfLazy: <Props>(props: CompProps<Props>) => ComponentType<Props> | null;
49
51
  /**
@@ -1,8 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
3
  import { Composition, Internals } from 'remotion';
4
- import { PlayerEventEmitterContext } from './emitter-context.js';
5
- import { PlayerEmitter } from './event-emitter.js';
4
+ import { PlayerEmitterProvider } from './EmitterProvider.js';
6
5
  import { PLAYER_CSS_CLASSNAME } from './player-css-classname.js';
7
6
  import PlayerUI from './PlayerUI.js';
8
7
  import { PLAYER_COMP_ID, SharedPlayerContexts } from './SharedPlayerContext.js';
@@ -16,7 +15,7 @@ export const componentOrNullIfLazy = (props) => {
16
15
  }
17
16
  return null;
18
17
  };
19
- const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps, inputProps, style, controls = false, loop = false, autoPlay = false, showVolumeControls = true, allowFullscreen = true, clickToPlay, doubleClickToFullscreen = false, spaceKeyToPlayOrPause = true, moveToBeginningWhenEnded = true, numberOfSharedAudioTags = 5, errorFallback = () => '⚠️', playbackRate = 1, renderLoading, className, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, renderFullscreenButton, renderPlayPauseButton, alwaysShowControls = false, initiallyMuted = false, showPlaybackRateControl = false, posterFillMode = 'player-size', ...componentProps }, ref) => {
18
+ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps, inputProps, style, controls = false, loop = false, autoPlay = false, showVolumeControls = true, allowFullscreen = true, clickToPlay, doubleClickToFullscreen = false, spaceKeyToPlayOrPause = true, moveToBeginningWhenEnded = true, numberOfSharedAudioTags = 5, errorFallback = () => '⚠️', playbackRate = 1, renderLoading, className, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, renderFullscreenButton, renderPlayPauseButton, alwaysShowControls = false, initiallyMuted = false, showPlaybackRateControl = false, posterFillMode = 'player-size', bufferStateDelayInMilliseconds, ...componentProps }, ref) => {
20
19
  if (typeof window !== 'undefined') {
21
20
  // eslint-disable-next-line react-hooks/rules-of-hooks
22
21
  useLayoutEffect(() => {
@@ -42,7 +41,6 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
42
41
  }));
43
42
  const [playing, setPlaying] = useState(false);
44
43
  const [rootId] = useState('player-comp');
45
- const [emitter] = useState(() => new PlayerEmitter());
46
44
  const rootRef = useRef(null);
47
45
  const audioAndVideoTags = useRef([]);
48
46
  const imperativePlaying = useRef(false);
@@ -102,9 +100,6 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
102
100
  throw new TypeError(`'numberOfSharedAudioTags' must be an integer but got '${numberOfSharedAudioTags}' instead`);
103
101
  }
104
102
  validatePlaybackRate(currentPlaybackRate);
105
- useEffect(() => {
106
- emitter.dispatchRateChange(currentPlaybackRate);
107
- }, [emitter, currentPlaybackRate]);
108
103
  useEffect(() => {
109
104
  setCurrentPlaybackRate(playbackRate);
110
105
  }, [playbackRate]);
@@ -136,9 +131,9 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
136
131
  }, []);
137
132
  }
138
133
  const actualInputProps = useMemo(() => inputProps !== null && inputProps !== void 0 ? inputProps : {}, [inputProps]);
139
- return (_jsx(Internals.IsPlayerContextProvider, { children: _jsx(SharedPlayerContexts, { timelineContext: timelineContextValue, component: component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, numberOfSharedAudioTags: numberOfSharedAudioTags, initiallyMuted: initiallyMuted, children: _jsx(Internals.Timeline.SetTimelineContext.Provider, { value: setTimelineContextValue, children: _jsx(PlayerEventEmitterContext.Provider, { value: emitter, children: _jsx(PlayerUI, { ref: rootRef, posterFillMode: posterFillMode, renderLoading: renderLoading, autoPlay: Boolean(autoPlay), loop: Boolean(loop), controls: Boolean(controls), errorFallback: errorFallback, style: style, inputProps: actualInputProps, allowFullscreen: Boolean(allowFullscreen), moveToBeginningWhenEnded: Boolean(moveToBeginningWhenEnded), clickToPlay: typeof clickToPlay === 'boolean'
134
+ return (_jsx(Internals.IsPlayerContextProvider, { children: _jsx(SharedPlayerContexts, { timelineContext: timelineContextValue, component: component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, numberOfSharedAudioTags: numberOfSharedAudioTags, initiallyMuted: initiallyMuted, children: _jsx(Internals.Timeline.SetTimelineContext.Provider, { value: setTimelineContextValue, children: _jsx(PlayerEmitterProvider, { currentPlaybackRate: currentPlaybackRate, children: _jsx(PlayerUI, { ref: rootRef, posterFillMode: posterFillMode, renderLoading: renderLoading, autoPlay: Boolean(autoPlay), loop: Boolean(loop), controls: Boolean(controls), errorFallback: errorFallback, style: style, inputProps: actualInputProps, allowFullscreen: Boolean(allowFullscreen), moveToBeginningWhenEnded: Boolean(moveToBeginningWhenEnded), clickToPlay: typeof clickToPlay === 'boolean'
140
135
  ? clickToPlay
141
- : Boolean(controls), showVolumeControls: Boolean(showVolumeControls), doubleClickToFullscreen: Boolean(doubleClickToFullscreen), spaceKeyToPlayOrPause: Boolean(spaceKeyToPlayOrPause), playbackRate: currentPlaybackRate, className: className !== null && className !== void 0 ? className : undefined, showPosterWhenUnplayed: Boolean(showPosterWhenUnplayed), showPosterWhenEnded: Boolean(showPosterWhenEnded), showPosterWhenPaused: Boolean(showPosterWhenPaused), renderPoster: renderPoster, inFrame: inFrame !== null && inFrame !== void 0 ? inFrame : null, outFrame: outFrame !== null && outFrame !== void 0 ? outFrame : null, initiallyShowControls: initiallyShowControls !== null && initiallyShowControls !== void 0 ? initiallyShowControls : true, renderFullscreen: renderFullscreenButton !== null && renderFullscreenButton !== void 0 ? renderFullscreenButton : null, renderPlayPauseButton: renderPlayPauseButton !== null && renderPlayPauseButton !== void 0 ? renderPlayPauseButton : null, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl }) }) }) }) }));
136
+ : Boolean(controls), showVolumeControls: Boolean(showVolumeControls), doubleClickToFullscreen: Boolean(doubleClickToFullscreen), spaceKeyToPlayOrPause: Boolean(spaceKeyToPlayOrPause), playbackRate: currentPlaybackRate, className: className !== null && className !== void 0 ? className : undefined, showPosterWhenUnplayed: Boolean(showPosterWhenUnplayed), showPosterWhenEnded: Boolean(showPosterWhenEnded), showPosterWhenPaused: Boolean(showPosterWhenPaused), showPosterWhenBuffering: Boolean(showPosterWhenBuffering), renderPoster: renderPoster, inFrame: inFrame !== null && inFrame !== void 0 ? inFrame : null, outFrame: outFrame !== null && outFrame !== void 0 ? outFrame : null, initiallyShowControls: initiallyShowControls !== null && initiallyShowControls !== void 0 ? initiallyShowControls : true, renderFullscreen: renderFullscreenButton !== null && renderFullscreenButton !== void 0 ? renderFullscreenButton : null, renderPlayPauseButton: renderPlayPauseButton !== null && renderPlayPauseButton !== void 0 ? renderPlayPauseButton : null, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl, bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds !== null && bufferStateDelayInMilliseconds !== void 0 ? bufferStateDelayInMilliseconds : 300 }) }) }) }) }));
142
137
  };
143
138
  const forward = forwardRef;
144
139
  /**
@@ -4,7 +4,8 @@ import type { usePlayer } from './use-player.js';
4
4
  import type { Size } from './utils/use-element-size.js';
5
5
  export type RenderPlayPauseButton = (props: {
6
6
  playing: boolean;
7
- }) => ReactNode;
7
+ isBuffering: boolean;
8
+ }) => ReactNode | null;
8
9
  export type RenderFullscreenButton = (props: {
9
10
  isFullscreen: boolean;
10
11
  }) => ReactNode;
@@ -39,4 +40,5 @@ export declare const Controls: React.FC<{
39
40
  alwaysShowControls: boolean;
40
41
  showPlaybackRateControl: boolean | number[];
41
42
  containerRef: React.RefObject<HTMLDivElement>;
43
+ buffering: boolean;
42
44
  }>;
@@ -1,8 +1,9 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { Internals } from 'remotion';
4
+ import { DefaultPlayPauseButton } from './DefaultPlayPauseButton.js';
4
5
  import { formatTime } from './format-time.js';
5
- import { FullscreenIcon, PauseIcon, PlayIcon } from './icons.js';
6
+ import { FullscreenIcon } from './icons.js';
6
7
  import { MediaVolumeSlider } from './MediaVolumeSlider.js';
7
8
  import { PlaybackrateControl, playerButtonStyle } from './PlaybackrateControl.js';
8
9
  import { PlayerSeekBar } from './PlayerSeekBar.js';
@@ -60,9 +61,8 @@ const flex1 = {
60
61
  flex: 1,
61
62
  };
62
63
  const fullscreen = {};
63
- const PlayPauseButton = ({ playing }) => playing ? _jsx(PauseIcon, {}) : _jsx(PlayIcon, {});
64
- export const Controls = ({ durationInFrames, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, canvasSize, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, showPlaybackRateControl, containerRef, }) => {
65
- var _a;
64
+ export const Controls = ({ durationInFrames, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, canvasSize, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, showPlaybackRateControl, containerRef, buffering, }) => {
65
+ var _a, _b;
66
66
  const playButtonRef = useRef(null);
67
67
  const frame = Internals.Timeline.useTimelinePosition();
68
68
  const [supportsFullscreen, setSupportsFullscreen] = useState(false);
@@ -153,7 +153,10 @@ export const Controls = ({ durationInFrames, isFullscreen, fps, player, showVolu
153
153
  }
154
154
  return null;
155
155
  }, [showPlaybackRateControl]);
156
- return (_jsxs("div", { style: containerCss, children: [_jsxs("div", { style: controlsRow, children: [_jsxs("div", { style: leftPartStyle, children: [_jsx("button", { ref: playButtonRef, type: "button", style: playerButtonStyle, onClick: player.playing ? player.pause : player.play, "aria-label": player.playing ? 'Pause video' : 'Play video', title: player.playing ? 'Pause video' : 'Play video', children: renderPlayPauseButton === null ? (_jsx(PlayPauseButton, { playing: player.playing })) : (renderPlayPauseButton({ playing: player.playing })) }), showVolumeControls ? (_jsxs(_Fragment, { children: [_jsx("div", { style: xSpacer }), _jsx(MediaVolumeSlider, { displayVerticalVolumeSlider: displayVerticalVolumeSlider })] })) : null, _jsx("div", { style: xSpacer }), _jsxs("div", { style: timeLabel, children: [formatTime(frame / fps), " / ", formatTime(durationInFrames / fps)] }), _jsx("div", { style: xSpacer })] }), _jsx("div", { style: flex1 }), playbackRates && canvasSize && (_jsx(PlaybackrateControl, { canvasSize: canvasSize, playbackRates: playbackRates })), playbackRates && supportsFullscreen && allowFullscreen ? (_jsx("div", { style: xSpacer })) : null, _jsx("div", { style: fullscreen, children: supportsFullscreen && allowFullscreen ? (_jsx("button", { type: "button", "aria-label": isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', title: isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', style: playerButtonStyle, onClick: isFullscreen
156
+ return (_jsxs("div", { style: containerCss, children: [_jsxs("div", { style: controlsRow, children: [_jsxs("div", { style: leftPartStyle, children: [_jsx("button", { ref: playButtonRef, type: "button", style: playerButtonStyle, onClick: player.playing ? player.pause : player.play, "aria-label": player.playing ? 'Pause video' : 'Play video', title: player.playing ? 'Pause video' : 'Play video', children: renderPlayPauseButton === null ? (_jsx(DefaultPlayPauseButton, { buffering: buffering, playing: player.playing })) : ((_b = renderPlayPauseButton({
157
+ playing: player.playing,
158
+ isBuffering: buffering,
159
+ })) !== null && _b !== void 0 ? _b : (_jsx(DefaultPlayPauseButton, { buffering: buffering, playing: player.playing }))) }), showVolumeControls ? (_jsxs(_Fragment, { children: [_jsx("div", { style: xSpacer }), _jsx(MediaVolumeSlider, { displayVerticalVolumeSlider: displayVerticalVolumeSlider })] })) : null, _jsx("div", { style: xSpacer }), _jsxs("div", { style: timeLabel, children: [formatTime(frame / fps), " / ", formatTime(durationInFrames / fps)] }), _jsx("div", { style: xSpacer })] }), _jsx("div", { style: flex1 }), playbackRates && canvasSize && (_jsx(PlaybackrateControl, { canvasSize: canvasSize, playbackRates: playbackRates })), playbackRates && supportsFullscreen && allowFullscreen ? (_jsx("div", { style: xSpacer })) : null, _jsx("div", { style: fullscreen, children: supportsFullscreen && allowFullscreen ? (_jsx("button", { type: "button", "aria-label": isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', title: isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', style: playerButtonStyle, onClick: isFullscreen
157
160
  ? onExitFullscreenButtonClick
158
161
  : onFullscreenButtonClick, children: renderFullscreenButton === null ? (_jsx(FullscreenIcon, { isFullscreen: isFullscreen })) : (renderFullscreenButton({ isFullscreen })) })) : null })] }), _jsx("div", { style: ySpacer }), _jsx(PlayerSeekBar, { onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, durationInFrames: durationInFrames, inFrame: inFrame, outFrame: outFrame })] }));
159
162
  };
@@ -51,16 +51,14 @@ export const PlayerSeekBar = ({ durationInFrames, onSeekEnd, onSeekStart, inFram
51
51
  const [dragging, setDragging] = useState({
52
52
  dragging: false,
53
53
  });
54
- const left = size ? size.left : null;
55
54
  const width = (_a = size === null || size === void 0 ? void 0 : size.width) !== null && _a !== void 0 ? _a : 0;
56
55
  const onPointerDown = useCallback((e) => {
57
- if (left === null) {
58
- throw new Error('Player has no size');
59
- }
56
+ var _a;
60
57
  if (e.button !== 0) {
61
58
  return;
62
59
  }
63
- const _frame = getFrameFromX(e.clientX - left, durationInFrames, width);
60
+ const posLeft = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left;
61
+ const _frame = getFrameFromX(e.clientX - posLeft, durationInFrames, width);
64
62
  pause();
65
63
  seek(_frame);
66
64
  setDragging({
@@ -68,7 +66,7 @@ export const PlayerSeekBar = ({ durationInFrames, onSeekEnd, onSeekStart, inFram
68
66
  wasPlaying: playing,
69
67
  });
70
68
  onSeekStart();
71
- }, [left, durationInFrames, width, pause, seek, playing, onSeekStart]);
69
+ }, [durationInFrames, width, pause, seek, playing, onSeekStart]);
72
70
  const onPointerMove = useCallback((e) => {
73
71
  var _a;
74
72
  if (!size) {
@@ -77,7 +75,8 @@ export const PlayerSeekBar = ({ durationInFrames, onSeekEnd, onSeekStart, inFram
77
75
  if (!dragging.dragging) {
78
76
  return;
79
77
  }
80
- const _frame = getFrameFromX(e.clientX - ((_a = size === null || size === void 0 ? void 0 : size.left) !== null && _a !== void 0 ? _a : 0), durationInFrames, size.width);
78
+ const posLeft = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left;
79
+ const _frame = getFrameFromX(e.clientX - posLeft, durationInFrames, size.width);
81
80
  seek(_frame);
82
81
  }, [dragging.dragging, durationInFrames, seek, size]);
83
82
  const onPointerUp = useCallback(() => {
@@ -7,6 +7,7 @@ export type ErrorFallback = (info: {
7
7
  export type RenderLoading = (canvas: {
8
8
  height: number;
9
9
  width: number;
10
+ isBuffering: boolean;
10
11
  }) => React.ReactNode;
11
12
  export type RenderPoster = RenderLoading;
12
13
  export type PosterFillMode = 'player-size' | 'composition-size';
@@ -30,6 +31,7 @@ declare const _default: React.ForwardRefExoticComponent<{
30
31
  showPosterWhenPaused: boolean;
31
32
  showPosterWhenEnded: boolean;
32
33
  showPosterWhenUnplayed: boolean;
34
+ showPosterWhenBuffering: boolean;
33
35
  inFrame: number | null;
34
36
  outFrame: number | null;
35
37
  initiallyShowControls: number | boolean;
@@ -38,5 +40,6 @@ declare const _default: React.ForwardRefExoticComponent<{
38
40
  alwaysShowControls: boolean;
39
41
  showPlaybackRateControl: boolean | number[];
40
42
  posterFillMode: PosterFillMode;
43
+ bufferStateDelayInMilliseconds: number;
41
44
  } & React.RefAttributes<PlayerRef>>;
42
45
  export default _default;
@@ -15,7 +15,7 @@ if (reactVersion === '0') {
15
15
  throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
16
16
  }
17
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, inFrame, outFrame, initiallyShowControls, renderFullscreen: renderFullscreenButton, renderPlayPauseButton, alwaysShowControls, showPlaybackRateControl, posterFillMode, }, ref) => {
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, }, ref) => {
19
19
  var _a, _b, _c;
20
20
  const config = Internals.useUnsafeVideoConfig();
21
21
  const video = Internals.useVideo();
@@ -151,6 +151,44 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
151
151
  isMuted,
152
152
  });
153
153
  }, [player.emitter, isMuted]);
154
+ const [showBufferIndicator, setShowBufferState] = useState(false);
155
+ useEffect(() => {
156
+ let timeout = null;
157
+ let stopped = false;
158
+ const onBuffer = () => {
159
+ requestAnimationFrame(() => {
160
+ if (bufferStateDelayInMilliseconds === 0) {
161
+ setShowBufferState(true);
162
+ }
163
+ else {
164
+ timeout = setTimeout(() => {
165
+ if (!stopped) {
166
+ setShowBufferState(true);
167
+ }
168
+ }, bufferStateDelayInMilliseconds);
169
+ }
170
+ });
171
+ };
172
+ const onResume = () => {
173
+ requestAnimationFrame(() => {
174
+ setShowBufferState(false);
175
+ if (timeout) {
176
+ clearTimeout(timeout);
177
+ }
178
+ });
179
+ };
180
+ player.emitter.addEventListener('waiting', onBuffer);
181
+ player.emitter.addEventListener('resume', onResume);
182
+ return () => {
183
+ player.emitter.removeEventListener('waiting', onBuffer);
184
+ player.emitter.removeEventListener('resume', onResume);
185
+ setShowBufferState(false);
186
+ if (timeout) {
187
+ clearTimeout(timeout);
188
+ }
189
+ stopped = true;
190
+ };
191
+ }, [bufferStateDelayInMilliseconds, player.emitter]);
154
192
  useImperativeHandle(ref, () => {
155
193
  const methods = {
156
194
  play: player.play,
@@ -278,9 +316,16 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
278
316
  ? renderLoading({
279
317
  height: outerStyle.height,
280
318
  width: outerStyle.width,
319
+ isBuffering: showBufferIndicator,
281
320
  })
282
321
  : null;
283
- }, [outerStyle.height, outerStyle.width, renderLoading]);
322
+ }, [outerStyle.height, outerStyle.width, renderLoading, showBufferIndicator]);
323
+ const currentScale = useMemo(() => {
324
+ return {
325
+ type: 'scale',
326
+ scale,
327
+ };
328
+ }, [scale]);
284
329
  if (!config) {
285
330
  return null;
286
331
  }
@@ -292,6 +337,7 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
292
337
  width: posterFillMode === 'player-size'
293
338
  ? outerStyle.width
294
339
  : config.width,
340
+ isBuffering: showBufferIndicator,
295
341
  })
296
342
  : null;
297
343
  if (poster === undefined) {
@@ -302,13 +348,14 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
302
348
  showPosterWhenPaused && !player.isPlaying() && !seeking,
303
349
  showPosterWhenEnded && player.isLastFrame && !player.isPlaying(),
304
350
  showPosterWhenUnplayed && !player.hasPlayed && !player.isPlaying(),
351
+ showPosterWhenBuffering && showBufferIndicator && player.isPlaying(),
305
352
  ].some(Boolean);
306
353
  const { left, top, width, height, ...outerWithoutScale } = outer;
307
- const content = (_jsxs(_Fragment, { children: [_jsx("div", { style: outer, onClick: 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(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: {
354
+ const content = (_jsxs(_Fragment, { children: [_jsx("div", { style: outer, onClick: 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: {
308
355
  ...outerWithoutScale,
309
356
  width: config.width,
310
357
  height: config.height,
311
- }, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null] }) }), shouldShowPoster && posterFillMode === 'player-size' ? (_jsx("div", { style: outer, onClick: 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 })) : null] }));
358
+ }, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null] }) }), shouldShowPoster && posterFillMode === 'player-size' ? (_jsx("div", { style: outer, onClick: 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 })) : null] }));
312
359
  if (IS_NODE && !doesReactVersionSupportSuspense) {
313
360
  return (_jsx("div", { ref: container, style: outerStyle, className: className, children: content }));
314
361
  }
@@ -51,5 +51,5 @@ export const SharedPlayerContexts = ({ children, timelineContext, fps, compositi
51
51
  setMediaVolume: setMediaVolumeAndPersist,
52
52
  };
53
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: children }) }) }) }) }) }) }) }) }) }));
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
55
  };
@@ -67,13 +67,20 @@ const ThumbnailUI = ({ style, inputProps, errorFallback, renderLoading, classNam
67
67
  ? renderLoading({
68
68
  height: outerStyle.height,
69
69
  width: outerStyle.width,
70
+ isBuffering: false,
70
71
  })
71
72
  : null;
72
73
  }, [outerStyle.height, outerStyle.width, renderLoading]);
74
+ const currentScaleContext = useMemo(() => {
75
+ return {
76
+ type: 'scale',
77
+ scale,
78
+ };
79
+ }, [scale]);
73
80
  if (!config) {
74
81
  return null;
75
82
  }
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.props) !== null && _b !== void 0 ? _b : {}), ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}) }) })) : null }) }));
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 }) }));
77
84
  if (IS_NODE && !doesReactVersionSupportSuspense) {
78
85
  return (_jsx("div", { ref: container, style: outerStyle, className: className, children: content }));
79
86
  }
@@ -1,12 +1,5 @@
1
- import type { VideoConfig } from 'remotion';
2
- import type { PreviewSize } from './utils/preview-size.js';
1
+ import type { PreviewSize, VideoConfig } from 'remotion';
3
2
  import type { Size } from './utils/use-element-size.js';
4
- export declare const calculateScale: ({ canvasSize, compositionHeight, compositionWidth, previewSize, }: {
5
- previewSize: PreviewSize['size'];
6
- compositionWidth: number;
7
- compositionHeight: number;
8
- canvasSize: Size;
9
- }) => number;
10
3
  type Layout = {
11
4
  centerX: number;
12
5
  centerY: number;
@@ -1,12 +1,7 @@
1
+ import { Internals } from 'remotion';
1
2
  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
3
  export const calculateCanvasTransformation = ({ previewSize, compositionWidth, compositionHeight, canvasSize, }) => {
9
- const scale = calculateScale({
4
+ const scale = Internals.calculateScale({
10
5
  canvasSize,
11
6
  compositionHeight,
12
7
  compositionWidth,
@@ -15,5 +15,5 @@ export declare class ErrorBoundary extends React.Component<{
15
15
  hasError: Error;
16
16
  };
17
17
  componentDidCatch(error: Error): void;
18
- render(): string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | null | undefined;
18
+ render(): string | number | boolean | Iterable<React.ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
19
19
  }
@@ -25,6 +25,8 @@ type FullscreenChangeEventPayload = {
25
25
  type MuteChangeEventPayload = {
26
26
  isMuted: boolean;
27
27
  };
28
+ type WaitingEventPayload = {};
29
+ type ResumeEventPayload = {};
28
30
  type PlayerStateEventMap = {
29
31
  seeked: SeekPayload;
30
32
  pause: undefined;
@@ -38,6 +40,8 @@ type PlayerStateEventMap = {
38
40
  frameupdate: FrameUpdateEventPayload;
39
41
  fullscreenchange: FullscreenChangeEventPayload;
40
42
  mutechange: MuteChangeEventPayload;
43
+ waiting: WaitingEventPayload;
44
+ resume: ResumeEventPayload;
41
45
  };
42
46
  type ThumbnailStateEventMap = {
43
47
  error: ErrorPayload;
@@ -70,6 +74,8 @@ export declare class PlayerEmitter {
70
74
  dispatchFrameUpdate(event: FrameUpdateEventPayload): void;
71
75
  dispatchFullscreenChange(event: FullscreenChangeEventPayload): void;
72
76
  dispatchMuteChange(event: MuteChangeEventPayload): void;
77
+ dispatchWaiting(event: WaitingEventPayload): void;
78
+ dispatchResume(event: ResumeEventPayload): void;
73
79
  }
74
80
  export declare class ThumbnailEmitter {
75
81
  listeners: ThumbnailListeners;
@@ -13,6 +13,8 @@ export class PlayerEmitter {
13
13
  fullscreenchange: [],
14
14
  volumechange: [],
15
15
  mutechange: [],
16
+ waiting: [],
17
+ resume: [],
16
18
  };
17
19
  }
18
20
  addEventListener(name, callback) {
@@ -72,6 +74,12 @@ export class PlayerEmitter {
72
74
  dispatchMuteChange(event) {
73
75
  this.dispatchEvent('mutechange', event);
74
76
  }
77
+ dispatchWaiting(event) {
78
+ this.dispatchEvent('waiting', event);
79
+ }
80
+ dispatchResume(event) {
81
+ this.dispatchEvent('resume', event);
82
+ }
75
83
  }
76
84
  export class ThumbnailEmitter {
77
85
  constructor() {
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  export const ICON_SIZE = 25;
3
3
  export const fullscreenIconSize = 16;
4
4
  export const PlayIcon = () => {
5
- return (_jsx("svg", { width: ICON_SIZE, height: ICON_SIZE, viewBox: "0 0 25 25", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M8 6.375C7.40904 8.17576 7.06921 10.2486 7.01438 12.3871C6.95955 14.5255 7.19163 16.6547 7.6875 18.5625C9.95364 18.2995 12.116 17.6164 14.009 16.5655C15.902 15.5147 17.4755 14.124 18.6088 12.5C17.5158 10.8949 15.9949 9.51103 14.1585 8.45082C12.3222 7.3906 10.2174 6.68116 8 6.375Z", fill: "white", stroke: "white", strokeWidth: "6.25", strokeLinejoin: "round" }) }));
5
+ return (_jsx("svg", { width: ICON_SIZE, height: ICON_SIZE, viewBox: "0 0 25 25", fill: "none", children: _jsx("path", { d: "M8 6.375C7.40904 8.17576 7.06921 10.2486 7.01438 12.3871C6.95955 14.5255 7.19163 16.6547 7.6875 18.5625C9.95364 18.2995 12.116 17.6164 14.009 16.5655C15.902 15.5147 17.4755 14.124 18.6088 12.5C17.5158 10.8949 15.9949 9.51103 14.1585 8.45082C12.3222 7.3906 10.2174 6.68116 8 6.375Z", fill: "white", stroke: "white", strokeWidth: "6.25", strokeLinejoin: "round" }) }));
6
6
  };
7
7
  export const PauseIcon = () => {
8
8
  return (_jsxs("svg", { viewBox: "0 0 100 100", width: ICON_SIZE, height: ICON_SIZE, children: [_jsx("rect", { x: "25", y: "20", width: "20", height: "60", fill: "#fff", ry: "5", rx: "5" }), _jsx("rect", { x: "55", y: "20", width: "20", height: "60", fill: "#fff", ry: "5", rx: "5" })] }));
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import type { CallbackListener, PlayerEventTypes } from './event-emitter.js';
3
2
  import { PlayerEmitter } from './event-emitter.js';
4
3
  export { PlayerMethods, PlayerRef, ThumbnailMethods, ThumbnailRef, } from './player-methods.js';
@@ -6,7 +5,6 @@ export { Player, PlayerProps } from './Player.js';
6
5
  export type { RenderFullscreenButton, RenderPlayPauseButton, } from './PlayerControls.js';
7
6
  export type { ErrorFallback, RenderLoading, RenderPoster } from './PlayerUI.js';
8
7
  export { Thumbnail } from './Thumbnail.js';
9
- export { PreviewSize, Translation } from './utils/preview-size.js';
10
8
  export { Size } from './utils/use-element-size.js';
11
9
  export type { CallbackListener, PlayerEventTypes as EventTypes };
12
10
  export declare const PlayerInternals: {
@@ -26,6 +24,7 @@ export declare const PlayerInternals: {
26
24
  getCurrentFrame: () => number;
27
25
  isPlaying: () => boolean;
28
26
  hasPlayed: boolean;
27
+ isBuffering: () => boolean;
29
28
  remotionInternal_currentFrameRef: import("react").MutableRefObject<number>;
30
29
  };
31
30
  usePlayback: ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, outFrame, frameRef, }: {
@@ -54,10 +53,11 @@ export declare const PlayerInternals: {
54
53
  };
55
54
  useHoverState: (ref: import("react").RefObject<HTMLDivElement>) => boolean;
56
55
  updateAllElementsSizes: () => void;
57
- calculateScale: ({ canvasSize, compositionHeight, compositionWidth, previewSize, }: {
58
- previewSize: number | "auto";
59
- compositionWidth: number;
60
- compositionHeight: number;
61
- canvasSize: import("./utils/use-element-size.js").Size;
62
- }) => number;
56
+ PlayerEmitterProvider: import("react").FC<{
57
+ children: import("react").ReactNode;
58
+ currentPlaybackRate: number | null;
59
+ }>;
60
+ BufferingIndicator: import("react").FC<{
61
+ type: "player" | "studio";
62
+ }>;
63
63
  };
@@ -1,5 +1,7 @@
1
- import { calculateCanvasTransformation, calculateScale, } from './calculate-scale.js';
1
+ import { BufferingIndicator } from './BufferingIndicator.js';
2
+ import { calculateCanvasTransformation } from './calculate-scale.js';
2
3
  import { PlayerEventEmitterContext } from './emitter-context.js';
4
+ import { PlayerEmitterProvider } from './EmitterProvider.js';
3
5
  import { PlayerEmitter } from './event-emitter.js';
4
6
  import { useHoverState } from './use-hover-state.js';
5
7
  import { usePlayback } from './use-playback.js';
@@ -16,5 +18,6 @@ export const PlayerInternals = {
16
18
  calculateCanvasTransformation,
17
19
  useHoverState,
18
20
  updateAllElementsSizes,
19
- calculateScale,
21
+ PlayerEmitterProvider,
22
+ BufferingIndicator,
20
23
  };