@remotion/player
Version:
React component for embedding a Remotion preview into your app
193 lines (192 loc) • 7.19 kB
JavaScript
;
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 } = remotion_1.Internals.useTimelineContext();
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;