@remotion/player 4.0.0-umungobongo.5 → 4.0.0-webhook.26
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/MediaVolumeSlider.d.ts +4 -1
- package/dist/MediaVolumeSlider.js +80 -55
- package/dist/Player.d.ts +10 -2
- package/dist/Player.js +23 -7
- package/dist/PlayerControls.d.ts +8 -0
- package/dist/PlayerControls.js +55 -13
- package/dist/PlayerSeekBar.d.ts +4 -0
- package/dist/PlayerSeekBar.js +35 -11
- package/dist/PlayerUI.d.ts +9 -1
- package/dist/PlayerUI.js +47 -28
- package/dist/calculate-scale.d.ts +8 -2
- package/dist/calculate-scale.js +13 -4
- package/dist/event-emitter.d.ts +5 -0
- package/dist/event-emitter.js +4 -0
- package/dist/icons.d.ts +1 -0
- package/dist/icons.js +3 -3
- package/dist/index.d.ts +13 -5
- package/dist/index.js +2 -1
- package/dist/player-css-classname.d.ts +0 -1
- package/dist/player-css-classname.js +1 -2
- package/dist/player-methods.d.ts +1 -0
- package/dist/test/validate-in-out-frames.test.d.ts +1 -0
- package/dist/test/validate-in-out-frames.test.js +55 -0
- package/dist/test/validate-prop.test.js +1 -1
- package/dist/use-playback.js +3 -0
- package/dist/use-player.d.ts +2 -0
- package/dist/use-player.js +13 -6
- package/dist/use-video-controls-resize.d.ts +7 -0
- package/dist/use-video-controls-resize.js +36 -0
- package/dist/utils/preview-size.d.ts +8 -1
- package/dist/utils/validate-in-out-frame.d.ts +6 -0
- package/dist/utils/validate-in-out-frame.js +54 -0
- package/dist/utils/validate-initial-frame.d.ts +4 -0
- package/dist/utils/validate-initial-frame.js +27 -0
- package/package.json +4 -4
|
@@ -1,72 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MediaVolumeSlider = void 0;
|
|
3
|
+
exports.MediaVolumeSlider = exports.VOLUME_SLIDER_WIDTH = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const remotion_1 = require("remotion");
|
|
7
7
|
const icons_1 = require("./icons");
|
|
8
|
-
const player_css_classname_1 = require("./player-css-classname");
|
|
9
8
|
const use_hover_state_1 = require("./use-hover-state");
|
|
10
9
|
const BAR_HEIGHT = 5;
|
|
11
10
|
const KNOB_SIZE = 12;
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const sliderStyle = `
|
|
15
|
-
${scope} {
|
|
16
|
-
-webkit-appearance: none;
|
|
17
|
-
background-color: rgba(255, 255, 255, 0.5);
|
|
18
|
-
border-radius: ${BAR_HEIGHT / 2}px;
|
|
19
|
-
cursor: pointer;
|
|
20
|
-
height: ${BAR_HEIGHT}px;
|
|
21
|
-
margin-left: 5px;
|
|
22
|
-
width: ${VOLUME_SLIDER_WIDTH}px;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
${scope}::-webkit-slider-thumb {
|
|
26
|
-
-webkit-appearance: none;
|
|
27
|
-
background-color: white;
|
|
28
|
-
border-radius: ${KNOB_SIZE / 2}px;
|
|
29
|
-
box-shadow: 0 0 2px black;
|
|
30
|
-
height: ${KNOB_SIZE}px;
|
|
31
|
-
width: ${KNOB_SIZE}px;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
${scope}::-moz-range-thumb {
|
|
35
|
-
-webkit-appearance: none;
|
|
36
|
-
background-color: white;
|
|
37
|
-
border-radius: ${KNOB_SIZE / 2}px;
|
|
38
|
-
box-shadow: 0 0 2px black;
|
|
39
|
-
height: ${KNOB_SIZE}px;
|
|
40
|
-
width: ${KNOB_SIZE}px;
|
|
41
|
-
}
|
|
42
|
-
`;
|
|
43
|
-
remotion_1.Internals.CSSUtils.injectCSS(sliderStyle);
|
|
44
|
-
const parentDivStyle = {
|
|
45
|
-
display: 'inline-flex',
|
|
46
|
-
background: 'none',
|
|
47
|
-
border: 'none',
|
|
48
|
-
padding: '6px',
|
|
49
|
-
justifyContent: 'center',
|
|
50
|
-
alignItems: 'center',
|
|
51
|
-
touchAction: 'none',
|
|
52
|
-
};
|
|
53
|
-
const volumeContainer = {
|
|
54
|
-
display: 'inline',
|
|
55
|
-
width: icons_1.ICON_SIZE,
|
|
56
|
-
height: icons_1.ICON_SIZE,
|
|
57
|
-
cursor: 'pointer',
|
|
58
|
-
appearance: 'none',
|
|
59
|
-
background: 'none',
|
|
60
|
-
border: 'none',
|
|
61
|
-
padding: 0,
|
|
62
|
-
};
|
|
63
|
-
const MediaVolumeSlider = () => {
|
|
11
|
+
exports.VOLUME_SLIDER_WIDTH = 100;
|
|
12
|
+
const MediaVolumeSlider = ({ displayVerticalVolumeSlider }) => {
|
|
64
13
|
const [mediaMuted, setMediaMuted] = remotion_1.Internals.useMediaMutedState();
|
|
65
14
|
const [mediaVolume, setMediaVolume] = remotion_1.Internals.useMediaVolumeState();
|
|
66
15
|
const [focused, setFocused] = (0, react_1.useState)(false);
|
|
67
16
|
const parentDivRef = (0, react_1.useRef)(null);
|
|
68
17
|
const inputRef = (0, react_1.useRef)(null);
|
|
69
18
|
const hover = (0, use_hover_state_1.useHoverState)(parentDivRef);
|
|
19
|
+
const [randomClass] = (0, react_1.useState)(() => `slider-${(0, remotion_1.random)(null)}`.replace('.', ''));
|
|
70
20
|
const isMutedOrZero = mediaMuted || mediaVolume === 0;
|
|
71
21
|
const onVolumeChange = (e) => {
|
|
72
22
|
setMediaVolume(parseFloat(e.target.value));
|
|
@@ -88,6 +38,81 @@ const MediaVolumeSlider = () => {
|
|
|
88
38
|
}
|
|
89
39
|
setMediaMuted((mute) => !mute);
|
|
90
40
|
}, [mediaVolume, setMediaMuted, setMediaVolume]);
|
|
91
|
-
|
|
41
|
+
const parentDivStyle = (0, react_1.useMemo)(() => {
|
|
42
|
+
return {
|
|
43
|
+
display: 'inline-flex',
|
|
44
|
+
background: 'none',
|
|
45
|
+
border: 'none',
|
|
46
|
+
padding: '6px',
|
|
47
|
+
justifyContent: 'center',
|
|
48
|
+
alignItems: 'center',
|
|
49
|
+
touchAction: 'none',
|
|
50
|
+
...(displayVerticalVolumeSlider && { position: 'relative' }),
|
|
51
|
+
};
|
|
52
|
+
}, [displayVerticalVolumeSlider]);
|
|
53
|
+
const volumeContainer = (0, react_1.useMemo)(() => {
|
|
54
|
+
return {
|
|
55
|
+
display: 'inline',
|
|
56
|
+
width: icons_1.ICON_SIZE,
|
|
57
|
+
height: icons_1.ICON_SIZE,
|
|
58
|
+
cursor: 'pointer',
|
|
59
|
+
appearance: 'none',
|
|
60
|
+
background: 'none',
|
|
61
|
+
border: 'none',
|
|
62
|
+
padding: 0,
|
|
63
|
+
};
|
|
64
|
+
}, []);
|
|
65
|
+
const inputStyle = (0, react_1.useMemo)(() => {
|
|
66
|
+
const commonStyle = {
|
|
67
|
+
WebkitAppearance: 'none',
|
|
68
|
+
backgroundColor: 'rgba(255, 255, 255, 0.5)',
|
|
69
|
+
borderRadius: BAR_HEIGHT / 2,
|
|
70
|
+
cursor: 'pointer',
|
|
71
|
+
height: BAR_HEIGHT,
|
|
72
|
+
width: exports.VOLUME_SLIDER_WIDTH,
|
|
73
|
+
};
|
|
74
|
+
if (displayVerticalVolumeSlider) {
|
|
75
|
+
return {
|
|
76
|
+
...commonStyle,
|
|
77
|
+
transform: `rotate(-90deg)`,
|
|
78
|
+
position: 'absolute',
|
|
79
|
+
bottom: icons_1.ICON_SIZE + exports.VOLUME_SLIDER_WIDTH / 2 + 5,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
...commonStyle,
|
|
84
|
+
marginLeft: 5,
|
|
85
|
+
};
|
|
86
|
+
}, [displayVerticalVolumeSlider]);
|
|
87
|
+
const sliderStyle = `
|
|
88
|
+
.${randomClass}::-webkit-slider-thumb {
|
|
89
|
+
-webkit-appearance: none;
|
|
90
|
+
background-color: white;
|
|
91
|
+
border-radius: ${KNOB_SIZE / 2}px;
|
|
92
|
+
box-shadow: 0 0 2px black;
|
|
93
|
+
height: ${KNOB_SIZE}px;
|
|
94
|
+
width: ${KNOB_SIZE}px;
|
|
95
|
+
}
|
|
96
|
+
.${randomClass} {
|
|
97
|
+
background-image: linear-gradient(
|
|
98
|
+
to right,
|
|
99
|
+
white ${mediaVolume * 100}%, rgba(255, 255, 255, 0) ${mediaVolume * 100}%
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.${randomClass}::-moz-range-thumb {
|
|
104
|
+
-webkit-appearance: none;
|
|
105
|
+
background-color: white;
|
|
106
|
+
border-radius: ${KNOB_SIZE / 2}px;
|
|
107
|
+
box-shadow: 0 0 2px black;
|
|
108
|
+
height: ${KNOB_SIZE}px;
|
|
109
|
+
width: ${KNOB_SIZE}px;
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: parentDivRef, style: parentDivStyle, children: [(0, jsx_runtime_1.jsx)("style", {
|
|
113
|
+
// eslint-disable-next-line react/no-danger
|
|
114
|
+
dangerouslySetInnerHTML: {
|
|
115
|
+
__html: sliderStyle,
|
|
116
|
+
} }), (0, jsx_runtime_1.jsx)("button", { "aria-label": isMutedOrZero ? 'Unmute sound' : 'Mute sound', title: isMutedOrZero ? 'Unmute sound' : 'Mute sound', onClick: onClick, onBlur: onBlur, onFocus: () => setFocused(true), style: volumeContainer, type: "button", children: isMutedOrZero ? (0, jsx_runtime_1.jsx)(icons_1.VolumeOffIcon, {}) : (0, jsx_runtime_1.jsx)(icons_1.VolumeOnIcon, {}) }), (focused || hover) && !mediaMuted ? ((0, jsx_runtime_1.jsx)("input", { ref: inputRef, "aria-label": "Change volume", className: randomClass, max: 1, min: 0, onBlur: () => setFocused(false), onChange: onVolumeChange, step: 0.01, type: "range", value: mediaVolume, style: inputStyle })) : null] }));
|
|
92
117
|
};
|
|
93
118
|
exports.MediaVolumeSlider = MediaVolumeSlider;
|
package/dist/Player.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ComponentType, MutableRefObject } from 'react';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import type { CompProps } from 'remotion';
|
|
4
4
|
import type { PlayerRef } from './player-methods';
|
|
5
|
-
import type { RenderLoading } from './PlayerUI';
|
|
5
|
+
import type { RenderLoading, RenderPoster } from './PlayerUI';
|
|
6
6
|
declare type PropsIfHasProps<Props> = {} extends Props ? {
|
|
7
7
|
inputProps?: Props;
|
|
8
8
|
} : {
|
|
@@ -31,9 +31,17 @@ export declare type PlayerProps<T> = {
|
|
|
31
31
|
renderLoading?: RenderLoading;
|
|
32
32
|
moveToBeginningWhenEnded?: boolean;
|
|
33
33
|
className?: string;
|
|
34
|
+
initialFrame?: number;
|
|
35
|
+
renderPoster?: RenderPoster;
|
|
36
|
+
showPosterWhenPaused?: boolean;
|
|
37
|
+
showPosterWhenEnded?: boolean;
|
|
38
|
+
showPosterWhenUnplayed?: boolean;
|
|
39
|
+
inFrame?: number | null;
|
|
40
|
+
outFrame?: number | null;
|
|
41
|
+
initiallyShowControls?: number | boolean;
|
|
34
42
|
} & PropsIfHasProps<T> & CompProps<T>;
|
|
35
43
|
export declare const componentOrNullIfLazy: <T>(props: CompProps<T>) => ComponentType<T> | null;
|
|
36
|
-
export declare const PlayerFn: <T>({ durationInFrames, compositionHeight, compositionWidth, fps, inputProps, style, controls, loop, autoPlay, showVolumeControls, allowFullscreen, clickToPlay, doubleClickToFullscreen, spaceKeyToPlayOrPause, moveToBeginningWhenEnded, numberOfSharedAudioTags, errorFallback, playbackRate, renderLoading, className, ...componentProps }: PlayerProps<T>, ref: MutableRefObject<PlayerRef>) => JSX.Element;
|
|
44
|
+
export declare const PlayerFn: <T>({ durationInFrames, compositionHeight, compositionWidth, fps, inputProps, style, controls, loop, autoPlay, showVolumeControls, allowFullscreen, clickToPlay, doubleClickToFullscreen, spaceKeyToPlayOrPause, moveToBeginningWhenEnded, numberOfSharedAudioTags, errorFallback, playbackRate, renderLoading, className, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, ...componentProps }: PlayerProps<T>, ref: MutableRefObject<PlayerRef>) => JSX.Element;
|
|
37
45
|
declare module 'react' {
|
|
38
46
|
function forwardRef<T, P = {}>(render: (props: P, ref: React.MutableRefObject<T>) => React.ReactElement | null): (props: P & React.RefAttributes<T>) => React.ReactElement | null;
|
|
39
47
|
}
|
package/dist/Player.js
CHANGED
|
@@ -11,9 +11,10 @@ const emitter_context_1 = require("./emitter-context");
|
|
|
11
11
|
const event_emitter_1 = require("./event-emitter");
|
|
12
12
|
const player_css_classname_1 = require("./player-css-classname");
|
|
13
13
|
const PlayerUI_1 = __importDefault(require("./PlayerUI"));
|
|
14
|
+
const validate_in_out_frame_1 = require("./utils/validate-in-out-frame");
|
|
15
|
+
const validate_initial_frame_1 = require("./utils/validate-initial-frame");
|
|
14
16
|
const validate_playbackrate_1 = require("./utils/validate-playbackrate");
|
|
15
17
|
const volume_persistance_1 = require("./volume-persistance");
|
|
16
|
-
remotion_1.Internals.CSSUtils.injectCSS(remotion_1.Internals.CSSUtils.makeDefaultCSS(`.${player_css_classname_1.PLAYER_CSS_CLASSNAME}`, '#fff'));
|
|
17
18
|
const componentOrNullIfLazy = (props) => {
|
|
18
19
|
if ('component' in props) {
|
|
19
20
|
return props.component;
|
|
@@ -21,7 +22,7 @@ const componentOrNullIfLazy = (props) => {
|
|
|
21
22
|
return null;
|
|
22
23
|
};
|
|
23
24
|
exports.componentOrNullIfLazy = componentOrNullIfLazy;
|
|
24
|
-
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, ...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, ...componentProps }, ref) => {
|
|
25
26
|
if (typeof window !== 'undefined') {
|
|
26
27
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
27
28
|
(0, react_1.useLayoutEffect)(() => {
|
|
@@ -41,7 +42,8 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
41
42
|
throw new TypeError(`'component' must not be the 'Composition' component. Pass your own React component directly, and set the duration, fps and dimensions as separate props. See https://www.remotion.dev/docs/player/examples for an example.`);
|
|
42
43
|
}
|
|
43
44
|
const component = remotion_1.Internals.useLazyComponent(componentProps);
|
|
44
|
-
|
|
45
|
+
(0, validate_initial_frame_1.validateInitialFrame)({ initialFrame, durationInFrames });
|
|
46
|
+
const [frame, setFrame] = (0, react_1.useState)(() => initialFrame !== null && initialFrame !== void 0 ? initialFrame : 0);
|
|
45
47
|
const [playing, setPlaying] = (0, react_1.useState)(false);
|
|
46
48
|
const [rootId] = (0, react_1.useState)('player-comp');
|
|
47
49
|
const [emitter] = (0, react_1.useState)(() => new event_emitter_1.PlayerEmitter());
|
|
@@ -60,6 +62,11 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
60
62
|
remotion_1.Internals.validateDimension(compositionWidth, 'compositionWidth', 'of the <Player /> component');
|
|
61
63
|
remotion_1.Internals.validateDurationInFrames(durationInFrames, 'of the <Player/> component');
|
|
62
64
|
remotion_1.Internals.validateFps(fps, 'as a prop of the <Player/> component', false);
|
|
65
|
+
(0, validate_in_out_frame_1.validateInOutFrames)({
|
|
66
|
+
durationInFrames,
|
|
67
|
+
inFrame,
|
|
68
|
+
outFrame,
|
|
69
|
+
});
|
|
63
70
|
if (typeof controls !== 'boolean' && typeof controls !== 'undefined') {
|
|
64
71
|
throw new TypeError(`'controls' must be a boolean or undefined but got '${typeof controls}' instead`);
|
|
65
72
|
}
|
|
@@ -103,7 +110,7 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
103
110
|
setMediaVolume(vol);
|
|
104
111
|
(0, volume_persistance_1.persistVolume)(vol);
|
|
105
112
|
}, []);
|
|
106
|
-
(0, react_1.useImperativeHandle)(ref, () => rootRef.current);
|
|
113
|
+
(0, react_1.useImperativeHandle)(ref, () => rootRef.current, []);
|
|
107
114
|
const timelineContextValue = (0, react_1.useMemo)(() => {
|
|
108
115
|
return {
|
|
109
116
|
frame,
|
|
@@ -166,6 +173,8 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
166
173
|
unregisterSequence: () => undefined,
|
|
167
174
|
registerAsset: () => undefined,
|
|
168
175
|
unregisterAsset: () => undefined,
|
|
176
|
+
currentCompositionMetadata: null,
|
|
177
|
+
setCurrentCompositionMetadata: () => undefined,
|
|
169
178
|
assets: [],
|
|
170
179
|
};
|
|
171
180
|
}, [
|
|
@@ -179,9 +188,16 @@ const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps,
|
|
|
179
188
|
const passedInputProps = (0, react_1.useMemo)(() => {
|
|
180
189
|
return inputProps !== null && inputProps !== void 0 ? inputProps : {};
|
|
181
190
|
}, [inputProps]);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
191
|
+
if (typeof window !== 'undefined') {
|
|
192
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
193
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
194
|
+
// Inject CSS only on client, and also only after the Player has hydrated
|
|
195
|
+
remotion_1.Internals.CSSUtils.injectCSS(remotion_1.Internals.CSSUtils.makeDefaultCSS(`.${player_css_classname_1.PLAYER_CSS_CLASSNAME}`, '#fff'));
|
|
196
|
+
}, []);
|
|
197
|
+
}
|
|
198
|
+
return ((0, jsx_runtime_1.jsx)(remotion_1.Internals.CanUseRemotionHooksProvider, { children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.Timeline.TimelineContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.Timeline.SetTimelineContext.Provider, { value: setTimelineContextValue, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.CompositionManager.Provider, { value: compositionManagerContext, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.MediaVolumeContext.Provider, { value: mediaVolumeContextValue, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.SetMediaVolumeContext.Provider, { value: setMediaVolumeContextValue, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.SharedAudioContextProvider, { numberOfAudioTags: numberOfSharedAudioTags, children: (0, jsx_runtime_1.jsx)(emitter_context_1.PlayerEventEmitterContext.Provider, { value: emitter, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(PlayerUI_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'
|
|
199
|
+
? clickToPlay
|
|
200
|
+
: Boolean(controls), showVolumeControls: Boolean(showVolumeControls), setMediaVolume: setMediaVolumeAndPersist, mediaVolume: mediaVolume, mediaMuted: mediaMuted, doubleClickToFullscreen: Boolean(doubleClickToFullscreen), setMediaMuted: setMediaMuted, spaceKeyToPlayOrPause: Boolean(spaceKeyToPlayOrPause), playbackRate: playbackRate, 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 }) }) }) }) }) }) }) }) }) }));
|
|
185
201
|
};
|
|
186
202
|
exports.PlayerFn = PlayerFn;
|
|
187
203
|
exports.Player = (0, react_1.forwardRef)(exports.PlayerFn);
|
package/dist/PlayerControls.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { MouseEventHandler } from 'react';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import type { usePlayer } from './use-player';
|
|
4
|
+
export declare const X_SPACER = 10;
|
|
5
|
+
export declare const X_PADDING = 12;
|
|
4
6
|
declare global {
|
|
5
7
|
interface Document {
|
|
6
8
|
webkitFullscreenEnabled?: boolean;
|
|
@@ -22,4 +24,10 @@ export declare const Controls: React.FC<{
|
|
|
22
24
|
allowFullscreen: boolean;
|
|
23
25
|
onExitFullscreenButtonClick: MouseEventHandler<HTMLButtonElement>;
|
|
24
26
|
spaceKeyToPlayOrPause: boolean;
|
|
27
|
+
onSeekEnd: () => void;
|
|
28
|
+
onSeekStart: () => void;
|
|
29
|
+
inFrame: number | null;
|
|
30
|
+
outFrame: number | null;
|
|
31
|
+
initiallyShowControls: number | boolean;
|
|
32
|
+
playerWidth: number;
|
|
25
33
|
}>;
|
package/dist/PlayerControls.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Controls = void 0;
|
|
3
|
+
exports.Controls = exports.X_PADDING = exports.X_SPACER = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const remotion_1 = require("remotion");
|
|
@@ -8,6 +8,9 @@ const format_time_1 = require("./format-time");
|
|
|
8
8
|
const icons_1 = require("./icons");
|
|
9
9
|
const MediaVolumeSlider_1 = require("./MediaVolumeSlider");
|
|
10
10
|
const PlayerSeekBar_1 = require("./PlayerSeekBar");
|
|
11
|
+
const use_video_controls_resize_1 = require("./use-video-controls-resize");
|
|
12
|
+
exports.X_SPACER = 10;
|
|
13
|
+
exports.X_PADDING = 12;
|
|
11
14
|
const containerStyle = {
|
|
12
15
|
boxSizing: 'border-box',
|
|
13
16
|
position: 'absolute',
|
|
@@ -17,8 +20,8 @@ const containerStyle = {
|
|
|
17
20
|
paddingBottom: 10,
|
|
18
21
|
background: 'linear-gradient(transparent, rgba(0, 0, 0, 0.4))',
|
|
19
22
|
display: 'flex',
|
|
20
|
-
paddingRight:
|
|
21
|
-
paddingLeft:
|
|
23
|
+
paddingRight: exports.X_PADDING,
|
|
24
|
+
paddingLeft: exports.X_PADDING,
|
|
22
25
|
flexDirection: 'column',
|
|
23
26
|
transition: 'opacity 0.3s',
|
|
24
27
|
};
|
|
@@ -57,23 +60,40 @@ const flex1 = {
|
|
|
57
60
|
flex: 1,
|
|
58
61
|
};
|
|
59
62
|
const fullscreen = {};
|
|
60
|
-
const
|
|
61
|
-
color: 'white',
|
|
62
|
-
fontFamily: 'sans-serif',
|
|
63
|
-
fontSize: 14,
|
|
64
|
-
};
|
|
65
|
-
const Controls = ({ durationInFrames, hovered, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, }) => {
|
|
63
|
+
const Controls = ({ durationInFrames, hovered, isFullscreen, fps, player, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, playerWidth, }) => {
|
|
66
64
|
const playButtonRef = (0, react_1.useRef)(null);
|
|
67
65
|
const frame = remotion_1.Internals.Timeline.useTimelinePosition();
|
|
68
66
|
const [supportsFullscreen, setSupportsFullscreen] = (0, react_1.useState)(false);
|
|
67
|
+
const { maxTimeLabelWidth, displayVerticalVolumeSlider } = (0, use_video_controls_resize_1.useVideoControlsResize)({ allowFullscreen, playerWidth });
|
|
68
|
+
const [shouldShowInitially, setInitiallyShowControls] = (0, react_1.useState)(() => {
|
|
69
|
+
if (typeof initiallyShowControls === 'boolean') {
|
|
70
|
+
return initiallyShowControls;
|
|
71
|
+
}
|
|
72
|
+
if (typeof initiallyShowControls === 'number') {
|
|
73
|
+
if (initiallyShowControls % 1 !== 0) {
|
|
74
|
+
throw new Error('initiallyShowControls must be an integer or a boolean');
|
|
75
|
+
}
|
|
76
|
+
if (Number.isNaN(initiallyShowControls)) {
|
|
77
|
+
throw new Error('initiallyShowControls must not be NaN');
|
|
78
|
+
}
|
|
79
|
+
if (!Number.isFinite(initiallyShowControls)) {
|
|
80
|
+
throw new Error('initiallyShowControls must be finite');
|
|
81
|
+
}
|
|
82
|
+
if (initiallyShowControls <= 0) {
|
|
83
|
+
throw new Error('initiallyShowControls must be a positive integer');
|
|
84
|
+
}
|
|
85
|
+
return initiallyShowControls;
|
|
86
|
+
}
|
|
87
|
+
throw new TypeError('initiallyShowControls must be a number or a boolean');
|
|
88
|
+
});
|
|
69
89
|
const containerCss = (0, react_1.useMemo)(() => {
|
|
70
90
|
// Hide if playing and mouse outside
|
|
71
|
-
const shouldShow = hovered || !player.playing;
|
|
91
|
+
const shouldShow = hovered || !player.playing || shouldShowInitially;
|
|
72
92
|
return {
|
|
73
93
|
...containerStyle,
|
|
74
94
|
opacity: Number(shouldShow),
|
|
75
95
|
};
|
|
76
|
-
}, [hovered, player.playing]);
|
|
96
|
+
}, [hovered, shouldShowInitially, player.playing]);
|
|
77
97
|
(0, react_1.useEffect)(() => {
|
|
78
98
|
if (playButtonRef.current && spaceKeyToPlayOrPause) {
|
|
79
99
|
// This switches focus to play button when player.playing flag changes
|
|
@@ -88,8 +108,30 @@ const Controls = ({ durationInFrames, hovered, isFullscreen, fps, player, showVo
|
|
|
88
108
|
setSupportsFullscreen((_a = (typeof document !== 'undefined' &&
|
|
89
109
|
(document.fullscreenEnabled || document.webkitFullscreenEnabled))) !== null && _a !== void 0 ? _a : false);
|
|
90
110
|
}, []);
|
|
91
|
-
|
|
111
|
+
(0, react_1.useEffect)(() => {
|
|
112
|
+
if (shouldShowInitially === false) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const time = shouldShowInitially === true ? 2000 : shouldShowInitially;
|
|
116
|
+
const timeout = setTimeout(() => {
|
|
117
|
+
setInitiallyShowControls(false);
|
|
118
|
+
}, time);
|
|
119
|
+
return () => {
|
|
120
|
+
clearInterval(timeout);
|
|
121
|
+
};
|
|
122
|
+
}, [shouldShowInitially]);
|
|
123
|
+
const timeLabel = (0, react_1.useMemo)(() => {
|
|
124
|
+
return {
|
|
125
|
+
color: 'white',
|
|
126
|
+
fontFamily: 'sans-serif',
|
|
127
|
+
fontSize: 14,
|
|
128
|
+
maxWidth: maxTimeLabelWidth,
|
|
129
|
+
overflow: 'hidden',
|
|
130
|
+
textOverflow: 'ellipsis',
|
|
131
|
+
};
|
|
132
|
+
}, [maxTimeLabelWidth]);
|
|
133
|
+
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: player.playing ? (0, jsx_runtime_1.jsx)(icons_1.PauseIcon, {}) : (0, jsx_runtime_1.jsx)(icons_1.PlayIcon, {}) }), 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_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_1.formatTime)(frame / fps), " / ", (0, format_time_1.formatTime)(durationInFrames / fps)] }), (0, jsx_runtime_1.jsx)("div", { style: xSpacer })] }), (0, jsx_runtime_1.jsx)("div", { style: flex1 }), (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
|
|
92
134
|
? onExitFullscreenButtonClick
|
|
93
|
-
: onFullscreenButtonClick, children: (0, jsx_runtime_1.jsx)(icons_1.FullscreenIcon, { minimized: !isFullscreen }) })) : null })] }), (0, jsx_runtime_1.jsx)("div", { style: ySpacer }), (0, jsx_runtime_1.jsx)(PlayerSeekBar_1.PlayerSeekBar, { durationInFrames: durationInFrames })] }));
|
|
135
|
+
: onFullscreenButtonClick, children: (0, jsx_runtime_1.jsx)(icons_1.FullscreenIcon, { minimized: !isFullscreen }) })) : null })] }), (0, jsx_runtime_1.jsx)("div", { style: ySpacer }), (0, jsx_runtime_1.jsx)(PlayerSeekBar_1.PlayerSeekBar, { onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, durationInFrames: durationInFrames, inFrame: inFrame, outFrame: outFrame })] }));
|
|
94
136
|
};
|
|
95
137
|
exports.Controls = Controls;
|
package/dist/PlayerSeekBar.d.ts
CHANGED
package/dist/PlayerSeekBar.js
CHANGED
|
@@ -30,11 +30,18 @@ const containerStyle = {
|
|
|
30
30
|
};
|
|
31
31
|
const barBackground = {
|
|
32
32
|
height: BAR_HEIGHT,
|
|
33
|
-
backgroundColor: 'rgba(255, 255, 255, 0.
|
|
33
|
+
backgroundColor: 'rgba(255, 255, 255, 0.25)',
|
|
34
34
|
width: '100%',
|
|
35
35
|
borderRadius: BAR_HEIGHT / 2,
|
|
36
36
|
};
|
|
37
|
-
const
|
|
37
|
+
const findBodyInWhichDivIsLocated = (div) => {
|
|
38
|
+
let current = div;
|
|
39
|
+
while (current.parentElement) {
|
|
40
|
+
current = current.parentElement;
|
|
41
|
+
}
|
|
42
|
+
return current;
|
|
43
|
+
};
|
|
44
|
+
const PlayerSeekBar = ({ durationInFrames, onSeekEnd, onSeekStart, inFrame, outFrame }) => {
|
|
38
45
|
const containerRef = (0, react_1.useRef)(null);
|
|
39
46
|
const barHovered = (0, use_hover_state_1.useHoverState)(containerRef);
|
|
40
47
|
const size = (0, use_element_size_1.useElementSize)(containerRef, {
|
|
@@ -57,7 +64,8 @@ const PlayerSeekBar = ({ durationInFrames }) => {
|
|
|
57
64
|
dragging: true,
|
|
58
65
|
wasPlaying: playing,
|
|
59
66
|
});
|
|
60
|
-
|
|
67
|
+
onSeekStart();
|
|
68
|
+
}, [size, durationInFrames, pause, seek, playing, onSeekStart]);
|
|
61
69
|
const onPointerMove = (0, react_1.useCallback)((e) => {
|
|
62
70
|
var _a;
|
|
63
71
|
if (!size) {
|
|
@@ -82,16 +90,18 @@ const PlayerSeekBar = ({ durationInFrames }) => {
|
|
|
82
90
|
else {
|
|
83
91
|
pause();
|
|
84
92
|
}
|
|
85
|
-
|
|
93
|
+
onSeekEnd();
|
|
94
|
+
}, [dragging, onSeekEnd, pause, play]);
|
|
86
95
|
(0, react_1.useEffect)(() => {
|
|
87
96
|
if (!dragging.dragging) {
|
|
88
97
|
return;
|
|
89
98
|
}
|
|
90
|
-
|
|
91
|
-
|
|
99
|
+
const body = findBodyInWhichDivIsLocated(containerRef.current);
|
|
100
|
+
body.addEventListener('pointermove', onPointerMove);
|
|
101
|
+
body.addEventListener('pointerup', onPointerUp);
|
|
92
102
|
return () => {
|
|
93
|
-
|
|
94
|
-
|
|
103
|
+
body.removeEventListener('pointermove', onPointerMove);
|
|
104
|
+
body.removeEventListener('pointerup', onPointerUp);
|
|
95
105
|
};
|
|
96
106
|
}, [dragging.dragging, onPointerMove, onPointerUp]);
|
|
97
107
|
const knobStyle = (0, react_1.useMemo)(() => {
|
|
@@ -113,10 +123,24 @@ const PlayerSeekBar = ({ durationInFrames }) => {
|
|
|
113
123
|
return {
|
|
114
124
|
height: BAR_HEIGHT,
|
|
115
125
|
backgroundColor: 'rgba(255, 255, 255, 1)',
|
|
116
|
-
width: (frame / (durationInFrames - 1)) * 100 + '%',
|
|
126
|
+
width: ((frame - (inFrame !== null && inFrame !== void 0 ? inFrame : 0)) / (durationInFrames - 1)) * 100 + '%',
|
|
127
|
+
marginLeft: ((inFrame !== null && inFrame !== void 0 ? inFrame : 0) / (durationInFrames - 1)) * 100 + '%',
|
|
128
|
+
borderRadius: BAR_HEIGHT / 2,
|
|
129
|
+
};
|
|
130
|
+
}, [durationInFrames, frame, inFrame]);
|
|
131
|
+
const active = (0, react_1.useMemo)(() => {
|
|
132
|
+
return {
|
|
133
|
+
height: BAR_HEIGHT,
|
|
134
|
+
backgroundColor: 'rgba(255, 255, 255, 0.25)',
|
|
135
|
+
width: (((outFrame !== null && outFrame !== void 0 ? outFrame : durationInFrames - 1) - (inFrame !== null && inFrame !== void 0 ? inFrame : 0)) /
|
|
136
|
+
(durationInFrames - 1)) *
|
|
137
|
+
100 +
|
|
138
|
+
'%',
|
|
139
|
+
marginLeft: ((inFrame !== null && inFrame !== void 0 ? inFrame : 0) / (durationInFrames - 1)) * 100 + '%',
|
|
117
140
|
borderRadius: BAR_HEIGHT / 2,
|
|
141
|
+
position: 'absolute',
|
|
118
142
|
};
|
|
119
|
-
}, [durationInFrames,
|
|
120
|
-
return ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, onPointerDown: onPointerDown, style: containerStyle, children: [(0, jsx_runtime_1.
|
|
143
|
+
}, [durationInFrames, inFrame, outFrame]);
|
|
144
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, onPointerDown: onPointerDown, style: containerStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: barBackground, children: [(0, jsx_runtime_1.jsx)("div", { style: active }), (0, jsx_runtime_1.jsx)("div", { style: fillStyle })] }), (0, jsx_runtime_1.jsx)("div", { style: knobStyle })] }));
|
|
121
145
|
};
|
|
122
146
|
exports.PlayerSeekBar = PlayerSeekBar;
|
package/dist/PlayerUI.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare type RenderLoading = (canvas: {
|
|
|
7
7
|
height: number;
|
|
8
8
|
width: number;
|
|
9
9
|
}) => React.ReactChild;
|
|
10
|
+
export declare type RenderPoster = RenderLoading;
|
|
10
11
|
declare const _default: (props: {
|
|
11
12
|
controls: boolean;
|
|
12
13
|
loop: boolean;
|
|
@@ -24,8 +25,15 @@ declare const _default: (props: {
|
|
|
24
25
|
mediaVolume: number;
|
|
25
26
|
errorFallback: ErrorFallback;
|
|
26
27
|
playbackRate: number;
|
|
27
|
-
renderLoading
|
|
28
|
+
renderLoading: RenderLoading | undefined;
|
|
29
|
+
renderPoster: RenderLoading | undefined;
|
|
28
30
|
className: string | undefined;
|
|
29
31
|
moveToBeginningWhenEnded: boolean;
|
|
32
|
+
showPosterWhenPaused: boolean;
|
|
33
|
+
showPosterWhenEnded: boolean;
|
|
34
|
+
showPosterWhenUnplayed: boolean;
|
|
35
|
+
inFrame: number | null;
|
|
36
|
+
outFrame: number | null;
|
|
37
|
+
initiallyShowControls: number | boolean;
|
|
30
38
|
} & React.RefAttributes<PlayerRef | null>) => React.ReactElement<any, string | React.JSXElementConstructor<any>> | null;
|
|
31
39
|
export default _default;
|
package/dist/PlayerUI.js
CHANGED
|
@@ -42,8 +42,8 @@ if (reactVersion === '0') {
|
|
|
42
42
|
throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
|
|
43
43
|
}
|
|
44
44
|
const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
|
|
45
|
-
const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, mediaVolume, mediaMuted, doubleClickToFullscreen, setMediaMuted, setMediaVolume, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, className, moveToBeginningWhenEnded, }, ref) => {
|
|
46
|
-
var _a, _b, _c;
|
|
45
|
+
const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, mediaVolume, mediaMuted, doubleClickToFullscreen, setMediaMuted, setMediaVolume, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, renderPoster, className, moveToBeginningWhenEnded, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, inFrame, outFrame, initiallyShowControls, }, ref) => {
|
|
46
|
+
var _a, _b, _c, _d, _e;
|
|
47
47
|
const config = remotion_1.Internals.useUnsafeVideoConfig();
|
|
48
48
|
const video = remotion_1.Internals.useVideo();
|
|
49
49
|
const container = (0, react_1.useRef)(null);
|
|
@@ -55,12 +55,13 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
55
55
|
const [hasPausedToResume, setHasPausedToResume] = (0, react_1.useState)(false);
|
|
56
56
|
const [shouldAutoplay, setShouldAutoPlay] = (0, react_1.useState)(autoPlay);
|
|
57
57
|
const [isFullscreen, setIsFullscreen] = (0, react_1.useState)(() => false);
|
|
58
|
+
const [seeking, setSeeking] = (0, react_1.useState)(false);
|
|
58
59
|
(0, use_playback_1.usePlayback)({
|
|
59
60
|
loop,
|
|
60
61
|
playbackRate,
|
|
61
62
|
moveToBeginningWhenEnded,
|
|
62
|
-
inFrame
|
|
63
|
-
outFrame
|
|
63
|
+
inFrame,
|
|
64
|
+
outFrame,
|
|
64
65
|
});
|
|
65
66
|
const player = (0, use_player_1.usePlayer)();
|
|
66
67
|
(0, react_1.useEffect)(() => {
|
|
@@ -146,6 +147,18 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
146
147
|
};
|
|
147
148
|
}, [player.emitter]);
|
|
148
149
|
const durationInFrames = (_a = config === null || config === void 0 ? void 0 : config.durationInFrames) !== null && _a !== void 0 ? _a : 1;
|
|
150
|
+
const layout = (0, react_1.useMemo)(() => {
|
|
151
|
+
if (!config || !canvasSize) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
return (0, calculate_scale_1.calculateCanvasTransformation)({
|
|
155
|
+
canvasSize,
|
|
156
|
+
compositionHeight: config.height,
|
|
157
|
+
compositionWidth: config.width,
|
|
158
|
+
previewSize: 'auto',
|
|
159
|
+
});
|
|
160
|
+
}, [canvasSize, config]);
|
|
161
|
+
const scale = (_b = layout === null || layout === void 0 ? void 0 : layout.scale) !== null && _b !== void 0 ? _b : 1;
|
|
149
162
|
(0, react_1.useImperativeHandle)(ref, () => {
|
|
150
163
|
const methods = {
|
|
151
164
|
play: player.play,
|
|
@@ -195,6 +208,7 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
195
208
|
unmute: () => {
|
|
196
209
|
setMediaMuted(false);
|
|
197
210
|
},
|
|
211
|
+
getScale: () => scale,
|
|
198
212
|
};
|
|
199
213
|
return Object.assign(player.emitter, methods);
|
|
200
214
|
}, [
|
|
@@ -209,6 +223,7 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
209
223
|
setMediaMuted,
|
|
210
224
|
setMediaVolume,
|
|
211
225
|
toggle,
|
|
226
|
+
scale,
|
|
212
227
|
]);
|
|
213
228
|
const VideoComponent = video ? video.component : null;
|
|
214
229
|
const outerStyle = (0, react_1.useMemo)(() => {
|
|
@@ -228,22 +243,11 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
228
243
|
...style,
|
|
229
244
|
};
|
|
230
245
|
}, [canvasSize, config, style]);
|
|
231
|
-
const layout = (0, react_1.useMemo)(() => {
|
|
232
|
-
if (!config || !canvasSize) {
|
|
233
|
-
return null;
|
|
234
|
-
}
|
|
235
|
-
return (0, calculate_scale_1.calculateScale)({
|
|
236
|
-
canvasSize,
|
|
237
|
-
compositionHeight: config.height,
|
|
238
|
-
compositionWidth: config.width,
|
|
239
|
-
previewSize: 'auto',
|
|
240
|
-
});
|
|
241
|
-
}, [canvasSize, config]);
|
|
242
246
|
const outer = (0, react_1.useMemo)(() => {
|
|
243
247
|
if (!layout || !config) {
|
|
244
248
|
return {};
|
|
245
249
|
}
|
|
246
|
-
const { centerX, centerY
|
|
250
|
+
const { centerX, centerY } = layout;
|
|
247
251
|
return {
|
|
248
252
|
width: config.width * scale,
|
|
249
253
|
height: config.height * scale,
|
|
@@ -254,28 +258,22 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
254
258
|
top: centerY,
|
|
255
259
|
overflow: 'hidden',
|
|
256
260
|
};
|
|
257
|
-
}, [config, layout]);
|
|
261
|
+
}, [config, layout, scale]);
|
|
258
262
|
const containerStyle = (0, react_1.useMemo)(() => {
|
|
259
|
-
if (!config || !canvasSize) {
|
|
263
|
+
if (!config || !canvasSize || !layout) {
|
|
260
264
|
return {};
|
|
261
265
|
}
|
|
262
|
-
const { scale, xCorrection, yCorrection } = (0, calculate_scale_1.calculateScale)({
|
|
263
|
-
canvasSize,
|
|
264
|
-
compositionHeight: config.height,
|
|
265
|
-
compositionWidth: config.width,
|
|
266
|
-
previewSize: 'auto',
|
|
267
|
-
});
|
|
268
266
|
return {
|
|
269
267
|
position: 'absolute',
|
|
270
268
|
width: config.width,
|
|
271
269
|
height: config.height,
|
|
272
270
|
display: 'flex',
|
|
273
271
|
transform: `scale(${scale})`,
|
|
274
|
-
marginLeft: xCorrection,
|
|
275
|
-
marginTop: yCorrection,
|
|
272
|
+
marginLeft: layout.xCorrection,
|
|
273
|
+
marginTop: layout.yCorrection,
|
|
276
274
|
overflow: 'hidden',
|
|
277
275
|
};
|
|
278
|
-
}, [canvasSize, config]);
|
|
276
|
+
}, [canvasSize, config, layout, scale]);
|
|
279
277
|
const onError = (0, react_1.useCallback)((error) => {
|
|
280
278
|
player.pause();
|
|
281
279
|
// Pay attention to `this context`
|
|
@@ -292,6 +290,12 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
292
290
|
const onSingleClick = (0, react_1.useCallback)((e) => {
|
|
293
291
|
toggle(e);
|
|
294
292
|
}, [toggle]);
|
|
293
|
+
const onSeekStart = (0, react_1.useCallback)(() => {
|
|
294
|
+
setSeeking(true);
|
|
295
|
+
}, []);
|
|
296
|
+
const onSeekEnd = (0, react_1.useCallback)(() => {
|
|
297
|
+
setSeeking(false);
|
|
298
|
+
}, []);
|
|
295
299
|
const onDoubleClick = (0, react_1.useCallback)(() => {
|
|
296
300
|
if (isFullscreen) {
|
|
297
301
|
exitFullscreen();
|
|
@@ -310,7 +314,22 @@ const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps
|
|
|
310
314
|
if (!config) {
|
|
311
315
|
return null;
|
|
312
316
|
}
|
|
313
|
-
const
|
|
317
|
+
const poster = renderPoster
|
|
318
|
+
? renderPoster({
|
|
319
|
+
height: outerStyle.height,
|
|
320
|
+
width: outerStyle.width,
|
|
321
|
+
})
|
|
322
|
+
: null;
|
|
323
|
+
if (poster === undefined) {
|
|
324
|
+
throw new TypeError('renderPoster() must return a React element, but undefined was returned');
|
|
325
|
+
}
|
|
326
|
+
const shouldShowPoster = poster &&
|
|
327
|
+
[
|
|
328
|
+
showPosterWhenPaused && !player.isPlaying() && !seeking,
|
|
329
|
+
showPosterWhenEnded && player.isLastFrame && !player.isPlaying(),
|
|
330
|
+
showPosterWhenUnplayed && !player.hasPlayed && !player.isPlaying(),
|
|
331
|
+
].some(Boolean);
|
|
332
|
+
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_1.PLAYER_CSS_CLASSNAME, children: VideoComponent ? ((0, jsx_runtime_1.jsx)(error_boundary_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_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 })) : null] }));
|
|
314
333
|
if (is_node_1.IS_NODE && !doesReactVersionSupportSuspense) {
|
|
315
334
|
return ((0, jsx_runtime_1.jsx)("div", { ref: container, style: outerStyle, className: className, children: content }));
|
|
316
335
|
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { PreviewSize } from './utils/preview-size';
|
|
2
2
|
import type { Size } from './utils/use-element-size';
|
|
3
|
-
export declare const calculateScale: ({
|
|
4
|
-
previewSize: PreviewSize;
|
|
3
|
+
export declare const calculateScale: ({ canvasSize, compositionHeight, compositionWidth, previewSize, }: {
|
|
4
|
+
previewSize: PreviewSize['size'];
|
|
5
|
+
compositionWidth: number;
|
|
6
|
+
compositionHeight: number;
|
|
7
|
+
canvasSize: Size;
|
|
8
|
+
}) => number;
|
|
9
|
+
export declare const calculateCanvasTransformation: ({ previewSize, compositionWidth, compositionHeight, canvasSize, }: {
|
|
10
|
+
previewSize: PreviewSize['size'];
|
|
5
11
|
compositionWidth: number;
|
|
6
12
|
compositionHeight: number;
|
|
7
13
|
canvasSize: Size;
|
package/dist/calculate-scale.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateScale = void 0;
|
|
4
|
-
const calculateScale = ({
|
|
3
|
+
exports.calculateCanvasTransformation = exports.calculateScale = void 0;
|
|
4
|
+
const calculateScale = ({ canvasSize, compositionHeight, compositionWidth, previewSize, }) => {
|
|
5
5
|
const heightRatio = canvasSize.height / compositionHeight;
|
|
6
6
|
const widthRatio = canvasSize.width / compositionWidth;
|
|
7
7
|
const ratio = Math.min(heightRatio, widthRatio);
|
|
8
|
-
|
|
8
|
+
return previewSize === 'auto' ? ratio : Number(previewSize);
|
|
9
|
+
};
|
|
10
|
+
exports.calculateScale = calculateScale;
|
|
11
|
+
const calculateCanvasTransformation = ({ previewSize, compositionWidth, compositionHeight, canvasSize, }) => {
|
|
12
|
+
const scale = (0, exports.calculateScale)({
|
|
13
|
+
canvasSize,
|
|
14
|
+
compositionHeight,
|
|
15
|
+
compositionWidth,
|
|
16
|
+
previewSize,
|
|
17
|
+
});
|
|
9
18
|
const correction = 0 - (1 - scale) / 2;
|
|
10
19
|
const xCorrection = correction * compositionWidth;
|
|
11
20
|
const yCorrection = correction * compositionHeight;
|
|
@@ -21,4 +30,4 @@ const calculateScale = ({ previewSize, compositionWidth, compositionHeight, canv
|
|
|
21
30
|
scale,
|
|
22
31
|
};
|
|
23
32
|
};
|
|
24
|
-
exports.
|
|
33
|
+
exports.calculateCanvasTransformation = calculateCanvasTransformation;
|
package/dist/event-emitter.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ declare type ErrorPayload = {
|
|
|
7
7
|
declare type TimeUpdateEventPayload = {
|
|
8
8
|
frame: number;
|
|
9
9
|
};
|
|
10
|
+
declare type FrameUpdateEventPayload = {
|
|
11
|
+
frame: number;
|
|
12
|
+
};
|
|
10
13
|
declare type RateChangeEventPayload = {
|
|
11
14
|
playbackRate: number;
|
|
12
15
|
};
|
|
@@ -21,6 +24,7 @@ declare type StateEventMap = {
|
|
|
21
24
|
ended: undefined;
|
|
22
25
|
error: ErrorPayload;
|
|
23
26
|
timeupdate: TimeUpdateEventPayload;
|
|
27
|
+
frameupdate: FrameUpdateEventPayload;
|
|
24
28
|
fullscreenchange: FullscreenChangeEventPayload;
|
|
25
29
|
};
|
|
26
30
|
export declare type EventTypes = keyof StateEventMap;
|
|
@@ -42,6 +46,7 @@ export declare class PlayerEmitter {
|
|
|
42
46
|
dispatchRatechange(playbackRate: number): void;
|
|
43
47
|
dispatchError(error: Error): void;
|
|
44
48
|
dispatchTimeUpdate(event: TimeUpdateEventPayload): void;
|
|
49
|
+
dispatchFrameUpdate(event: FrameUpdateEventPayload): void;
|
|
45
50
|
dispatchFullscreenChangeUpdate(event: FullscreenChangeEventPayload): void;
|
|
46
51
|
}
|
|
47
52
|
export {};
|
package/dist/event-emitter.js
CHANGED
|
@@ -11,6 +11,7 @@ class PlayerEmitter {
|
|
|
11
11
|
ratechange: [],
|
|
12
12
|
seeked: [],
|
|
13
13
|
timeupdate: [],
|
|
14
|
+
frameupdate: [],
|
|
14
15
|
fullscreenchange: [],
|
|
15
16
|
};
|
|
16
17
|
}
|
|
@@ -52,6 +53,9 @@ class PlayerEmitter {
|
|
|
52
53
|
dispatchTimeUpdate(event) {
|
|
53
54
|
this.dispatchEvent('timeupdate', event);
|
|
54
55
|
}
|
|
56
|
+
dispatchFrameUpdate(event) {
|
|
57
|
+
this.dispatchEvent('frameupdate', event);
|
|
58
|
+
}
|
|
55
59
|
dispatchFullscreenChangeUpdate(event) {
|
|
56
60
|
this.dispatchEvent('fullscreenchange', event);
|
|
57
61
|
}
|
package/dist/icons.d.ts
CHANGED
package/dist/icons.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VolumeOnIcon = exports.VolumeOffIcon = exports.FullscreenIcon = exports.PauseIcon = exports.PlayIcon = exports.ICON_SIZE = void 0;
|
|
3
|
+
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;
|
|
7
7
|
const rotate = {
|
|
8
8
|
transform: `rotate(90deg)`,
|
|
9
9
|
};
|
|
@@ -21,7 +21,7 @@ const FullscreenIcon = ({ minimized }) => {
|
|
|
21
21
|
const out = minimized ? strokeWidth / 2 : 0;
|
|
22
22
|
const middleInset = minimized ? strokeWidth / 2 : strokeWidth * 1.6;
|
|
23
23
|
const inset = minimized ? strokeWidth * 2 : strokeWidth * 1.6;
|
|
24
|
-
return ((0, jsx_runtime_1.jsxs)("svg", { viewBox: `0 0 ${viewSize} ${viewSize}`, height: fullscreenIconSize, width: fullscreenIconSize, children: [(0, jsx_runtime_1.jsx)("path", { d: `
|
|
24
|
+
return ((0, jsx_runtime_1.jsxs)("svg", { viewBox: `0 0 ${viewSize} ${viewSize}`, height: exports.fullscreenIconSize, width: exports.fullscreenIconSize, children: [(0, jsx_runtime_1.jsx)("path", { d: `
|
|
25
25
|
M ${out} ${inset}
|
|
26
26
|
L ${middleInset} ${middleInset}
|
|
27
27
|
L ${inset} ${out}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { CallbackListener, EventTypes } from './event-emitter';
|
|
3
3
|
import { PlayerEmitter } from './event-emitter';
|
|
4
|
-
export { ErrorFallback, Player } from './Player';
|
|
4
|
+
export { ErrorFallback, Player, PlayerProps } from './Player';
|
|
5
5
|
export { PlayerMethods, PlayerRef } from './player-methods';
|
|
6
|
-
export type { RenderLoading } from './PlayerUI';
|
|
7
|
-
export { PreviewSize } from './utils/preview-size';
|
|
6
|
+
export type { RenderLoading, RenderPoster } from './PlayerUI';
|
|
7
|
+
export { PreviewSize, Translation } from './utils/preview-size';
|
|
8
8
|
export { Size } from './utils/use-element-size';
|
|
9
9
|
export type { CallbackListener, EventTypes };
|
|
10
10
|
export declare const PlayerInternals: {
|
|
@@ -14,6 +14,7 @@ export declare const PlayerInternals: {
|
|
|
14
14
|
frameBack: (frames: number) => void;
|
|
15
15
|
frameForward: (frames: number) => void;
|
|
16
16
|
isLastFrame: boolean;
|
|
17
|
+
isFirstFrame: boolean;
|
|
17
18
|
emitter: PlayerEmitter;
|
|
18
19
|
playing: boolean;
|
|
19
20
|
play: (e?: import("react").SyntheticEvent<Element, Event> | undefined) => void;
|
|
@@ -22,6 +23,7 @@ export declare const PlayerInternals: {
|
|
|
22
23
|
seek: (newFrame: number) => void;
|
|
23
24
|
getCurrentFrame: () => number;
|
|
24
25
|
isPlaying: () => boolean;
|
|
26
|
+
hasPlayed: boolean;
|
|
25
27
|
};
|
|
26
28
|
usePlayback: ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, outFrame, }: {
|
|
27
29
|
loop: boolean;
|
|
@@ -34,8 +36,8 @@ export declare const PlayerInternals: {
|
|
|
34
36
|
triggerOnWindowResize: boolean;
|
|
35
37
|
shouldApplyCssTransforms: boolean;
|
|
36
38
|
}) => import("./utils/use-element-size").Size | null;
|
|
37
|
-
|
|
38
|
-
previewSize:
|
|
39
|
+
calculateCanvasTransformation: ({ previewSize, compositionWidth, compositionHeight, canvasSize, }: {
|
|
40
|
+
previewSize: number | "auto";
|
|
39
41
|
compositionWidth: number;
|
|
40
42
|
compositionHeight: number;
|
|
41
43
|
canvasSize: import("./utils/use-element-size").Size;
|
|
@@ -48,4 +50,10 @@ export declare const PlayerInternals: {
|
|
|
48
50
|
};
|
|
49
51
|
useHoverState: (ref: import("react").RefObject<HTMLDivElement>) => boolean;
|
|
50
52
|
updateAllElementsSizes: () => void;
|
|
53
|
+
calculateScale: ({ canvasSize, compositionHeight, compositionWidth, previewSize, }: {
|
|
54
|
+
previewSize: number | "auto";
|
|
55
|
+
compositionWidth: number;
|
|
56
|
+
compositionHeight: number;
|
|
57
|
+
canvasSize: import("./utils/use-element-size").Size;
|
|
58
|
+
}) => number;
|
|
51
59
|
};
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,8 @@ exports.PlayerInternals = {
|
|
|
16
16
|
usePlayer: use_player_1.usePlayer,
|
|
17
17
|
usePlayback: use_playback_1.usePlayback,
|
|
18
18
|
useElementSize: use_element_size_1.useElementSize,
|
|
19
|
-
|
|
19
|
+
calculateCanvasTransformation: calculate_scale_1.calculateCanvasTransformation,
|
|
20
20
|
useHoverState: use_hover_state_1.useHoverState,
|
|
21
21
|
updateAllElementsSizes: use_element_size_1.updateAllElementsSizes,
|
|
22
|
+
calculateScale: calculate_scale_1.calculateScale,
|
|
22
23
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.PLAYER_CSS_CLASSNAME = void 0;
|
|
4
4
|
exports.PLAYER_CSS_CLASSNAME = '__remotion-player';
|
|
5
|
-
exports.VOLUME_SLIDER_INPUT_CSS_CLASSNAME = exports.PLAYER_CSS_CLASSNAME.concat('_volume-slider-input');
|
package/dist/player-methods.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const validate_in_out_frame_1 = require("../utils/validate-in-out-frame");
|
|
4
|
+
test('Validate in out frames', () => {
|
|
5
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
6
|
+
durationInFrames: 200,
|
|
7
|
+
inFrame: 201,
|
|
8
|
+
outFrame: undefined,
|
|
9
|
+
})).toThrow(/inFrame must be less than \(durationInFrames - 1\)/);
|
|
10
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
11
|
+
durationInFrames: 200,
|
|
12
|
+
inFrame: 199,
|
|
13
|
+
outFrame: 201,
|
|
14
|
+
})).toThrow(/outFrame must be less than \(durationInFrames - 1\)/);
|
|
15
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
16
|
+
durationInFrames: 200,
|
|
17
|
+
inFrame: -10,
|
|
18
|
+
outFrame: null,
|
|
19
|
+
})).toThrow(/inFrame must be greater than 0, but is -10/);
|
|
20
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
21
|
+
durationInFrames: 200,
|
|
22
|
+
inFrame: null,
|
|
23
|
+
outFrame: -10,
|
|
24
|
+
})).toThrow(/outFrame must be greater than 0, but is -10/);
|
|
25
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
26
|
+
durationInFrames: 200,
|
|
27
|
+
inFrame: 1.5,
|
|
28
|
+
outFrame: null,
|
|
29
|
+
})).toThrow(/"inFrame" must be an integer, but is 1.5/);
|
|
30
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
31
|
+
durationInFrames: 200,
|
|
32
|
+
inFrame: 20,
|
|
33
|
+
outFrame: 20,
|
|
34
|
+
})).toThrow(/outFrame must be greater than inFrame, but is 20/);
|
|
35
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
36
|
+
durationInFrames: 200,
|
|
37
|
+
inFrame: 21,
|
|
38
|
+
outFrame: 20,
|
|
39
|
+
})).toThrow(/outFrame must be greater than inFrame, but is 20 <= 21/);
|
|
40
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
41
|
+
durationInFrames: 200,
|
|
42
|
+
inFrame: null,
|
|
43
|
+
outFrame: 20,
|
|
44
|
+
})).not.toThrow();
|
|
45
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
46
|
+
durationInFrames: 200,
|
|
47
|
+
inFrame: null,
|
|
48
|
+
outFrame: null,
|
|
49
|
+
})).not.toThrow();
|
|
50
|
+
expect(() => (0, validate_in_out_frame_1.validateInOutFrames)({
|
|
51
|
+
durationInFrames: 200,
|
|
52
|
+
inFrame: 10,
|
|
53
|
+
outFrame: 20,
|
|
54
|
+
})).not.toThrow();
|
|
55
|
+
});
|
|
@@ -51,7 +51,7 @@ test('No durationInFrames should give errors', () => {
|
|
|
51
51
|
durationInFrames: undefined, component: test_utils_1.HelloWorld, controls: true, showVolumeControls: true }));
|
|
52
52
|
}
|
|
53
53
|
catch (e) {
|
|
54
|
-
expect(e.message).toMatch(/
|
|
54
|
+
expect(e.message).toMatch(/durationInFrames` must be a number, but is undefined/);
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
test('Invalid playbackRate should give error', () => {
|
package/dist/use-playback.js
CHANGED
|
@@ -85,5 +85,8 @@ const usePlayback = ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, ou
|
|
|
85
85
|
}, 250);
|
|
86
86
|
return () => clearInterval(interval);
|
|
87
87
|
}, [emitter]);
|
|
88
|
+
(0, react_1.useEffect)(() => {
|
|
89
|
+
emitter.dispatchFrameUpdate({ frame });
|
|
90
|
+
}, [emitter, frame]);
|
|
88
91
|
};
|
|
89
92
|
exports.usePlayback = usePlayback;
|
package/dist/use-player.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ declare type UsePlayerMethods = {
|
|
|
4
4
|
frameBack: (frames: number) => void;
|
|
5
5
|
frameForward: (frames: number) => void;
|
|
6
6
|
isLastFrame: boolean;
|
|
7
|
+
isFirstFrame: boolean;
|
|
7
8
|
emitter: PlayerEmitter;
|
|
8
9
|
playing: boolean;
|
|
9
10
|
play: (e?: SyntheticEvent) => void;
|
|
@@ -12,6 +13,7 @@ declare type UsePlayerMethods = {
|
|
|
12
13
|
seek: (newFrame: number) => void;
|
|
13
14
|
getCurrentFrame: () => number;
|
|
14
15
|
isPlaying: () => boolean;
|
|
16
|
+
hasPlayed: boolean;
|
|
15
17
|
};
|
|
16
18
|
export declare const usePlayer: () => UsePlayerMethods;
|
|
17
19
|
export {};
|
package/dist/use-player.js
CHANGED
|
@@ -7,8 +7,9 @@ const emitter_context_1 = require("./emitter-context");
|
|
|
7
7
|
const usePlayer = () => {
|
|
8
8
|
var _a;
|
|
9
9
|
const [playing, setPlaying, imperativePlaying] = remotion_1.Internals.Timeline.usePlayingState();
|
|
10
|
+
const [hasPlayed, setHasPlayed] = (0, react_1.useState)(false);
|
|
10
11
|
const frame = remotion_1.Internals.Timeline.useTimelinePosition();
|
|
11
|
-
const playStart = (0, react_1.useRef)(
|
|
12
|
+
const playStart = (0, react_1.useRef)(frame);
|
|
12
13
|
const setFrame = remotion_1.Internals.Timeline.useTimelineSetFrame();
|
|
13
14
|
const setTimelinePosition = remotion_1.Internals.Timeline.useTimelineSetFrame();
|
|
14
15
|
const audioContext = (0, react_1.useContext)(remotion_1.Internals.SharedAudioContext);
|
|
@@ -20,6 +21,7 @@ const usePlayer = () => {
|
|
|
20
21
|
const emitter = (0, react_1.useContext)(emitter_context_1.PlayerEventEmitterContext);
|
|
21
22
|
const lastFrame = ((_a = config === null || config === void 0 ? void 0 : config.durationInFrames) !== null && _a !== void 0 ? _a : 1) - 1;
|
|
22
23
|
const isLastFrame = frame === lastFrame;
|
|
24
|
+
const isFirstFrame = frame === 0;
|
|
23
25
|
if (!emitter) {
|
|
24
26
|
throw new TypeError('Expected Player event emitter context');
|
|
25
27
|
}
|
|
@@ -31,6 +33,7 @@ const usePlayer = () => {
|
|
|
31
33
|
if (imperativePlaying.current) {
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
36
|
+
setHasPlayed(true);
|
|
34
37
|
if (isLastFrame) {
|
|
35
38
|
seek(0);
|
|
36
39
|
}
|
|
@@ -104,21 +107,25 @@ const usePlayer = () => {
|
|
|
104
107
|
play,
|
|
105
108
|
pause,
|
|
106
109
|
seek,
|
|
110
|
+
isFirstFrame,
|
|
107
111
|
getCurrentFrame: () => frameRef.current,
|
|
108
112
|
isPlaying: () => imperativePlaying.current,
|
|
109
113
|
pauseAndReturnToPlayStart,
|
|
114
|
+
hasPlayed,
|
|
110
115
|
};
|
|
111
116
|
}, [
|
|
112
|
-
emitter,
|
|
113
117
|
frameBack,
|
|
114
118
|
frameForward,
|
|
115
|
-
imperativePlaying,
|
|
116
119
|
isLastFrame,
|
|
117
|
-
|
|
118
|
-
play,
|
|
120
|
+
emitter,
|
|
119
121
|
playing,
|
|
120
|
-
|
|
122
|
+
play,
|
|
123
|
+
pause,
|
|
121
124
|
seek,
|
|
125
|
+
isFirstFrame,
|
|
126
|
+
pauseAndReturnToPlayStart,
|
|
127
|
+
imperativePlaying,
|
|
128
|
+
hasPlayed,
|
|
122
129
|
]);
|
|
123
130
|
return returnValue;
|
|
124
131
|
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useVideoControlsResize = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const icons_1 = require("./icons");
|
|
6
|
+
const MediaVolumeSlider_1 = require("./MediaVolumeSlider");
|
|
7
|
+
const PlayerControls_1 = require("./PlayerControls");
|
|
8
|
+
const useVideoControlsResize = ({ allowFullscreen: allowFullScreen, playerWidth, }) => {
|
|
9
|
+
const resizeInfo = (0, react_1.useMemo)(() => {
|
|
10
|
+
const playPauseIconSize = icons_1.ICON_SIZE;
|
|
11
|
+
const volumeIconSize = icons_1.ICON_SIZE;
|
|
12
|
+
const _fullscreenIconSize = allowFullScreen ? icons_1.fullscreenIconSize : 0;
|
|
13
|
+
const elementsSize = volumeIconSize +
|
|
14
|
+
playPauseIconSize +
|
|
15
|
+
_fullscreenIconSize +
|
|
16
|
+
PlayerControls_1.X_PADDING * 2 +
|
|
17
|
+
PlayerControls_1.X_SPACER * 2;
|
|
18
|
+
const maxTimeLabelWidth = playerWidth - elementsSize;
|
|
19
|
+
const maxTimeLabelWidthWithoutNegativeValue = Math.max(maxTimeLabelWidth, 0);
|
|
20
|
+
const availableTimeLabelWidthIfVolumeOpen = maxTimeLabelWidthWithoutNegativeValue - MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH;
|
|
21
|
+
// If max label width is lower than the volume width
|
|
22
|
+
// then it means we need to take it's width as the max label width
|
|
23
|
+
// otherwise we took the available width when volume open
|
|
24
|
+
const computedLabelWidth = availableTimeLabelWidthIfVolumeOpen < MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH
|
|
25
|
+
? maxTimeLabelWidthWithoutNegativeValue
|
|
26
|
+
: availableTimeLabelWidthIfVolumeOpen;
|
|
27
|
+
const minWidthForHorizontalDisplay = computedLabelWidth + elementsSize + MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH;
|
|
28
|
+
const displayVerticalVolumeSlider = playerWidth < minWidthForHorizontalDisplay;
|
|
29
|
+
return {
|
|
30
|
+
maxTimeLabelWidth: maxTimeLabelWidthWithoutNegativeValue,
|
|
31
|
+
displayVerticalVolumeSlider,
|
|
32
|
+
};
|
|
33
|
+
}, [allowFullScreen, playerWidth]);
|
|
34
|
+
return resizeInfo;
|
|
35
|
+
};
|
|
36
|
+
exports.useVideoControlsResize = useVideoControlsResize;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const validateSingleFrameFrame: (frame: unknown, variableName: string) => number | null;
|
|
2
|
+
export declare const validateInOutFrames: ({ inFrame, durationInFrames, outFrame, }: {
|
|
3
|
+
inFrame: unknown;
|
|
4
|
+
outFrame: unknown;
|
|
5
|
+
durationInFrames: number;
|
|
6
|
+
}) => void;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateInOutFrames = exports.validateSingleFrameFrame = void 0;
|
|
4
|
+
const validateSingleFrameFrame = (frame, variableName) => {
|
|
5
|
+
if (typeof frame === 'undefined' || frame === null) {
|
|
6
|
+
return frame !== null && frame !== void 0 ? frame : null;
|
|
7
|
+
}
|
|
8
|
+
if (typeof frame !== 'number') {
|
|
9
|
+
throw new TypeError(`"${variableName}" must be a number, but is ${JSON.stringify(frame)}`);
|
|
10
|
+
}
|
|
11
|
+
if (Number.isNaN(frame)) {
|
|
12
|
+
throw new TypeError(`"${variableName}" must not be NaN, but is ${JSON.stringify(frame)}`);
|
|
13
|
+
}
|
|
14
|
+
if (!Number.isFinite(frame)) {
|
|
15
|
+
throw new TypeError(`"${variableName}" must be finite, but is ${JSON.stringify(frame)}`);
|
|
16
|
+
}
|
|
17
|
+
if (frame % 1 !== 0) {
|
|
18
|
+
throw new TypeError(`"${variableName}" must be an integer, but is ${JSON.stringify(frame)}`);
|
|
19
|
+
}
|
|
20
|
+
return frame;
|
|
21
|
+
};
|
|
22
|
+
exports.validateSingleFrameFrame = validateSingleFrameFrame;
|
|
23
|
+
const validateInOutFrames = ({ inFrame, durationInFrames, outFrame, }) => {
|
|
24
|
+
const validatedInFrame = (0, exports.validateSingleFrameFrame)(inFrame, 'inFrame');
|
|
25
|
+
const validateOutFrame = (0, exports.validateSingleFrameFrame)(outFrame, 'outFrame');
|
|
26
|
+
if (validatedInFrame === null && validateOutFrame === null) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// Must not be over the duration
|
|
30
|
+
if (validatedInFrame !== null && validatedInFrame > durationInFrames - 1) {
|
|
31
|
+
throw new Error('inFrame must be less than (durationInFrames - 1), but is ' +
|
|
32
|
+
validatedInFrame);
|
|
33
|
+
}
|
|
34
|
+
if (validateOutFrame !== null && validateOutFrame > durationInFrames - 1) {
|
|
35
|
+
throw new Error('outFrame must be less than (durationInFrames - 1), but is ' +
|
|
36
|
+
validatedInFrame);
|
|
37
|
+
}
|
|
38
|
+
// Must not be under 0
|
|
39
|
+
if (validatedInFrame !== null && validatedInFrame < 0) {
|
|
40
|
+
throw new Error('inFrame must be greater than 0, but is ' + validatedInFrame);
|
|
41
|
+
}
|
|
42
|
+
if (validateOutFrame !== null && validateOutFrame < 0) {
|
|
43
|
+
throw new Error('outFrame must be greater than 0, but is ' + validateOutFrame);
|
|
44
|
+
}
|
|
45
|
+
if (validateOutFrame !== null &&
|
|
46
|
+
validatedInFrame !== null &&
|
|
47
|
+
validateOutFrame <= validatedInFrame) {
|
|
48
|
+
throw new Error('outFrame must be greater than inFrame, but is ' +
|
|
49
|
+
validateOutFrame +
|
|
50
|
+
' <= ' +
|
|
51
|
+
validatedInFrame);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
exports.validateInOutFrames = validateInOutFrames;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateInitialFrame = void 0;
|
|
4
|
+
const validateInitialFrame = ({ initialFrame, durationInFrames, }) => {
|
|
5
|
+
if (typeof durationInFrames !== 'number') {
|
|
6
|
+
throw new Error(`\`durationInFrames\` must be a number, but is ${JSON.stringify(durationInFrames)}`);
|
|
7
|
+
}
|
|
8
|
+
if (typeof initialFrame === 'undefined') {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (typeof initialFrame !== 'number') {
|
|
12
|
+
throw new Error(`\`initialFrame\` must be a number, but is ${JSON.stringify(initialFrame)}`);
|
|
13
|
+
}
|
|
14
|
+
if (Number.isNaN(initialFrame)) {
|
|
15
|
+
throw new Error(`\`initialFrame\` must be a number, but is NaN`);
|
|
16
|
+
}
|
|
17
|
+
if (!Number.isFinite(initialFrame)) {
|
|
18
|
+
throw new Error(`\`initialFrame\` must be a number, but is Infinity`);
|
|
19
|
+
}
|
|
20
|
+
if (initialFrame % 1 !== 0) {
|
|
21
|
+
throw new Error(`\`initialFrame\` must be an integer, but is ${JSON.stringify(initialFrame)}`);
|
|
22
|
+
}
|
|
23
|
+
if (initialFrame > durationInFrames - 1) {
|
|
24
|
+
throw new Error(`\`initialFrame\` must be less or equal than \`durationInFrames - 1\`, but is ${JSON.stringify(initialFrame)}`);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.validateInitialFrame = validateInitialFrame;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/player",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-webhook.26+c8e41db11",
|
|
4
4
|
"description": "Remotion Player",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
],
|
|
29
29
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"remotion": "4.0.0-
|
|
31
|
+
"remotion": "4.0.0-webhook.26+c8e41db11"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"react": ">=16.8.0",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"react-dom": "^18.0.0",
|
|
51
51
|
"ts-jest": "^27.0.5",
|
|
52
52
|
"typescript": "^4.7.0",
|
|
53
|
-
"webpack": "5.
|
|
53
|
+
"webpack": "5.74.0"
|
|
54
54
|
},
|
|
55
55
|
"keywords": [
|
|
56
56
|
"remotion",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"publishConfig": {
|
|
64
64
|
"access": "public"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "c8e41db114d645c5183edbf016a22b733243dce2"
|
|
67
67
|
}
|