media-stream-player
Version:
Player built on top of media-stream-library
96 lines • 4.17 kB
JavaScript
import React, { useState, forwardRef, useEffect, useCallback, useMemo, useLayoutEffect, useRef, } from 'react';
import { Container, Layer } from './Container';
import { PlaybackArea, Format, } from './PlaybackArea';
import { ControlArea, ControlBar } from './Controls';
import { Button } from './components/Button';
import { Pause, Play } from './img';
import { useUserActive } from './hooks/useUserActive';
import { MediaStreamPlayerContainer } from './components/MediaStreamPlayerContainer';
import { Limiter } from './components/Limiter';
const DEFAULT_FORMAT = Format.JPEG;
export const BasicPlayer = forwardRef(({ hostname, vapixParams = {}, format = DEFAULT_FORMAT, autoPlay = false, secure, className, autoRetry, }, ref) => {
const [play, setPlay] = useState(autoPlay);
const [host, setHost] = useState(hostname);
/**
* Controls
*/
const [videoProperties, setVideoProperties] = useState();
const onPlaying = useCallback((props) => {
setVideoProperties(props);
}, [setVideoProperties]);
const onPlayPause = useCallback(() => {
if (play) {
setPlay(false);
}
else {
setHost(hostname);
setPlay(true);
}
}, [play, hostname]);
useEffect(() => {
const cb = () => {
if (document.visibilityState === 'visible') {
setPlay(true);
setHost(hostname);
}
else if (document.visibilityState === 'hidden') {
setPlay(false);
setHost('');
}
};
document.addEventListener('visibilitychange', cb);
return () => document.removeEventListener('visibilitychange', cb);
}, [hostname]);
/**
* Aspect ratio
*
* This needs to be set so make the Container (and Layers) match the size of
* the visible image of the video or still image.
*/
const naturalAspectRatio = useMemo(() => {
if (videoProperties === undefined) {
return undefined;
}
const { width, height } = videoProperties;
return width / height;
}, [videoProperties]);
/**
* Limit video size.
*
* The video size should not expand outside the available container, and
* should be recomputed on resize.
*/
const limiterRef = useRef(null);
useLayoutEffect(() => {
if (naturalAspectRatio === undefined || limiterRef.current === null) {
return;
}
const observer = new window.ResizeObserver(([entry]) => {
const element = entry.target;
const maxWidth = element.clientHeight * naturalAspectRatio;
element.style.maxWidth = `${maxWidth}px`;
});
observer.observe(limiterRef.current);
return () => observer.disconnect();
}, [naturalAspectRatio]);
const controlArea = useRef(null);
const userActive = useUserActive(controlArea);
/**
* Render
*
* Each layer is positioned exactly on top of the visible image, since the
* aspect ratio is carried over to the container, and the layers match the
* container size.
*/
return (React.createElement(MediaStreamPlayerContainer, { className: className },
React.createElement(Limiter, { ref: limiterRef },
React.createElement(Container, { aspectRatio: naturalAspectRatio },
React.createElement(Layer, null,
React.createElement(PlaybackArea, { forwardedRef: ref, refresh: 0, play: play, host: host, format: format, parameters: vapixParams, onPlaying: onPlaying, secure: secure, autoRetry: autoRetry })),
React.createElement(Layer, null,
React.createElement(ControlArea, { ref: controlArea, visible: play !== true || userActive },
React.createElement(ControlBar, null,
React.createElement(Button, { onClick: onPlayPause }, play === true ? (React.createElement(Pause, { title: "Pause" })) : (React.createElement(Play, { title: "Play" }))))))))));
});
BasicPlayer.displayName = 'BasicPlayer';
//# sourceMappingURL=BasicPlayer.js.map