Add .gitignore to exclude all node packages and lock files

This commit is contained in:
Adolfo Reyna
2026-02-23 21:56:04 -05:00
parent faae96c9ed
commit dcc5c6c044
9747 changed files with 1555105 additions and 2 deletions
@@ -0,0 +1,5 @@
import React from 'react';
export declare const bufferingIndicatorStrokeWidth = 3;
export declare const BufferingIndicator: React.FC<{
readonly type: 'player' | 'studio';
}>;
@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BufferingIndicator = exports.bufferingIndicatorStrokeWidth = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const icons_js_1 = require("./icons.js");
const className = '__remotion_buffering_indicator';
const remotionBufferingAnimation = '__remotion_buffering_animation';
exports.bufferingIndicatorStrokeWidth = 3;
const playerStyle = {
width: icons_js_1.ICON_SIZE,
height: icons_js_1.ICON_SIZE,
overflow: 'hidden',
lineHeight: 'normal',
fontSize: 'inherit',
};
const studioStyle = {
width: 14,
height: 14,
overflow: 'hidden',
lineHeight: 'normal',
fontSize: 'inherit',
};
const BufferingIndicator = ({ type }) => {
const style = type === 'player' ? playerStyle : studioStyle;
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("style", { type: "text/css", children: `
@keyframes ${remotionBufferingAnimation} {
0% {
rotate: 0deg;
}
100% {
rotate: 360deg;
}
}
.${className} {
animation: ${remotionBufferingAnimation} 1s linear infinite;
}
` }), (0, jsx_runtime_1.jsx)("div", { style: style, children: (0, jsx_runtime_1.jsx)("svg", { viewBox: type === 'player' ? '0 0 22 22' : '0 0 18 18', style: style, className: className, children: (0, jsx_runtime_1.jsx)("path", { d: type === 'player'
? 'M 11 4 A 7 7 0 0 1 15.1145 16.66312'
: 'M 9 2 A 7 7 0 0 1 13.1145 14.66312', stroke: "white", strokeLinecap: "round", fill: "none", strokeWidth: 3 }) }) })] }));
};
exports.BufferingIndicator = BufferingIndicator;
@@ -0,0 +1,4 @@
export declare const DefaultPlayPauseButton: React.FC<{
playing: boolean;
buffering: boolean;
}>;
@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DefaultPlayPauseButton = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const BufferingIndicator_js_1 = require("./BufferingIndicator.js");
const icons_js_1 = require("./icons.js");
const DefaultPlayPauseButton = ({ playing, buffering }) => {
if (playing && buffering) {
return (0, jsx_runtime_1.jsx)(BufferingIndicator_js_1.BufferingIndicator, { type: "player" });
}
if (playing) {
return (0, jsx_runtime_1.jsx)(icons_js_1.PauseIcon, {});
}
return (0, jsx_runtime_1.jsx)(icons_js_1.PlayIcon, {});
};
exports.DefaultPlayPauseButton = DefaultPlayPauseButton;
@@ -0,0 +1,5 @@
import React from 'react';
export declare const PlayerEmitterProvider: React.FC<{
readonly children: React.ReactNode;
readonly currentPlaybackRate: number | null;
}>;
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlayerEmitterProvider = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const emitter_context_js_1 = require("./emitter-context.js");
const event_emitter_js_1 = require("./event-emitter.js");
const use_buffer_state_emitter_js_1 = require("./use-buffer-state-emitter.js");
const PlayerEmitterProvider = ({ children, currentPlaybackRate }) => {
const [emitter] = (0, react_1.useState)(() => new event_emitter_js_1.PlayerEmitter());
const bufferManager = (0, react_1.useContext)(remotion_1.Internals.BufferingContextReact);
if (!bufferManager) {
throw new Error('BufferingContextReact not found');
}
(0, react_1.useEffect)(() => {
if (currentPlaybackRate) {
emitter.dispatchRateChange(currentPlaybackRate);
}
}, [emitter, currentPlaybackRate]);
(0, use_buffer_state_emitter_js_1.useBufferStateEmitter)(emitter);
return ((0, jsx_runtime_1.jsx)(emitter_context_js_1.PlayerEventEmitterContext.Provider, { value: emitter, children: children }));
};
exports.PlayerEmitterProvider = PlayerEmitterProvider;
@@ -0,0 +1,12 @@
import React from 'react';
import type { RenderVolumeSlider } from './render-volume-slider.js';
export declare const VOLUME_SLIDER_WIDTH = 100;
export type RenderMuteButton = (props: {
muted: boolean;
volume: number;
}) => React.ReactNode;
export declare const MediaVolumeSlider: React.FC<{
readonly displayVerticalVolumeSlider: boolean;
readonly renderMuteButton: RenderMuteButton | null;
readonly renderVolumeSlider: RenderVolumeSlider | null;
}>;
@@ -0,0 +1,89 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MediaVolumeSlider = exports.VOLUME_SLIDER_WIDTH = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const icons_js_1 = require("./icons.js");
const render_volume_slider_js_1 = require("./render-volume-slider.js");
const use_hover_state_js_1 = require("./use-hover-state.js");
exports.VOLUME_SLIDER_WIDTH = 100;
const MediaVolumeSlider = ({ displayVerticalVolumeSlider, renderMuteButton, renderVolumeSlider }) => {
const [mediaMuted, setMediaMuted] = remotion_1.Internals.useMediaMutedState();
const [mediaVolume, setMediaVolume] = remotion_1.Internals.useMediaVolumeState();
const [focused, setFocused] = (0, react_1.useState)(false);
const parentDivRef = (0, react_1.useRef)(null);
const inputRef = (0, react_1.useRef)(null);
const hover = (0, use_hover_state_js_1.useHoverState)(parentDivRef, false);
const onBlur = (0, react_1.useCallback)(() => {
setTimeout(() => {
// We need a small delay to check which element was focused next,
// and if it wasn't the volume slider, we hide it
if (inputRef.current && document.activeElement !== inputRef.current) {
setFocused(false);
}
}, 10);
}, []);
const isVolume0 = mediaVolume === 0;
const onClick = (0, react_1.useCallback)(() => {
if (isVolume0) {
setMediaVolume(1);
setMediaMuted(false);
return;
}
setMediaMuted((mute) => !mute);
}, [isVolume0, setMediaMuted, setMediaVolume]);
const parentDivStyle = (0, react_1.useMemo)(() => {
return {
display: 'inline-flex',
background: 'none',
border: 'none',
justifyContent: 'center',
alignItems: 'center',
touchAction: 'none',
...(displayVerticalVolumeSlider && { position: 'relative' }),
};
}, [displayVerticalVolumeSlider]);
const volumeContainer = (0, react_1.useMemo)(() => {
return {
display: 'inline',
width: icons_js_1.ICON_SIZE,
height: icons_js_1.ICON_SIZE,
cursor: 'pointer',
appearance: 'none',
background: 'none',
border: 'none',
padding: 0,
};
}, []);
const renderDefaultMuteButton = (0, react_1.useCallback)(({ muted, volume }) => {
const isMutedOrZero = muted || volume === 0;
return ((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_js_1.VolumeOffIcon, {}) : (0, jsx_runtime_1.jsx)(icons_js_1.VolumeOnIcon, {}) }));
}, [onBlur, onClick, volumeContainer]);
const muteButton = (0, react_1.useMemo)(() => {
return renderMuteButton
? renderMuteButton({ muted: mediaMuted, volume: mediaVolume })
: renderDefaultMuteButton({ muted: mediaMuted, volume: mediaVolume });
}, [mediaMuted, mediaVolume, renderDefaultMuteButton, renderMuteButton]);
const volumeSlider = (0, react_1.useMemo)(() => {
return (focused || hover) && !mediaMuted && !remotion_1.Internals.isIosSafari()
? (renderVolumeSlider !== null && renderVolumeSlider !== void 0 ? renderVolumeSlider : render_volume_slider_js_1.renderDefaultVolumeSlider)({
isVertical: displayVerticalVolumeSlider,
volume: mediaVolume,
onBlur: () => setFocused(false),
inputRef,
setVolume: setMediaVolume,
})
: null;
}, [
displayVerticalVolumeSlider,
focused,
hover,
mediaMuted,
mediaVolume,
renderVolumeSlider,
setMediaVolume,
]);
return ((0, jsx_runtime_1.jsxs)("div", { ref: parentDivRef, style: parentDivStyle, children: [muteButton, volumeSlider] }));
};
exports.MediaVolumeSlider = MediaVolumeSlider;
@@ -0,0 +1,8 @@
import React from 'react';
import type { Size } from './utils/use-element-size.js';
export declare const Checkmark: () => import("react/jsx-runtime.js").JSX.Element;
export declare const playerButtonStyle: React.CSSProperties;
export declare const PlaybackrateControl: React.FC<{
readonly playbackRates: number[];
readonly canvasSize: Size;
}>;
@@ -0,0 +1,169 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlaybackrateControl = exports.playerButtonStyle = exports.Checkmark = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const use_component_visible_js_1 = __importDefault(require("./utils/use-component-visible.js"));
// To align
const BOTTOM = 35;
// Arbitrary to clamp the height of the popup
const THRESHOLD = 70;
const rateDiv = {
height: 30,
paddingRight: 15,
paddingLeft: 12,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
};
const checkmarkContainer = {
width: 22,
display: 'flex',
alignItems: 'center',
};
const checkmarkStyle = {
width: 14,
height: 14,
color: 'black',
};
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" }) }));
exports.Checkmark = Checkmark;
const formatPlaybackRate = (rate) => {
const str = rate.toString();
// If the string doesn't contain a decimal point, add ".0"
return str.includes('.') ? str : str + '.0';
};
const PlaybackrateOption = ({ rate, onSelect, selectedRate, keyboardSelectedRate }) => {
const onClick = (0, react_1.useCallback)((e) => {
e.stopPropagation();
e.preventDefault();
onSelect(rate);
}, [onSelect, rate]);
const [hovered, setHovered] = (0, react_1.useState)(false);
const onMouseEnter = (0, react_1.useCallback)(() => {
setHovered(true);
}, []);
const onMouseLeave = (0, react_1.useCallback)(() => {
setHovered(false);
}, []);
const isFocused = keyboardSelectedRate === rate;
const actualStyle = (0, react_1.useMemo)(() => {
return {
...rateDiv,
backgroundColor: hovered || isFocused ? '#eee' : 'transparent',
};
}, [hovered, isFocused]);
return ((0, jsx_runtime_1.jsxs)("div", { onPointerEnter: onMouseEnter, onPointerLeave: 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 }), formatPlaybackRate(rate), "x"] }, rate));
};
const PlaybackPopup = ({ setIsComponentVisible, playbackRates, canvasSize }) => {
const { setPlaybackRate, playbackRate } = (0, react_1.useContext)(remotion_1.Internals.TimelineContext);
const [keyboardSelectedRate, setKeyboardSelectedRate] = (0, react_1.useState)(playbackRate);
(0, react_1.useEffect)(() => {
const listener = (e) => {
e.preventDefault();
if (e.key === 'ArrowUp') {
const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
if (currentIndex === 0) {
return;
}
if (currentIndex === -1) {
setKeyboardSelectedRate(playbackRates[0]);
}
else {
setKeyboardSelectedRate(playbackRates[currentIndex - 1]);
}
}
else if (e.key === 'ArrowDown') {
const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
if (currentIndex === playbackRates.length - 1) {
return;
}
if (currentIndex === -1) {
setKeyboardSelectedRate(playbackRates[playbackRates.length - 1]);
}
else {
setKeyboardSelectedRate(playbackRates[currentIndex + 1]);
}
}
else if (e.key === 'Enter') {
setPlaybackRate(keyboardSelectedRate);
setIsComponentVisible(false);
}
};
window.addEventListener('keydown', listener);
return () => {
window.removeEventListener('keydown', listener);
};
}, [
playbackRates,
keyboardSelectedRate,
setPlaybackRate,
setIsComponentVisible,
]);
const onSelect = (0, react_1.useCallback)((rate) => {
setPlaybackRate(rate);
setIsComponentVisible(false);
}, [setIsComponentVisible, setPlaybackRate]);
const playbackPopup = (0, react_1.useMemo)(() => {
return {
position: 'absolute',
right: 0,
width: 125,
maxHeight: canvasSize.height - THRESHOLD - BOTTOM,
bottom: 35,
background: '#fff',
borderRadius: 4,
overflow: 'auto',
color: 'black',
textAlign: 'left',
};
}, [canvasSize.height]);
return ((0, jsx_runtime_1.jsx)("div", { style: playbackPopup, children: playbackRates.map((rate) => {
return ((0, jsx_runtime_1.jsx)(PlaybackrateOption, { selectedRate: playbackRate, onSelect: onSelect, rate: rate, keyboardSelectedRate: keyboardSelectedRate }, rate));
}) }));
};
const label = {
fontSize: 13,
fontWeight: 'bold',
color: 'white',
border: '2px solid white',
borderRadius: 20,
paddingLeft: 8,
paddingRight: 8,
paddingTop: 2,
paddingBottom: 2,
};
exports.playerButtonStyle = {
appearance: 'none',
backgroundColor: 'transparent',
border: 'none',
cursor: 'pointer',
paddingLeft: 0,
paddingRight: 0,
paddingTop: 6,
paddingBottom: 6,
height: 37,
display: 'inline-flex',
marginBottom: 0,
marginTop: 0,
alignItems: 'center',
};
const button = {
...exports.playerButtonStyle,
position: 'relative',
};
const PlaybackrateControl = ({ playbackRates, canvasSize }) => {
const { ref, isComponentVisible, setIsComponentVisible } = (0, use_component_visible_js_1.default)(false);
const { playbackRate } = (0, react_1.useContext)(remotion_1.Internals.TimelineContext);
const onClick = (0, react_1.useCallback)((e) => {
e.stopPropagation();
e.preventDefault();
setIsComponentVisible((prevIsComponentVisible) => !prevIsComponentVisible);
}, [setIsComponentVisible]);
return ((0, jsx_runtime_1.jsx)("div", { ref: ref, children: (0, jsx_runtime_1.jsxs)("button", { type: "button", "aria-label": "Change playback rate", style: button, onClick: onClick, children: [(0, jsx_runtime_1.jsxs)("div", { style: label, children: [playbackRate, "x"] }), isComponentVisible && ((0, jsx_runtime_1.jsx)(PlaybackPopup, { canvasSize: canvasSize, playbackRates: playbackRates, setIsComponentVisible: setIsComponentVisible }))] }) }));
};
exports.PlaybackrateControl = PlaybackrateControl;
@@ -0,0 +1,68 @@
import type { ComponentType } from 'react';
import React from 'react';
import type { CompProps, LogLevel } from 'remotion';
import type { AnyZodObject } from 'zod';
import type { RenderMuteButton } from './MediaVolumeSlider.js';
import type { RenderFullscreenButton, RenderPlayPauseButton } from './PlayerControls.js';
import type { PosterFillMode, RenderLoading, RenderPoster } from './PlayerUI.js';
import type { BrowserMediaControlsBehavior } from './browser-mediasession.js';
import type { PlayerRef, RenderCustomControls } from './player-methods.js';
import type { RenderVolumeSlider } from './render-volume-slider.js';
import type { PropsIfHasProps } from './utils/props-if-has-props.js';
export type ErrorFallback = (info: {
error: Error;
}) => React.ReactNode;
export type PlayerProps<Schema extends AnyZodObject, Props extends Record<string, unknown>> = {
readonly durationInFrames: number;
readonly compositionWidth: number;
readonly compositionHeight: number;
readonly fps: number;
readonly showVolumeControls?: boolean;
readonly controls?: boolean;
readonly errorFallback?: ErrorFallback;
readonly style?: React.CSSProperties;
readonly loop?: boolean;
readonly autoPlay?: boolean;
readonly allowFullscreen?: boolean;
readonly clickToPlay?: boolean;
readonly doubleClickToFullscreen?: boolean;
readonly spaceKeyToPlayOrPause?: boolean;
readonly numberOfSharedAudioTags?: number;
readonly playbackRate?: number;
readonly renderLoading?: RenderLoading;
readonly moveToBeginningWhenEnded?: boolean;
readonly className?: string;
readonly initialFrame?: number;
readonly renderPoster?: RenderPoster;
readonly showPosterWhenPaused?: boolean;
readonly showPosterWhenEnded?: boolean;
readonly showPosterWhenUnplayed?: boolean;
readonly showPosterWhenBuffering?: boolean;
readonly showPosterWhenBufferingAndPaused?: boolean;
readonly inFrame?: number | null;
readonly outFrame?: number | null;
readonly initiallyShowControls?: number | boolean;
readonly renderPlayPauseButton?: RenderPlayPauseButton;
readonly renderFullscreenButton?: RenderFullscreenButton;
readonly renderMuteButton?: RenderMuteButton;
readonly renderVolumeSlider?: RenderVolumeSlider;
readonly renderCustomControls?: RenderCustomControls;
readonly alwaysShowControls?: boolean;
readonly schema?: Schema;
readonly initiallyMuted?: boolean;
readonly showPlaybackRateControl?: boolean | number[];
readonly posterFillMode?: PosterFillMode;
readonly bufferStateDelayInMilliseconds?: number;
readonly hideControlsWhenPointerDoesntMove?: boolean | number;
readonly overflowVisible?: boolean;
readonly browserMediaControlsBehavior?: BrowserMediaControlsBehavior;
readonly overrideInternalClassName?: string;
readonly logLevel?: LogLevel;
readonly noSuspense?: boolean;
readonly acknowledgeRemotionLicense?: boolean;
readonly audioLatencyHint?: AudioContextLatencyCategory;
readonly volumePersistenceKey?: string;
} & CompProps<Props> & PropsIfHasProps<Schema, Props>;
export type PlayerPropsWithoutZod<Props extends Record<string, unknown>> = PlayerProps<AnyZodObject, Props>;
export declare const componentOrNullIfLazy: <Props>(props: CompProps<Props>) => ComponentType<Props> | null;
export declare const Player: <Schema extends AnyZodObject, Props extends Record<string, unknown>>(props: PlayerProps<Schema, Props> & React.RefAttributes<PlayerRef>) => React.ReactElement | null;
@@ -0,0 +1,166 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Player = exports.componentOrNullIfLazy = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const EmitterProvider_js_1 = require("./EmitterProvider.js");
const PlayerUI_js_1 = __importDefault(require("./PlayerUI.js"));
const SharedPlayerContext_js_1 = require("./SharedPlayerContext.js");
const player_css_classname_js_1 = require("./player-css-classname.js");
const use_remotion_license_acknowledge_js_1 = require("./use-remotion-license-acknowledge.js");
const validate_in_out_frame_js_1 = require("./utils/validate-in-out-frame.js");
const validate_initial_frame_js_1 = require("./utils/validate-initial-frame.js");
const validate_playbackrate_js_1 = require("./utils/validate-playbackrate.js");
const validate_js_1 = require("./validate.js");
const componentOrNullIfLazy = (props) => {
if ('component' in props) {
return props.component;
}
return null;
};
exports.componentOrNullIfLazy = componentOrNullIfLazy;
const PlayerFn = ({ durationInFrames, compositionHeight, compositionWidth, fps, inputProps, style, controls = false, loop = false, autoPlay = false, showVolumeControls = true, allowFullscreen = true, clickToPlay, doubleClickToFullscreen = false, spaceKeyToPlayOrPause = true, moveToBeginningWhenEnded = true, numberOfSharedAudioTags = 5, errorFallback = () => '⚠️', playbackRate = 1, renderLoading, className, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, showPosterWhenBufferingAndPaused, initialFrame, renderPoster, inFrame, outFrame, initiallyShowControls, renderFullscreenButton, renderPlayPauseButton, renderVolumeSlider, renderCustomControls, alwaysShowControls = false, initiallyMuted = false, showPlaybackRateControl = false, posterFillMode = 'player-size', bufferStateDelayInMilliseconds, hideControlsWhenPointerDoesntMove = true, overflowVisible = false, renderMuteButton, browserMediaControlsBehavior: passedBrowserMediaControlsBehavior, overrideInternalClassName, logLevel = 'info', noSuspense, acknowledgeRemotionLicense, audioLatencyHint = 'interactive', volumePersistenceKey, ...componentProps }, ref) => {
if (typeof window !== 'undefined') {
window.remotion_isPlayer = true;
}
// @ts-expect-error
if (componentProps.defaultProps !== undefined) {
throw new Error('The <Player /> component does not accept `defaultProps`, but some were passed. Use `inputProps` instead.');
}
const componentForValidation = (0, exports.componentOrNullIfLazy)(componentProps);
// @ts-expect-error
if ((componentForValidation === null || componentForValidation === void 0 ? void 0 : componentForValidation.type) === remotion_1.Composition) {
throw new TypeError(`'component' should not be an instance of <Composition/>. Pass the React component directly, and set the duration, fps and dimensions as separate props. See https://www.remotion.dev/docs/player/examples for an example.`);
}
if (componentForValidation === remotion_1.Composition) {
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.`);
}
(0, react_1.useState)(() => (0, use_remotion_license_acknowledge_js_1.acknowledgeRemotionLicenseMessage)(Boolean(acknowledgeRemotionLicense), logLevel));
const component = remotion_1.Internals.useLazyComponent({
compProps: componentProps,
componentName: 'Player',
noSuspense: Boolean(noSuspense),
});
(0, validate_initial_frame_js_1.validateInitialFrame)({ initialFrame, durationInFrames });
const [frame, setFrame] = (0, react_1.useState)(() => ({
[SharedPlayerContext_js_1.PLAYER_COMP_ID]: initialFrame !== null && initialFrame !== void 0 ? initialFrame : 0,
}));
const [playing, setPlaying] = (0, react_1.useState)(false);
const [rootId] = (0, react_1.useState)('player-comp');
const rootRef = (0, react_1.useRef)(null);
const audioAndVideoTags = (0, react_1.useRef)([]);
const imperativePlaying = (0, react_1.useRef)(false);
const [currentPlaybackRate, setCurrentPlaybackRate] = (0, react_1.useState)(playbackRate);
if (typeof compositionHeight !== 'number') {
throw new TypeError(`'compositionHeight' must be a number but got '${typeof compositionHeight}' instead`);
}
if (typeof compositionWidth !== 'number') {
throw new TypeError(`'compositionWidth' must be a number but got '${typeof compositionWidth}' instead`);
}
(0, validate_js_1.validateDimension)(compositionHeight, 'compositionHeight', 'of the <Player /> component');
(0, validate_js_1.validateDimension)(compositionWidth, 'compositionWidth', 'of the <Player /> component');
(0, validate_js_1.validateDurationInFrames)(durationInFrames, {
component: 'of the <Player/> component',
allowFloats: false,
});
(0, validate_js_1.validateFps)(fps, 'as a prop of the <Player/> component', false);
(0, validate_js_1.validateDefaultAndInputProps)(inputProps, 'inputProps', null);
(0, validate_in_out_frame_js_1.validateInOutFrames)({
durationInFrames,
inFrame,
outFrame,
});
if (typeof controls !== 'boolean' && typeof controls !== 'undefined') {
throw new TypeError(`'controls' must be a boolean or undefined but got '${typeof controls}' instead`);
}
if (typeof autoPlay !== 'boolean' && typeof autoPlay !== 'undefined') {
throw new TypeError(`'autoPlay' must be a boolean or undefined but got '${typeof autoPlay}' instead`);
}
if (typeof loop !== 'boolean' && typeof loop !== 'undefined') {
throw new TypeError(`'loop' must be a boolean or undefined but got '${typeof loop}' instead`);
}
if (typeof doubleClickToFullscreen !== 'boolean' &&
typeof doubleClickToFullscreen !== 'undefined') {
throw new TypeError(`'doubleClickToFullscreen' must be a boolean or undefined but got '${typeof doubleClickToFullscreen}' instead`);
}
if (typeof showVolumeControls !== 'boolean' &&
typeof showVolumeControls !== 'undefined') {
throw new TypeError(`'showVolumeControls' must be a boolean or undefined but got '${typeof showVolumeControls}' instead`);
}
if (typeof allowFullscreen !== 'boolean' &&
typeof allowFullscreen !== 'undefined') {
throw new TypeError(`'allowFullscreen' must be a boolean or undefined but got '${typeof allowFullscreen}' instead`);
}
if (typeof clickToPlay !== 'boolean' && typeof clickToPlay !== 'undefined') {
throw new TypeError(`'clickToPlay' must be a boolean or undefined but got '${typeof clickToPlay}' instead`);
}
if (typeof spaceKeyToPlayOrPause !== 'boolean' &&
typeof spaceKeyToPlayOrPause !== 'undefined') {
throw new TypeError(`'spaceKeyToPlayOrPause' must be a boolean or undefined but got '${typeof spaceKeyToPlayOrPause}' instead`);
}
if (typeof numberOfSharedAudioTags !== 'number' ||
numberOfSharedAudioTags % 1 !== 0 ||
!Number.isFinite(numberOfSharedAudioTags) ||
Number.isNaN(numberOfSharedAudioTags) ||
numberOfSharedAudioTags < 0) {
throw new TypeError(`'numberOfSharedAudioTags' must be an integer but got '${numberOfSharedAudioTags}' instead`);
}
(0, validate_playbackrate_js_1.validatePlaybackRate)(currentPlaybackRate);
(0, react_1.useEffect)(() => {
setCurrentPlaybackRate(playbackRate);
}, [playbackRate]);
(0, react_1.useImperativeHandle)(ref, () => rootRef.current, []);
(0, react_1.useState)(() => {
remotion_1.Internals.playbackLogging({
logLevel,
message: `[player] Mounting <Player>. User agent = ${typeof navigator === 'undefined' ? 'server' : navigator.userAgent}`,
tag: 'player',
mountTime: Date.now(),
});
});
const timelineContextValue = (0, react_1.useMemo)(() => {
return {
frame,
playing,
rootId,
playbackRate: currentPlaybackRate,
imperativePlaying,
setPlaybackRate: (rate) => {
setCurrentPlaybackRate(rate);
},
audioAndVideoTags,
};
}, [frame, currentPlaybackRate, playing, rootId]);
const setTimelineContextValue = (0, react_1.useMemo)(() => {
return {
setFrame,
setPlaying,
};
}, [setFrame]);
if (typeof window !== 'undefined') {
// eslint-disable-next-line react-hooks/rules-of-hooks
(0, react_1.useLayoutEffect)(() => {
// Inject CSS only on client, and also only after the Player has hydrated
remotion_1.Internals.CSSUtils.injectCSS(remotion_1.Internals.CSSUtils.makeDefaultPreviewCSS(`.${(0, player_css_classname_js_1.playerCssClassname)(overrideInternalClassName)}`, '#fff'));
}, [overrideInternalClassName]);
}
const actualInputProps = (0, react_1.useMemo)(() => inputProps !== null && inputProps !== void 0 ? inputProps : {}, [inputProps]);
const browserMediaControlsBehavior = (0, react_1.useMemo)(() => {
return (passedBrowserMediaControlsBehavior !== null && passedBrowserMediaControlsBehavior !== void 0 ? passedBrowserMediaControlsBehavior : {
mode: 'prevent-media-session',
});
}, [passedBrowserMediaControlsBehavior]);
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, numberOfSharedAudioTags: numberOfSharedAudioTags, initiallyMuted: initiallyMuted, logLevel: logLevel, audioLatencyHint: audioLatencyHint, volumePersistenceKey: volumePersistenceKey, inputProps: actualInputProps, audioEnabled: true, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.SetTimelineContext.Provider, { value: setTimelineContextValue, children: (0, jsx_runtime_1.jsx)(EmitterProvider_js_1.PlayerEmitterProvider, { currentPlaybackRate: currentPlaybackRate, children: (0, jsx_runtime_1.jsx)(PlayerUI_js_1.default, { ref: rootRef, posterFillMode: posterFillMode, renderLoading: renderLoading, autoPlay: Boolean(autoPlay), loop: Boolean(loop), controls: Boolean(controls), errorFallback: errorFallback, style: style, inputProps: actualInputProps, allowFullscreen: Boolean(allowFullscreen), moveToBeginningWhenEnded: Boolean(moveToBeginningWhenEnded), clickToPlay: typeof clickToPlay === 'boolean'
? clickToPlay
: Boolean(controls), showVolumeControls: Boolean(showVolumeControls), doubleClickToFullscreen: Boolean(doubleClickToFullscreen), spaceKeyToPlayOrPause: Boolean(spaceKeyToPlayOrPause), playbackRate: currentPlaybackRate, className: className !== null && className !== void 0 ? className : undefined, showPosterWhenUnplayed: Boolean(showPosterWhenUnplayed), showPosterWhenEnded: Boolean(showPosterWhenEnded), showPosterWhenPaused: Boolean(showPosterWhenPaused), showPosterWhenBuffering: Boolean(showPosterWhenBuffering), showPosterWhenBufferingAndPaused: Boolean(showPosterWhenBufferingAndPaused), 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, renderMuteButton: renderMuteButton !== null && renderMuteButton !== void 0 ? renderMuteButton : null, renderVolumeSlider: renderVolumeSlider !== null && renderVolumeSlider !== void 0 ? renderVolumeSlider : null, renderCustomControls: renderCustomControls !== null && renderCustomControls !== void 0 ? renderCustomControls : null, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl, bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds !== null && bufferStateDelayInMilliseconds !== void 0 ? bufferStateDelayInMilliseconds : 300, hideControlsWhenPointerDoesntMove: hideControlsWhenPointerDoesntMove, overflowVisible: overflowVisible, browserMediaControlsBehavior: browserMediaControlsBehavior, overrideInternalClassName: overrideInternalClassName !== null && overrideInternalClassName !== void 0 ? overrideInternalClassName : undefined, noSuspense: Boolean(noSuspense) }) }) }) }) }));
};
const forward = react_1.forwardRef;
/*
* @description A component which can be rendered in a regular React App to display a Remotion video.
* @see [Documentation](https://www.remotion.dev/docs/player/player)
*/
exports.Player = forward(PlayerFn);
@@ -0,0 +1,43 @@
import type { MouseEventHandler, ReactNode, SyntheticEvent } from 'react';
import React from 'react';
import type { RenderMuteButton } from './MediaVolumeSlider.js';
import type { RenderCustomControls } from './player-methods.js';
import type { RenderVolumeSlider } from './render-volume-slider.js';
import type { Size } from './utils/use-element-size.js';
export type RenderPlayPauseButton = (props: {
playing: boolean;
isBuffering: boolean;
}) => ReactNode | null;
export type RenderFullscreenButton = (props: {
isFullscreen: boolean;
}) => ReactNode;
export declare const Controls: React.FC<{
readonly fps: number;
readonly durationInFrames: number;
readonly showVolumeControls: boolean;
readonly onFullscreenButtonClick: MouseEventHandler<HTMLButtonElement>;
readonly isFullscreen: boolean;
readonly allowFullscreen: boolean;
readonly onExitFullscreenButtonClick: MouseEventHandler<HTMLButtonElement>;
readonly spaceKeyToPlayOrPause: boolean;
readonly onSeekEnd: () => void;
readonly onSeekStart: () => void;
readonly inFrame: number | null;
readonly outFrame: number | null;
readonly initiallyShowControls: number | boolean;
readonly canvasSize: Size | null;
readonly renderPlayPauseButton: RenderPlayPauseButton | null;
readonly renderFullscreenButton: RenderFullscreenButton | null;
readonly alwaysShowControls: boolean;
readonly showPlaybackRateControl: boolean | number[];
readonly containerRef: React.RefObject<HTMLDivElement | null>;
readonly buffering: boolean;
readonly hideControlsWhenPointerDoesntMove: boolean | number;
readonly onPointerDown: ((ev: PointerEvent | SyntheticEvent) => void) | undefined;
readonly onDoubleClick: MouseEventHandler<HTMLDivElement> | undefined;
readonly renderMuteButton: RenderMuteButton | null;
readonly renderVolumeSlider: RenderVolumeSlider | null;
readonly playing: boolean;
readonly toggle: (e?: SyntheticEvent | PointerEvent) => void;
readonly renderCustomControls: RenderCustomControls | null;
}>;
@@ -0,0 +1,175 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Controls = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const DefaultPlayPauseButton_js_1 = require("./DefaultPlayPauseButton.js");
const MediaVolumeSlider_js_1 = require("./MediaVolumeSlider.js");
const PlaybackrateControl_js_1 = require("./PlaybackrateControl.js");
const PlayerSeekBar_js_1 = require("./PlayerSeekBar.js");
const PlayerTimeLabel_js_1 = require("./PlayerTimeLabel.js");
const icons_js_1 = require("./icons.js");
const use_hover_state_js_1 = require("./use-hover-state.js");
const use_video_controls_resize_js_1 = require("./use-video-controls-resize.js");
const gradientSteps = [
0, 0.013, 0.049, 0.104, 0.175, 0.259, 0.352, 0.45, 0.55, 0.648, 0.741, 0.825,
0.896, 0.951, 0.987,
];
const gradientOpacities = [
0, 8.1, 15.5, 22.5, 29, 35.3, 41.2, 47.1, 52.9, 58.8, 64.7, 71, 77.5, 84.5,
91.9,
];
const globalGradientOpacity = 1 / 0.7;
const containerStyle = {
boxSizing: 'border-box',
position: 'absolute',
bottom: 0,
width: '100%',
paddingTop: 40,
paddingBottom: 10,
backgroundImage: `linear-gradient(to bottom,${gradientSteps
.map((g, i) => {
return `hsla(0, 0%, 0%, ${g}) ${gradientOpacities[i] * globalGradientOpacity}%`;
})
.join(', ')}, hsl(0, 0%, 0%) 100%)`,
backgroundSize: 'auto 145px',
display: 'flex',
paddingRight: use_video_controls_resize_js_1.X_PADDING,
paddingLeft: use_video_controls_resize_js_1.X_PADDING,
flexDirection: 'column',
transition: 'opacity 0.3s',
};
const controlsRow = {
display: 'flex',
flexDirection: 'row',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
userSelect: 'none',
WebkitUserSelect: 'none',
};
const leftPartStyle = {
display: 'flex',
flexDirection: 'row',
userSelect: 'none',
WebkitUserSelect: 'none',
alignItems: 'center',
};
const xSpacer = {
width: 12,
};
const ySpacer = {
height: 8,
};
const flex1 = {
flex: 1,
};
const fullscreen = {};
const Controls = ({ durationInFrames, isFullscreen, fps, showVolumeControls, onFullscreenButtonClick, allowFullscreen, onExitFullscreenButtonClick, spaceKeyToPlayOrPause, onSeekEnd, onSeekStart, inFrame, outFrame, initiallyShowControls, canvasSize, renderPlayPauseButton, renderFullscreenButton, alwaysShowControls, showPlaybackRateControl, containerRef, buffering, hideControlsWhenPointerDoesntMove, onPointerDown, onDoubleClick, renderMuteButton, renderVolumeSlider, playing, toggle, renderCustomControls, }) => {
var _a, _b;
const playButtonRef = (0, react_1.useRef)(null);
const [supportsFullscreen, setSupportsFullscreen] = (0, react_1.useState)(false);
const hovered = (0, use_hover_state_js_1.useHoverState)(containerRef, hideControlsWhenPointerDoesntMove);
const { maxTimeLabelWidth, displayVerticalVolumeSlider } = (0, use_video_controls_resize_js_1.useVideoControlsResize)({
allowFullscreen,
playerWidth: (_a = canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.width) !== null && _a !== void 0 ? _a : 0,
});
const [shouldShowInitially, setInitiallyShowControls] = (0, react_1.useState)(() => {
if (typeof initiallyShowControls === 'boolean') {
return initiallyShowControls;
}
if (typeof initiallyShowControls === 'number') {
if (initiallyShowControls % 1 !== 0) {
throw new Error('initiallyShowControls must be an integer or a boolean');
}
if (Number.isNaN(initiallyShowControls)) {
throw new Error('initiallyShowControls must not be NaN');
}
if (!Number.isFinite(initiallyShowControls)) {
throw new Error('initiallyShowControls must be finite');
}
if (initiallyShowControls <= 0) {
throw new Error('initiallyShowControls must be a positive integer');
}
return initiallyShowControls;
}
throw new TypeError('initiallyShowControls must be a number or a boolean');
});
const containerCss = (0, react_1.useMemo)(() => {
// Hide if playing and mouse outside
const shouldShow = hovered || !playing || shouldShowInitially || alwaysShowControls;
return {
...containerStyle,
opacity: Number(shouldShow),
};
}, [hovered, shouldShowInitially, playing, alwaysShowControls]);
(0, react_1.useEffect)(() => {
if (playButtonRef.current && spaceKeyToPlayOrPause) {
// This switches focus to play button when player.playing flag changes
playButtonRef.current.focus({
preventScroll: true,
});
}
}, [playing, spaceKeyToPlayOrPause]);
(0, react_1.useEffect)(() => {
var _a;
// Must be handled client-side to avoid SSR hydration mismatch
setSupportsFullscreen((_a = (typeof document !== 'undefined' &&
(document.fullscreenEnabled ||
// @ts-expect-error Types not defined
document.webkitFullscreenEnabled))) !== null && _a !== void 0 ? _a : false);
}, []);
(0, react_1.useEffect)(() => {
if (shouldShowInitially === false) {
return;
}
const time = shouldShowInitially === true ? 2000 : shouldShowInitially;
const timeout = setTimeout(() => {
setInitiallyShowControls(false);
}, time);
return () => {
clearInterval(timeout);
};
}, [shouldShowInitially]);
const playbackRates = (0, react_1.useMemo)(() => {
if (showPlaybackRateControl === true) {
return [0.5, 0.8, 1, 1.2, 1.5, 1.8, 2, 2.5, 3];
}
if (Array.isArray(showPlaybackRateControl)) {
for (const rate of showPlaybackRateControl) {
if (typeof rate !== 'number') {
throw new Error('Every item in showPlaybackRateControl must be a number');
}
if (rate <= 0) {
throw new Error('Every item in showPlaybackRateControl must be positive');
}
}
return showPlaybackRateControl;
}
return null;
}, [showPlaybackRateControl]);
const customControlsElement = renderCustomControls
? renderCustomControls()
: null;
const ref = (0, react_1.useRef)(null);
const flexRef = (0, react_1.useRef)(null);
const onPointerDownIfContainer = (0, react_1.useCallback)((e) => {
// Only if pressing the container
if (e.target === ref.current || e.target === flexRef.current) {
onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(e);
}
}, [onPointerDown]);
const onDoubleClickIfContainer = (0, react_1.useCallback)((e) => {
// Only if pressing the container
if (e.target === ref.current || e.target === flexRef.current) {
onDoubleClick === null || onDoubleClick === void 0 ? void 0 : onDoubleClick(e);
}
}, [onDoubleClick]);
return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, style: containerCss, onPointerDown: onPointerDownIfContainer, onDoubleClick: onDoubleClickIfContainer, children: [(0, jsx_runtime_1.jsxs)("div", { ref: flexRef, style: controlsRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: leftPartStyle, children: [(0, jsx_runtime_1.jsx)("button", { ref: playButtonRef, type: "button", style: PlaybackrateControl_js_1.playerButtonStyle, onClick: toggle, "aria-label": playing ? 'Pause video' : 'Play video', title: playing ? 'Pause video' : 'Play video', children: renderPlayPauseButton === null ? ((0, jsx_runtime_1.jsx)(DefaultPlayPauseButton_js_1.DefaultPlayPauseButton, { buffering: buffering, playing: playing })) : (((_b = renderPlayPauseButton({
playing,
isBuffering: buffering,
})) !== null && _b !== void 0 ? _b : ((0, jsx_runtime_1.jsx)(DefaultPlayPauseButton_js_1.DefaultPlayPauseButton, { buffering: buffering, playing: 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, { renderMuteButton: renderMuteButton, renderVolumeSlider: renderVolumeSlider, displayVerticalVolumeSlider: displayVerticalVolumeSlider })] })) : null, (0, jsx_runtime_1.jsx)("div", { style: xSpacer }), (0, jsx_runtime_1.jsx)(PlayerTimeLabel_js_1.PlayerTimeLabel, { durationInFrames: durationInFrames, fps: fps, maxTimeLabelWidth: maxTimeLabelWidth }), (0, jsx_runtime_1.jsx)("div", { style: xSpacer })] }), (0, jsx_runtime_1.jsx)("div", { style: flex1 }), customControlsElement, customControlsElement && playbackRates && canvasSize ? ((0, jsx_runtime_1.jsx)("div", { style: xSpacer })) : null, playbackRates && canvasSize && ((0, jsx_runtime_1.jsx)(PlaybackrateControl_js_1.PlaybackrateControl, { canvasSize: canvasSize, 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: PlaybackrateControl_js_1.playerButtonStyle, onClick: isFullscreen
? onExitFullscreenButtonClick
: 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 })] }));
};
exports.Controls = Controls;
@@ -0,0 +1,7 @@
export declare const PlayerSeekBar: React.FC<{
durationInFrames: number;
onSeekStart: () => void;
onSeekEnd: () => void;
inFrame: number | null;
outFrame: number | null;
}>;
@@ -0,0 +1,149 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlayerSeekBar = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const use_hover_state_js_1 = require("./use-hover-state.js");
const use_player_js_1 = require("./use-player.js");
const use_element_size_js_1 = require("./utils/use-element-size.js");
const getFrameFromX = (clientX, durationInFrames, width) => {
const pos = clientX;
const frame = Math.round((0, remotion_1.interpolate)(pos, [0, width], [0, durationInFrames - 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
}));
return frame;
};
const BAR_HEIGHT = 5;
const KNOB_SIZE = 12;
const VERTICAL_PADDING = 4;
const containerStyle = {
userSelect: 'none',
WebkitUserSelect: 'none',
paddingTop: VERTICAL_PADDING,
paddingBottom: VERTICAL_PADDING,
boxSizing: 'border-box',
cursor: 'pointer',
position: 'relative',
touchAction: 'none',
};
const barBackground = {
height: BAR_HEIGHT,
backgroundColor: 'rgba(255, 255, 255, 0.25)',
width: '100%',
borderRadius: BAR_HEIGHT / 2,
};
const findBodyInWhichDivIsLocated = (div) => {
let current = div;
while (current.parentElement) {
current = current.parentElement;
}
return current;
};
const PlayerSeekBar = ({ durationInFrames, onSeekEnd, onSeekStart, inFrame, outFrame }) => {
var _a;
const containerRef = (0, react_1.useRef)(null);
const barHovered = (0, use_hover_state_js_1.useHoverState)(containerRef, false);
const size = (0, use_element_size_js_1.useElementSize)(containerRef, {
triggerOnWindowResize: true,
shouldApplyCssTransforms: true,
});
const { seek, play, pause, playing } = (0, use_player_js_1.usePlayer)();
const frame = remotion_1.Internals.Timeline.useTimelinePosition();
const [dragging, setDragging] = (0, react_1.useState)({
dragging: false,
});
const width = (_a = size === null || size === void 0 ? void 0 : size.width) !== null && _a !== void 0 ? _a : 0;
const onPointerDown = (0, react_1.useCallback)((e) => {
var _a;
if (e.button !== 0) {
return;
}
const posLeft = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left;
const _frame = getFrameFromX(e.clientX - posLeft, durationInFrames, width);
pause();
seek(_frame);
setDragging({
dragging: true,
wasPlaying: playing,
});
onSeekStart();
}, [durationInFrames, width, pause, seek, playing, onSeekStart]);
const onPointerMove = (0, react_1.useCallback)((e) => {
var _a;
if (!size) {
throw new Error('Player has no size');
}
if (!dragging.dragging) {
return;
}
const posLeft = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left;
const _frame = getFrameFromX(e.clientX - posLeft, durationInFrames, size.width);
seek(_frame);
}, [dragging.dragging, durationInFrames, seek, size]);
const onPointerUp = (0, react_1.useCallback)(() => {
setDragging({
dragging: false,
});
if (!dragging.dragging) {
return;
}
if (dragging.wasPlaying) {
play();
}
else {
pause();
}
onSeekEnd();
}, [dragging, onSeekEnd, pause, play]);
(0, react_1.useEffect)(() => {
if (!dragging.dragging) {
return;
}
const body = findBodyInWhichDivIsLocated(containerRef.current);
body.addEventListener('pointermove', onPointerMove);
body.addEventListener('pointerup', onPointerUp);
return () => {
body.removeEventListener('pointermove', onPointerMove);
body.removeEventListener('pointerup', onPointerUp);
};
}, [dragging.dragging, onPointerMove, onPointerUp]);
const knobStyle = (0, react_1.useMemo)(() => {
return {
height: KNOB_SIZE,
width: KNOB_SIZE,
borderRadius: KNOB_SIZE / 2,
position: 'absolute',
top: VERTICAL_PADDING - KNOB_SIZE / 2 + 5 / 2,
backgroundColor: 'white',
left: Math.max(0, (frame / Math.max(1, durationInFrames - 1)) * width - KNOB_SIZE / 2),
boxShadow: '0 0 2px black',
opacity: Number(barHovered || dragging.dragging),
};
}, [barHovered, dragging.dragging, durationInFrames, frame, width]);
const fillStyle = (0, react_1.useMemo)(() => {
return {
height: BAR_HEIGHT,
backgroundColor: 'rgba(255, 255, 255, 1)',
width: ((frame - (inFrame !== null && inFrame !== void 0 ? inFrame : 0)) / (durationInFrames - 1)) * width,
marginLeft: ((inFrame !== null && inFrame !== void 0 ? inFrame : 0) / (durationInFrames - 1)) * width,
borderRadius: BAR_HEIGHT / 2,
};
}, [durationInFrames, frame, inFrame, width]);
const active = (0, react_1.useMemo)(() => {
return {
height: BAR_HEIGHT,
backgroundColor: 'rgba(255, 255, 255, 0.25)',
width: (((outFrame !== null && outFrame !== void 0 ? outFrame : durationInFrames - 1) - (inFrame !== null && inFrame !== void 0 ? inFrame : 0)) /
(durationInFrames - 1)) *
100 +
'%',
marginLeft: ((inFrame !== null && inFrame !== void 0 ? inFrame : 0) / (durationInFrames - 1)) * 100 + '%',
borderRadius: BAR_HEIGHT / 2,
position: 'absolute',
};
}, [durationInFrames, inFrame, outFrame]);
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 })] }));
};
exports.PlayerSeekBar = PlayerSeekBar;
@@ -0,0 +1,6 @@
import React from 'react';
export declare const PlayerTimeLabel: React.FC<{
readonly maxTimeLabelWidth: number | null;
readonly durationInFrames: number;
readonly fps: number;
}>;
@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlayerTimeLabel = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const format_time_1 = require("./format-time");
const PlayerTimeLabel = ({ durationInFrames, maxTimeLabelWidth, fps }) => {
const frame = remotion_1.Internals.Timeline.useTimelinePosition();
const timeLabel = (0, react_1.useMemo)(() => {
return {
color: 'white',
fontFamily: 'sans-serif',
fontSize: 14,
maxWidth: maxTimeLabelWidth === null ? undefined : maxTimeLabelWidth,
overflow: 'hidden',
textOverflow: 'ellipsis',
};
}, [maxTimeLabelWidth]);
// If the video ended and is not looping, it should show 0:04 / 0:04 instead of 0:03 / 0:04
const isLastFrame = frame === durationInFrames - 1;
const frameToDisplay = isLastFrame ? frame + 1 : frame;
return ((0, jsx_runtime_1.jsxs)("div", { style: timeLabel, children: [(0, format_time_1.formatTime)(frameToDisplay / fps), " / ", (0, format_time_1.formatTime)(durationInFrames / fps)] }));
};
exports.PlayerTimeLabel = PlayerTimeLabel;
@@ -0,0 +1,57 @@
import React from 'react';
import type { RenderMuteButton } from './MediaVolumeSlider.js';
import type { RenderFullscreenButton, RenderPlayPauseButton } from './PlayerControls.js';
import type { BrowserMediaControlsBehavior } from './browser-mediasession.js';
import type { PlayerRef, RenderCustomControls } from './player-methods.js';
import type { RenderVolumeSlider } from './render-volume-slider.js';
export type ErrorFallback = (info: {
error: Error;
}) => React.ReactNode;
export type RenderLoading = (canvas: {
height: number;
width: number;
isBuffering: boolean;
}) => React.ReactNode;
export type RenderPoster = RenderLoading;
export type PosterFillMode = 'player-size' | 'composition-size';
declare const _default: React.ForwardRefExoticComponent<{
readonly controls: boolean;
readonly loop: boolean;
readonly autoPlay: boolean;
readonly allowFullscreen: boolean;
readonly inputProps: Record<string, unknown>;
readonly showVolumeControls: boolean;
readonly style?: React.CSSProperties;
readonly clickToPlay: boolean;
readonly doubleClickToFullscreen: boolean;
readonly spaceKeyToPlayOrPause: boolean;
readonly errorFallback: ErrorFallback;
readonly playbackRate: number;
readonly renderLoading: RenderLoading | undefined;
readonly renderPoster: RenderPoster | undefined;
readonly className: string | undefined;
readonly moveToBeginningWhenEnded: boolean;
readonly showPosterWhenPaused: boolean;
readonly showPosterWhenEnded: boolean;
readonly showPosterWhenUnplayed: boolean;
readonly showPosterWhenBuffering: boolean;
readonly showPosterWhenBufferingAndPaused: boolean;
readonly inFrame: number | null;
readonly outFrame: number | null;
readonly initiallyShowControls: number | boolean;
readonly renderPlayPauseButton: RenderPlayPauseButton | null;
readonly renderFullscreen: RenderFullscreenButton | null;
readonly renderMuteButton: RenderMuteButton | null;
readonly renderVolumeSlider: RenderVolumeSlider | null;
readonly renderCustomControls: RenderCustomControls | null;
readonly alwaysShowControls: boolean;
readonly showPlaybackRateControl: boolean | number[];
readonly posterFillMode: PosterFillMode;
readonly bufferStateDelayInMilliseconds: number;
readonly hideControlsWhenPointerDoesntMove: boolean | number;
readonly overflowVisible: boolean;
readonly browserMediaControlsBehavior: BrowserMediaControlsBehavior;
readonly overrideInternalClassName: string | undefined;
readonly noSuspense: boolean;
} & React.RefAttributes<PlayerRef>>;
export default _default;
@@ -0,0 +1,445 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importStar(require("react"));
const remotion_1 = require("remotion");
const PlayerControls_js_1 = require("./PlayerControls.js");
const calculate_scale_js_1 = require("./calculate-scale.js");
const error_boundary_js_1 = require("./error-boundary.js");
const license_blacklist_js_1 = require("./license-blacklist.js");
const player_css_classname_js_1 = require("./player-css-classname.js");
const use_playback_js_1 = require("./use-playback.js");
const use_player_js_1 = require("./use-player.js");
const is_node_js_1 = require("./utils/is-node.js");
const use_click_prevention_on_double_click_js_1 = require("./utils/use-click-prevention-on-double-click.js");
const use_element_size_js_1 = require("./utils/use-element-size.js");
const reactVersion = react_1.default.version.split('.')[0];
if (reactVersion === '0') {
throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
}
const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
const PlayerUI = ({ controls, style, loop, autoPlay, allowFullscreen, inputProps, clickToPlay, showVolumeControls, doubleClickToFullscreen, spaceKeyToPlayOrPause, errorFallback, playbackRate, renderLoading, renderPoster, className, moveToBeginningWhenEnded, showPosterWhenUnplayed, showPosterWhenEnded, showPosterWhenPaused, showPosterWhenBuffering, showPosterWhenBufferingAndPaused, inFrame, outFrame, initiallyShowControls, renderFullscreen: renderFullscreenButton, renderPlayPauseButton, renderMuteButton, renderVolumeSlider, renderCustomControls, alwaysShowControls, showPlaybackRateControl, posterFillMode, bufferStateDelayInMilliseconds, hideControlsWhenPointerDoesntMove, overflowVisible, browserMediaControlsBehavior, overrideInternalClassName, noSuspense, }, ref) => {
var _a, _b, _c;
const config = remotion_1.Internals.useUnsafeVideoConfig();
const video = remotion_1.Internals.useVideo();
const container = (0, react_1.useRef)(null);
const canvasSize = (0, use_element_size_js_1.useElementSize)(container, {
triggerOnWindowResize: false,
shouldApplyCssTransforms: false,
});
const [hasPausedToResume, setHasPausedToResume] = (0, react_1.useState)(false);
const [shouldAutoplay, setShouldAutoPlay] = (0, react_1.useState)(autoPlay);
const [isFullscreen, setIsFullscreen] = (0, react_1.useState)(() => false);
const [seeking, setSeeking] = (0, react_1.useState)(false);
const supportsFullScreen = (0, react_1.useMemo)(() => {
if (typeof document === 'undefined') {
return false;
}
return Boolean(document.fullscreenEnabled ||
// @ts-expect-error Types not defined
document.webkitFullscreenEnabled);
}, []);
const player = (0, use_player_js_1.usePlayer)();
const playerToggle = player.toggle;
(0, use_playback_js_1.usePlayback)({
loop,
playbackRate,
moveToBeginningWhenEnded,
inFrame,
outFrame,
getCurrentFrame: player.getCurrentFrame,
browserMediaControlsBehavior,
});
(0, react_1.useEffect)(() => {
if (hasPausedToResume && !player.playing) {
setHasPausedToResume(false);
player.play();
}
}, [hasPausedToResume, player]);
(0, react_1.useEffect)(() => {
const { current } = container;
if (!current) {
return;
}
const onFullscreenChange = () => {
const newValue = document.fullscreenElement === current ||
// @ts-expect-error Types not defined
document.webkitFullscreenElement === current;
setIsFullscreen(newValue);
};
document.addEventListener('fullscreenchange', onFullscreenChange);
document.addEventListener('webkitfullscreenchange', onFullscreenChange);
return () => {
document.removeEventListener('fullscreenchange', onFullscreenChange);
document.removeEventListener('webkitfullscreenchange', onFullscreenChange);
};
}, []);
const toggle = (0, react_1.useCallback)((e) => {
playerToggle(e);
}, [playerToggle]);
const requestFullscreen = (0, react_1.useCallback)(() => {
if (!allowFullscreen) {
throw new Error('allowFullscreen is false');
}
if (!supportsFullScreen) {
throw new Error('Browser doesnt support fullscreen');
}
if (!container.current) {
throw new Error('No player ref found');
}
// @ts-expect-error Types not defined
if (container.current.webkitRequestFullScreen) {
// @ts-expect-error Types not defined
container.current.webkitRequestFullScreen();
}
else {
container.current.requestFullscreen();
}
}, [allowFullscreen, supportsFullScreen]);
const exitFullscreen = (0, react_1.useCallback)(() => {
// @ts-expect-error Types not defined
if (document.webkitExitFullscreen) {
// @ts-expect-error Types not defined
document.webkitExitFullscreen();
}
else {
document.exitFullscreen();
}
}, []);
(0, react_1.useEffect)(() => {
const { current } = container;
if (!current) {
return;
}
const fullscreenChange = () => {
var _a;
const element =
// @ts-expect-error Types not defined
(_a = document.webkitFullscreenElement) !== null && _a !== void 0 ? _a :
// defined
document.fullscreenElement;
if (element && element === container.current) {
player.emitter.dispatchFullscreenChange({
isFullscreen: true,
});
}
else {
player.emitter.dispatchFullscreenChange({
isFullscreen: false,
});
}
};
current.addEventListener('webkitfullscreenchange', fullscreenChange);
current.addEventListener('fullscreenchange', fullscreenChange);
return () => {
current.removeEventListener('webkitfullscreenchange', fullscreenChange);
current.removeEventListener('fullscreenchange', fullscreenChange);
};
}, [player.emitter]);
const durationInFrames = (_a = config === null || config === void 0 ? void 0 : config.durationInFrames) !== null && _a !== void 0 ? _a : 1;
const layout = (0, react_1.useMemo)(() => {
if (!config || !canvasSize) {
return null;
}
return (0, calculate_scale_js_1.calculateCanvasTransformation)({
canvasSize,
compositionHeight: config.height,
compositionWidth: config.width,
previewSize: 'auto',
});
}, [canvasSize, config]);
const scale = (_b = layout === null || layout === void 0 ? void 0 : layout.scale) !== null && _b !== void 0 ? _b : 1;
const initialScaleIgnored = (0, react_1.useRef)(false);
(0, react_1.useEffect)(() => {
if (!initialScaleIgnored.current) {
initialScaleIgnored.current = true;
return;
}
player.emitter.dispatchScaleChange(scale);
}, [player.emitter, scale]);
const { setMediaVolume, setMediaMuted } = (0, react_1.useContext)(remotion_1.Internals.SetMediaVolumeContext);
const { mediaMuted, mediaVolume } = (0, react_1.useContext)(remotion_1.Internals.MediaVolumeContext);
(0, react_1.useEffect)(() => {
player.emitter.dispatchVolumeChange(mediaVolume);
}, [player.emitter, mediaVolume]);
const isMuted = mediaMuted || mediaVolume === 0;
(0, react_1.useEffect)(() => {
player.emitter.dispatchMuteChange({
isMuted,
});
}, [player.emitter, isMuted]);
const [showBufferIndicator, setShowBufferState] = (0, react_1.useState)(false);
(0, react_1.useEffect)(() => {
let timeout = null;
let stopped = false;
const onBuffer = () => {
stopped = false;
requestAnimationFrame(() => {
if (bufferStateDelayInMilliseconds === 0) {
setShowBufferState(true);
}
else {
timeout = setTimeout(() => {
if (!stopped) {
setShowBufferState(true);
}
}, bufferStateDelayInMilliseconds);
}
});
};
const onResume = () => {
requestAnimationFrame(() => {
stopped = true;
setShowBufferState(false);
if (timeout) {
clearTimeout(timeout);
}
});
};
player.emitter.addEventListener('waiting', onBuffer);
player.emitter.addEventListener('resume', onResume);
return () => {
player.emitter.removeEventListener('waiting', onBuffer);
player.emitter.removeEventListener('resume', onResume);
setShowBufferState(false);
if (timeout) {
clearTimeout(timeout);
}
stopped = true;
};
}, [bufferStateDelayInMilliseconds, player.emitter]);
(0, react_1.useImperativeHandle)(ref, () => {
const methods = {
play: player.play,
pause: () => {
// If, after .seek()-ing, the player was explicitly paused, we don't resume
setHasPausedToResume(false);
player.pause();
},
toggle,
getContainerNode: () => container.current,
getCurrentFrame: player.getCurrentFrame,
isPlaying: player.isPlaying,
seekTo: (f) => {
const lastFrame = durationInFrames - 1;
const frameToSeekTo = Math.max(0, Math.min(lastFrame, f));
// continue playing after seeking if the player was playing before
if (player.isPlaying()) {
const pauseToResume = frameToSeekTo !== lastFrame || loop;
setHasPausedToResume(pauseToResume);
player.pause();
}
if (frameToSeekTo === lastFrame && !loop) {
player.emitter.dispatchEnded();
}
player.seek(frameToSeekTo);
},
isFullscreen: () => {
const { current } = container;
if (!current) {
return false;
}
return (document.fullscreenElement === current ||
// @ts-expect-error Types not defined
document.webkitFullscreenElement === current);
},
requestFullscreen,
exitFullscreen,
getVolume: () => {
if (mediaMuted) {
return 0;
}
return mediaVolume;
},
setVolume: (vol) => {
if (typeof vol !== 'number') {
throw new TypeError(`setVolume() takes a number, got value of type ${typeof vol}`);
}
if (isNaN(vol)) {
throw new TypeError(`setVolume() got a number that is NaN. Volume must be between 0 and 1.`);
}
if (vol < 0 || vol > 1) {
throw new TypeError(`setVolume() got a number that is out of range. Must be between 0 and 1, got ${typeof vol}`);
}
setMediaVolume(vol);
},
isMuted: () => isMuted,
mute: () => {
setMediaMuted(true);
},
unmute: () => {
setMediaMuted(false);
},
getScale: () => scale,
pauseAndReturnToPlayStart: () => {
player.pauseAndReturnToPlayStart();
},
};
return Object.assign(player.emitter, methods);
}, [
durationInFrames,
exitFullscreen,
loop,
mediaMuted,
isMuted,
mediaVolume,
player,
requestFullscreen,
setMediaMuted,
setMediaVolume,
toggle,
scale,
]);
const VideoComponent = video ? video.component : null;
const outerStyle = (0, react_1.useMemo)(() => {
return (0, calculate_scale_js_1.calculateOuterStyle)({
canvasSize,
config,
style,
overflowVisible,
layout,
});
}, [canvasSize, config, layout, overflowVisible, style]);
const outer = (0, react_1.useMemo)(() => {
return (0, calculate_scale_js_1.calculateOuter)({ config, layout, scale, overflowVisible });
}, [config, layout, overflowVisible, scale]);
const containerStyle = (0, react_1.useMemo)(() => {
return (0, calculate_scale_js_1.calculateContainerStyle)({
config,
layout,
scale,
overflowVisible,
});
}, [config, layout, overflowVisible, scale]);
const playerPause = player.pause;
const playerDispatchError = player.emitter.dispatchError;
const onError = (0, react_1.useCallback)((error) => {
playerPause();
// Pay attention to `this context`
playerDispatchError(error);
}, [playerDispatchError, playerPause]);
const onFullscreenButtonClick = (0, react_1.useCallback)((e) => {
e.stopPropagation();
requestFullscreen();
}, [requestFullscreen]);
const onExitFullscreenButtonClick = (0, react_1.useCallback)((e) => {
e.stopPropagation();
exitFullscreen();
}, [exitFullscreen]);
const onSingleClick = (0, react_1.useCallback)((e) => {
const rightClick = e instanceof MouseEvent ? e.button === 2 : e.nativeEvent.button;
if (rightClick) {
return;
}
toggle(e);
}, [toggle]);
const onSeekStart = (0, react_1.useCallback)(() => {
setSeeking(true);
}, []);
const onSeekEnd = (0, react_1.useCallback)(() => {
setSeeking(false);
}, []);
const onDoubleClick = (0, react_1.useCallback)(() => {
if (isFullscreen) {
exitFullscreen();
}
else {
requestFullscreen();
}
}, [exitFullscreen, isFullscreen, requestFullscreen]);
const { handlePointerDown, handleDoubleClick } = (0, use_click_prevention_on_double_click_js_1.useClickPreventionOnDoubleClick)(onSingleClick, onDoubleClick, doubleClickToFullscreen && allowFullscreen && supportsFullScreen);
(0, react_1.useEffect)(() => {
if (shouldAutoplay) {
player.play();
setShouldAutoPlay(false);
}
}, [shouldAutoplay, player]);
const loadingMarkup = (0, react_1.useMemo)(() => {
return renderLoading
? renderLoading({
height: outerStyle.height,
width: outerStyle.width,
isBuffering: showBufferIndicator,
})
: null;
}, [outerStyle.height, outerStyle.width, renderLoading, showBufferIndicator]);
const currentScale = (0, react_1.useMemo)(() => {
return {
type: 'scale',
scale,
};
}, [scale]);
if (!config) {
return null;
}
const poster = renderPoster
? renderPoster({
height: posterFillMode === 'player-size'
? outerStyle.height
: config.height,
width: posterFillMode === 'player-size'
? outerStyle.width
: config.width,
isBuffering: showBufferIndicator,
})
: null;
if (poster === undefined) {
throw new TypeError('renderPoster() must return a React element, but undefined was returned');
}
const shouldShowPoster = poster &&
[
showPosterWhenPaused && !player.isPlaying() && !seeking,
showPosterWhenEnded && player.isLastFrame && !player.isPlaying(),
showPosterWhenUnplayed && !player.hasPlayed && !player.isPlaying(),
showPosterWhenBuffering && showBufferIndicator && player.isPlaying(),
showPosterWhenBufferingAndPaused &&
showBufferIndicator &&
!player.isPlaying(),
].some(Boolean);
const { left, top, width, height, ...outerWithoutScale } = outer;
const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { style: outer, onPointerDown: clickToPlay ? handlePointerDown : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: [(0, jsx_runtime_1.jsxs)("div", { style: containerStyle, className: (0, player_css_classname_js_1.playerCssClassname)(overrideInternalClassName), children: [VideoComponent ? ((0, jsx_runtime_1.jsx)(error_boundary_js_1.ErrorBoundary, { onError: onError, errorFallback: errorFallback, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.CurrentScaleContext.Provider, { value: currentScale, children: (0, jsx_runtime_1.jsx)(VideoComponent, { ...((_c = video === null || video === void 0 ? void 0 : video.props) !== null && _c !== void 0 ? _c : {}), ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}) }) }) })) : null, shouldShowPoster && posterFillMode === 'composition-size' ? ((0, jsx_runtime_1.jsx)("div", { style: {
...outerWithoutScale,
width: config.width,
height: config.height,
}, onPointerDown: clickToPlay ? handlePointerDown : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null] }), (0, jsx_runtime_1.jsx)(license_blacklist_js_1.RenderWarningIfBlacklist, {})] }), shouldShowPoster && posterFillMode === 'player-size' ? ((0, jsx_runtime_1.jsx)("div", { style: outer, onPointerDown: clickToPlay ? handlePointerDown : undefined, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, children: poster })) : null, controls ? ((0, jsx_runtime_1.jsx)(PlayerControls_js_1.Controls, { fps: config.fps, playing: player.playing, toggle: player.toggle, durationInFrames: config.durationInFrames, containerRef: container, onFullscreenButtonClick: onFullscreenButtonClick, isFullscreen: isFullscreen, allowFullscreen: allowFullscreen, showVolumeControls: showVolumeControls, onExitFullscreenButtonClick: onExitFullscreenButtonClick, spaceKeyToPlayOrPause: spaceKeyToPlayOrPause, onSeekEnd: onSeekEnd, onSeekStart: onSeekStart, inFrame: inFrame, outFrame: outFrame, initiallyShowControls: initiallyShowControls, canvasSize: canvasSize, renderFullscreenButton: renderFullscreenButton, renderPlayPauseButton: renderPlayPauseButton, alwaysShowControls: alwaysShowControls, showPlaybackRateControl: showPlaybackRateControl, buffering: showBufferIndicator, hideControlsWhenPointerDoesntMove: hideControlsWhenPointerDoesntMove, onDoubleClick: doubleClickToFullscreen ? handleDoubleClick : undefined, onPointerDown: clickToPlay
? handlePointerDown
: undefined, renderMuteButton: renderMuteButton, renderVolumeSlider: renderVolumeSlider, renderCustomControls: renderCustomControls })) : null] }));
if (noSuspense || (is_node_js_1.IS_NODE && !doesReactVersionSupportSuspense)) {
return ((0, jsx_runtime_1.jsx)("div", { ref: container, style: outerStyle, className: className, children: content }));
}
return ((0, jsx_runtime_1.jsx)("div", { ref: container, style: outerStyle, className: className, children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: loadingMarkup, children: content }) }));
};
exports.default = (0, react_1.forwardRef)(PlayerUI);
@@ -0,0 +1,20 @@
import type { ComponentType, LazyExoticComponent } from 'react';
import React from 'react';
import type { LogLevel, TimelineContextValue } from 'remotion';
export declare const PLAYER_COMP_ID = "player-comp";
export declare const SharedPlayerContexts: React.FC<{
readonly children: React.ReactNode;
readonly timelineContext: TimelineContextValue;
readonly fps: number;
readonly compositionWidth: number;
readonly compositionHeight: number;
readonly durationInFrames: number;
readonly component: LazyExoticComponent<ComponentType<unknown>>;
readonly numberOfSharedAudioTags: number;
readonly initiallyMuted: boolean;
readonly logLevel: LogLevel;
readonly audioLatencyHint: AudioContextLatencyCategory;
readonly volumePersistenceKey?: string;
readonly inputProps: Record<string, unknown>;
readonly audioEnabled: boolean;
}>;
@@ -0,0 +1,86 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SharedPlayerContexts = exports.PLAYER_COMP_ID = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const volume_persistance_js_1 = require("./volume-persistance.js");
exports.PLAYER_COMP_ID = 'player-comp';
const SharedPlayerContexts = ({ children, timelineContext, fps, compositionHeight, compositionWidth, durationInFrames, component, numberOfSharedAudioTags, initiallyMuted, logLevel, audioLatencyHint, volumePersistenceKey, inputProps, audioEnabled, }) => {
const compositionManagerContext = (0, react_1.useMemo)(() => {
const context = {
compositions: [
{
component: component,
durationInFrames,
height: compositionHeight,
width: compositionWidth,
fps,
id: exports.PLAYER_COMP_ID,
nonce: 777,
folderName: null,
parentFolderName: null,
schema: null,
calculateMetadata: null,
},
],
folders: [],
currentCompositionMetadata: {
defaultCodec: null,
defaultOutName: null,
defaultPixelFormat: null,
defaultProResProfile: null,
defaultVideoImageFormat: null,
durationInFrames,
fps,
height: compositionHeight,
width: compositionWidth,
props: inputProps,
},
canvasContent: { type: 'composition', compositionId: 'player-comp' },
};
return context;
}, [
component,
durationInFrames,
compositionHeight,
compositionWidth,
fps,
inputProps,
]);
const [mediaMuted, setMediaMuted] = (0, react_1.useState)(() => initiallyMuted);
const [mediaVolume, setMediaVolume] = (0, react_1.useState)(() => (0, volume_persistance_js_1.getPreferredVolume)(volumePersistenceKey !== null && volumePersistenceKey !== void 0 ? volumePersistenceKey : null));
const mediaVolumeContextValue = (0, react_1.useMemo)(() => {
return {
mediaMuted,
mediaVolume,
};
}, [mediaMuted, mediaVolume]);
const setMediaVolumeAndPersist = (0, react_1.useCallback)((vol) => {
setMediaVolume(vol);
(0, volume_persistance_js_1.persistVolume)(vol, logLevel, volumePersistenceKey !== null && volumePersistenceKey !== void 0 ? volumePersistenceKey : null);
}, [logLevel, volumePersistenceKey]);
const setMediaVolumeContextValue = (0, react_1.useMemo)(() => {
return {
setMediaMuted,
setMediaVolume: setMediaVolumeAndPersist,
};
}, [setMediaVolumeAndPersist]);
const logLevelContext = (0, react_1.useMemo)(() => {
return {
logLevel,
mountTime: Date.now(),
};
}, [logLevel]);
const env = (0, react_1.useMemo)(() => {
return {
isPlayer: true,
isRendering: false,
isStudio: false,
isClientSideRendering: false,
isReadOnlyStudio: false,
};
}, []);
return ((0, jsx_runtime_1.jsx)(remotion_1.Internals.RemotionEnvironmentContext.Provider, { value: env, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.LogLevelContext.Provider, { value: logLevelContext, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.CanUseRemotionHooksProvider, { children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.TimelineContext.Provider, { value: timelineContext, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.CompositionManager.Provider, { value: compositionManagerContext, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.DurationsContextProvider, { 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, audioLatencyHint: audioLatencyHint, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.BufferingProvider, { children: children }) }) }) }) }) }) }) }) }) }) }));
};
exports.SharedPlayerContexts = SharedPlayerContexts;
@@ -0,0 +1,23 @@
import type { CSSProperties } from 'react';
import type { CompProps, LogLevel } from 'remotion';
import type { AnyZodObject } from 'zod';
import type { ThumbnailMethods } from './player-methods.js';
import type { ErrorFallback, RenderLoading } from './PlayerUI.js';
import type { PropsIfHasProps } from './utils/props-if-has-props.js';
export type ThumbnailProps<Schema extends AnyZodObject, Props extends Record<string, unknown>> = PropsIfHasProps<Schema, Props> & CompProps<Props> & {
readonly frameToDisplay: number;
readonly style?: CSSProperties;
readonly durationInFrames: number;
readonly compositionWidth: number;
readonly compositionHeight: number;
readonly fps: number;
readonly overflowVisible?: boolean;
readonly errorFallback?: ErrorFallback;
readonly renderLoading?: RenderLoading;
readonly className?: string;
readonly overrideInternalClassName?: string;
readonly logLevel?: LogLevel;
readonly noSuspense?: boolean;
};
export type ThumbnailPropsWithoutZod<Props extends Record<string, unknown>> = ThumbnailProps<AnyZodObject, Props>;
export declare const Thumbnail: <Schema extends AnyZodObject, Props extends Record<string, unknown>>(props: ThumbnailProps<Schema, Props> & import("react").RefAttributes<ThumbnailMethods>) => React.ReactElement | null;
@@ -0,0 +1,58 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Thumbnail = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const emitter_context_js_1 = require("./emitter-context.js");
const event_emitter_js_1 = require("./event-emitter.js");
const SharedPlayerContext_js_1 = require("./SharedPlayerContext.js");
const ThumbnailUI_js_1 = __importDefault(require("./ThumbnailUI.js"));
const ThumbnailFn = ({ frameToDisplay, style, inputProps, compositionHeight, compositionWidth, durationInFrames, fps, className, errorFallback = () => '⚠️', renderLoading, overflowVisible = false, overrideInternalClassName, logLevel = 'info', noSuspense, ...componentProps }, ref) => {
if (typeof window !== 'undefined') {
// eslint-disable-next-line react-hooks/rules-of-hooks
(0, react_1.useLayoutEffect)(() => {
window.remotion_isPlayer = true;
}, []);
}
const [thumbnailId] = (0, react_1.useState)(() => String((0, remotion_1.random)(null)));
const rootRef = (0, react_1.useRef)(null);
const timelineState = (0, react_1.useMemo)(() => {
const value = {
playing: false,
frame: {
[SharedPlayerContext_js_1.PLAYER_COMP_ID]: frameToDisplay,
},
rootId: thumbnailId,
imperativePlaying: {
current: false,
},
playbackRate: 1,
setPlaybackRate: () => {
throw new Error('thumbnail');
},
audioAndVideoTags: { current: [] },
};
return value;
}, [frameToDisplay, thumbnailId]);
(0, react_1.useImperativeHandle)(ref, () => rootRef.current, []);
const Component = remotion_1.Internals.useLazyComponent({
compProps: componentProps,
componentName: 'Thumbnail',
noSuspense: Boolean(noSuspense),
});
const [emitter] = (0, react_1.useState)(() => new event_emitter_js_1.ThumbnailEmitter());
const passedInputProps = (0, react_1.useMemo)(() => {
return inputProps !== null && inputProps !== void 0 ? inputProps : {};
}, [inputProps]);
return ((0, jsx_runtime_1.jsx)(remotion_1.Internals.IsPlayerContextProvider, { children: (0, jsx_runtime_1.jsx)(SharedPlayerContext_js_1.SharedPlayerContexts, { timelineContext: timelineState, component: Component, compositionHeight: compositionHeight, compositionWidth: compositionWidth, durationInFrames: durationInFrames, fps: fps, numberOfSharedAudioTags: 0, initiallyMuted: true, logLevel: logLevel, audioLatencyHint: "playback", inputProps: passedInputProps, audioEnabled: false, children: (0, jsx_runtime_1.jsx)(emitter_context_js_1.ThumbnailEmitterContext.Provider, { value: emitter, children: (0, jsx_runtime_1.jsx)(ThumbnailUI_js_1.default, { ref: rootRef, className: className, errorFallback: errorFallback, inputProps: passedInputProps, renderLoading: renderLoading, style: style, overflowVisible: overflowVisible, overrideInternalClassName: overrideInternalClassName, noSuspense: Boolean(noSuspense) }) }) }) }));
};
const forward = react_1.forwardRef;
/*
* @description A component which can be rendered in a regular React App (for example: for example: Next.JS, Vite.js, Create React App) to display a single frame of a video.
* @see [Documentation](https://www.remotion.dev/docs/player/thumbnail)
*/
exports.Thumbnail = forward(ThumbnailFn);
@@ -0,0 +1,14 @@
import React from 'react';
import type { ThumbnailMethods } from './player-methods.js';
import type { ErrorFallback, RenderLoading } from './PlayerUI.js';
declare const _default: React.ForwardRefExoticComponent<{
readonly inputProps: Record<string, unknown>;
readonly style?: React.CSSProperties;
readonly errorFallback: ErrorFallback;
readonly renderLoading: RenderLoading | undefined;
readonly className: string | undefined;
readonly overflowVisible: boolean;
readonly overrideInternalClassName: string | undefined;
readonly noSuspense: boolean;
} & React.RefAttributes<ThumbnailMethods>>;
export default _default;
@@ -0,0 +1,130 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importStar(require("react"));
const remotion_1 = require("remotion");
const calculate_scale_js_1 = require("./calculate-scale.js");
const error_boundary_js_1 = require("./error-boundary.js");
const player_css_classname_js_1 = require("./player-css-classname.js");
const use_buffer_state_emitter_js_1 = require("./use-buffer-state-emitter.js");
const use_thumbnail_js_1 = require("./use-thumbnail.js");
const is_node_js_1 = require("./utils/is-node.js");
const use_element_size_js_1 = require("./utils/use-element-size.js");
const reactVersion = react_1.default.version.split('.')[0];
if (reactVersion === '0') {
throw new Error(`Version ${reactVersion} of "react" is not supported by Remotion`);
}
const doesReactVersionSupportSuspense = parseInt(reactVersion, 10) >= 18;
const ThumbnailUI = ({ style, inputProps, errorFallback, renderLoading, className, overflowVisible, noSuspense, overrideInternalClassName, }, ref) => {
var _a, _b;
const config = remotion_1.Internals.useUnsafeVideoConfig();
const video = remotion_1.Internals.useVideo();
const container = (0, react_1.useRef)(null);
const canvasSize = (0, use_element_size_js_1.useElementSize)(container, {
triggerOnWindowResize: false,
shouldApplyCssTransforms: false,
});
const layout = (0, react_1.useMemo)(() => {
if (!config || !canvasSize) {
return null;
}
return (0, calculate_scale_js_1.calculateCanvasTransformation)({
canvasSize,
compositionHeight: config.height,
compositionWidth: config.width,
previewSize: 'auto',
});
}, [canvasSize, config]);
const scale = (_a = layout === null || layout === void 0 ? void 0 : layout.scale) !== null && _a !== void 0 ? _a : 1;
const thumbnail = (0, use_thumbnail_js_1.useThumbnail)();
(0, use_buffer_state_emitter_js_1.useBufferStateEmitter)(thumbnail.emitter);
(0, react_1.useImperativeHandle)(ref, () => {
const methods = {
getContainerNode: () => container.current,
getScale: () => scale,
};
return Object.assign(thumbnail.emitter, methods);
}, [scale, thumbnail.emitter]);
const VideoComponent = video ? video.component : null;
const outerStyle = (0, react_1.useMemo)(() => {
return (0, calculate_scale_js_1.calculateOuterStyle)({
config,
style,
canvasSize,
overflowVisible,
layout,
});
}, [canvasSize, config, layout, overflowVisible, style]);
const outer = (0, react_1.useMemo)(() => {
return (0, calculate_scale_js_1.calculateOuter)({ config, layout, scale, overflowVisible });
}, [config, layout, overflowVisible, scale]);
const containerStyle = (0, react_1.useMemo)(() => {
return (0, calculate_scale_js_1.calculateContainerStyle)({
config,
layout,
scale,
overflowVisible,
});
}, [config, layout, overflowVisible, scale]);
const onError = (0, react_1.useCallback)((error) => {
// Pay attention to `this context`
thumbnail.emitter.dispatchError(error);
}, [thumbnail.emitter]);
const loadingMarkup = (0, react_1.useMemo)(() => {
return renderLoading
? renderLoading({
height: outerStyle.height,
width: outerStyle.width,
isBuffering: false,
})
: null;
}, [outerStyle.height, outerStyle.width, renderLoading]);
const currentScaleContext = (0, react_1.useMemo)(() => {
return {
type: 'scale',
scale,
};
}, [scale]);
if (!config) {
return null;
}
const content = ((0, jsx_runtime_1.jsx)("div", { style: outer, children: (0, jsx_runtime_1.jsx)("div", { style: containerStyle, className: (0, player_css_classname_js_1.playerCssClassname)(overrideInternalClassName), children: VideoComponent ? ((0, jsx_runtime_1.jsx)(error_boundary_js_1.ErrorBoundary, { onError: onError, errorFallback: errorFallback, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.CurrentScaleContext.Provider, { value: currentScaleContext, children: (0, jsx_runtime_1.jsx)(VideoComponent, { ...((_b = video === null || video === void 0 ? void 0 : video.props) !== null && _b !== void 0 ? _b : {}), ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}) }) }) })) : null }) }));
if (noSuspense || (is_node_js_1.IS_NODE && !doesReactVersionSupportSuspense)) {
return ((0, jsx_runtime_1.jsx)("div", { ref: container, style: outerStyle, className: className, children: content }));
}
return ((0, jsx_runtime_1.jsx)("div", { ref: container, style: outerStyle, className: className, children: (0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: loadingMarkup, children: content }) }));
};
exports.default = (0, react_1.forwardRef)(ThumbnailUI);
@@ -0,0 +1 @@
export {};
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
if (typeof react_1.createContext !== 'function') {
const err = [
'Remotion requires React.createContext, but it is "undefined".',
'If you are in a React Server Component, turn it into a client component by adding "use client" at the top of the file.',
'',
'Before:',
' import {Player} from "@remotion/player";',
'',
'After:',
' "use client";',
' import {Player} from "@remotion/player";',
];
throw new Error(err.join('\n'));
}
@@ -0,0 +1,13 @@
import type { VideoConfig } from 'remotion';
export type BrowserMediaControlsBehavior = {
mode: 'do-nothing';
} | {
mode: 'prevent-media-session';
} | {
mode: 'register-media-session';
};
export declare const useBrowserMediaSession: ({ browserMediaControlsBehavior, videoConfig, playbackRate, }: {
browserMediaControlsBehavior: BrowserMediaControlsBehavior;
videoConfig: VideoConfig | null;
playbackRate: number;
}) => void;
@@ -0,0 +1,111 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useBrowserMediaSession = void 0;
const react_1 = require("react");
const use_player_js_1 = require("./use-player.js");
const useBrowserMediaSession = ({ browserMediaControlsBehavior, videoConfig, playbackRate, }) => {
const { playing, pause, play, emitter, getCurrentFrame, seek } = (0, use_player_js_1.usePlayer)();
(0, react_1.useEffect)(() => {
if (!navigator.mediaSession) {
return;
}
if (browserMediaControlsBehavior.mode === 'do-nothing') {
return;
}
if (playing) {
navigator.mediaSession.playbackState = 'playing';
}
else {
navigator.mediaSession.playbackState = 'paused';
}
}, [browserMediaControlsBehavior.mode, playing]);
(0, react_1.useEffect)(() => {
if (!navigator.mediaSession) {
return;
}
if (browserMediaControlsBehavior.mode === 'do-nothing') {
return;
}
const onTimeUpdate = () => {
if (!videoConfig) {
return;
}
if (navigator.mediaSession) {
navigator.mediaSession.setPositionState({
duration: videoConfig.durationInFrames / videoConfig.fps,
playbackRate,
position: getCurrentFrame() / videoConfig.fps,
});
}
};
emitter.addEventListener('timeupdate', onTimeUpdate);
return () => {
emitter.removeEventListener('timeupdate', onTimeUpdate);
};
}, [
browserMediaControlsBehavior.mode,
emitter,
getCurrentFrame,
playbackRate,
videoConfig,
]);
(0, react_1.useEffect)(() => {
if (!navigator.mediaSession) {
return;
}
if (browserMediaControlsBehavior.mode === 'do-nothing') {
return;
}
navigator.mediaSession.setActionHandler('play', () => {
if (browserMediaControlsBehavior.mode === 'register-media-session') {
play();
}
});
navigator.mediaSession.setActionHandler('pause', () => {
if (browserMediaControlsBehavior.mode === 'register-media-session') {
pause();
}
});
navigator.mediaSession.setActionHandler('seekto', (event) => {
if (browserMediaControlsBehavior.mode === 'register-media-session' &&
event.seekTime !== undefined &&
videoConfig) {
seek(Math.round(event.seekTime * videoConfig.fps));
}
});
navigator.mediaSession.setActionHandler('seekbackward', () => {
if (browserMediaControlsBehavior.mode === 'register-media-session' &&
videoConfig) {
seek(Math.max(0, Math.round((getCurrentFrame() - 10) * videoConfig.fps)));
}
});
navigator.mediaSession.setActionHandler('seekforward', () => {
if (browserMediaControlsBehavior.mode === 'register-media-session' &&
videoConfig) {
seek(Math.max(videoConfig.durationInFrames - 1, Math.round((getCurrentFrame() + 10) * videoConfig.fps)));
}
});
navigator.mediaSession.setActionHandler('previoustrack', () => {
if (browserMediaControlsBehavior.mode === 'register-media-session') {
seek(0);
}
});
return () => {
navigator.mediaSession.metadata = null;
navigator.mediaSession.setActionHandler('play', null);
navigator.mediaSession.setActionHandler('pause', null);
navigator.mediaSession.setActionHandler('seekto', null);
navigator.mediaSession.setActionHandler('seekbackward', null);
navigator.mediaSession.setActionHandler('seekforward', null);
navigator.mediaSession.setActionHandler('previoustrack', null);
};
}, [
browserMediaControlsBehavior.mode,
getCurrentFrame,
pause,
play,
seek,
videoConfig,
]);
};
exports.useBrowserMediaSession = useBrowserMediaSession;
@@ -0,0 +1,14 @@
export declare const calculateNextFrame: ({ time, currentFrame: startFrame, playbackSpeed, fps, actualLastFrame, actualFirstFrame, framesAdvanced, shouldLoop, }: {
time: number;
currentFrame: number;
playbackSpeed: number;
fps: number;
actualFirstFrame: number;
actualLastFrame: number;
framesAdvanced: number;
shouldLoop: boolean;
}) => {
nextFrame: number;
framesToAdvance: number;
hasEnded: boolean;
};
@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateNextFrame = void 0;
const calculateNextFrame = ({ time, currentFrame: startFrame, playbackSpeed, fps, actualLastFrame, actualFirstFrame, framesAdvanced, shouldLoop, }) => {
const op = playbackSpeed < 0 ? Math.ceil : Math.floor;
const framesToAdvance = op((time * playbackSpeed) / (1000 / fps)) - framesAdvanced;
const nextFrame = framesToAdvance + startFrame;
const isCurrentFrameOutside = startFrame > actualLastFrame || startFrame < actualFirstFrame;
const isNextFrameOutside = nextFrame > actualLastFrame || nextFrame < actualFirstFrame;
const hasEnded = !shouldLoop && isNextFrameOutside && !isCurrentFrameOutside;
if (playbackSpeed > 0) {
// Play forwards
if (isNextFrameOutside) {
return {
nextFrame: actualFirstFrame,
framesToAdvance,
hasEnded,
};
}
return { nextFrame, framesToAdvance, hasEnded };
}
// Reverse playback
if (isNextFrameOutside) {
return { nextFrame: actualLastFrame, framesToAdvance, hasEnded };
}
return { nextFrame, framesToAdvance, hasEnded };
};
exports.calculateNextFrame = calculateNextFrame;
@@ -0,0 +1,62 @@
import type { PreviewSize, VideoConfig } from 'remotion';
import type { Size } from './utils/use-element-size.js';
type Layout = {
centerX: number;
centerY: number;
xCorrection: number;
yCorrection: number;
scale: number;
};
export declare const calculateCanvasTransformation: ({ previewSize, compositionWidth, compositionHeight, canvasSize, }: {
previewSize: PreviewSize["size"];
compositionWidth: number;
compositionHeight: number;
canvasSize: Size;
}) => Layout;
export declare const calculateOuterStyle: ({ config, style, canvasSize, overflowVisible, layout, }: {
config: VideoConfig | null;
style: React.CSSProperties | undefined;
canvasSize: Size | null;
overflowVisible: boolean;
layout: Layout | null;
}) => React.CSSProperties;
export declare const calculateContainerStyle: ({ config, layout, scale, overflowVisible, }: {
config: VideoConfig | null;
layout: Layout | null;
scale: number;
overflowVisible: boolean;
}) => React.CSSProperties;
export declare const calculateOuter: ({ layout, scale, config, overflowVisible, }: {
layout: Layout | null;
scale: number;
config: VideoConfig | null;
overflowVisible: boolean;
}) => {
readonly width?: undefined;
readonly height?: undefined;
readonly display?: undefined;
readonly flexDirection?: undefined;
readonly position?: undefined;
readonly overflow?: undefined;
readonly left?: undefined;
readonly top?: undefined;
} | {
readonly width: number;
readonly height: number;
readonly display: "flex";
readonly flexDirection: "column";
readonly position: "absolute";
readonly overflow: "hidden" | "visible";
readonly left?: undefined;
readonly top?: undefined;
} | {
readonly width: number;
readonly height: number;
readonly display: "flex";
readonly flexDirection: "column";
readonly position: "absolute";
readonly left: number;
readonly top: number;
readonly overflow: "hidden" | "visible";
};
export {};
@@ -0,0 +1,100 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateOuter = exports.calculateContainerStyle = exports.calculateOuterStyle = exports.calculateCanvasTransformation = void 0;
const remotion_1 = require("remotion");
const calculate_player_size_js_1 = require("./utils/calculate-player-size.js");
const calculateCanvasTransformation = ({ previewSize, compositionWidth, compositionHeight, canvasSize, }) => {
const scale = remotion_1.Internals.calculateScale({
canvasSize,
compositionHeight,
compositionWidth,
previewSize,
});
const correction = 0 - (1 - scale) / 2;
const xCorrection = correction * compositionWidth;
const yCorrection = correction * compositionHeight;
const width = compositionWidth * scale;
const height = compositionHeight * scale;
const centerX = canvasSize.width / 2 - width / 2;
const centerY = canvasSize.height / 2 - height / 2;
return {
centerX,
centerY,
xCorrection,
yCorrection,
scale,
};
};
exports.calculateCanvasTransformation = calculateCanvasTransformation;
const calculateOuterStyle = ({ config, style, canvasSize, overflowVisible, layout, }) => {
if (!config) {
return {};
}
return {
position: 'relative',
overflow: overflowVisible ? 'visible' : 'hidden',
...(0, calculate_player_size_js_1.calculatePlayerSize)({
compositionHeight: config.height,
compositionWidth: config.width,
currentSize: canvasSize,
height: style === null || style === void 0 ? void 0 : style.height,
width: style === null || style === void 0 ? void 0 : style.width,
}),
opacity: layout ? 1 : 0,
...style,
};
};
exports.calculateOuterStyle = calculateOuterStyle;
const calculateContainerStyle = ({ config, layout, scale, overflowVisible, }) => {
if (!config) {
return {};
}
if (!layout) {
return {
position: 'absolute',
width: config.width,
height: config.height,
display: 'flex',
transform: `scale(${scale})`,
overflow: overflowVisible ? 'visible' : 'hidden',
};
}
return {
position: 'absolute',
width: config.width,
height: config.height,
display: 'flex',
transform: `scale(${scale})`,
marginLeft: layout.xCorrection,
marginTop: layout.yCorrection,
overflow: overflowVisible ? 'visible' : 'hidden',
};
};
exports.calculateContainerStyle = calculateContainerStyle;
const calculateOuter = ({ layout, scale, config, overflowVisible, }) => {
if (!config) {
return {};
}
if (!layout) {
return {
width: config.width * scale,
height: config.height * scale,
display: 'flex',
flexDirection: 'column',
position: 'absolute',
overflow: overflowVisible ? 'visible' : 'hidden',
};
}
const { centerX, centerY } = layout;
return {
width: config.width * scale,
height: config.height * scale,
display: 'flex',
flexDirection: 'column',
position: 'absolute',
left: centerX,
top: centerY,
overflow: overflowVisible ? 'visible' : 'hidden',
};
};
exports.calculateOuter = calculateOuter;
@@ -0,0 +1,4 @@
import React from 'react';
import type { PlayerEmitter, ThumbnailEmitter } from './event-emitter.js';
export declare const PlayerEventEmitterContext: React.Context<PlayerEmitter | undefined>;
export declare const ThumbnailEmitterContext: React.Context<ThumbnailEmitter | undefined>;
@@ -0,0 +1,9 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThumbnailEmitterContext = exports.PlayerEventEmitterContext = void 0;
const react_1 = __importDefault(require("react"));
exports.PlayerEventEmitterContext = react_1.default.createContext(undefined);
exports.ThumbnailEmitterContext = react_1.default.createContext(undefined);
@@ -0,0 +1,19 @@
import React from 'react';
export declare class ErrorBoundary extends React.Component<{
onError: (error: Error) => void;
children: React.ReactNode;
errorFallback: (info: {
error: Error;
}) => React.ReactNode;
}, {
hasError: Error | null;
}> {
state: {
hasError: null;
};
static getDerivedStateFromError(error: Error): {
hasError: Error;
};
componentDidCatch(error: Error): void;
render(): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined;
}
@@ -0,0 +1,39 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ErrorBoundary = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
const errorStyle = {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flex: 1,
height: '100%',
width: '100%',
};
class ErrorBoundary extends react_1.default.Component {
constructor() {
super(...arguments);
this.state = { hasError: null };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: error };
}
componentDidCatch(error) {
this.props.onError(error);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return ((0, jsx_runtime_1.jsx)("div", { style: errorStyle, children: this.props.errorFallback({
error: this.state.hasError,
}) }));
}
return this.props.children;
}
}
exports.ErrorBoundary = ErrorBoundary;
@@ -0,0 +1,91 @@
type SeekPayload = {
frame: number;
};
type ErrorPayload = {
error: Error;
};
type TimeUpdateEventPayload = {
frame: number;
};
type FrameUpdateEventPayload = {
frame: number;
};
type RateChangeEventPayload = {
playbackRate: number;
};
type ScaleChangeEventPayload = {
scale: number;
};
type VolumeChangeEventPayload = {
volume: number;
};
type FullscreenChangeEventPayload = {
isFullscreen: boolean;
};
type MuteChangeEventPayload = {
isMuted: boolean;
};
type WaitingEventPayload = {};
type ResumeEventPayload = {};
type PlayerStateEventMap = {
seeked: SeekPayload;
pause: undefined;
play: undefined;
ratechange: RateChangeEventPayload;
scalechange: ScaleChangeEventPayload;
volumechange: VolumeChangeEventPayload;
ended: undefined;
error: ErrorPayload;
timeupdate: TimeUpdateEventPayload;
frameupdate: FrameUpdateEventPayload;
fullscreenchange: FullscreenChangeEventPayload;
mutechange: MuteChangeEventPayload;
waiting: WaitingEventPayload;
resume: ResumeEventPayload;
};
type ThumbnailStateEventMap = {
error: ErrorPayload;
waiting: WaitingEventPayload;
resume: ResumeEventPayload;
};
export type PlayerEventTypes = keyof PlayerStateEventMap;
export type ThumbnailEventTypes = keyof ThumbnailStateEventMap;
export type CallbackListener<T extends PlayerEventTypes> = (data: {
detail: PlayerStateEventMap[T];
}) => void;
type PlayerListeners = {
[EventType in PlayerEventTypes]: CallbackListener<EventType>[];
};
type ThumbnailListeners = {
[EventType in ThumbnailEventTypes]: CallbackListener<EventType>[];
};
export declare class PlayerEmitter {
listeners: PlayerListeners;
addEventListener<Q extends PlayerEventTypes>(name: Q, callback: CallbackListener<Q>): void;
removeEventListener<Q extends PlayerEventTypes>(name: Q, callback: CallbackListener<Q>): void;
private dispatchEvent;
dispatchSeek: (frame: number) => void;
dispatchVolumeChange: (volume: number) => void;
dispatchPause: () => void;
dispatchPlay: () => void;
dispatchEnded: () => void;
dispatchRateChange: (playbackRate: number) => void;
dispatchScaleChange: (scale: number) => void;
dispatchError: (error: Error) => void;
dispatchTimeUpdate: (event: TimeUpdateEventPayload) => void;
dispatchFrameUpdate: (event: FrameUpdateEventPayload) => void;
dispatchFullscreenChange: (event: FullscreenChangeEventPayload) => void;
dispatchMuteChange: (event: MuteChangeEventPayload) => void;
dispatchWaiting: (event: WaitingEventPayload) => void;
dispatchResume: (event: ResumeEventPayload) => void;
}
export declare class ThumbnailEmitter {
listeners: ThumbnailListeners;
addEventListener<Q extends ThumbnailEventTypes>(name: Q, callback: CallbackListener<Q>): void;
removeEventListener<Q extends ThumbnailEventTypes>(name: Q, callback: CallbackListener<Q>): void;
private dispatchEvent;
dispatchError: (error: Error) => void;
dispatchWaiting: (event: WaitingEventPayload) => void;
dispatchResume: (event: ResumeEventPayload) => void;
}
export {};
@@ -0,0 +1,119 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThumbnailEmitter = exports.PlayerEmitter = void 0;
class PlayerEmitter {
constructor() {
this.listeners = {
ended: [],
error: [],
pause: [],
play: [],
ratechange: [],
scalechange: [],
seeked: [],
timeupdate: [],
frameupdate: [],
fullscreenchange: [],
volumechange: [],
mutechange: [],
waiting: [],
resume: [],
};
this.dispatchSeek = (frame) => {
this.dispatchEvent('seeked', {
frame,
});
};
this.dispatchVolumeChange = (volume) => {
this.dispatchEvent('volumechange', {
volume,
});
};
this.dispatchPause = () => {
this.dispatchEvent('pause', undefined);
};
this.dispatchPlay = () => {
this.dispatchEvent('play', undefined);
};
this.dispatchEnded = () => {
this.dispatchEvent('ended', undefined);
};
this.dispatchRateChange = (playbackRate) => {
this.dispatchEvent('ratechange', {
playbackRate,
});
};
this.dispatchScaleChange = (scale) => {
this.dispatchEvent('scalechange', {
scale,
});
};
this.dispatchError = (error) => {
this.dispatchEvent('error', {
error,
});
};
this.dispatchTimeUpdate = (event) => {
this.dispatchEvent('timeupdate', event);
};
this.dispatchFrameUpdate = (event) => {
this.dispatchEvent('frameupdate', event);
};
this.dispatchFullscreenChange = (event) => {
this.dispatchEvent('fullscreenchange', event);
};
this.dispatchMuteChange = (event) => {
this.dispatchEvent('mutechange', event);
};
this.dispatchWaiting = (event) => {
this.dispatchEvent('waiting', event);
};
this.dispatchResume = (event) => {
this.dispatchEvent('resume', event);
};
}
addEventListener(name, callback) {
this.listeners[name].push(callback);
}
removeEventListener(name, callback) {
this.listeners[name] = this.listeners[name].filter((l) => l !== callback);
}
dispatchEvent(dispatchName, context) {
this.listeners[dispatchName].forEach((callback) => {
callback({ detail: context });
});
}
}
exports.PlayerEmitter = PlayerEmitter;
class ThumbnailEmitter {
constructor() {
this.listeners = {
error: [],
waiting: [],
resume: [],
};
this.dispatchError = (error) => {
this.dispatchEvent('error', {
error,
});
};
this.dispatchWaiting = (event) => {
this.dispatchEvent('waiting', event);
};
this.dispatchResume = (event) => {
this.dispatchEvent('resume', event);
};
}
addEventListener(name, callback) {
this.listeners[name].push(callback);
}
removeEventListener(name, callback) {
this.listeners[name] = this.listeners[name].filter((l) => l !== callback);
}
dispatchEvent(dispatchName, context) {
this.listeners[dispatchName].forEach((callback) => {
callback({ detail: context });
});
}
}
exports.ThumbnailEmitter = ThumbnailEmitter;
@@ -0,0 +1 @@
export declare const formatTime: (timeInSeconds: number) => string;
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatTime = void 0;
const formatTime = (timeInSeconds) => {
const minutes = Math.floor(timeInSeconds / 60);
const seconds = Math.floor(timeInSeconds - minutes * 60);
return `${String(minutes)}:${String(seconds).padStart(2, '0')}`;
};
exports.formatTime = formatTime;
@@ -0,0 +1,10 @@
import React from 'react';
export declare const ICON_SIZE = 25;
export declare const fullscreenIconSize = 16;
export declare const PlayIcon: React.FC;
export declare const PauseIcon: React.FC;
export declare const FullscreenIcon: React.FC<{
readonly isFullscreen: boolean;
}>;
export declare const VolumeOffIcon: React.FC;
export declare const VolumeOnIcon: React.FC;
@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VolumeOnIcon = exports.VolumeOffIcon = exports.FullscreenIcon = exports.PauseIcon = exports.PlayIcon = exports.fullscreenIconSize = exports.ICON_SIZE = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
exports.ICON_SIZE = 25;
exports.fullscreenIconSize = 16;
const PlayIcon = () => {
return ((0, jsx_runtime_1.jsx)("svg", { width: exports.ICON_SIZE, height: exports.ICON_SIZE, viewBox: "0 0 25 25", fill: "none", children: (0, jsx_runtime_1.jsx)("path", { d: "M8 6.375C7.40904 8.17576 7.06921 10.2486 7.01438 12.3871C6.95955 14.5255 7.19163 16.6547 7.6875 18.5625C9.95364 18.2995 12.116 17.6164 14.009 16.5655C15.902 15.5147 17.4755 14.124 18.6088 12.5C17.5158 10.8949 15.9949 9.51103 14.1585 8.45082C12.3222 7.3906 10.2174 6.68116 8 6.375Z", fill: "white", stroke: "white", strokeWidth: "6.25", strokeLinejoin: "round" }) }));
};
exports.PlayIcon = PlayIcon;
const PauseIcon = () => {
return ((0, jsx_runtime_1.jsxs)("svg", { viewBox: "0 0 100 100", width: exports.ICON_SIZE, height: exports.ICON_SIZE, children: [(0, jsx_runtime_1.jsx)("rect", { x: "25", y: "20", width: "20", height: "60", fill: "#fff", ry: "5", rx: "5" }), (0, jsx_runtime_1.jsx)("rect", { x: "55", y: "20", width: "20", height: "60", fill: "#fff", ry: "5", rx: "5" })] }));
};
exports.PauseIcon = PauseIcon;
const FullscreenIcon = ({ isFullscreen, }) => {
const strokeWidth = 6;
const viewSize = 32;
const out = isFullscreen ? 0 : strokeWidth / 2;
const middleInset = isFullscreen ? strokeWidth * 1.6 : strokeWidth / 2;
const inset = isFullscreen ? strokeWidth * 1.6 : strokeWidth * 2;
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: `
M ${out} ${inset}
L ${middleInset} ${middleInset}
L ${inset} ${out}
`, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" }), (0, jsx_runtime_1.jsx)("path", { d: `
M ${viewSize - out} ${inset}
L ${viewSize - middleInset} ${middleInset}
L ${viewSize - inset} ${out}
`, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" }), (0, jsx_runtime_1.jsx)("path", { d: `
M ${out} ${viewSize - inset}
L ${middleInset} ${viewSize - middleInset}
L ${inset} ${viewSize - out}
`, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" }), (0, jsx_runtime_1.jsx)("path", { d: `
M ${viewSize - out} ${viewSize - inset}
L ${viewSize - middleInset} ${viewSize - middleInset}
L ${viewSize - inset} ${viewSize - out}
`, stroke: "#fff", strokeWidth: strokeWidth, fill: "none" })] }));
};
exports.FullscreenIcon = FullscreenIcon;
const VolumeOffIcon = () => {
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.63 3.63a.996.996 0 000 1.41L7.29 8.7 7 9H4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h3l3.29 3.29c.63.63 1.71.18 1.71-.71v-4.17l4.18 4.18c-.49.37-1.02.68-1.6.91-.36.15-.58.53-.58.92 0 .72.73 1.18 1.39.91.8-.33 1.55-.77 2.22-1.31l1.34 1.34a.996.996 0 101.41-1.41L5.05 3.63c-.39-.39-1.02-.39-1.42 0zM19 12c0 .82-.15 1.61-.41 2.34l1.53 1.53c.56-1.17.88-2.48.88-3.87 0-3.83-2.4-7.11-5.78-8.4-.59-.23-1.22.23-1.22.86v.19c0 .38.25.71.61.85C17.18 6.54 19 9.06 19 12zm-8.71-6.29l-.17.17L12 7.76V6.41c0-.89-1.08-1.33-1.71-.7zM16.5 12A4.5 4.5 0 0014 7.97v1.79l2.48 2.48c.01-.08.02-.16.02-.24z", fill: "#fff" }) }));
};
exports.VolumeOffIcon = VolumeOffIcon;
const VolumeOnIcon = () => {
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" }) }));
};
exports.VolumeOnIcon = VolumeOnIcon;
@@ -0,0 +1,70 @@
import './_check-rsc.js';
import type { CallbackListener, PlayerEventTypes } from './event-emitter.js';
import { PlayerEmitter } from './event-emitter.js';
export type { RenderMuteButton } from './MediaVolumeSlider.js';
export type { PlayerMethods, PlayerRef, RenderCustomControls, ThumbnailMethods, ThumbnailRef, } from './player-methods.js';
export { Player } from './Player.js';
export type { PlayerProps, PlayerPropsWithoutZod } from './Player.js';
export type { RenderFullscreenButton, RenderPlayPauseButton, } from './PlayerControls.js';
export type { ErrorFallback, RenderLoading, RenderPoster } from './PlayerUI.js';
export type { RenderVolumeSlider } from './render-volume-slider.js';
export { Thumbnail } from './Thumbnail.js';
export type { ThumbnailProps, ThumbnailPropsWithoutZod } from './Thumbnail.js';
export type { Size } from './utils/use-element-size.js';
export type { CallbackListener, PlayerEventTypes as EventTypes };
export declare const PlayerInternals: {
PlayerEventEmitterContext: import("react").Context<PlayerEmitter | undefined>;
PlayerEmitter: typeof PlayerEmitter;
usePlayer: () => {
frameBack: (frames: number) => void;
frameForward: (frames: number) => void;
isLastFrame: boolean;
isFirstFrame: boolean;
emitter: PlayerEmitter;
playing: boolean;
play: (e?: import("react").SyntheticEvent | PointerEvent) => void;
pause: () => void;
pauseAndReturnToPlayStart: () => void;
seek: (newFrame: number) => void;
getCurrentFrame: () => number;
isPlaying: () => boolean;
hasPlayed: boolean;
isBuffering: () => boolean;
toggle: (e?: import("react").SyntheticEvent | PointerEvent) => void;
};
usePlayback: ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, outFrame, browserMediaControlsBehavior, getCurrentFrame, }: {
loop: boolean;
playbackRate: number;
moveToBeginningWhenEnded: boolean;
inFrame: number | null;
outFrame: number | null;
browserMediaControlsBehavior: import("./browser-mediasession.js").BrowserMediaControlsBehavior;
getCurrentFrame: import("./use-frame-imperative.js").GetCurrentFrame;
}) => void;
useElementSize: (ref: React.RefObject<HTMLElement | null>, options: {
triggerOnWindowResize: boolean;
shouldApplyCssTransforms: boolean;
}) => import("./utils/use-element-size.js").Size | null;
calculateCanvasTransformation: ({ previewSize, compositionWidth, compositionHeight, canvasSize, }: {
previewSize: import("remotion").PreviewSize["size"];
compositionWidth: number;
compositionHeight: number;
canvasSize: import("./utils/use-element-size.js").Size;
}) => {
centerX: number;
centerY: number;
xCorrection: number;
yCorrection: number;
scale: number;
};
useHoverState: (ref: React.RefObject<HTMLDivElement | null>, hideControlsWhenPointerDoesntMove: boolean | number) => boolean;
updateAllElementsSizes: () => void;
PlayerEmitterProvider: import("react").FC<{
readonly children: React.ReactNode;
readonly currentPlaybackRate: number | null;
}>;
BufferingIndicator: import("react").FC<{
readonly type: "player" | "studio";
}>;
useFrameImperative: () => import("./use-frame-imperative.js").GetCurrentFrame;
};
@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlayerInternals = exports.Thumbnail = exports.Player = void 0;
require("./_check-rsc.js");
const BufferingIndicator_js_1 = require("./BufferingIndicator.js");
const calculate_scale_js_1 = require("./calculate-scale.js");
const emitter_context_js_1 = require("./emitter-context.js");
const EmitterProvider_js_1 = require("./EmitterProvider.js");
const event_emitter_js_1 = require("./event-emitter.js");
const use_frame_imperative_js_1 = require("./use-frame-imperative.js");
const use_hover_state_js_1 = require("./use-hover-state.js");
const use_playback_js_1 = require("./use-playback.js");
const use_player_js_1 = require("./use-player.js");
const use_element_size_js_1 = require("./utils/use-element-size.js");
var Player_js_1 = require("./Player.js");
Object.defineProperty(exports, "Player", { enumerable: true, get: function () { return Player_js_1.Player; } });
var Thumbnail_js_1 = require("./Thumbnail.js");
Object.defineProperty(exports, "Thumbnail", { enumerable: true, get: function () { return Thumbnail_js_1.Thumbnail; } });
exports.PlayerInternals = {
PlayerEventEmitterContext: emitter_context_js_1.PlayerEventEmitterContext,
PlayerEmitter: event_emitter_js_1.PlayerEmitter,
usePlayer: use_player_js_1.usePlayer,
usePlayback: use_playback_js_1.usePlayback,
useElementSize: use_element_size_js_1.useElementSize,
calculateCanvasTransformation: calculate_scale_js_1.calculateCanvasTransformation,
useHoverState: use_hover_state_js_1.useHoverState,
updateAllElementsSizes: use_element_size_js_1.updateAllElementsSizes,
PlayerEmitterProvider: EmitterProvider_js_1.PlayerEmitterProvider,
BufferingIndicator: BufferingIndicator_js_1.BufferingIndicator,
useFrameImperative: use_frame_imperative_js_1.useFrameImperative,
};
@@ -0,0 +1 @@
export declare const useIsBackgrounded: () => import("react").RefObject<boolean>;
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useIsBackgrounded = void 0;
const react_1 = require("react");
const getIsBackgrounded = () => {
if (typeof document === 'undefined') {
return false;
}
return document.visibilityState === 'hidden';
};
const useIsBackgrounded = () => {
const isBackgrounded = (0, react_1.useRef)(getIsBackgrounded());
(0, react_1.useEffect)(() => {
const onVisibilityChange = () => {
isBackgrounded.current = getIsBackgrounded();
};
document.addEventListener('visibilitychange', onVisibilityChange);
return () => {
document.removeEventListener('visibilitychange', onVisibilityChange);
};
}, []);
return isBackgrounded;
};
exports.useIsBackgrounded = useIsBackgrounded;
@@ -0,0 +1,3 @@
import React from 'react';
export declare const getHashOfDomain: () => Promise<string | null>;
export declare const RenderWarningIfBlacklist: React.FC;
@@ -0,0 +1,128 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.RenderWarningIfBlacklist = exports.getHashOfDomain = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importStar(require("react"));
const getHashOfDomain = async () => {
if (typeof window === 'undefined') {
return null;
}
if (typeof window.crypto === 'undefined') {
return null;
}
if (typeof window.crypto.subtle === 'undefined') {
return null;
}
try {
const hashBuffer = await crypto.subtle.digest('SHA-256',
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
// @ts-ignore
new TextEncoder().encode(window.location.hostname));
return Array.from(new Uint8Array(hashBuffer))
.map((b) => b.toString(16).padStart(2, '0'))
.join('');
}
catch (_a) {
return null;
}
};
exports.getHashOfDomain = getHashOfDomain;
const style = {
backgroundColor: 'red',
position: 'absolute',
padding: 12,
fontFamily: 'Arial',
};
const DOMAIN_BLACKLIST = [
'28d262b44cc61fa750f1686b16ad0604dabfe193fbc263eec05c89b7ad4c2cd6',
'4db1b0a94be33165dfefcb3ba03d04c7a2666dd27c496d3dc9fa41858e94925e',
'fbc48530bbf245da790f63675e84e06bab38c3b114fab07eb350025119922bdc',
'7baf10a8932757b1b3a22b3fce10a048747ac2f8eaf638603487e3705b07eb83',
'8a6c21a598d8c667272b5207c051b85997bf5b45d5fb712378be3f27cd72c6a6',
'a2f7aaac9c50a9255e7fc376110c4e0bfe153722dc66ed3c5d3bf2a135f65518',
];
let ran = false;
const RenderWarningIfBlacklist = () => {
const [unlicensed, setUnlicensed] = react_1.default.useState(false);
(0, react_1.useEffect)(() => {
// Prevent firing twice in strict mode
if (ran) {
return;
}
ran = true;
(0, exports.getHashOfDomain)()
.then((hash) => {
if (hash && DOMAIN_BLACKLIST.includes(hash)) {
setUnlicensed(true);
}
})
.catch(() => { });
}, []);
(0, react_1.useEffect)(() => {
if (!unlicensed) {
return;
}
const ensureBanner = () => {
const banner = document.querySelector('.warning-banner');
if (!banner) {
const div = document.createElement('div');
div.className = 'warning-banner';
Object.assign(div.style, style, {
zIndex: '9999',
// @ts-expect-error
cssText: `${style.cssText} !important;`,
});
div.innerHTML = `
<a href="https://github.com/remotion-dev/remotion/pull/4589" style="color: white;">
Remotion Unlicensed Contact hi@remotion.dev
</a>
`;
document.body.appendChild(div);
}
};
// Using MutationObserver to watch for changes
const observer = new MutationObserver(() => ensureBanner());
observer.observe(document.body, { childList: true, subtree: true });
return () => {
observer.disconnect();
};
}, [unlicensed]);
if (!unlicensed) {
return null;
}
return ((0, jsx_runtime_1.jsx)("div", { style: style, className: "warning-banner", children: (0, jsx_runtime_1.jsx)("a", { style: { color: 'white' }, href: "https://github.com/remotion-dev/remotion/pull/4589", children: "Remotion Unlicensed \u2013 Contact hi@remotion.dev" }) }));
};
exports.RenderWarningIfBlacklist = RenderWarningIfBlacklist;
@@ -0,0 +1 @@
export declare const playerCssClassname: (override?: string) => string;
@@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.playerCssClassname = void 0;
const playerCssClassname = (override) => {
return override !== null && override !== void 0 ? override : '__remotion-player';
};
exports.playerCssClassname = playerCssClassname;
@@ -0,0 +1,26 @@
import type { ReactElement, SyntheticEvent } from 'react';
import type { PlayerEmitter, ThumbnailEmitter } from './event-emitter.js';
export type ThumbnailMethods = {
getContainerNode: () => HTMLDivElement | null;
getScale: () => number;
};
export type PlayerMethods = ThumbnailMethods & {
play: (e?: SyntheticEvent) => void;
pause: () => void;
toggle: (e?: SyntheticEvent) => void;
seekTo: (frame: number) => void;
getCurrentFrame: () => number;
requestFullscreen: () => void;
exitFullscreen: () => void;
isFullscreen: () => boolean;
setVolume: (num: number) => void;
getVolume: () => number;
isMuted: () => boolean;
isPlaying: () => boolean;
mute: () => void;
unmute: () => void;
pauseAndReturnToPlayStart: () => void;
};
export type ThumbnailRef = ThumbnailEmitter & ThumbnailMethods;
export type PlayerRef = PlayerEmitter & PlayerMethods;
export type RenderCustomControls = () => ReactElement | null;
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,11 @@
import React from 'react';
type RenderVolumeSliderProps = {
readonly volume: number;
readonly isVertical: boolean;
readonly onBlur: () => void;
readonly inputRef: React.RefObject<HTMLInputElement | null>;
readonly setVolume: (u: number) => void;
};
export type RenderVolumeSlider = (props: RenderVolumeSliderProps) => React.ReactNode;
export declare const renderDefaultVolumeSlider: RenderVolumeSlider;
export {};
@@ -0,0 +1,122 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderDefaultVolumeSlider = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importStar(require("react"));
const remotion_1 = require("remotion");
const MediaVolumeSlider_1 = require("./MediaVolumeSlider");
const icons_1 = require("./icons");
const KNOB_SIZE = 12;
const BAR_HEIGHT = 5;
const DefaultVolumeSlider = ({ volume, isVertical, onBlur, inputRef, setVolume, }) => {
const sliderContainer = (0, react_1.useMemo)(() => {
const paddingLeft = 5;
const common = {
paddingLeft,
height: icons_1.ICON_SIZE,
width: MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH,
display: 'inline-flex',
alignItems: 'center',
};
if (isVertical) {
return {
...common,
position: 'absolute',
transform: `rotate(-90deg) translateX(${MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH / 2 + icons_1.ICON_SIZE / 2}px)`,
};
}
return {
...common,
};
}, [isVertical]);
// Need to import it from React to fix React 17 ESM support.
const randomId =
// eslint-disable-next-line react-hooks/rules-of-hooks
typeof react_1.default.useId === 'undefined' ? 'volume-slider' : react_1.default.useId();
const [randomClass] = (0, react_1.useState)(() => `__remotion-volume-slider-${(0, remotion_1.random)(randomId)}`.replace('.', ''));
const onVolumeChange = (0, react_1.useCallback)((e) => {
setVolume(parseFloat(e.target.value));
}, [setVolume]);
const inputStyle = (0, react_1.useMemo)(() => {
const commonStyle = {
WebkitAppearance: 'none',
backgroundColor: 'rgba(255, 255, 255, 0.5)',
borderRadius: BAR_HEIGHT / 2,
cursor: 'pointer',
height: BAR_HEIGHT,
width: MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH,
backgroundImage: `linear-gradient(
to right,
white ${volume * 100}%, rgba(255, 255, 255, 0) ${volume * 100}%
)`,
};
if (isVertical) {
return {
...commonStyle,
bottom: icons_1.ICON_SIZE + MediaVolumeSlider_1.VOLUME_SLIDER_WIDTH / 2,
};
}
return commonStyle;
}, [isVertical, volume]);
const sliderStyle = `
.${randomClass}::-webkit-slider-thumb {
-webkit-appearance: none;
background-color: white;
border-radius: ${KNOB_SIZE / 2}px;
box-shadow: 0 0 2px black;
height: ${KNOB_SIZE}px;
width: ${KNOB_SIZE}px;
}
.${randomClass}::-moz-range-thumb {
-webkit-appearance: none;
background-color: white;
border-radius: ${KNOB_SIZE / 2}px;
box-shadow: 0 0 2px black;
height: ${KNOB_SIZE}px;
width: ${KNOB_SIZE}px;
}
`;
return ((0, jsx_runtime_1.jsxs)("div", { style: sliderContainer, children: [(0, jsx_runtime_1.jsx)("style", {
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML: {
__html: sliderStyle,
} }), (0, jsx_runtime_1.jsx)("input", { ref: inputRef, "aria-label": "Change volume", className: randomClass, max: 1, min: 0, onBlur: onBlur, onChange: onVolumeChange, step: 0.01, type: "range", value: volume, style: inputStyle })] }));
};
const renderDefaultVolumeSlider = (props) => {
return (0, jsx_runtime_1.jsx)(DefaultVolumeSlider, { ...props });
};
exports.renderDefaultVolumeSlider = renderDefaultVolumeSlider;
@@ -0,0 +1,2 @@
import type { PlayerEmitter, ThumbnailEmitter } from './event-emitter.js';
export declare const useBufferStateEmitter: (emitter: PlayerEmitter | ThumbnailEmitter) => void;
@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useBufferStateEmitter = void 0;
const react_1 = require("react");
const remotion_1 = require("remotion");
const useBufferStateEmitter = (emitter) => {
const bufferManager = (0, react_1.useContext)(remotion_1.Internals.BufferingContextReact);
if (!bufferManager) {
throw new Error('BufferingContextReact not found');
}
(0, react_1.useLayoutEffect)(() => {
const clear1 = bufferManager.listenForBuffering(() => {
bufferManager.buffering.current = true;
emitter.dispatchWaiting({});
});
const clear2 = bufferManager.listenForResume(() => {
bufferManager.buffering.current = false;
emitter.dispatchResume({});
});
return () => {
clear1.remove();
clear2.remove();
};
}, [bufferManager, emitter]);
};
exports.useBufferStateEmitter = useBufferStateEmitter;
@@ -0,0 +1,2 @@
export type GetCurrentFrame = () => number;
export declare const useFrameImperative: () => GetCurrentFrame;
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useFrameImperative = void 0;
const react_1 = require("react");
const remotion_1 = require("remotion");
const useFrameImperative = () => {
const frame = remotion_1.Internals.Timeline.useTimelinePosition();
const frameRef = (0, react_1.useRef)(frame);
frameRef.current = frame;
const getCurrentFrame = (0, react_1.useCallback)(() => {
return frameRef.current;
}, []);
return getCurrentFrame;
};
exports.useFrameImperative = useFrameImperative;
@@ -0,0 +1 @@
export declare const useHoverState: (ref: React.RefObject<HTMLDivElement | null>, hideControlsWhenPointerDoesntMove: boolean | number) => boolean;
@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useHoverState = void 0;
const react_1 = require("react");
const useHoverState = (ref, hideControlsWhenPointerDoesntMove) => {
const [hovered, setHovered] = (0, react_1.useState)(false);
(0, react_1.useEffect)(() => {
const { current } = ref;
if (!current) {
return;
}
let hoverTimeout;
const addHoverTimeout = () => {
if (hideControlsWhenPointerDoesntMove) {
clearTimeout(hoverTimeout);
hoverTimeout = setTimeout(() => {
setHovered(false);
}, hideControlsWhenPointerDoesntMove === true
? 3000
: hideControlsWhenPointerDoesntMove);
}
};
const onHover = () => {
setHovered(true);
addHoverTimeout();
};
const onLeave = () => {
setHovered(false);
clearTimeout(hoverTimeout);
};
const onMove = () => {
setHovered(true);
addHoverTimeout();
};
current.addEventListener('mouseenter', onHover);
current.addEventListener('mouseleave', onLeave);
current.addEventListener('mousemove', onMove);
return () => {
current.removeEventListener('mouseenter', onHover);
current.removeEventListener('mouseleave', onLeave);
current.removeEventListener('mousemove', onMove);
clearTimeout(hoverTimeout);
};
}, [hideControlsWhenPointerDoesntMove, ref]);
return hovered;
};
exports.useHoverState = useHoverState;
@@ -0,0 +1,11 @@
import type { BrowserMediaControlsBehavior } from './browser-mediasession.js';
import type { GetCurrentFrame } from './use-frame-imperative.js';
export declare const usePlayback: ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, outFrame, browserMediaControlsBehavior, getCurrentFrame, }: {
loop: boolean;
playbackRate: number;
moveToBeginningWhenEnded: boolean;
inFrame: number | null;
outFrame: number | null;
browserMediaControlsBehavior: BrowserMediaControlsBehavior;
getCurrentFrame: GetCurrentFrame;
}) => void;
@@ -0,0 +1,155 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.usePlayback = void 0;
/* eslint-disable @typescript-eslint/no-use-before-define */
const react_1 = require("react");
const remotion_1 = require("remotion");
const browser_mediasession_js_1 = require("./browser-mediasession.js");
const calculate_next_frame_js_1 = require("./calculate-next-frame.js");
const is_backgrounded_js_1 = require("./is-backgrounded.js");
const use_player_js_1 = require("./use-player.js");
const usePlayback = ({ loop, playbackRate, moveToBeginningWhenEnded, inFrame, outFrame, browserMediaControlsBehavior, getCurrentFrame, }) => {
const config = remotion_1.Internals.useUnsafeVideoConfig();
const frame = remotion_1.Internals.Timeline.useTimelinePosition();
const { playing, pause, emitter, isPlaying } = (0, use_player_js_1.usePlayer)();
const setFrame = remotion_1.Internals.Timeline.useTimelineSetFrame();
// requestAnimationFrame() does not work if the tab is not active.
// This means that audio will keep playing even if it has ended.
// In that case, we use setTimeout() instead.
const isBackgroundedRef = (0, is_backgrounded_js_1.useIsBackgrounded)();
const lastTimeUpdateEvent = (0, react_1.useRef)(null);
const context = (0, react_1.useContext)(remotion_1.Internals.BufferingContextReact);
if (!context) {
throw new Error('Missing the buffering context. Most likely you have a Remotion version mismatch.');
}
(0, browser_mediasession_js_1.useBrowserMediaSession)({
browserMediaControlsBehavior,
playbackRate,
videoConfig: config,
});
// complete code for media session API
(0, react_1.useEffect)(() => {
if (!config) {
return;
}
if (!playing) {
return;
}
let hasBeenStopped = false;
let reqAnimFrameCall = null;
let startedTime = performance.now();
let framesAdvanced = 0;
const cancelQueuedFrame = () => {
if (reqAnimFrameCall !== null) {
if (reqAnimFrameCall.type === 'raf') {
cancelAnimationFrame(reqAnimFrameCall.id);
}
else {
clearTimeout(reqAnimFrameCall.id);
}
}
};
const stop = () => {
hasBeenStopped = true;
cancelQueuedFrame();
};
const callback = () => {
if (hasBeenStopped) {
return;
}
if (!isPlaying()) {
return;
}
const time = performance.now() - startedTime;
const actualLastFrame = outFrame !== null && outFrame !== void 0 ? outFrame : config.durationInFrames - 1;
const actualFirstFrame = inFrame !== null && inFrame !== void 0 ? inFrame : 0;
const currentFrame = getCurrentFrame();
const { nextFrame, framesToAdvance, hasEnded } = (0, calculate_next_frame_js_1.calculateNextFrame)({
time,
currentFrame,
playbackSpeed: playbackRate,
fps: config.fps,
actualFirstFrame,
actualLastFrame,
framesAdvanced,
shouldLoop: loop,
});
framesAdvanced += framesToAdvance;
if (nextFrame !== getCurrentFrame() &&
(!hasEnded || moveToBeginningWhenEnded)) {
setFrame((c) => ({ ...c, [config.id]: nextFrame }));
}
if (hasEnded) {
stop();
pause();
emitter.dispatchEnded();
return;
}
queueNextFrame();
};
const queueNextFrame = () => {
if (context.buffering.current) {
const stopListening = context.listenForResume(() => {
stopListening.remove();
startedTime = performance.now();
framesAdvanced = 0;
queueNextFrame();
});
return;
}
if (isBackgroundedRef.current) {
reqAnimFrameCall = {
type: 'timeout',
// Note: Most likely, this will not be 1000 / fps, but the browser will throttle it to ~1/sec.
id: setTimeout(callback, 1000 / config.fps),
};
return;
}
reqAnimFrameCall = { type: 'raf', id: requestAnimationFrame(callback) };
};
queueNextFrame();
const onVisibilityChange = () => {
if (document.visibilityState === 'visible') {
return;
}
// If tab goes into the background, cancel requestAnimationFrame() and update immediately.
// , so the transition to setTimeout() can be fulfilled.
cancelQueuedFrame();
callback();
};
window.addEventListener('visibilitychange', onVisibilityChange);
return () => {
window.removeEventListener('visibilitychange', onVisibilityChange);
stop();
};
}, [
config,
loop,
pause,
playing,
setFrame,
emitter,
playbackRate,
inFrame,
outFrame,
moveToBeginningWhenEnded,
isBackgroundedRef,
getCurrentFrame,
context,
isPlaying,
]);
(0, react_1.useEffect)(() => {
const interval = setInterval(() => {
if (lastTimeUpdateEvent.current === getCurrentFrame()) {
return;
}
emitter.dispatchTimeUpdate({ frame: getCurrentFrame() });
lastTimeUpdateEvent.current = getCurrentFrame();
}, 250);
return () => clearInterval(interval);
}, [emitter, getCurrentFrame]);
(0, react_1.useEffect)(() => {
emitter.dispatchFrameUpdate({ frame });
}, [emitter, frame]);
};
exports.usePlayback = usePlayback;
@@ -0,0 +1,21 @@
import type { SyntheticEvent } from 'react';
import type { PlayerEmitter } from './event-emitter.js';
type UsePlayerMethods = {
frameBack: (frames: number) => void;
frameForward: (frames: number) => void;
isLastFrame: boolean;
isFirstFrame: boolean;
emitter: PlayerEmitter;
playing: boolean;
play: (e?: SyntheticEvent | PointerEvent) => void;
pause: () => void;
pauseAndReturnToPlayStart: () => void;
seek: (newFrame: number) => void;
getCurrentFrame: () => number;
isPlaying: () => boolean;
hasPlayed: boolean;
isBuffering: () => boolean;
toggle: (e?: SyntheticEvent | PointerEvent) => void;
};
export declare const usePlayer: () => UsePlayerMethods;
export {};
@@ -0,0 +1,192 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.usePlayer = void 0;
const react_1 = require("react");
const remotion_1 = require("remotion");
const emitter_context_js_1 = require("./emitter-context.js");
const usePlayer = () => {
var _a;
const [playing, setPlaying, imperativePlaying] = remotion_1.Internals.Timeline.usePlayingState();
const [hasPlayed, setHasPlayed] = (0, react_1.useState)(false);
const frame = remotion_1.Internals.Timeline.useTimelinePosition();
const playStart = (0, react_1.useRef)(frame);
const setFrame = remotion_1.Internals.Timeline.useTimelineSetFrame();
const setTimelinePosition = remotion_1.Internals.Timeline.useTimelineSetFrame();
const audioContext = (0, react_1.useContext)(remotion_1.Internals.SharedAudioContext);
const { audioAndVideoTags } = (0, react_1.useContext)(remotion_1.Internals.TimelineContext);
const frameRef = (0, react_1.useRef)(frame);
frameRef.current = frame;
const video = remotion_1.Internals.useVideo();
const config = remotion_1.Internals.useUnsafeVideoConfig();
const emitter = (0, react_1.useContext)(emitter_context_js_1.PlayerEventEmitterContext);
const lastFrame = ((_a = config === null || config === void 0 ? void 0 : config.durationInFrames) !== null && _a !== void 0 ? _a : 1) - 1;
const isLastFrame = frame === lastFrame;
const isFirstFrame = frame === 0;
if (!emitter) {
throw new TypeError('Expected Player event emitter context');
}
const bufferingContext = (0, react_1.useContext)(remotion_1.Internals.BufferingContextReact);
if (!bufferingContext) {
throw new Error('Missing the buffering context. Most likely you have a Remotion version mismatch.');
}
const { buffering } = bufferingContext;
const seek = (0, react_1.useCallback)((newFrame) => {
if (video === null || video === void 0 ? void 0 : video.id) {
setTimelinePosition((c) => ({ ...c, [video.id]: newFrame }));
}
frameRef.current = newFrame;
emitter.dispatchSeek(newFrame);
}, [emitter, setTimelinePosition, video === null || video === void 0 ? void 0 : video.id]);
const play = (0, react_1.useCallback)((e) => {
var _a;
if (imperativePlaying.current) {
return;
}
setHasPlayed(true);
if (isLastFrame) {
seek(0);
}
(_a = audioContext === null || audioContext === void 0 ? void 0 : audioContext.audioContext) === null || _a === void 0 ? void 0 : _a.resume();
/**
* Play silent audio tags to warm them up for autoplay
*/
if (audioContext && audioContext.numberOfAudioTags > 0 && e) {
audioContext.playAllAudios();
}
/**
* Play audios and videos directly here so they can benefit from
* being triggered by a click
*/
audioAndVideoTags.current.forEach((a) => a.play('player play() was called and playing audio from a click'));
imperativePlaying.current = true;
setPlaying(true);
playStart.current = frameRef.current;
emitter.dispatchPlay();
}, [
imperativePlaying,
isLastFrame,
audioContext,
setPlaying,
emitter,
seek,
audioAndVideoTags,
]);
const pause = (0, react_1.useCallback)(() => {
var _a;
if (imperativePlaying.current) {
imperativePlaying.current = false;
setPlaying(false);
emitter.dispatchPause();
(_a = audioContext === null || audioContext === void 0 ? void 0 : audioContext.audioContext) === null || _a === void 0 ? void 0 : _a.suspend();
}
}, [emitter, imperativePlaying, setPlaying, audioContext]);
const pauseAndReturnToPlayStart = (0, react_1.useCallback)(() => {
if (imperativePlaying.current) {
imperativePlaying.current = false;
frameRef.current = playStart.current;
if (config) {
setTimelinePosition((c) => ({
...c,
[config.id]: playStart.current,
}));
setPlaying(false);
emitter.dispatchPause();
}
}
}, [config, emitter, imperativePlaying, setPlaying, setTimelinePosition]);
const videoId = video === null || video === void 0 ? void 0 : video.id;
const frameBack = (0, react_1.useCallback)((frames) => {
if (!videoId) {
return null;
}
if (imperativePlaying.current) {
return;
}
setFrame((c) => {
var _a, _b;
const prevFrame = (_b = (_a = c[videoId]) !== null && _a !== void 0 ? _a : window.remotion_initialFrame) !== null && _b !== void 0 ? _b : 0;
const newFrame = Math.max(0, prevFrame - frames);
if (prevFrame === newFrame) {
return c;
}
return {
...c,
[videoId]: newFrame,
};
});
}, [imperativePlaying, setFrame, videoId]);
const frameForward = (0, react_1.useCallback)((frames) => {
if (!videoId) {
return null;
}
if (imperativePlaying.current) {
return;
}
setFrame((c) => {
var _a, _b;
const prevFrame = (_b = (_a = c[videoId]) !== null && _a !== void 0 ? _a : window.remotion_initialFrame) !== null && _b !== void 0 ? _b : 0;
const newFrame = Math.min(lastFrame, prevFrame + frames);
if (prevFrame === newFrame) {
return c;
}
return {
...c,
[videoId]: newFrame,
};
});
}, [videoId, imperativePlaying, lastFrame, setFrame]);
const toggle = (0, react_1.useCallback)((e) => {
if (imperativePlaying.current) {
pause();
}
else {
play(e);
}
}, [imperativePlaying, pause, play]);
const isPlaying = (0, react_1.useCallback)(() => {
return imperativePlaying.current;
}, [imperativePlaying]);
const getCurrentFrame = (0, react_1.useCallback)(() => {
return frameRef.current;
}, [frameRef]);
const isBuffering = (0, react_1.useCallback)(() => {
return buffering.current;
}, [buffering]);
const returnValue = (0, react_1.useMemo)(() => {
return {
frameBack,
frameForward,
isLastFrame,
emitter,
playing,
play,
pause,
seek,
isFirstFrame,
getCurrentFrame,
isPlaying,
isBuffering,
pauseAndReturnToPlayStart,
hasPlayed,
toggle,
};
}, [
emitter,
frameBack,
frameForward,
hasPlayed,
isFirstFrame,
isLastFrame,
getCurrentFrame,
pause,
pauseAndReturnToPlayStart,
play,
playing,
seek,
toggle,
isPlaying,
isBuffering,
]);
return returnValue;
};
exports.usePlayer = usePlayer;
@@ -0,0 +1,2 @@
import { type LogLevel } from 'remotion';
export declare const acknowledgeRemotionLicenseMessage: (acknowledge: boolean, logLevel: LogLevel) => void;
@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.acknowledgeRemotionLicenseMessage = void 0;
const remotion_1 = require("remotion");
let warningShown = false;
const acknowledgeRemotionLicenseMessage = (acknowledge, logLevel) => {
if (acknowledge) {
return;
}
if (warningShown) {
return;
}
warningShown = true;
remotion_1.Internals.Log.warn({ logLevel, tag: null }, 'Note: Some companies are required to obtain a license to use Remotion. See: https://remotion.dev/license\nPass the `acknowledgeRemotionLicense` prop to `<Player />` function to make this message disappear.');
};
exports.acknowledgeRemotionLicenseMessage = acknowledgeRemotionLicenseMessage;
@@ -0,0 +1,6 @@
import type { ThumbnailEmitter } from './event-emitter.js';
type UseThumbnailMethods = {
emitter: ThumbnailEmitter;
};
export declare const useThumbnail: () => UseThumbnailMethods;
export {};
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useThumbnail = void 0;
const react_1 = require("react");
const emitter_context_js_1 = require("./emitter-context.js");
const useThumbnail = () => {
const emitter = (0, react_1.useContext)(emitter_context_js_1.ThumbnailEmitterContext);
if (!emitter) {
throw new TypeError('Expected Player event emitter context');
}
const returnValue = (0, react_1.useMemo)(() => {
return {
emitter,
};
}, [emitter]);
return returnValue;
};
exports.useThumbnail = useThumbnail;
@@ -0,0 +1,11 @@
type Info = {
maxTimeLabelWidth: number | null;
displayVerticalVolumeSlider: boolean;
};
export declare const X_SPACER = 10;
export declare const X_PADDING = 12;
export declare const useVideoControlsResize: ({ allowFullscreen: allowFullScreen, playerWidth, }: {
allowFullscreen: boolean;
playerWidth: number;
}) => Info;
export {};
@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useVideoControlsResize = exports.X_PADDING = exports.X_SPACER = void 0;
const react_1 = require("react");
const icons_js_1 = require("./icons.js");
const MediaVolumeSlider_js_1 = require("./MediaVolumeSlider.js");
exports.X_SPACER = 10;
exports.X_PADDING = 12;
const useVideoControlsResize = ({ allowFullscreen: allowFullScreen, playerWidth, }) => {
const resizeInfo = (0, react_1.useMemo)(() => {
const playPauseIconSize = icons_js_1.ICON_SIZE;
const volumeIconSize = icons_js_1.ICON_SIZE;
const _fullscreenIconSize = allowFullScreen ? icons_js_1.fullscreenIconSize : 0;
const elementsSize = volumeIconSize +
playPauseIconSize +
_fullscreenIconSize +
exports.X_PADDING * 2 +
exports.X_SPACER * 2;
const maxTimeLabelWidth = playerWidth - elementsSize;
const maxTimeLabelWidthWithoutNegativeValue = Math.max(maxTimeLabelWidth, 0);
const availableTimeLabelWidthIfVolumeOpen = maxTimeLabelWidthWithoutNegativeValue - MediaVolumeSlider_js_1.VOLUME_SLIDER_WIDTH;
// If max label width is lower than the volume width
// then it means we need to take it's width as the max label width
// otherwise we took the available width when volume open
const computedLabelWidth = availableTimeLabelWidthIfVolumeOpen < MediaVolumeSlider_js_1.VOLUME_SLIDER_WIDTH
? maxTimeLabelWidthWithoutNegativeValue
: availableTimeLabelWidthIfVolumeOpen;
const minWidthForHorizontalDisplay = computedLabelWidth + elementsSize + MediaVolumeSlider_js_1.VOLUME_SLIDER_WIDTH;
const displayVerticalVolumeSlider = playerWidth < minWidthForHorizontalDisplay;
return {
maxTimeLabelWidth: maxTimeLabelWidthWithoutNegativeValue === 0
? null
: maxTimeLabelWidthWithoutNegativeValue,
displayVerticalVolumeSlider,
};
}, [allowFullScreen, playerWidth]);
return resizeInfo;
};
exports.useVideoControlsResize = useVideoControlsResize;
@@ -0,0 +1,9 @@
import type { StandardLonghandProperties } from 'csstype';
import type { Size } from './use-element-size.js';
export declare const calculatePlayerSize: ({ currentSize, width, height, compositionWidth, compositionHeight, }: {
currentSize: Size | null;
width: StandardLonghandProperties["width"] | undefined;
height: StandardLonghandProperties["height"] | undefined;
compositionWidth: number;
compositionHeight: number;
}) => React.CSSProperties;
@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculatePlayerSize = void 0;
const calculatePlayerSize = ({ currentSize, width, height, compositionWidth, compositionHeight, }) => {
if (width !== undefined && height === undefined) {
return {
aspectRatio: [compositionWidth, compositionHeight].join('/'),
};
}
// Opposite: If has height specified, evaluate the height and specify a default width.
if (height !== undefined && width === undefined) {
return {
// Aspect ratio CSS prop will work
aspectRatio: [compositionWidth, compositionHeight].join('/'),
};
}
if (!currentSize) {
return {
width: compositionWidth,
height: compositionHeight,
};
}
return {
width: compositionWidth,
height: compositionHeight,
};
};
exports.calculatePlayerSize = calculatePlayerSize;
@@ -0,0 +1,5 @@
export type CancellablePromise = {
promise: Promise<unknown>;
cancel: () => void;
};
export declare const cancellablePromise: (promise: Promise<unknown>) => CancellablePromise;
@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cancellablePromise = void 0;
const cancellablePromise = (promise) => {
let isCanceled = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise
.then((value) => {
if (isCanceled) {
reject({ isCanceled, value });
return;
}
resolve(value);
})
.catch((error) => {
reject({ isCanceled, error });
});
});
return {
promise: wrappedPromise,
cancel: () => {
isCanceled = true;
},
};
};
exports.cancellablePromise = cancellablePromise;
@@ -0,0 +1 @@
export declare const delay: (n: number) => Promise<unknown>;
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.delay = void 0;
/* eslint-disable no-promise-executor-return */
const delay = (n) => new Promise((resolve) => setTimeout(resolve, n));
exports.delay = delay;
@@ -0,0 +1 @@
export declare const IS_NODE: boolean;
@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IS_NODE = void 0;
exports.IS_NODE = typeof document === 'undefined';
@@ -0,0 +1,10 @@
import type { AnyZodObject, z } from 'zod';
export type PropsIfHasProps<Schema extends AnyZodObject, Props> = AnyZodObject extends Schema ? {} extends Props ? {
inputProps?: z.input<Schema> & Props;
} : {
inputProps: Props;
} : {} extends Props ? {
inputProps: z.input<Schema>;
} : {
inputProps: z.input<Schema> & Props;
};
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
import type { CancellablePromise } from './cancellable-promise.js';
declare const useCancellablePromises: () => {
appendPendingPromise: (promise: CancellablePromise) => void;
removePendingPromise: (promise: CancellablePromise) => void;
clearPendingPromises: () => void[];
};
export { useCancellablePromises };
@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useCancellablePromises = void 0;
const react_1 = require("react");
const useCancellablePromises = () => {
const pendingPromises = (0, react_1.useRef)([]);
const appendPendingPromise = (0, react_1.useCallback)((promise) => {
pendingPromises.current = [...pendingPromises.current, promise];
}, []);
const removePendingPromise = (0, react_1.useCallback)((promise) => {
pendingPromises.current = pendingPromises.current.filter((p) => p !== promise);
}, []);
const clearPendingPromises = (0, react_1.useCallback)(() => pendingPromises.current.map((p) => p.cancel()), []);
const api = (0, react_1.useMemo)(() => ({
appendPendingPromise,
removePendingPromise,
clearPendingPromises,
}), [appendPendingPromise, clearPendingPromises, removePendingPromise]);
return api;
};
exports.useCancellablePromises = useCancellablePromises;
@@ -0,0 +1,7 @@
import type { SyntheticEvent } from 'react';
type ReturnVal = {
handlePointerDown: (e: SyntheticEvent<Element, PointerEvent> | PointerEvent) => void;
handleDoubleClick: () => void;
};
declare const useClickPreventionOnDoubleClick: (onClick: (e: PointerEvent | SyntheticEvent<Element, PointerEvent>) => void, onDoubleClick: () => void, doubleClickToFullscreen: boolean) => ReturnVal;
export { useClickPreventionOnDoubleClick };
@@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useClickPreventionOnDoubleClick = void 0;
const react_1 = require("react");
const cancellable_promise_js_1 = require("./cancellable-promise.js");
const delay_js_1 = require("./delay.js");
const use_cancellable_promises_js_1 = require("./use-cancellable-promises.js");
const useClickPreventionOnDoubleClick = (onClick, onDoubleClick, doubleClickToFullscreen) => {
const api = (0, use_cancellable_promises_js_1.useCancellablePromises)();
const handleClick = (0, react_1.useCallback)(async (e) => {
// UnSupported double click on touch.(mobile)
if (e instanceof PointerEvent
? e.pointerType === 'touch'
: e.nativeEvent.pointerType === 'touch') {
onClick(e);
return;
}
api.clearPendingPromises();
const waitForClick = (0, cancellable_promise_js_1.cancellablePromise)((0, delay_js_1.delay)(200));
api.appendPendingPromise(waitForClick);
try {
await waitForClick.promise;
api.removePendingPromise(waitForClick);
onClick(e);
}
catch (errorInfo) {
const info = errorInfo;
api.removePendingPromise(waitForClick);
if (!info.isCanceled) {
throw info.error;
}
}
}, [api, onClick]);
const handlePointerDown = (0, react_1.useCallback)(() => {
document.addEventListener('pointerup', (newEvt) => {
handleClick(newEvt);
}, {
once: true,
});
}, [handleClick]);
const handleDoubleClick = (0, react_1.useCallback)(() => {
api.clearPendingPromises();
onDoubleClick();
}, [api, onDoubleClick]);
const returnValue = (0, react_1.useMemo)(() => {
if (!doubleClickToFullscreen) {
return { handlePointerDown: onClick, handleDoubleClick: () => undefined };
}
return { handlePointerDown, handleDoubleClick };
}, [doubleClickToFullscreen, handleDoubleClick, handlePointerDown, onClick]);
return returnValue;
};
exports.useClickPreventionOnDoubleClick = useClickPreventionOnDoubleClick;
@@ -0,0 +1,5 @@
export default function useComponentVisible(initialIsVisible: boolean): {
ref: import("react").RefObject<HTMLDivElement | null>;
isComponentVisible: boolean;
setIsComponentVisible: import("react").Dispatch<import("react").SetStateAction<boolean>>;
};
@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = useComponentVisible;
const react_1 = require("react");
// hook to hide a popup/modal when clicked outside
function useComponentVisible(initialIsVisible) {
const [isComponentVisible, setIsComponentVisible] = (0, react_1.useState)(initialIsVisible);
const ref = (0, react_1.useRef)(null);
(0, react_1.useEffect)(() => {
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setIsComponentVisible(false);
}
};
document.addEventListener('pointerup', handleClickOutside, true);
return () => {
document.removeEventListener('pointerup', handleClickOutside, true);
};
}, []);
return { ref, isComponentVisible, setIsComponentVisible };
}
@@ -0,0 +1,16 @@
export type Size = {
width: number;
height: number;
left: number;
top: number;
windowSize: {
width: number;
height: number;
};
refresh: () => void;
};
export declare const updateAllElementsSizes: () => void;
export declare const useElementSize: (ref: React.RefObject<HTMLElement | null>, options: {
triggerOnWindowResize: boolean;
shouldApplyCssTransforms: boolean;
}) => Size | null;
@@ -0,0 +1,144 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useElementSize = exports.updateAllElementsSizes = void 0;
const react_1 = require("react");
let elementSizeHooks = [];
const updateAllElementsSizes = () => {
for (const listener of elementSizeHooks) {
listener();
}
};
exports.updateAllElementsSizes = updateAllElementsSizes;
const useElementSize = (ref, options) => {
const [size, setSize] = (0, react_1.useState)(() => {
if (!ref.current) {
return null;
}
const rect = ref.current.getClientRects();
if (!rect[0]) {
return null;
}
return {
width: rect[0].width,
height: rect[0].height,
left: rect[0].x,
top: rect[0].y,
windowSize: {
height: window.innerHeight,
width: window.innerWidth,
},
};
});
const observer = (0, react_1.useMemo)(() => {
if (typeof ResizeObserver === 'undefined') {
return null;
}
return new ResizeObserver((entries) => {
// The contentRect returns the width without any `scale()`'s being applied. The height is wrong
const { contentRect, target } = entries[0];
// The clientRect returns the size with `scale()` being applied.
const newSize = target.getClientRects();
if (!(newSize === null || newSize === void 0 ? void 0 : newSize[0])) {
setSize(null);
return;
}
const probableCssParentScale = contentRect.width === 0 ? 1 : newSize[0].width / contentRect.width;
const width = options.shouldApplyCssTransforms || probableCssParentScale === 0
? newSize[0].width
: newSize[0].width * (1 / probableCssParentScale);
const height = options.shouldApplyCssTransforms || probableCssParentScale === 0
? newSize[0].height
: newSize[0].height * (1 / probableCssParentScale);
setSize((prevState) => {
const isSame = prevState &&
prevState.width === width &&
prevState.height === height &&
prevState.left === newSize[0].x &&
prevState.top === newSize[0].y &&
prevState.windowSize.height === window.innerHeight &&
prevState.windowSize.width === window.innerWidth;
if (isSame) {
return prevState;
}
return {
width,
height,
left: newSize[0].x,
top: newSize[0].y,
windowSize: {
height: window.innerHeight,
width: window.innerWidth,
},
};
});
});
}, [options.shouldApplyCssTransforms]);
const updateSize = (0, react_1.useCallback)(() => {
if (!ref.current) {
return;
}
const rect = ref.current.getClientRects();
if (!rect[0]) {
setSize(null);
return;
}
setSize((prevState) => {
const isSame = prevState &&
prevState.width === rect[0].width &&
prevState.height === rect[0].height &&
prevState.left === rect[0].x &&
prevState.top === rect[0].y &&
prevState.windowSize.height === window.innerHeight &&
prevState.windowSize.width === window.innerWidth;
if (isSame) {
return prevState;
}
return {
width: rect[0].width,
height: rect[0].height,
left: rect[0].x,
top: rect[0].y,
windowSize: {
height: window.innerHeight,
width: window.innerWidth,
},
};
});
}, [ref]);
(0, react_1.useEffect)(() => {
if (!observer) {
return;
}
const { current } = ref;
if (current) {
observer.observe(current);
}
return () => {
if (current) {
observer.unobserve(current);
}
};
}, [observer, ref, updateSize]);
(0, react_1.useEffect)(() => {
if (!options.triggerOnWindowResize) {
return;
}
window.addEventListener('resize', updateSize);
return () => {
window.removeEventListener('resize', updateSize);
};
}, [options.triggerOnWindowResize, updateSize]);
(0, react_1.useEffect)(() => {
elementSizeHooks.push(updateSize);
return () => {
elementSizeHooks = elementSizeHooks.filter((e) => e !== updateSize);
};
}, [updateSize]);
return (0, react_1.useMemo)(() => {
if (!size) {
return null;
}
return { ...size, refresh: updateSize };
}, [size, updateSize]);
};
exports.useElementSize = useElementSize;
@@ -0,0 +1,6 @@
export declare const validateSingleFrame: (frame: unknown, variableName: string) => number | null;
export declare const validateInOutFrames: ({ inFrame, durationInFrames, outFrame, }: {
inFrame: unknown;
outFrame: unknown;
durationInFrames: number;
}) => void;
@@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateInOutFrames = exports.validateSingleFrame = void 0;
const validateSingleFrame = (frame, variableName) => {
if (typeof frame === 'undefined' || frame === null) {
return frame !== null && frame !== void 0 ? frame : null;
}
if (typeof frame !== 'number') {
throw new TypeError(`"${variableName}" must be a number, but is ${JSON.stringify(frame)}`);
}
if (Number.isNaN(frame)) {
throw new TypeError(`"${variableName}" must not be NaN, but is ${JSON.stringify(frame)}`);
}
if (!Number.isFinite(frame)) {
throw new TypeError(`"${variableName}" must be finite, but is ${JSON.stringify(frame)}`);
}
if (frame % 1 !== 0) {
throw new TypeError(`"${variableName}" must be an integer, but is ${JSON.stringify(frame)}`);
}
return frame;
};
exports.validateSingleFrame = validateSingleFrame;
const validateInOutFrames = ({ inFrame, durationInFrames, outFrame, }) => {
const validatedInFrame = (0, exports.validateSingleFrame)(inFrame, 'inFrame');
const validatedOutFrame = (0, exports.validateSingleFrame)(outFrame, 'outFrame');
if (validatedInFrame === null && validatedOutFrame === null) {
return;
}
// Must not be over the duration
if (validatedInFrame !== null && validatedInFrame > durationInFrames - 1) {
throw new Error('inFrame must be less than (durationInFrames - 1), but is ' +
validatedInFrame);
}
if (validatedOutFrame !== null && validatedOutFrame > durationInFrames - 1) {
throw new Error('outFrame must be less than (durationInFrames - 1), but is ' +
validatedOutFrame);
}
// Must not be under 0
if (validatedInFrame !== null && validatedInFrame < 0) {
throw new Error('inFrame must be greater than 0, but is ' + validatedInFrame);
}
if (validatedOutFrame !== null && validatedOutFrame <= 0) {
throw new Error(`outFrame must be greater than 0, but is ${validatedOutFrame}. If you want to render a single frame, use <Thumbnail /> instead.`);
}
if (validatedOutFrame !== null &&
validatedInFrame !== null &&
validatedOutFrame <= validatedInFrame) {
throw new Error('outFrame must be greater than inFrame, but is ' +
validatedOutFrame +
' <= ' +
validatedInFrame);
}
};
exports.validateInOutFrames = validateInOutFrames;
@@ -0,0 +1,4 @@
export declare const validateInitialFrame: ({ initialFrame, durationInFrames, }: {
initialFrame: unknown;
durationInFrames: unknown;
}) => void;
@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateInitialFrame = void 0;
const validateInitialFrame = ({ initialFrame, durationInFrames, }) => {
if (typeof durationInFrames !== 'number') {
throw new Error(`\`durationInFrames\` must be a number, but is ${JSON.stringify(durationInFrames)}`);
}
if (typeof initialFrame === 'undefined') {
return;
}
if (typeof initialFrame !== 'number') {
throw new Error(`\`initialFrame\` must be a number, but is ${JSON.stringify(initialFrame)}`);
}
if (Number.isNaN(initialFrame)) {
throw new Error(`\`initialFrame\` must be a number, but is NaN`);
}
if (!Number.isFinite(initialFrame)) {
throw new Error(`\`initialFrame\` must be a number, but is Infinity`);
}
if (initialFrame % 1 !== 0) {
throw new Error(`\`initialFrame\` must be an integer, but is ${JSON.stringify(initialFrame)}`);
}
if (initialFrame > durationInFrames - 1) {
throw new Error(`\`initialFrame\` must be less or equal than \`durationInFrames - 1\`, but is ${JSON.stringify(initialFrame)}`);
}
};
exports.validateInitialFrame = validateInitialFrame;
@@ -0,0 +1 @@
export declare const validatePlaybackRate: (playbackRate: number | undefined) => void;
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validatePlaybackRate = void 0;
const validatePlaybackRate = (playbackRate) => {
if (playbackRate === undefined) {
return;
}
if (playbackRate > 4) {
throw new Error(`The highest possible playback rate is 4. You passed: ${playbackRate}`);
}
if (playbackRate < -4) {
throw new Error(`The lowest possible playback rate is -4. You passed: ${playbackRate}`);
}
if (playbackRate === 0) {
throw new Error(`A playback rate of 0 is not supported.`);
}
};
exports.validatePlaybackRate = validatePlaybackRate;
@@ -0,0 +1,5 @@
import { NoReactInternals } from 'remotion/no-react';
export declare const validateFps: typeof NoReactInternals.validateFps;
export declare const validateDimension: typeof NoReactInternals.validateDimension;
export declare const validateDurationInFrames: typeof NoReactInternals.validateDurationInFrames;
export declare const validateDefaultAndInputProps: typeof NoReactInternals.validateDefaultAndInputProps;
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateDefaultAndInputProps = exports.validateDurationInFrames = exports.validateDimension = exports.validateFps = void 0;
/* eslint-disable prefer-destructuring */
const no_react_1 = require("remotion/no-react");
exports.validateFps = no_react_1.NoReactInternals.validateFps;
exports.validateDimension = no_react_1.NoReactInternals.validateDimension;
exports.validateDurationInFrames = no_react_1.NoReactInternals.validateDurationInFrames;
exports.validateDefaultAndInputProps = no_react_1.NoReactInternals.validateDefaultAndInputProps;
@@ -0,0 +1,3 @@
import { type LogLevel } from 'remotion';
export declare const persistVolume: (volume: number, logLevel: LogLevel, volumePersistenceKey: string | null) => void;
export declare const getPreferredVolume: (volumePersistenceKey: string | null) => number;
@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPreferredVolume = exports.persistVolume = void 0;
const remotion_1 = require("remotion");
const DEFAULT_VOLUME_PERSISTANCE_KEY = 'remotion.volumePreference';
const persistVolume = (volume, logLevel, volumePersistenceKey) => {
if (typeof window === 'undefined') {
return;
}
try {
window.localStorage.setItem(volumePersistenceKey !== null && volumePersistenceKey !== void 0 ? volumePersistenceKey : DEFAULT_VOLUME_PERSISTANCE_KEY, String(volume));
}
catch (e) {
// User can disallow localStorage access
// https://github.com/remotion-dev/remotion/issues/3540
remotion_1.Internals.Log.error({ logLevel, tag: null }, 'Could not persist volume', e);
}
};
exports.persistVolume = persistVolume;
const getPreferredVolume = (volumePersistenceKey) => {
if (typeof window === 'undefined') {
return 1;
}
try {
const val = window.localStorage.getItem(volumePersistenceKey !== null && volumePersistenceKey !== void 0 ? volumePersistenceKey : DEFAULT_VOLUME_PERSISTANCE_KEY);
return val ? Number(val) : 1;
}
catch (_a) {
// User can disallow localStorage access
// https://github.com/remotion-dev/remotion/issues/3540
return 1;
}
};
exports.getPreferredVolume = getPreferredVolume;