@remotion/player 3.3.97 → 3.3.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/MediaVolumeSlider.js +0 -1
- package/dist/cjs/PlaybackrateControl.d.ts +5 -0
- package/dist/cjs/PlaybackrateControl.js +136 -0
- package/dist/cjs/Player.d.ts +1 -0
- package/dist/cjs/Player.js +13 -9
- package/dist/cjs/PlayerControls.d.ts +1 -0
- package/dist/cjs/PlayerControls.js +21 -3
- package/dist/cjs/PlayerUI.d.ts +1 -0
- package/dist/cjs/PlayerUI.js +13 -4
- package/dist/cjs/event-emitter.d.ts +5 -0
- package/dist/cjs/event-emitter.js +4 -0
- package/dist/cjs/icons.d.ts +3 -0
- package/dist/cjs/icons.js +5 -1
- package/dist/cjs/utils/use-component-visible.d.ts +6 -0
- package/dist/cjs/utils/use-component-visible.js +21 -0
- package/dist/esm/PlaybackrateControl.d.ts +5 -0
- package/dist/esm/Player.d.ts +1 -0
- package/dist/esm/PlayerControls.d.ts +1 -0
- package/dist/esm/PlayerUI.d.ts +1 -0
- package/dist/esm/event-emitter.d.ts +5 -0
- package/dist/esm/icons.d.ts +3 -0
- package/dist/esm/index.mjs +195 -17
- package/dist/esm/utils/use-component-visible.d.ts +6 -0
- package/dist/tsconfig-esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PlaybackrateControl = exports.Checkmark = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const remotion_1 = require("remotion");
|
|
10
|
+
const icons_js_1 = require("./icons.js");
|
|
11
|
+
const use_component_visible_js_1 = __importDefault(require("./utils/use-component-visible.js"));
|
|
12
|
+
const playbackPopup = {
|
|
13
|
+
position: 'absolute',
|
|
14
|
+
right: 0,
|
|
15
|
+
width: 125,
|
|
16
|
+
bottom: 35,
|
|
17
|
+
background: '#fff',
|
|
18
|
+
borderRadius: 4,
|
|
19
|
+
overflow: 'hidden',
|
|
20
|
+
color: 'black',
|
|
21
|
+
textAlign: 'left',
|
|
22
|
+
};
|
|
23
|
+
const rateDiv = {
|
|
24
|
+
height: 30,
|
|
25
|
+
paddingRight: 15,
|
|
26
|
+
paddingLeft: 12,
|
|
27
|
+
display: 'flex',
|
|
28
|
+
flexDirection: 'row',
|
|
29
|
+
alignItems: 'center',
|
|
30
|
+
};
|
|
31
|
+
const checkmarkContainer = {
|
|
32
|
+
width: 22,
|
|
33
|
+
display: 'flex',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
};
|
|
36
|
+
const checkmarkStyle = {
|
|
37
|
+
width: 14,
|
|
38
|
+
height: 14,
|
|
39
|
+
color: 'black',
|
|
40
|
+
};
|
|
41
|
+
const Checkmark = () => ((0, jsx_runtime_1.jsx)("svg", { viewBox: "0 0 512 512", style: checkmarkStyle, children: (0, jsx_runtime_1.jsx)("path", { fill: "currentColor", d: "M435.848 83.466L172.804 346.51l-96.652-96.652c-4.686-4.686-12.284-4.686-16.971 0l-28.284 28.284c-4.686 4.686-4.686 12.284 0 16.971l133.421 133.421c4.686 4.686 12.284 4.686 16.971 0l299.813-299.813c4.686-4.686 4.686-12.284 0-16.971l-28.284-28.284c-4.686-4.686-12.284-4.686-16.97 0z" }) }));
|
|
42
|
+
exports.Checkmark = Checkmark;
|
|
43
|
+
const PlaybackPopup = ({ setIsComponentVisible, playbackRates }) => {
|
|
44
|
+
const { setPlaybackRate, playbackRate } = (0, react_1.useContext)(remotion_1.Internals.Timeline.TimelineContext);
|
|
45
|
+
const [keyboardSelectedRate, setKeyboardSelectedRate] = (0, react_1.useState)(playbackRate);
|
|
46
|
+
(0, react_1.useEffect)(() => {
|
|
47
|
+
const listener = (e) => {
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
if (e.key === 'ArrowUp') {
|
|
50
|
+
const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
|
|
51
|
+
if (currentIndex === 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (currentIndex === -1) {
|
|
55
|
+
setKeyboardSelectedRate(playbackRates[0]);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
setKeyboardSelectedRate(playbackRates[currentIndex - 1]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else if (e.key === 'ArrowDown') {
|
|
62
|
+
const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
|
|
63
|
+
if (currentIndex === playbackRates.length - 1) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (currentIndex === -1) {
|
|
67
|
+
setKeyboardSelectedRate(playbackRates[playbackRates.length - 1]);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
setKeyboardSelectedRate(playbackRates[currentIndex + 1]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (e.key === 'Enter') {
|
|
74
|
+
setPlaybackRate(keyboardSelectedRate);
|
|
75
|
+
setIsComponentVisible(false);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
window.addEventListener('keydown', listener);
|
|
79
|
+
return () => {
|
|
80
|
+
window.removeEventListener('keydown', listener);
|
|
81
|
+
};
|
|
82
|
+
}, [
|
|
83
|
+
playbackRates,
|
|
84
|
+
keyboardSelectedRate,
|
|
85
|
+
setPlaybackRate,
|
|
86
|
+
setIsComponentVisible,
|
|
87
|
+
]);
|
|
88
|
+
const onSelect = (0, react_1.useCallback)((rate) => {
|
|
89
|
+
setPlaybackRate(rate);
|
|
90
|
+
setIsComponentVisible(false);
|
|
91
|
+
}, [setIsComponentVisible, setPlaybackRate]);
|
|
92
|
+
return ((0, jsx_runtime_1.jsx)("div", { style: playbackPopup, children: playbackRates.map((rate) => {
|
|
93
|
+
return ((0, jsx_runtime_1.jsx)(PlaybackrateOption, { selectedRate: playbackRate, onSelect: onSelect, rate: rate, keyboardSelectedRate: keyboardSelectedRate }, rate));
|
|
94
|
+
}) }));
|
|
95
|
+
};
|
|
96
|
+
const PlaybackrateOption = ({ rate, onSelect, selectedRate, keyboardSelectedRate }) => {
|
|
97
|
+
const onClick = (0, react_1.useCallback)((e) => {
|
|
98
|
+
e.stopPropagation();
|
|
99
|
+
e.preventDefault();
|
|
100
|
+
onSelect(rate);
|
|
101
|
+
}, [onSelect, rate]);
|
|
102
|
+
const [hovered, setHovered] = (0, react_1.useState)(false);
|
|
103
|
+
const onMouseEnter = (0, react_1.useCallback)(() => {
|
|
104
|
+
setHovered(true);
|
|
105
|
+
}, []);
|
|
106
|
+
const onMouseLeave = (0, react_1.useCallback)(() => {
|
|
107
|
+
setHovered(false);
|
|
108
|
+
}, []);
|
|
109
|
+
const actualStyle = (0, react_1.useMemo)(() => {
|
|
110
|
+
return {
|
|
111
|
+
...rateDiv,
|
|
112
|
+
backgroundColor: hovered || keyboardSelectedRate === rate ? '#eee' : 'transparent',
|
|
113
|
+
};
|
|
114
|
+
}, [hovered, keyboardSelectedRate, rate]);
|
|
115
|
+
return ((0, jsx_runtime_1.jsxs)("div", { onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, tabIndex: 0, style: actualStyle, onClick: onClick, children: [(0, jsx_runtime_1.jsx)("div", { style: checkmarkContainer, children: rate === selectedRate ? (0, jsx_runtime_1.jsx)(exports.Checkmark, {}) : null }), rate.toFixed(1), "x"] }, rate));
|
|
116
|
+
};
|
|
117
|
+
const playbackButton = {
|
|
118
|
+
position: 'relative',
|
|
119
|
+
display: 'inline-flex',
|
|
120
|
+
alignItems: 'center',
|
|
121
|
+
padding: '6px 0 6px 0',
|
|
122
|
+
border: 'none',
|
|
123
|
+
background: 'none',
|
|
124
|
+
height: 36,
|
|
125
|
+
cursor: 'pointer',
|
|
126
|
+
};
|
|
127
|
+
const PlaybackrateControl = ({ playbackRates }) => {
|
|
128
|
+
const { ref, isComponentVisible, setIsComponentVisible } = (0, use_component_visible_js_1.default)(false);
|
|
129
|
+
const onClick = (0, react_1.useCallback)((e) => {
|
|
130
|
+
e.stopPropagation();
|
|
131
|
+
e.preventDefault();
|
|
132
|
+
setIsComponentVisible(!isComponentVisible);
|
|
133
|
+
}, [isComponentVisible, setIsComponentVisible]);
|
|
134
|
+
return ((0, jsx_runtime_1.jsx)("div", { ref: ref, children: (0, jsx_runtime_1.jsxs)("button", { type: "button", "aria-label": "Change playback rate", style: playbackButton, onClick: onClick, children: [(0, jsx_runtime_1.jsx)(icons_js_1.SettingsIcon, { iconSize: 22 }), isComponentVisible && ((0, jsx_runtime_1.jsx)(PlaybackPopup, { playbackRates: playbackRates, setIsComponentVisible: setIsComponentVisible }))] }) }));
|
|
135
|
+
};
|
|
136
|
+
exports.PlaybackrateControl = PlaybackrateControl;
|
package/dist/cjs/Player.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export declare type PlayerProps<T> = {
|
|
|
40
40
|
renderFullscreenButton?: RenderFullscreenButton;
|
|
41
41
|
alwaysShowControls?: boolean;
|
|
42
42
|
initiallyMuted?: boolean;
|
|
43
|
+
showPlaybackRateControl?: boolean | number[];
|
|
43
44
|
} & PropsIfHasProps<T> & CompProps<T>;
|
|
44
45
|
export declare const componentOrNullIfLazy: <T>(props: CompProps<T>) => ComponentType<T> | null;
|
|
45
46
|
/**
|
package/dist/cjs/Player.js
CHANGED
|
@@ -22,7 +22,7 @@ const componentOrNullIfLazy = (props) => {
|
|
|
22
22
|
return null;
|
|
23
23
|
};
|
|
24
24
|
exports.componentOrNullIfLazy = componentOrNullIfLazy;
|
|
25
|
-
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, ...componentProps }, ref) => {
|
|
25
|
+
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, ...componentProps }, ref) => {
|
|
26
26
|
if (typeof window !== 'undefined') {
|
|
27
27
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
28
28
|
(0, react_1.useLayoutEffect)(() => {
|
|
@@ -50,6 +50,7 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
50
50
|
const rootRef = (0, react_1.useRef)(null);
|
|
51
51
|
const audioAndVideoTags = (0, react_1.useRef)([]);
|
|
52
52
|
const imperativePlaying = (0, react_1.useRef)(false);
|
|
53
|
+
const [currentPlaybackRate, setCurrentPlaybackRate] = (0, react_1.useState)(playbackRate);
|
|
53
54
|
if (typeof compositionHeight !== 'number') {
|
|
54
55
|
throw new TypeError(`'compositionHeight' must be a number but got '${typeof compositionHeight}' instead`);
|
|
55
56
|
}
|
|
@@ -104,10 +105,13 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
104
105
|
numberOfSharedAudioTags < 0) {
|
|
105
106
|
throw new TypeError(`'numberOfSharedAudioTags' must be an integer but got '${numberOfSharedAudioTags}' instead`);
|
|
106
107
|
}
|
|
107
|
-
(0, validate_playbackrate_js_1.validatePlaybackRate)(
|
|
108
|
+
(0, validate_playbackrate_js_1.validatePlaybackRate)(currentPlaybackRate);
|
|
108
109
|
(0, react_1.useEffect)(() => {
|
|
109
|
-
emitter.dispatchRateChange(
|
|
110
|
-
}, [emitter,
|
|
110
|
+
emitter.dispatchRateChange(currentPlaybackRate);
|
|
111
|
+
}, [emitter, currentPlaybackRate]);
|
|
112
|
+
(0, react_1.useEffect)(() => {
|
|
113
|
+
setCurrentPlaybackRate(playbackRate);
|
|
114
|
+
}, [playbackRate]);
|
|
111
115
|
(0, react_1.useImperativeHandle)(ref, () => rootRef.current, []);
|
|
112
116
|
const timelineContextValue = (0, react_1.useMemo)(() => {
|
|
113
117
|
return {
|
|
@@ -115,14 +119,14 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
115
119
|
playing,
|
|
116
120
|
rootId,
|
|
117
121
|
shouldRegisterSequences: false,
|
|
118
|
-
playbackRate,
|
|
122
|
+
playbackRate: currentPlaybackRate,
|
|
119
123
|
imperativePlaying,
|
|
120
|
-
setPlaybackRate: () => {
|
|
121
|
-
|
|
124
|
+
setPlaybackRate: (rate) => {
|
|
125
|
+
setCurrentPlaybackRate(rate);
|
|
122
126
|
},
|
|
123
127
|
audioAndVideoTags,
|
|
124
128
|
};
|
|
125
|
-
}, [frame,
|
|
129
|
+
}, [frame, currentPlaybackRate, playing, rootId]);
|
|
126
130
|
const setTimelineContextValue = (0, react_1.useMemo)(() => {
|
|
127
131
|
return {
|
|
128
132
|
setFrame,
|
|
@@ -141,7 +145,7 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
141
145
|
}
|
|
142
146
|
return ((0, jsx_runtime_1.jsx)(remotion_1.Internals.IsPlayerContextProvider, { children: (0, jsx_runtime_1.jsx)(SharedPlayerContext_js_1.SharedPlayerContexts, { timelineContext: timelineContextValue, component: component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, inputProps: inputProps, numberOfSharedAudioTags: numberOfSharedAudioTags, initiallyMuted: initiallyMuted, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.Timeline.SetTimelineContext.Provider, { value: setTimelineContextValue, children: (0, jsx_runtime_1.jsx)(emitter_context_js_1.PlayerEventEmitterContext.Provider, { value: emitter, children: (0, jsx_runtime_1.jsx)(PlayerUI_js_1.default, { ref: rootRef, renderLoading: renderLoading, autoPlay: Boolean(autoPlay), loop: Boolean(loop), controls: Boolean(controls), errorFallback: errorFallback, style: style, inputProps: passedInputProps, allowFullscreen: Boolean(allowFullscreen), moveToBeginningWhenEnded: Boolean(moveToBeginningWhenEnded), clickToPlay: typeof clickToPlay === 'boolean'
|
|
143
147
|
? clickToPlay
|
|
144
|
-
: Boolean(controls), showVolumeControls: Boolean(showVolumeControls), doubleClickToFullscreen: Boolean(doubleClickToFullscreen), spaceKeyToPlayOrPause: Boolean(spaceKeyToPlayOrPause), playbackRate:
|
|
148
|
+
: 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 }) }) }) }) }));
|
|
145
149
|
};
|
|
146
150
|
const forward = react_1.forwardRef;
|
|
147
151
|
/**
|
|
@@ -7,6 +7,7 @@ const remotion_1 = require("remotion");
|
|
|
7
7
|
const format_time_js_1 = require("./format-time.js");
|
|
8
8
|
const icons_js_1 = require("./icons.js");
|
|
9
9
|
const MediaVolumeSlider_js_1 = require("./MediaVolumeSlider.js");
|
|
10
|
+
const PlaybackrateControl_js_1 = require("./PlaybackrateControl.js");
|
|
10
11
|
const PlayerSeekBar_js_1 = require("./PlayerSeekBar.js");
|
|
11
12
|
const use_video_controls_resize_js_1 = require("./use-video-controls-resize.js");
|
|
12
13
|
const gradientSteps = [
|
|
@@ -66,7 +67,7 @@ const leftPartStyle = {
|
|
|
66
67
|
alignItems: 'center',
|
|
67
68
|
};
|
|
68
69
|
const xSpacer = {
|
|
69
|
-
width:
|
|
70
|
+
width: 12,
|
|
70
71
|
};
|
|
71
72
|
const ySpacer = {
|
|
72
73
|
height: 8,
|
|
@@ -76,7 +77,7 @@ const flex1 = {
|
|
|
76
77
|
};
|
|
77
78
|
const fullscreen = {};
|
|
78
79
|
const PlayPauseButton = ({ playing }) => playing ? (0, jsx_runtime_1.jsx)(icons_js_1.PauseIcon, {}) : (0, jsx_runtime_1.jsx)(icons_js_1.PlayIcon, {});
|
|
79
|
-
const Controls = ({ durationInFrames, hovered, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, playerWidth, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, }) => {
|
|
80
|
+
const Controls = ({ durationInFrames, hovered, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, playerWidth, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, showPlaybackRateControl, }) => {
|
|
80
81
|
const playButtonRef = (0, react_1.useRef)(null);
|
|
81
82
|
const frame = remotion_1.Internals.Timeline.useTimelinePosition();
|
|
82
83
|
const [supportsFullscreen, setSupportsFullscreen] = (0, react_1.useState)(false);
|
|
@@ -146,7 +147,24 @@ const Controls = ({ durationInFrames, hovered, isFullscreen, fps, player, showVo
|
|
|
146
147
|
textOverflow: 'ellipsis',
|
|
147
148
|
};
|
|
148
149
|
}, [maxTimeLabelWidth]);
|
|
149
|
-
|
|
150
|
+
const playbackRates = (0, react_1.useMemo)(() => {
|
|
151
|
+
if (showPlaybackRateControl === true) {
|
|
152
|
+
return [0.5, 0.8, 1, 1.2, 1.5, 1.8, 2, 2.5, 3];
|
|
153
|
+
}
|
|
154
|
+
if (Array.isArray(showPlaybackRateControl)) {
|
|
155
|
+
for (const rate of showPlaybackRateControl) {
|
|
156
|
+
if (typeof rate !== 'number') {
|
|
157
|
+
throw new Error('Every item in showPlaybackRateControl must be a number');
|
|
158
|
+
}
|
|
159
|
+
if (rate <= 0) {
|
|
160
|
+
throw new Error('Every item in showPlaybackRateControl must be positive');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return showPlaybackRateControl;
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}, [showPlaybackRateControl]);
|
|
167
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: containerCss, children: [(0, jsx_runtime_1.jsxs)("div", { style: controlsRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: leftPartStyle, children: [(0, jsx_runtime_1.jsx)("button", { ref: playButtonRef, type: "button", style: buttonStyle, 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 ? ((0, jsx_runtime_1.jsx)(PlayPauseButton, { playing: player.playing })) : (renderPlayPauseButton({ playing: player.playing })) }), showVolumeControls ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: xSpacer }), (0, jsx_runtime_1.jsx)(MediaVolumeSlider_js_1.MediaVolumeSlider, { displayVerticalVolumeSlider: displayVerticalVolumeSlider })] })) : null, (0, jsx_runtime_1.jsx)("div", { style: xSpacer }), (0, jsx_runtime_1.jsxs)("div", { style: timeLabel, children: [(0, format_time_js_1.formatTime)(frame / fps), " / ", (0, format_time_js_1.formatTime)(durationInFrames / fps)] }), (0, jsx_runtime_1.jsx)("div", { style: xSpacer })] }), (0, jsx_runtime_1.jsx)("div", { style: flex1 }), playbackRates && (0, jsx_runtime_1.jsx)(PlaybackrateControl_js_1.PlaybackrateControl, { playbackRates: playbackRates }), playbackRates && supportsFullscreen && allowFullscreen ? ((0, jsx_runtime_1.jsx)("div", { style: xSpacer })) : null, (0, jsx_runtime_1.jsx)("div", { style: fullscreen, children: supportsFullscreen && allowFullscreen ? ((0, jsx_runtime_1.jsx)("button", { type: "button", "aria-label": isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', title: isFullscreen ? 'Exit fullscreen' : 'Enter Fullscreen', style: buttonStyle, onClick: isFullscreen
|
|
150
168
|
? onExitFullscreenButtonClick
|
|
151
169
|
: onFullscreenButtonClick, children: renderFullscreenButton === null ? ((0, jsx_runtime_1.jsx)(icons_js_1.FullscreenIcon, { isFullscreen: isFullscreen })) : (renderFullscreenButton({ isFullscreen })) })) : null })] }), (0, jsx_runtime_1.jsx)("div", { style: ySpacer }), (0, jsx_runtime_1.jsx)(PlayerSeekBar_js_1.PlayerSeekBar, { onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, durationInFrames: durationInFrames, inFrame: inFrame, outFrame: outFrame })] }));
|
|
152
170
|
};
|
package/dist/cjs/PlayerUI.d.ts
CHANGED
|
@@ -35,5 +35,6 @@ declare const _default: React.ForwardRefExoticComponent<{
|
|
|
35
35
|
renderPlayPauseButton: RenderPlayPauseButton | null;
|
|
36
36
|
renderFullscreen: RenderFullscreenButton | null;
|
|
37
37
|
alwaysShowControls: boolean;
|
|
38
|
+
showPlaybackRateControl: boolean | number[];
|
|
38
39
|
} & React.RefAttributes<PlayerRef>>;
|
|
39
40
|
export default _default;
|
package/dist/cjs/PlayerUI.js
CHANGED
|
@@ -41,7 +41,7 @@ if (reactVersion === '0') {
|
|
|
41
41
|
throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
|
|
42
42
|
}
|
|
43
43
|
const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
|
|
44
|
-
const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, doubleClickToFullscreen, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, renderPoster, className, moveToBeginningWhenEnded, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, inFrame, outFrame, initiallyShowControls, renderFullscreen: renderFullscreenButton, renderPlayPauseButton, alwaysShowControls, }, ref) => {
|
|
44
|
+
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, }, ref) => {
|
|
45
45
|
var _a, _b, _c, _d, _e;
|
|
46
46
|
const config = remotion_1.Internals.useUnsafeVideoConfig();
|
|
47
47
|
const video = remotion_1.Internals.useVideo();
|
|
@@ -168,6 +168,15 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
168
168
|
}, [player.emitter, scale]);
|
|
169
169
|
const { setMediaVolume, setMediaMuted } = (0, react_1.useContext)(remotion_1.Internals.SetMediaVolumeContext);
|
|
170
170
|
const { mediaMuted, mediaVolume } = (0, react_1.useContext)(remotion_1.Internals.MediaVolumeContext);
|
|
171
|
+
(0, react_1.useEffect)(() => {
|
|
172
|
+
player.emitter.dispatchVolumeChange(mediaVolume);
|
|
173
|
+
}, [player.emitter, mediaVolume]);
|
|
174
|
+
const isMuted = mediaMuted || mediaVolume === 0;
|
|
175
|
+
(0, react_1.useEffect)(() => {
|
|
176
|
+
player.emitter.dispatchMuteChange({
|
|
177
|
+
isMuted,
|
|
178
|
+
});
|
|
179
|
+
}, [player.emitter, isMuted]);
|
|
171
180
|
(0, react_1.useImperativeHandle)(ref, () => {
|
|
172
181
|
const methods = {
|
|
173
182
|
play: player.play,
|
|
@@ -209,9 +218,8 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
209
218
|
throw new TypeError(`setVolume() got a number that is out of range. Must be between 0 and 1, got ${typeof vol}`);
|
|
210
219
|
}
|
|
211
220
|
setMediaVolume(vol);
|
|
212
|
-
player.emitter.dispatchVolumeChange(vol);
|
|
213
221
|
},
|
|
214
|
-
isMuted: () =>
|
|
222
|
+
isMuted: () => isMuted,
|
|
215
223
|
mute: () => {
|
|
216
224
|
setMediaMuted(true);
|
|
217
225
|
},
|
|
@@ -227,6 +235,7 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
227
235
|
isFullscreen,
|
|
228
236
|
loop,
|
|
229
237
|
mediaMuted,
|
|
238
|
+
isMuted,
|
|
230
239
|
mediaVolume,
|
|
231
240
|
player,
|
|
232
241
|
requestFullscreen,
|
|
@@ -308,7 +317,7 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
308
317
|
showPosterWhenEnded && player.isLastFrame && !player.isPlaying(),
|
|
309
318
|
showPosterWhenUnplayed && !player.hasPlayed && !player.isPlaying(),
|
|
310
319
|
].some(Boolean);
|
|
311
|
-
const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: (0, jsx_runtime_1.jsx)("div", { style: containerStyle, className: player_css_classname_js_1.PLAYER_CSS_CLASSNAME, children: VideoComponent ? ((0, jsx_runtime_1.jsx)(error_boundary_js_1.ErrorBoundary, { onError: onError, errorFallback: errorFallback, children: (0, jsx_runtime_1.jsx)(VideoComponent, { ...((_c = video === null || video === void 0 ? void 0 : video.defaultProps) !== null && _c !== void 0 ? _c : {}), ...((_d = inputProps) !== null && _d !== void 0 ? _d : {}) }) })) : null }) }), shouldShowPoster ? ((0, jsx_runtime_1.jsx)("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null, controls ? ((0, jsx_runtime_1.jsx)(PlayerControls_js_1.Controls, { fps: config.fps, durationInFrames: config.durationInFrames, hovered: hovered, player: player, onFullscreenButtonClick: onFullscreenButtonClick, isFullscreen: isFullscreen, allowFullscreen: allowFullscreen, showVolumeControls: showVolumeControls, onExitFullscreenButtonClick: onExitFullscreenButtonClick, spaceKeyToPlayOrPause: spaceKeyToPlayOrPause, onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, inFrame: inFrame, outFrame: outFrame, initiallyShowControls: initiallyShowControls, playerWidth: (_e = canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.width) !== null && _e !== void 0 ? _e : 0, renderFullscreenButton: renderFullscreenButton, renderPlayPauseButton: renderPlayPauseButton, alwaysShowControls: alwaysShowControls })) : null] }));
|
|
320
|
+
const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: (0, jsx_runtime_1.jsx)("div", { style: containerStyle, className: player_css_classname_js_1.PLAYER_CSS_CLASSNAME, children: VideoComponent ? ((0, jsx_runtime_1.jsx)(error_boundary_js_1.ErrorBoundary, { onError: onError, errorFallback: errorFallback, children: (0, jsx_runtime_1.jsx)(VideoComponent, { ...((_c = video === null || video === void 0 ? void 0 : video.defaultProps) !== null && _c !== void 0 ? _c : {}), ...((_d = inputProps) !== null && _d !== void 0 ? _d : {}) }) })) : null }) }), shouldShowPoster ? ((0, jsx_runtime_1.jsx)("div", { style: outer, onClick: clickToPlay ? handleClick : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null, controls ? ((0, jsx_runtime_1.jsx)(PlayerControls_js_1.Controls, { fps: config.fps, durationInFrames: config.durationInFrames, hovered: hovered, player: player, onFullscreenButtonClick: onFullscreenButtonClick, isFullscreen: isFullscreen, allowFullscreen: allowFullscreen, showVolumeControls: showVolumeControls, onExitFullscreenButtonClick: onExitFullscreenButtonClick, spaceKeyToPlayOrPause: spaceKeyToPlayOrPause, onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, inFrame: inFrame, outFrame: outFrame, initiallyShowControls: initiallyShowControls, playerWidth: (_e = canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.width) !== null && _e !== void 0 ? _e : 0, renderFullscreenButton: renderFullscreenButton, renderPlayPauseButton: renderPlayPauseButton, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl })) : null] }));
|
|
312
321
|
if (is_node_js_1.IS_NODE && !doesReactVersionSupportSuspense) {
|
|
313
322
|
return ((0, jsx_runtime_1.jsx)("div", { ref: container, style: outerStyle, className: className, children: content }));
|
|
314
323
|
}
|
|
@@ -22,6 +22,9 @@ declare type VolumeChangeEventPayload = {
|
|
|
22
22
|
declare type FullscreenChangeEventPayload = {
|
|
23
23
|
isFullscreen: boolean;
|
|
24
24
|
};
|
|
25
|
+
declare type MuteChangeEventPayload = {
|
|
26
|
+
isMuted: boolean;
|
|
27
|
+
};
|
|
25
28
|
declare type PlayerStateEventMap = {
|
|
26
29
|
seeked: SeekPayload;
|
|
27
30
|
pause: undefined;
|
|
@@ -34,6 +37,7 @@ declare type PlayerStateEventMap = {
|
|
|
34
37
|
timeupdate: TimeUpdateEventPayload;
|
|
35
38
|
frameupdate: FrameUpdateEventPayload;
|
|
36
39
|
fullscreenchange: FullscreenChangeEventPayload;
|
|
40
|
+
mutechange: MuteChangeEventPayload;
|
|
37
41
|
};
|
|
38
42
|
declare type ThumbnailStateEventMap = {
|
|
39
43
|
error: ErrorPayload;
|
|
@@ -65,6 +69,7 @@ export declare class PlayerEmitter {
|
|
|
65
69
|
dispatchTimeUpdate(event: TimeUpdateEventPayload): void;
|
|
66
70
|
dispatchFrameUpdate(event: FrameUpdateEventPayload): void;
|
|
67
71
|
dispatchFullscreenChange(event: FullscreenChangeEventPayload): void;
|
|
72
|
+
dispatchMuteChange(event: MuteChangeEventPayload): void;
|
|
68
73
|
}
|
|
69
74
|
export declare class ThumbnailEmitter {
|
|
70
75
|
listeners: ThumbnailListeners;
|
|
@@ -15,6 +15,7 @@ class PlayerEmitter {
|
|
|
15
15
|
frameupdate: [],
|
|
16
16
|
fullscreenchange: [],
|
|
17
17
|
volumechange: [],
|
|
18
|
+
mutechange: [],
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
addEventListener(name, callback) {
|
|
@@ -71,6 +72,9 @@ class PlayerEmitter {
|
|
|
71
72
|
dispatchFullscreenChange(event) {
|
|
72
73
|
this.dispatchEvent('fullscreenchange', event);
|
|
73
74
|
}
|
|
75
|
+
dispatchMuteChange(event) {
|
|
76
|
+
this.dispatchEvent('mutechange', event);
|
|
77
|
+
}
|
|
74
78
|
}
|
|
75
79
|
exports.PlayerEmitter = PlayerEmitter;
|
|
76
80
|
class ThumbnailEmitter {
|
package/dist/cjs/icons.d.ts
CHANGED
package/dist/cjs/icons.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VolumeOnIcon = exports.VolumeOffIcon = exports.FullscreenIcon = exports.PauseIcon = exports.PlayIcon = exports.fullscreenIconSize = exports.ICON_SIZE = void 0;
|
|
3
|
+
exports.SettingsIcon = exports.VolumeOnIcon = exports.VolumeOffIcon = exports.FullscreenIcon = exports.PauseIcon = exports.PlayIcon = exports.fullscreenIconSize = exports.ICON_SIZE = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
exports.ICON_SIZE = 25;
|
|
6
6
|
exports.fullscreenIconSize = 16;
|
|
@@ -48,3 +48,7 @@ const VolumeOnIcon = () => {
|
|
|
48
48
|
return ((0, jsx_runtime_1.jsx)("svg", { width: exports.ICON_SIZE, height: exports.ICON_SIZE, viewBox: "0 0 24 24", children: (0, jsx_runtime_1.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" }) }));
|
|
49
49
|
};
|
|
50
50
|
exports.VolumeOnIcon = VolumeOnIcon;
|
|
51
|
+
const SettingsIcon = ({ iconSize }) => {
|
|
52
|
+
return ((0, jsx_runtime_1.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", height: iconSize !== null && iconSize !== void 0 ? iconSize : exports.ICON_SIZE, viewBox: "0 0 512 512", style: { fill: '#fff' }, children: (0, jsx_runtime_1.jsx)("path", { d: "M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z" }) }));
|
|
53
|
+
};
|
|
54
|
+
exports.SettingsIcon = SettingsIcon;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export default function useComponentVisible(initialIsVisible: boolean): {
|
|
3
|
+
ref: import("react").RefObject<HTMLDivElement>;
|
|
4
|
+
isComponentVisible: boolean;
|
|
5
|
+
setIsComponentVisible: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
6
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const react_1 = require("react");
|
|
4
|
+
// hook to hide a popup/modal when clicked outside
|
|
5
|
+
function useComponentVisible(initialIsVisible) {
|
|
6
|
+
const [isComponentVisible, setIsComponentVisible] = (0, react_1.useState)(initialIsVisible);
|
|
7
|
+
const ref = (0, react_1.useRef)(null);
|
|
8
|
+
(0, react_1.useEffect)(() => {
|
|
9
|
+
const handleClickOutside = (event) => {
|
|
10
|
+
if (ref.current && !ref.current.contains(event.target)) {
|
|
11
|
+
setIsComponentVisible(false);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
document.addEventListener('pointerup', handleClickOutside, true);
|
|
15
|
+
return () => {
|
|
16
|
+
document.removeEventListener('pointerup', handleClickOutside, true);
|
|
17
|
+
};
|
|
18
|
+
}, []);
|
|
19
|
+
return { ref, isComponentVisible, setIsComponentVisible };
|
|
20
|
+
}
|
|
21
|
+
exports.default = useComponentVisible;
|
package/dist/esm/Player.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export declare type PlayerProps<T> = {
|
|
|
40
40
|
renderFullscreenButton?: RenderFullscreenButton;
|
|
41
41
|
alwaysShowControls?: boolean;
|
|
42
42
|
initiallyMuted?: boolean;
|
|
43
|
+
showPlaybackRateControl?: boolean | number[];
|
|
43
44
|
} & PropsIfHasProps<T> & CompProps<T>;
|
|
44
45
|
export declare const componentOrNullIfLazy: <T>(props: CompProps<T>) => ComponentType<T> | null;
|
|
45
46
|
/**
|
package/dist/esm/PlayerUI.d.ts
CHANGED
|
@@ -35,5 +35,6 @@ declare const _default: React.ForwardRefExoticComponent<{
|
|
|
35
35
|
renderPlayPauseButton: RenderPlayPauseButton | null;
|
|
36
36
|
renderFullscreen: RenderFullscreenButton | null;
|
|
37
37
|
alwaysShowControls: boolean;
|
|
38
|
+
showPlaybackRateControl: boolean | number[];
|
|
38
39
|
} & React.RefAttributes<PlayerRef>>;
|
|
39
40
|
export default _default;
|
|
@@ -22,6 +22,9 @@ declare type VolumeChangeEventPayload = {
|
|
|
22
22
|
declare type FullscreenChangeEventPayload = {
|
|
23
23
|
isFullscreen: boolean;
|
|
24
24
|
};
|
|
25
|
+
declare type MuteChangeEventPayload = {
|
|
26
|
+
isMuted: boolean;
|
|
27
|
+
};
|
|
25
28
|
declare type PlayerStateEventMap = {
|
|
26
29
|
seeked: SeekPayload;
|
|
27
30
|
pause: undefined;
|
|
@@ -34,6 +37,7 @@ declare type PlayerStateEventMap = {
|
|
|
34
37
|
timeupdate: TimeUpdateEventPayload;
|
|
35
38
|
frameupdate: FrameUpdateEventPayload;
|
|
36
39
|
fullscreenchange: FullscreenChangeEventPayload;
|
|
40
|
+
mutechange: MuteChangeEventPayload;
|
|
37
41
|
};
|
|
38
42
|
declare type ThumbnailStateEventMap = {
|
|
39
43
|
error: ErrorPayload;
|
|
@@ -65,6 +69,7 @@ export declare class PlayerEmitter {
|
|
|
65
69
|
dispatchTimeUpdate(event: TimeUpdateEventPayload): void;
|
|
66
70
|
dispatchFrameUpdate(event: FrameUpdateEventPayload): void;
|
|
67
71
|
dispatchFullscreenChange(event: FullscreenChangeEventPayload): void;
|
|
72
|
+
dispatchMuteChange(event: MuteChangeEventPayload): void;
|
|
68
73
|
}
|
|
69
74
|
export declare class ThumbnailEmitter {
|
|
70
75
|
listeners: ThumbnailListeners;
|