UNPKG

media-stream-player

Version:

Player built on top of media-stream-library

96 lines 4.17 kB
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