2022-04-27 05:29:13 +03:00
|
|
|
import React from 'react';
|
2022-05-11 01:36:09 +03:00
|
|
|
import { useSetRecoilState } from 'recoil';
|
2022-04-27 05:29:13 +03:00
|
|
|
import VideoJS from './player';
|
2022-05-09 09:42:40 +03:00
|
|
|
import ViewerPing from './viewer-ping';
|
2022-05-11 01:36:09 +03:00
|
|
|
import VideoPoster from './VideoPoster';
|
2022-05-09 09:42:40 +03:00
|
|
|
import { getLocalStorage, setLocalStorage } from '../../utils/helpers';
|
2022-05-11 01:36:09 +03:00
|
|
|
import { videoStateAtom } from '../stores/ClientConfigStore';
|
|
|
|
import { VideoState } from '../../interfaces/application-state';
|
2022-05-09 09:42:40 +03:00
|
|
|
|
|
|
|
const PLAYER_VOLUME = 'owncast_volume';
|
|
|
|
|
|
|
|
const ping = new ViewerPing();
|
2022-04-27 05:29:13 +03:00
|
|
|
|
2022-05-11 01:36:09 +03:00
|
|
|
interface Props {
|
|
|
|
source: string;
|
|
|
|
online: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export default function OwncastPlayer(props: Props) {
|
2022-04-27 05:29:13 +03:00
|
|
|
const playerRef = React.useRef(null);
|
2022-05-11 01:36:09 +03:00
|
|
|
const { source, online } = props;
|
|
|
|
|
|
|
|
const setVideoState = useSetRecoilState<VideoState>(videoStateAtom);
|
2022-04-27 05:29:13 +03:00
|
|
|
|
2022-05-09 09:42:40 +03:00
|
|
|
const setSavedVolume = () => {
|
|
|
|
try {
|
|
|
|
playerRef.current.volume(getLocalStorage(PLAYER_VOLUME) || 1);
|
|
|
|
} catch (err) {
|
|
|
|
console.warn(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleVolume = () => {
|
|
|
|
setLocalStorage(PLAYER_VOLUME, playerRef.current.muted() ? 0 : playerRef.current.volume());
|
|
|
|
};
|
|
|
|
|
2022-04-27 05:29:13 +03:00
|
|
|
const videoJsOptions = {
|
|
|
|
autoplay: false,
|
|
|
|
controls: true,
|
|
|
|
responsive: true,
|
2022-05-03 08:13:36 +03:00
|
|
|
fluid: false,
|
|
|
|
playsInline: true,
|
2022-04-27 05:29:13 +03:00
|
|
|
liveui: true,
|
|
|
|
preload: 'auto',
|
|
|
|
controlBar: {
|
|
|
|
progressControl: {
|
|
|
|
seekBar: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
html5: {
|
|
|
|
vhs: {
|
|
|
|
// used to select the lowest bitrate playlist initially. This helps to decrease playback start time. This setting is false by default.
|
|
|
|
enableLowInitialPlaylist: true,
|
|
|
|
experimentalBufferBasedABR: true,
|
|
|
|
useNetworkInformationApi: true,
|
|
|
|
maxPlaylistRetries: 30,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
liveTracker: {
|
|
|
|
trackingThreshold: 0,
|
|
|
|
liveTolerance: 15,
|
|
|
|
},
|
|
|
|
sources: [
|
|
|
|
{
|
2022-05-11 01:36:09 +03:00
|
|
|
src: source,
|
2022-04-27 05:29:13 +03:00
|
|
|
type: 'application/x-mpegURL',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
|
|
|
const handlePlayerReady = player => {
|
|
|
|
playerRef.current = player;
|
|
|
|
|
2022-05-09 09:42:40 +03:00
|
|
|
setSavedVolume();
|
|
|
|
|
2022-04-27 05:29:13 +03:00
|
|
|
// You can handle player events here, for example:
|
|
|
|
player.on('waiting', () => {
|
|
|
|
player.log('player is waiting');
|
|
|
|
});
|
|
|
|
|
|
|
|
player.on('dispose', () => {
|
|
|
|
player.log('player will dispose');
|
2022-05-09 09:42:40 +03:00
|
|
|
ping.stop();
|
2022-04-27 05:29:13 +03:00
|
|
|
});
|
2022-05-09 09:42:40 +03:00
|
|
|
|
|
|
|
player.on('playing', () => {
|
|
|
|
player.log('player is playing');
|
|
|
|
ping.start();
|
2022-05-11 01:36:09 +03:00
|
|
|
setVideoState(VideoState.Playing);
|
2022-05-09 09:42:40 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
player.on('pause', () => {
|
|
|
|
player.log('player is paused');
|
|
|
|
ping.stop();
|
|
|
|
});
|
|
|
|
|
|
|
|
player.on('ended', () => {
|
|
|
|
player.log('player is ended');
|
|
|
|
ping.stop();
|
2022-05-11 01:36:09 +03:00
|
|
|
setVideoState(VideoState.Unavailable);
|
2022-05-09 09:42:40 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
player.on('volumechange', handleVolume);
|
2022-04-27 05:29:13 +03:00
|
|
|
};
|
|
|
|
|
2022-05-11 01:36:09 +03:00
|
|
|
return (
|
|
|
|
<div style={{ display: 'grid' }}>
|
|
|
|
{online && (
|
|
|
|
<div style={{ gridColumn: 1, gridRow: 1 }}>
|
|
|
|
<VideoJS
|
|
|
|
style={{ gridColumn: 1, gridRow: 1 }}
|
|
|
|
options={videoJsOptions}
|
|
|
|
onReady={handlePlayerReady}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
<div style={{ gridColumn: 1, gridRow: 1 }}>
|
|
|
|
<VideoPoster online={online} initialSrc="/logo" src="/thumbnail.jpg" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
2022-04-27 05:29:13 +03:00
|
|
|
}
|