diff --git a/web/components/video/VideoJS/VideoJS.tsx b/web/components/video/VideoJS/VideoJS.tsx index 58d0ef7b8..25134f140 100644 --- a/web/components/video/VideoJS/VideoJS.tsx +++ b/web/components/video/VideoJS/VideoJS.tsx @@ -21,17 +21,24 @@ export const VideoJS: FC = ({ options, onReady }) => { // eslint-disable-next-line no-multi-assign const player = (playerRef.current = videojs(videoElement, options, () => { console.debug('player is ready'); - return onReady && onReady(player, videojs); })); - // TODO: Add airplay support, video settings menu, latency compensator, etc. - - // You can update player in the `else` block here, for example: - // } else { player.autoplay(options.autoplay); player.src(options.sources); } + + // Add a cachebuster param to playlist URLs. + videojs.Vhs.xhr.beforeRequest = o => { + console.log('beforeRequest'); + if (o.uri.match('m3u8')) { + const cachebuster = Math.random().toString(16).substr(2, 8); + // eslint-disable-next-line no-param-reassign + o.uri = `${o.uri}?cachebust=${cachebuster}`; + } + + return o; + }; }, [options, videoRef]); return ( @@ -46,338 +53,3 @@ export const VideoJS: FC = ({ options, onReady }) => { }; export default VideoJS; - -// class OwncastPlayer { -// constructor() { -// window.VIDEOJS_NO_DYNAMIC_STYLE = true; // style override - -// this.vjsPlayer = null; -// this.latencyCompensator = null; -// this.playbackMetrics = null; - -// this.appPlayerReadyCallback = null; -// this.appPlayerPlayingCallback = null; -// this.appPlayerEndedCallback = null; - -// this.hasStartedPlayback = false; -// this.latencyCompensatorEnabled = false; - -// // bind all the things because safari -// this.startPlayer = this.startPlayer.bind(this); -// this.handleReady = this.handleReady.bind(this); -// this.handlePlaying = this.handlePlaying.bind(this); -// this.handleVolume = this.handleVolume.bind(this); -// this.handleEnded = this.handleEnded.bind(this); -// this.handleError = this.handleError.bind(this); -// this.addQualitySelector = this.addVideoSettingsMenu.bind(this); -// this.addQualitySelector = this.addVideoSettingsMenu.bind(this); -// this.toggleLatencyCompensator = this.toggleLatencyCompensator.bind(this); -// this.startLatencyCompensator = this.startLatencyCompensator.bind(this); -// this.stopLatencyCompensator = this.stopLatencyCompensator.bind(this); -// this.qualitySelectionMenu = null; -// this.latencyCompensatorToggleButton = null; -// } - -// init() { -// // this.addAirplay(); -// // this.addVideoSettingsMenu(); - -// // Add a cachebuster param to playlist URLs. -// videojs.Vhs.xhr.beforeRequest = options => { -// if (options.uri.match('m3u8')) { -// const cachebuster = Math.random().toString(16).substr(2, 8); -// options.uri = `${options.uri}?cachebust=${cachebuster}`; -// } - -// return options; -// }; - -// this.vjsPlayer = videojs(VIDEO_ID, VIDEO_OPTIONS); - -// this.vjsPlayer.ready(this.handleReady); -// } - -// setupPlayerCallbacks(callbacks) { -// const { onReady, onPlaying, onEnded, onError } = callbacks; - -// this.appPlayerReadyCallback = onReady; -// this.appPlayerPlayingCallback = onPlaying; -// this.appPlayerEndedCallback = onEnded; -// this.appPlayerErrorCallback = onError; -// } - -// // play -// startPlayer() { -// this.log('Start playing'); -// const source = { ...VIDEO_SRC }; - -// try { -// this.vjsPlayer.volume(getLocalStorage(PLAYER_VOLUME) || 1); -// } catch (err) { -// console.warn(err); -// } -// this.vjsPlayer.src(source); -// } - -// setupPlaybackMetrics() { -// // this.playbackMetrics = new PlaybackMetrics(this.vjsPlayer, videojs); -// } - -// setupLatencyCompensator() { -// const tech = this.vjsPlayer.tech({ IWillNotUseThisInPlugins: true }); - -// // VHS is required. -// if (!tech || !tech.vhs) { -// } - -// // const latencyCompensatorEnabledSaved = getLocalStorage(LATENCY_COMPENSATION_ENABLED); - -// // if (latencyCompensatorEnabledSaved === 'true' && tech && tech.vhs) { -// // this.startLatencyCompensator(); -// // } else { -// // this.stopLatencyCompensator(); -// // } -// } - -// startLatencyCompensator() { -// // this.latencyCompensator = new LatencyCompensator(this.vjsPlayer); -// // this.latencyCompensator.enable(); -// // this.latencyCompensatorEnabled = true; -// // this.setLatencyCompensatorItemTitle('disable minimized latency'); -// } - -// stopLatencyCompensator() { -// // if (this.latencyCompensator) { -// // this.latencyCompensator.disable(); -// // } -// // this.LatencyCompensator = null; -// // this.latencyCompensatorEnabled = false; -// // this.setLatencyCompensatorItemTitle( -// // 'enable minimized latency (experimental)', -// // ); -// } - -// handleReady() { -// console.log('handleReady'); -// this.vjsPlayer.on('error', this.handleError); -// this.vjsPlayer.on('playing', this.handlePlaying); -// this.vjsPlayer.on('volumechange', this.handleVolume); -// this.vjsPlayer.on('ended', this.handleEnded); - -// this.vjsPlayer.on('loadeddata', () => { -// this.setupPlaybackMetrics(); -// this.setupLatencyCompensator(); -// }); - -// if (this.appPlayerReadyCallback) { -// // start polling -// this.appPlayerReadyCallback(); -// } - -// this.vjsPlayer.log.level('debug'); -// } - -// handleVolume() { -// setLocalStorage(PLAYER_VOLUME, this.vjsPlayer.muted() ? 0 : this.vjsPlayer.volume()); -// } - -// handlePlaying() { -// if (this.appPlayerPlayingCallback) { -// // start polling -// this.appPlayerPlayingCallback(); -// } - -// if (this.latencyCompensator && !this.hasStartedPlayback) { -// this.latencyCompensator.enable(); -// } - -// this.hasStartedPlayback = true; -// } - -// handleEnded() { -// if (this.appPlayerEndedCallback) { -// this.appPlayerEndedCallback(); -// } - -// this.stopLatencyCompensator(); -// } - -// handleError(e) { -// this.log(`on Error: ${JSON.stringify(e)}`); -// if (this.appPlayerEndedCallback) { -// this.appPlayerEndedCallback(); -// } -// } - -// toggleLatencyCompensator() { -// if (this.latencyCompensatorEnabled) { -// this.stopLatencyCompensator(); -// setLocalStorage(LATENCY_COMPENSATION_ENABLED, false); -// } else { -// this.startLatencyCompensator(); -// setLocalStorage(LATENCY_COMPENSATION_ENABLED, true); -// } -// } - -// setLatencyCompensatorItemTitle(title) { -// const item = document.querySelector('.latency-toggle-item > .vjs-menu-item-text'); -// if (!item) { -// return; -// } - -// item.innerHTML = title; -// } - -// log(message) { -// // console.log(`>>> Player: ${message}`); -// } - -// render(): JSX.Element { -// return ( -//
-//
-// ); -// } - -// async addVideoSettingsMenu() { -// if (this.qualityMenuButton) { -// player.controlBar.removeChild(this.qualityMenuButton); -// } - -// videojs.hookOnce('setup', async player => { -// let qualities = []; - -// try { -// const response = await fetch('http://localhost:8080/api/video/variants'); -// qualities = await response.json(); -// } catch (e) { -// console.error(e); -// } - -// const MenuItem = videojs.getComponent('MenuItem'); -// const MenuButtonClass = videojs.getComponent('MenuButton'); - -// const lowLatencyItem = new MenuItem(player, { -// selectable: true, -// }); -// lowLatencyItem.setAttribute('class', 'latency-toggle-item'); -// lowLatencyItem.on('click', () => { -// this.toggleLatencyCompensator(); -// }); -// this.latencyCompensatorToggleButton = lowLatencyItem; - -// const separator = new MenuSeparator(player, { -// selectable: false, -// }); - -// const MenuButton = videojs.extend(MenuButtonClass, { -// // The `init()` method will also work for constructor logic here, but it is -// // deprecated. If you provide an `init()` method, it will override the -// // `constructor()` method! -// constructor() { -// MenuButtonClass.call(this, player); -// }, - -// createItems() { -// const tech = this.player_.tech({ IWillNotUseThisInPlugins: true }); - -// const defaultAutoItem = new MenuItem(player, { -// selectable: true, -// label: 'Auto', -// }); - -// const items = qualities.map(item => { -// const newMenuItem = new MenuItem(player, { -// selectable: true, -// label: item.name, -// }); - -// // Quality selected -// newMenuItem.on('click', () => { -// // If for some reason tech doesn't exist, then don't do anything -// if (!tech) { -// console.warn('Invalid attempt to access null player tech'); -// return; -// } -// // Only enable this single, selected representation. -// tech.vhs.representations().forEach((rep, index) => { -// rep.enabled(index === item.index); -// }); -// newMenuItem.selected(false); -// }); - -// return newMenuItem; -// }); - -// defaultAutoItem.on('click', () => { -// // Re-enable all representations. -// tech.vhs.representations().forEach((rep, index) => { -// rep.enabled(true); -// }); -// defaultAutoItem.selected(false); -// }); - -// const supportsLatencyCompensator = !!tech && !!tech.vhs; - -// // Only show the quality selector if there is more than one option. -// if (qualities.length < 2 && supportsLatencyCompensator) { -// return [lowLatencyItem]; -// } -// if (qualities.length > 1 && supportsLatencyCompensator) { -// return [defaultAutoItem, ...items, separator, lowLatencyItem]; -// } -// if (!supportsLatencyCompensator && qualities.length == 1) { -// return []; -// } - -// return [defaultAutoItem, ...items]; -// }, -// }); - -// // If none of the settings in this menu are applicable then don't show it. -// const tech = player.tech({ IWillNotUseThisInPlugins: true }); - -// if (qualities.length < 2 && (!tech || !tech.vhs)) { -// return; -// } - -// const menuButton = new MenuButton(); -// menuButton.addClass('vjs-quality-selector'); -// player.controlBar.addChild(menuButton, {}, player.controlBar.children_.length - 2); -// this.qualityMenuButton = menuButton; -// this.latencyCompensatorToggleButton = lowLatencyItem; -// }); -// } - -// addAirplay() { -// videojs.hookOnce('setup', player => { -// if (window.WebKitPlaybackTargetAvailabilityEvent) { -// const videoJsButtonClass = videojs.getComponent('Button'); -// const concreteButtonClass = videojs.extend(videoJsButtonClass, { -// // The `init()` method will also work for constructor logic here, but it is -// // deprecated. If you provide an `init()` method, it will override the -// // `constructor()` method! -// constructor() { -// videoJsButtonClass.call(this, player); -// }, - -// handleClick() { -// const videoElement = document.getElementsByTagName('video')[0]; -// videoElement.webkitShowPlaybackTargetPicker(); -// }, -// }); - -// const concreteButtonInstance = player.controlBar.addChild(new concreteButtonClass()); -// concreteButtonInstance.addClass('vjs-airplay'); -// } -// }); -// } - -// } - -// export { OwncastPlayer }; - -// const VjsMenuItem = videojs.getComponent('MenuItem'); - -// VjsMenuItem.registerComponent('MenuSeparator', MenuSeparator);