@remotion/player 4.0.110 → 4.0.112

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 (46) hide show
  1. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/Player.d.ts +2 -0
  2. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/Player.js +4 -9
  3. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerControls.d.ts +3 -1
  4. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerControls.js +8 -5
  5. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerUI.d.ts +3 -0
  6. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/PlayerUI.js +51 -4
  7. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/SharedPlayerContext.js +1 -1
  8. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/ThumbnailUI.js +8 -1
  9. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/calculate-scale.d.ts +1 -8
  10. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/calculate-scale.js +2 -7
  11. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/event-emitter.d.ts +6 -0
  12. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/event-emitter.js +8 -0
  13. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/icons.js +1 -1
  14. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/index.d.ts +8 -7
  15. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/index.js +5 -2
  16. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-playback.js +35 -3
  17. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-player.d.ts +1 -0
  18. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/esm/use-player.js +8 -1
  19. package/.rollup.cache/Users/jonathanburger/remotion/packages/player/dist/tsconfig-esm.tsbuildinfo +1 -1
  20. package/dist/cjs/Player.d.ts +2 -0
  21. package/dist/cjs/Player.js +4 -9
  22. package/dist/cjs/PlayerControls.d.ts +3 -1
  23. package/dist/cjs/PlayerControls.js +7 -4
  24. package/dist/cjs/PlayerUI.d.ts +3 -0
  25. package/dist/cjs/PlayerUI.js +51 -4
  26. package/dist/cjs/SharedPlayerContext.js +1 -1
  27. package/dist/cjs/ThumbnailUI.js +8 -1
  28. package/dist/cjs/calculate-scale.d.ts +1 -8
  29. package/dist/cjs/calculate-scale.js +3 -9
  30. package/dist/cjs/event-emitter.d.ts +6 -0
  31. package/dist/cjs/event-emitter.js +8 -0
  32. package/dist/cjs/icons.js +1 -1
  33. package/dist/cjs/index.d.ts +8 -8
  34. package/dist/cjs/index.js +4 -1
  35. package/dist/cjs/use-playback.js +34 -2
  36. package/dist/cjs/use-player.d.ts +1 -0
  37. package/dist/cjs/use-player.js +8 -1
  38. package/dist/esm/Player.d.ts +2 -0
  39. package/dist/esm/PlayerControls.d.ts +3 -1
  40. package/dist/esm/PlayerUI.d.ts +3 -0
  41. package/dist/esm/calculate-scale.d.ts +1 -8
  42. package/dist/esm/event-emitter.d.ts +6 -0
  43. package/dist/esm/index.d.ts +8 -7
  44. package/dist/esm/index.mjs +237 -69
  45. package/dist/esm/use-player.d.ts +1 -0
  46. package/package.json +2 -2
@@ -1,9 +1,84 @@
1
1
  "use client";
2
- import React, { useState, useEffect, useRef, useContext, useCallback, useMemo, forwardRef, useImperativeHandle, Suspense, useLayoutEffect } from 'react';
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { Internals, random, interpolate, Composition } from 'remotion';
4
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import React, { useState, useContext, useEffect, useRef, useCallback, useMemo, forwardRef, useImperativeHandle, Suspense, useLayoutEffect } from 'react';
5
5
  import { NoReactInternals } from 'remotion/no-react';
6
6
 
7
+ const ICON_SIZE = 25;
8
+ const fullscreenIconSize = 16;
9
+ const PlayIcon = () => {
10
+ 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" }) }));
11
+ };
12
+ const PauseIcon = () => {
13
+ 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" })] }));
14
+ };
15
+ const FullscreenIcon = ({ isFullscreen, }) => {
16
+ const strokeWidth = 6;
17
+ const viewSize = 32;
18
+ const out = isFullscreen ? 0 : strokeWidth / 2;
19
+ const middleInset = isFullscreen ? strokeWidth * 1.6 : strokeWidth / 2;
20
+ const inset = isFullscreen ? strokeWidth * 1.6 : strokeWidth * 2;
21
+ return (jsxs("svg", { viewBox: `0 0 ${viewSize} ${viewSize}`, height: fullscreenIconSize, width: fullscreenIconSize, children: [jsx("path", { d: `
22
+ M ${out} ${inset}
23
+ L ${middleInset} ${middleInset}
24
+ L ${inset} ${out}
25
+ `, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" }), jsx("path", { d: `
26
+ M ${viewSize - out} ${inset}
27
+ L ${viewSize - middleInset} ${middleInset}
28
+ L ${viewSize - inset} ${out}
29
+ `, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" }), jsx("path", { d: `
30
+ M ${out} ${viewSize - inset}
31
+ L ${middleInset} ${viewSize - middleInset}
32
+ L ${inset} ${viewSize - out}
33
+ `, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" }), jsx("path", { d: `
34
+ M ${viewSize - out} ${viewSize - inset}
35
+ L ${viewSize - middleInset} ${viewSize - middleInset}
36
+ L ${viewSize - inset} ${viewSize - out}
37
+ `, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" })] }));
38
+ };
39
+ const VolumeOffIcon = () => {
40
+ return (jsx("svg", { width: ICON_SIZE, height: ICON_SIZE, viewBox: "0 0 24 24", children: jsx("path", { d: "M3.63 3.63a.996.996 0 000 1.41L7.29 8.7 7 9H4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h3l3.29 3.29c.63.63 1.71.18 1.71-.71v-4.17l4.18 4.18c-.49.37-1.02.68-1.6.91-.36.15-.58.53-.58.92 0 .72.73 1.18 1.39.91.8-.33 1.55-.77 2.22-1.31l1.34 1.34a.996.996 0 101.41-1.41L5.05 3.63c-.39-.39-1.02-.39-1.42 0zM19 12c0 .82-.15 1.61-.41 2.34l1.53 1.53c.56-1.17.88-2.48.88-3.87 0-3.83-2.4-7.11-5.78-8.4-.59-.23-1.22.23-1.22.86v.19c0 .38.25.71.61.85C17.18 6.54 19 9.06 19 12zm-8.71-6.29l-.17.17L12 7.76V6.41c0-.89-1.08-1.33-1.71-.7zM16.5 12A4.5 4.5 0 0014 7.97v1.79l2.48 2.48c.01-.08.02-.16.02-.24z", fill: "#fff" }) }));
41
+ };
42
+ const VolumeOnIcon = () => {
43
+ return (jsx("svg", { width: ICON_SIZE, height: ICON_SIZE, viewBox: "0 0 24 24", children: jsx("path", { d: "M3 10v4c0 .55.45 1 1 1h3l3.29 3.29c.63.63 1.71.18 1.71-.71V6.41c0-.89-1.08-1.34-1.71-.71L7 9H4c-.55 0-1 .45-1 1zm13.5 2A4.5 4.5 0 0014 7.97v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 4.45v.2c0 .38.25.71.6.85C17.18 6.53 19 9.06 19 12s-1.82 5.47-4.4 6.5c-.36.14-.6.47-.6.85v.2c0 .63.63 1.07 1.21.85C18.6 19.11 21 15.84 21 12s-2.4-7.11-5.79-8.4c-.58-.23-1.21.22-1.21.85z", fill: "#fff" }) }));
44
+ };
45
+
46
+ const className = '__remotion_buffering_indicator';
47
+ const remotionBufferingAnimation = '__remotion_buffering_animation';
48
+ const playerStyle = {
49
+ width: ICON_SIZE,
50
+ height: ICON_SIZE,
51
+ overflow: 'hidden',
52
+ lineHeight: 'normal',
53
+ fontSize: 'inherit',
54
+ };
55
+ const studioStyle = {
56
+ width: 14,
57
+ height: 14,
58
+ overflow: 'hidden',
59
+ lineHeight: 'normal',
60
+ fontSize: 'inherit',
61
+ };
62
+ const BufferingIndicator = ({ type }) => {
63
+ const style = type === 'player' ? playerStyle : studioStyle;
64
+ return (jsxs(Fragment, { children: [jsx("style", { type: "text/css", children: `
65
+ @keyframes ${remotionBufferingAnimation} {
66
+ 0% {
67
+ rotate: 0deg;
68
+ }
69
+ 100% {
70
+ rotate: 360deg;
71
+ }
72
+ }
73
+
74
+ .${className} {
75
+ animation: ${remotionBufferingAnimation} 1s linear infinite;
76
+ }
77
+ ` }), 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'
78
+ ? 'M 11 4 A 7 7 0 0 1 15.1145 16.66312'
79
+ : 'M 9 2 A 7 7 0 0 1 13.1145 14.66312', stroke: "white", strokeLinecap: "round", fill: "none", strokeWidth: 3 }) }) })] }));
80
+ };
81
+
7
82
  const calculatePlayerSize = ({ currentSize, width, height, compositionWidth, compositionHeight, }) => {
8
83
  if (width !== undefined && height === undefined) {
9
84
  return {
@@ -29,14 +104,8 @@ const calculatePlayerSize = ({ currentSize, width, height, compositionWidth, com
29
104
  };
30
105
  };
31
106
 
32
- const calculateScale = ({ canvasSize, compositionHeight, compositionWidth, previewSize, }) => {
33
- const heightRatio = canvasSize.height / compositionHeight;
34
- const widthRatio = canvasSize.width / compositionWidth;
35
- const ratio = Math.min(heightRatio, widthRatio);
36
- return previewSize === 'auto' ? ratio : Number(previewSize);
37
- };
38
107
  const calculateCanvasTransformation = ({ previewSize, compositionWidth, compositionHeight, canvasSize, }) => {
39
- const scale = calculateScale({
108
+ const scale = Internals.calculateScale({
40
109
  canvasSize,
41
110
  compositionHeight,
42
111
  compositionWidth,
@@ -124,6 +193,8 @@ class PlayerEmitter {
124
193
  fullscreenchange: [],
125
194
  volumechange: [],
126
195
  mutechange: [],
196
+ waiting: [],
197
+ resume: [],
127
198
  };
128
199
  }
129
200
  addEventListener(name, callback) {
@@ -183,6 +254,12 @@ class PlayerEmitter {
183
254
  dispatchMuteChange(event) {
184
255
  this.dispatchEvent('mutechange', event);
185
256
  }
257
+ dispatchWaiting(event) {
258
+ this.dispatchEvent('waiting', event);
259
+ }
260
+ dispatchResume(event) {
261
+ this.dispatchEvent('resume', event);
262
+ }
186
263
  }
187
264
  class ThumbnailEmitter {
188
265
  constructor() {
@@ -208,6 +285,34 @@ class ThumbnailEmitter {
208
285
  }
209
286
  }
210
287
 
288
+ const PlayerEmitterProvider = ({ children, currentPlaybackRate }) => {
289
+ const [emitter] = useState(() => new PlayerEmitter());
290
+ const bufferManager = useContext(Internals.BufferingContextReact);
291
+ if (!bufferManager) {
292
+ throw new Error('BufferingContextReact not found');
293
+ }
294
+ useEffect(() => {
295
+ if (currentPlaybackRate) {
296
+ emitter.dispatchRateChange(currentPlaybackRate);
297
+ }
298
+ }, [emitter, currentPlaybackRate]);
299
+ useEffect(() => {
300
+ const clear1 = bufferManager.listenForBuffering(() => {
301
+ bufferManager.buffering.current = true;
302
+ emitter.dispatchWaiting({});
303
+ });
304
+ const clear2 = bufferManager.listenForResume(() => {
305
+ bufferManager.buffering.current = false;
306
+ emitter.dispatchResume({});
307
+ });
308
+ return () => {
309
+ clear1.remove();
310
+ clear2.remove();
311
+ };
312
+ }, [bufferManager, emitter]);
313
+ return (jsx(PlayerEventEmitterContext.Provider, { value: emitter, children: children }));
314
+ };
315
+
211
316
  const useHoverState = (ref) => {
212
317
  const [hovered, stetHovered] = useState(false);
213
318
  useEffect(() => {
@@ -297,6 +402,11 @@ const usePlayer = () => {
297
402
  if (!emitter) {
298
403
  throw new TypeError('Expected Player event emitter context');
299
404
  }
405
+ const bufferingContext = useContext(Internals.BufferingContextReact);
406
+ if (!bufferingContext) {
407
+ throw new Error('Missing the buffering context. Most likely you have a Remotion version mismatch.');
408
+ }
409
+ const { buffering } = bufferingContext;
300
410
  const seek = useCallback((newFrame) => {
301
411
  if (video === null || video === void 0 ? void 0 : video.id) {
302
412
  setTimelinePosition((c) => ({ ...c, [video.id]: newFrame }));
@@ -403,6 +513,7 @@ const usePlayer = () => {
403
513
  isFirstFrame,
404
514
  getCurrentFrame: () => frameRef.current,
405
515
  isPlaying: () => imperativePlaying.current,
516
+ isBuffering: () => buffering.current,
406
517
  pauseAndReturnToPlayStart,
407
518
  hasPlayed,
408
519
  remotionInternal_currentFrameRef: frameRef,
@@ -418,8 +529,9 @@ const usePlayer = () => {
418
529
  seek,
419
530
  isFirstFrame,
420
531
  pauseAndReturnToPlayStart,
421
- imperativePlaying,
422
532
  hasPlayed,
533
+ imperativePlaying,
534
+ buffering,
423
535
  ]);
424
536
  return returnValue;
425
537
  };
@@ -430,11 +542,28 @@ const usePlayback = ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, ou
430
542
  const frame = Internals.Timeline.useTimelinePosition();
431
543
  const { playing, pause, emitter } = usePlayer();
432
544
  const setFrame = Internals.Timeline.useTimelineSetFrame();
545
+ const buffering = useRef(null);
433
546
  // requestAnimationFrame() does not work if the tab is not active.
434
547
  // This means that audio will keep playing even if it has ended.
435
548
  // In that case, we use setTimeout() instead.
436
549
  const isBackgroundedRef = useIsBackgrounded();
437
550
  const lastTimeUpdateEvent = useRef(null);
551
+ const context = useContext(Internals.BufferingContextReact);
552
+ if (!context) {
553
+ throw new Error('Missing the buffering context. Most likely you have a Remotion version mismatch.');
554
+ }
555
+ useEffect(() => {
556
+ const onBufferClear = context.listenForBuffering(() => {
557
+ buffering.current = performance.now();
558
+ });
559
+ const onResumeClear = context.listenForResume(() => {
560
+ buffering.current = null;
561
+ });
562
+ return () => {
563
+ onBufferClear.remove();
564
+ onResumeClear.remove();
565
+ };
566
+ }, [context]);
438
567
  useEffect(() => {
439
568
  if (!config) {
440
569
  return;
@@ -444,7 +573,7 @@ const usePlayback = ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, ou
444
573
  }
445
574
  let hasBeenStopped = false;
446
575
  let reqAnimFrameCall = null;
447
- const startedTime = performance.now();
576
+ let startedTime = performance.now();
448
577
  let framesAdvanced = 0;
449
578
  const cancelQueuedFrame = () => {
450
579
  if (reqAnimFrameCall !== null) {
@@ -464,9 +593,10 @@ const usePlayback = ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, ou
464
593
  const time = performance.now() - startedTime;
465
594
  const actualLastFrame = outFrame !== null && outFrame !== void 0 ? outFrame : config.durationInFrames - 1;
466
595
  const actualFirstFrame = inFrame !== null && inFrame !== void 0 ? inFrame : 0;
596
+ const currentFrame = frameRef.current;
467
597
  const { nextFrame, framesToAdvance, hasEnded } = calculateNextFrame({
468
598
  time,
469
- currentFrame: frameRef.current,
599
+ currentFrame,
470
600
  playbackSpeed: playbackRate,
471
601
  fps: config.fps,
472
602
  actualFirstFrame,
@@ -490,6 +620,18 @@ const usePlayback = ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, ou
490
620
  }
491
621
  };
492
622
  const queueNextFrame = () => {
623
+ if (buffering.current) {
624
+ const stopListening = context.listenForResume(() => {
625
+ stopListening.remove();
626
+ if (hasBeenStopped) {
627
+ return;
628
+ }
629
+ startedTime = performance.now();
630
+ framesAdvanced = 0;
631
+ callback();
632
+ });
633
+ return;
634
+ }
493
635
  if (isBackgroundedRef.current) {
494
636
  reqAnimFrameCall = {
495
637
  type: 'timeout',
@@ -529,6 +671,8 @@ const usePlayback = ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, ou
529
671
  moveToBeginningWhenEnded,
530
672
  isBackgroundedRef,
531
673
  frameRef,
674
+ buffering,
675
+ context,
532
676
  ]);
533
677
  useEffect(() => {
534
678
  const interval = setInterval(() => {
@@ -705,51 +849,22 @@ class ErrorBoundary extends React.Component {
705
849
  }
706
850
  }
707
851
 
852
+ const DefaultPlayPauseButton = ({ playing, buffering }) => {
853
+ if (playing && buffering) {
854
+ return jsx(BufferingIndicator, { type: "player" });
855
+ }
856
+ if (playing) {
857
+ return jsx(PauseIcon, {});
858
+ }
859
+ return jsx(PlayIcon, {});
860
+ };
861
+
708
862
  const formatTime = (timeInSeconds) => {
709
863
  const minutes = Math.floor(timeInSeconds / 60);
710
864
  const seconds = Math.floor(timeInSeconds - minutes * 60);
711
865
  return `${String(minutes)}:${String(seconds).padStart(2, '0')}`;
712
866
  };
713
867
 
714
- const ICON_SIZE = 25;
715
- const fullscreenIconSize = 16;
716
- const PlayIcon = () => {
717
- 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" }) }));
718
- };
719
- const PauseIcon = () => {
720
- 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" })] }));
721
- };
722
- const FullscreenIcon = ({ isFullscreen, }) => {
723
- const strokeWidth = 6;
724
- const viewSize = 32;
725
- const out = isFullscreen ? 0 : strokeWidth / 2;
726
- const middleInset = isFullscreen ? strokeWidth * 1.6 : strokeWidth / 2;
727
- const inset = isFullscreen ? strokeWidth * 1.6 : strokeWidth * 2;
728
- return (jsxs("svg", { viewBox: `0 0 ${viewSize} ${viewSize}`, height: fullscreenIconSize, width: fullscreenIconSize, children: [jsx("path", { d: `
729
- M ${out} ${inset}
730
- L ${middleInset} ${middleInset}
731
- L ${inset} ${out}
732
- `, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" }), jsx("path", { d: `
733
- M ${viewSize - out} ${inset}
734
- L ${viewSize - middleInset} ${middleInset}
735
- L ${viewSize - inset} ${out}
736
- `, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" }), jsx("path", { d: `
737
- M ${out} ${viewSize - inset}
738
- L ${middleInset} ${viewSize - middleInset}
739
- L ${inset} ${viewSize - out}
740
- `, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" }), jsx("path", { d: `
741
- M ${viewSize - out} ${viewSize - inset}
742
- L ${viewSize - middleInset} ${viewSize - middleInset}
743
- L ${viewSize - inset} ${viewSize - out}
744
- `, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" })] }));
745
- };
746
- const VolumeOffIcon = () => {
747
- return (jsx("svg", { width: ICON_SIZE, height: ICON_SIZE, viewBox: "0 0 24 24", children: jsx("path", { d: "M3.63 3.63a.996.996 0 000 1.41L7.29 8.7 7 9H4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h3l3.29 3.29c.63.63 1.71.18 1.71-.71v-4.17l4.18 4.18c-.49.37-1.02.68-1.6.91-.36.15-.58.53-.58.92 0 .72.73 1.18 1.39.91.8-.33 1.55-.77 2.22-1.31l1.34 1.34a.996.996 0 101.41-1.41L5.05 3.63c-.39-.39-1.02-.39-1.42 0zM19 12c0 .82-.15 1.61-.41 2.34l1.53 1.53c.56-1.17.88-2.48.88-3.87 0-3.83-2.4-7.11-5.78-8.4-.59-.23-1.22.23-1.22.86v.19c0 .38.25.71.61.85C17.18 6.54 19 9.06 19 12zm-8.71-6.29l-.17.17L12 7.76V6.41c0-.89-1.08-1.33-1.71-.7zM16.5 12A4.5 4.5 0 0014 7.97v1.79l2.48 2.48c.01-.08.02-.16.02-.24z", fill: "#fff" }) }));
748
- };
749
- const VolumeOnIcon = () => {
750
- return (jsx("svg", { width: ICON_SIZE, height: ICON_SIZE, viewBox: "0 0 24 24", children: jsx("path", { d: "M3 10v4c0 .55.45 1 1 1h3l3.29 3.29c.63.63 1.71.18 1.71-.71V6.41c0-.89-1.08-1.34-1.71-.71L7 9H4c-.55 0-1 .45-1 1zm13.5 2A4.5 4.5 0 0014 7.97v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 4.45v.2c0 .38.25.71.6.85C17.18 6.53 19 9.06 19 12s-1.82 5.47-4.4 6.5c-.36.14-.6.47-.6.85v.2c0 .63.63 1.07 1.21.85C18.6 19.11 21 15.84 21 12s-2.4-7.11-5.79-8.4c-.58-.23-1.21.22-1.21.85z", fill: "#fff" }) }));
751
- };
752
-
753
868
  const BAR_HEIGHT$1 = 5;
754
869
  const KNOB_SIZE$1 = 12;
755
870
  const VOLUME_SLIDER_WIDTH = 100;
@@ -1271,9 +1386,8 @@ const flex1 = {
1271
1386
  flex: 1,
1272
1387
  };
1273
1388
  const fullscreen = {};
1274
- const PlayPauseButton = ({ playing }) => playing ? jsx(PauseIcon, {}) : jsx(PlayIcon, {});
1275
- const Controls = ({ durationInFrames, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, canvasSize, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, showPlaybackRateControl, containerRef, }) => {
1276
- var _a;
1389
+ const Controls = ({ durationInFrames, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, canvasSize, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, showPlaybackRateControl, containerRef, buffering, }) => {
1390
+ var _a, _b;
1277
1391
  const playButtonRef = useRef(null);
1278
1392
  const frame = Internals.Timeline.useTimelinePosition();
1279
1393
  const [supportsFullscreen, setSupportsFullscreen] = useState(false);
@@ -1364,7 +1478,10 @@ const Controls = ({ durationInFrames, isFullscreen, fps, player, showVolumeContr
1364
1478
  }
1365
1479
  return null;
1366
1480
  }, [showPlaybackRateControl]);
1367
- 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
1481
+ 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({
1482
+ playing: player.playing,
1483
+ isBuffering: buffering,
1484
+ })) !== 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
1368
1485
  ? onExitFullscreenButtonClick
1369
1486
  : 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 })] }));
1370
1487
  };
@@ -1457,7 +1574,7 @@ if (reactVersion$1 === '0') {
1457
1574
  throw new Error(`Version ${reactVersion$1} of "react" is not supported by Remotion`);
1458
1575
  }
1459
1576
  const doesReactVersionSupportSuspense$1 = parseInt(reactVersion$1, 10) >= 18;
1460
- 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) => {
1577
+ 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) => {
1461
1578
  var _a, _b, _c;
1462
1579
  const config = Internals.useUnsafeVideoConfig();
1463
1580
  const video = Internals.useVideo();
@@ -1593,6 +1710,44 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
1593
1710
  isMuted,
1594
1711
  });
1595
1712
  }, [player.emitter, isMuted]);
1713
+ const [showBufferIndicator, setShowBufferState] = useState(false);
1714
+ useEffect(() => {
1715
+ let timeout = null;
1716
+ let stopped = false;
1717
+ const onBuffer = () => {
1718
+ requestAnimationFrame(() => {
1719
+ if (bufferStateDelayInMilliseconds === 0) {
1720
+ setShowBufferState(true);
1721
+ }
1722
+ else {
1723
+ timeout = setTimeout(() => {
1724
+ if (!stopped) {
1725
+ setShowBufferState(true);
1726
+ }
1727
+ }, bufferStateDelayInMilliseconds);
1728
+ }
1729
+ });
1730
+ };
1731
+ const onResume = () => {
1732
+ requestAnimationFrame(() => {
1733
+ setShowBufferState(false);
1734
+ if (timeout) {
1735
+ clearTimeout(timeout);
1736
+ }
1737
+ });
1738
+ };
1739
+ player.emitter.addEventListener('waiting', onBuffer);
1740
+ player.emitter.addEventListener('resume', onResume);
1741
+ return () => {
1742
+ player.emitter.removeEventListener('waiting', onBuffer);
1743
+ player.emitter.removeEventListener('resume', onResume);
1744
+ setShowBufferState(false);
1745
+ if (timeout) {
1746
+ clearTimeout(timeout);
1747
+ }
1748
+ stopped = true;
1749
+ };
1750
+ }, [bufferStateDelayInMilliseconds, player.emitter]);
1596
1751
  useImperativeHandle(ref, () => {
1597
1752
  const methods = {
1598
1753
  play: player.play,
@@ -1720,9 +1875,16 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
1720
1875
  ? renderLoading({
1721
1876
  height: outerStyle.height,
1722
1877
  width: outerStyle.width,
1878
+ isBuffering: showBufferIndicator,
1723
1879
  })
1724
1880
  : null;
1725
- }, [outerStyle.height, outerStyle.width, renderLoading]);
1881
+ }, [outerStyle.height, outerStyle.width, renderLoading, showBufferIndicator]);
1882
+ const currentScale = useMemo(() => {
1883
+ return {
1884
+ type: 'scale',
1885
+ scale,
1886
+ };
1887
+ }, [scale]);
1726
1888
  if (!config) {
1727
1889
  return null;
1728
1890
  }
@@ -1734,6 +1896,7 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
1734
1896
  width: posterFillMode === 'player-size'
1735
1897
  ? outerStyle.width
1736
1898
  : config.width,
1899
+ isBuffering: showBufferIndicator,
1737
1900
  })
1738
1901
  : null;
1739
1902
  if (poster === undefined) {
@@ -1744,13 +1907,14 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
1744
1907
  showPosterWhenPaused && !player.isPlaying() && !seeking,
1745
1908
  showPosterWhenEnded && player.isLastFrame && !player.isPlaying(),
1746
1909
  showPosterWhenUnplayed && !player.hasPlayed && !player.isPlaying(),
1910
+ showPosterWhenBuffering && showBufferIndicator && player.isPlaying(),
1747
1911
  ].some(Boolean);
1748
1912
  const { left, top, width, height, ...outerWithoutScale } = outer;
1749
- 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: {
1913
+ 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: {
1750
1914
  ...outerWithoutScale,
1751
1915
  width: config.width,
1752
1916
  height: config.height,
1753
- }, 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] }));
1917
+ }, 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] }));
1754
1918
  if (IS_NODE && !doesReactVersionSupportSuspense$1) {
1755
1919
  return (jsx("div", { ref: container, style: outerStyle, className: className, children: content }));
1756
1920
  }
@@ -1822,7 +1986,7 @@ const SharedPlayerContexts = ({ children, timelineContext, fps, compositionHeigh
1822
1986
  setMediaVolume: setMediaVolumeAndPersist,
1823
1987
  };
1824
1988
  }, [setMediaVolumeAndPersist]);
1825
- 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 }) }) }) }) }) }) }) }) }) }));
1989
+ 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 }) }) }) }) }) }) }) }) }) }) }));
1826
1990
  };
1827
1991
 
1828
1992
  const validateSingleFrame = (frame, variableName) => {
@@ -1926,7 +2090,7 @@ const componentOrNullIfLazy = (props) => {
1926
2090
  }
1927
2091
  return null;
1928
2092
  };
1929
- 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) => {
2093
+ 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) => {
1930
2094
  if (typeof window !== 'undefined') {
1931
2095
  // eslint-disable-next-line react-hooks/rules-of-hooks
1932
2096
  useLayoutEffect(() => {
@@ -1952,7 +2116,6 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
1952
2116
  }));
1953
2117
  const [playing, setPlaying] = useState(false);
1954
2118
  const [rootId] = useState('player-comp');
1955
- const [emitter] = useState(() => new PlayerEmitter());
1956
2119
  const rootRef = useRef(null);
1957
2120
  const audioAndVideoTags = useRef([]);
1958
2121
  const imperativePlaying = useRef(false);
@@ -2012,9 +2175,6 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
2012
2175
  throw new TypeError(`'numberOfSharedAudioTags' must be an integer but got '${numberOfSharedAudioTags}' instead`);
2013
2176
  }
2014
2177
  validatePlaybackRate(currentPlaybackRate);
2015
- useEffect(() => {
2016
- emitter.dispatchRateChange(currentPlaybackRate);
2017
- }, [emitter, currentPlaybackRate]);
2018
2178
  useEffect(() => {
2019
2179
  setCurrentPlaybackRate(playbackRate);
2020
2180
  }, [playbackRate]);
@@ -2046,9 +2206,9 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
2046
2206
  }, []);
2047
2207
  }
2048
2208
  const actualInputProps = useMemo(() => inputProps !== null && inputProps !== void 0 ? inputProps : {}, [inputProps]);
2049
- 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$1, { 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'
2209
+ 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$1, { 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'
2050
2210
  ? clickToPlay
2051
- : 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 }) }) }) }) }));
2211
+ : 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 }) }) }) }) }));
2052
2212
  };
2053
2213
  const forward$1 = forwardRef;
2054
2214
  /**
@@ -2130,13 +2290,20 @@ const ThumbnailUI = ({ style, inputProps, errorFallback, renderLoading, classNam
2130
2290
  ? renderLoading({
2131
2291
  height: outerStyle.height,
2132
2292
  width: outerStyle.width,
2293
+ isBuffering: false,
2133
2294
  })
2134
2295
  : null;
2135
2296
  }, [outerStyle.height, outerStyle.width, renderLoading]);
2297
+ const currentScaleContext = useMemo(() => {
2298
+ return {
2299
+ type: 'scale',
2300
+ scale,
2301
+ };
2302
+ }, [scale]);
2136
2303
  if (!config) {
2137
2304
  return null;
2138
2305
  }
2139
- 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 }) }));
2306
+ 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 }) }));
2140
2307
  if (IS_NODE && !doesReactVersionSupportSuspense) {
2141
2308
  return (jsx("div", { ref: container, style: outerStyle, className: className, children: content }));
2142
2309
  }
@@ -2195,7 +2362,8 @@ const PlayerInternals = {
2195
2362
  calculateCanvasTransformation,
2196
2363
  useHoverState,
2197
2364
  updateAllElementsSizes,
2198
- calculateScale,
2365
+ PlayerEmitterProvider,
2366
+ BufferingIndicator,
2199
2367
  };
2200
2368
 
2201
2369
  export { Player, PlayerInternals, Thumbnail };
@@ -14,6 +14,7 @@ type UsePlayerMethods = {
14
14
  getCurrentFrame: () => number;
15
15
  isPlaying: () => boolean;
16
16
  hasPlayed: boolean;
17
+ isBuffering: () => boolean;
17
18
  /**
18
19
  * @deprecated Remotion internal API
19
20
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/player",
3
- "version": "4.0.110",
3
+ "version": "4.0.112",
4
4
  "description": "Remotion Player",
5
5
  "main": "dist/cjs/index.js",
6
6
  "types": "dist/cjs/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  ],
29
29
  "license": "SEE LICENSE IN LICENSE.md",
30
30
  "dependencies": {
31
- "remotion": "4.0.110"
31
+ "remotion": "4.0.112"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": ">=16.8.0",