add Player.js Support (#378)
* Reorder video.js imports and props * Install player.js * Add player.js adapter for video.js
This commit is contained in:
parent
a7b991efb1
commit
4fd4309829
3 changed files with 73 additions and 68 deletions
|
@ -59,6 +59,7 @@
|
||||||
"if-env": "^1.0.4",
|
"if-env": "^1.0.4",
|
||||||
"match-sorter": "^6.3.0",
|
"match-sorter": "^6.3.0",
|
||||||
"parse-duration": "^1.0.0",
|
"parse-duration": "^1.0.0",
|
||||||
|
"player.js": "^0.1.0",
|
||||||
"proxy-polyfill": "0.1.6",
|
"proxy-polyfill": "0.1.6",
|
||||||
"re-reselect": "^4.0.0",
|
"re-reselect": "^4.0.0",
|
||||||
"react-datetime-picker": "^3.2.1",
|
"react-datetime-picker": "^3.2.1",
|
||||||
|
|
|
@ -1,72 +1,72 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
|
||||||
// import { SIMPLE_SITE } from 'config';
|
import './plugins/videojs-mobile-ui/plugin';
|
||||||
import Button from 'component/button';
|
|
||||||
import * as ICONS from 'constants/icons';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import videojs from 'video.js';
|
|
||||||
import 'videojs-contrib-ads'; // must be loaded in this order
|
import 'videojs-contrib-ads'; // must be loaded in this order
|
||||||
import 'videojs-ima'; // loads directly after contrib-ads
|
import 'videojs-ima'; // loads directly after contrib-ads
|
||||||
import 'video.js/dist/alt/video-js-cdn.min.css';
|
import 'video.js/dist/alt/video-js-cdn.min.css';
|
||||||
import eventTracking from 'videojs-event-tracking';
|
|
||||||
|
import * as ICONS from 'constants/icons';
|
||||||
import * as OVERLAY from './overlays';
|
import * as OVERLAY from './overlays';
|
||||||
import './plugins/videojs-mobile-ui/plugin';
|
import Button from 'component/button';
|
||||||
import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin';
|
import classnames from 'classnames';
|
||||||
import recsys from './plugins/videojs-recsys/plugin';
|
|
||||||
import qualityLevels from 'videojs-contrib-quality-levels';
|
|
||||||
import runAds from './ads';
|
|
||||||
import LbryVolumeBarClass from './lbry-volume-bar';
|
|
||||||
import keyboardShorcuts from './videojs-keyboard-shortcuts';
|
|
||||||
import events from './videojs-events';
|
import events from './videojs-events';
|
||||||
|
import eventTracking from 'videojs-event-tracking';
|
||||||
import functions from './videojs-functions';
|
import functions from './videojs-functions';
|
||||||
|
import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin';
|
||||||
|
import keyboardShorcuts from './videojs-keyboard-shortcuts';
|
||||||
|
import LbryVolumeBarClass from './lbry-volume-bar';
|
||||||
|
import playerjs from 'player.js';
|
||||||
|
import qualityLevels from 'videojs-contrib-quality-levels';
|
||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
import recsys from './plugins/videojs-recsys/plugin';
|
||||||
|
import runAds from './ads';
|
||||||
|
import videojs from 'video.js';
|
||||||
|
|
||||||
export type Player = {
|
export type Player = {
|
||||||
on: (string, (any) => void) => void,
|
controlBar: { addChild: (string, any) => void },
|
||||||
one: (string, (any) => void) => void,
|
loadingSpinner: any,
|
||||||
isFullscreen: () => boolean,
|
autoplay: (any) => boolean,
|
||||||
exitFullscreen: () => boolean,
|
|
||||||
requestFullscreen: () => boolean,
|
|
||||||
play: () => Promise<any>,
|
|
||||||
volume: (?number) => number,
|
|
||||||
muted: (?boolean) => boolean,
|
|
||||||
dispose: () => void,
|
|
||||||
currentTime: (?number) => number,
|
currentTime: (?number) => number,
|
||||||
|
dispose: () => void,
|
||||||
ended: () => boolean,
|
ended: () => boolean,
|
||||||
error: () => any,
|
error: () => any,
|
||||||
loadingSpinner: any,
|
exitFullscreen: () => boolean,
|
||||||
getChild: (string) => any,
|
getChild: (string) => any,
|
||||||
|
isFullscreen: () => boolean,
|
||||||
|
mobileUi: (any) => void,
|
||||||
|
muted: (?boolean) => boolean,
|
||||||
|
on: (string, (any) => void) => void,
|
||||||
|
one: (string, (any) => void) => void,
|
||||||
|
overlay: (any) => void,
|
||||||
|
play: () => Promise<any>,
|
||||||
playbackRate: (?number) => number,
|
playbackRate: (?number) => number,
|
||||||
readyState: () => number,
|
readyState: () => number,
|
||||||
|
requestFullscreen: () => boolean,
|
||||||
userActive: (?boolean) => boolean,
|
userActive: (?boolean) => boolean,
|
||||||
overlay: (any) => void,
|
volume: (?number) => number,
|
||||||
mobileUi: (any) => void,
|
|
||||||
controlBar: {
|
|
||||||
addChild: (string, any) => void,
|
|
||||||
},
|
|
||||||
autoplay: (any) => boolean,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
source: string,
|
adUrl: ?string,
|
||||||
sourceType: string,
|
allowPreRoll: ?boolean,
|
||||||
poster: ?string,
|
|
||||||
onPlayerReady: (Player, any) => void,
|
|
||||||
isAudio: boolean,
|
|
||||||
startMuted: boolean,
|
|
||||||
autoplay: boolean,
|
autoplay: boolean,
|
||||||
autoplaySetting: boolean,
|
autoplaySetting: boolean,
|
||||||
embedded: boolean,
|
|
||||||
toggleVideoTheaterMode: () => void,
|
|
||||||
adUrl: ?string,
|
|
||||||
claimId: ?string,
|
claimId: ?string,
|
||||||
userId: ?number,
|
embedded: boolean,
|
||||||
allowPreRoll: ?boolean,
|
|
||||||
internalFeatureEnabled: ?boolean,
|
internalFeatureEnabled: ?boolean,
|
||||||
shareTelemetry: boolean,
|
isAudio: boolean,
|
||||||
|
poster: ?string,
|
||||||
replay: boolean,
|
replay: boolean,
|
||||||
|
shareTelemetry: boolean,
|
||||||
|
source: string,
|
||||||
|
sourceType: string,
|
||||||
|
startMuted: boolean,
|
||||||
|
userId: ?number,
|
||||||
videoTheaterMode: boolean,
|
videoTheaterMode: boolean,
|
||||||
|
onPlayerReady: (Player, any) => void,
|
||||||
playNext: () => void,
|
playNext: () => void,
|
||||||
playPrevious: () => void,
|
playPrevious: () => void,
|
||||||
|
toggleVideoTheaterMode: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
const videoPlaybackRates = [0.25, 0.5, 0.75, 1, 1.1, 1.25, 1.5, 1.75, 2];
|
const videoPlaybackRates = [0.25, 0.5, 0.75, 1, 1.1, 1.25, 1.5, 1.75, 2];
|
||||||
|
@ -114,26 +114,26 @@ properties for this component should be kept to ONLY those that if changed shoul
|
||||||
*/
|
*/
|
||||||
export default React.memo<Props>(function VideoJs(props: Props) {
|
export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
const {
|
const {
|
||||||
|
// adUrl, // TODO: this ad functionality isn't used, can be pulled out
|
||||||
|
allowPreRoll,
|
||||||
autoplay,
|
autoplay,
|
||||||
autoplaySetting,
|
autoplaySetting,
|
||||||
|
claimId,
|
||||||
embedded,
|
embedded,
|
||||||
startMuted,
|
internalFeatureEnabled, // for people on the team to test new features internally
|
||||||
|
isAudio,
|
||||||
|
poster,
|
||||||
|
replay,
|
||||||
|
shareTelemetry,
|
||||||
source,
|
source,
|
||||||
sourceType,
|
sourceType,
|
||||||
poster,
|
startMuted,
|
||||||
isAudio,
|
|
||||||
onPlayerReady,
|
|
||||||
toggleVideoTheaterMode,
|
|
||||||
// adUrl, // TODO: this ad functionality isn't used, can be pulled out
|
|
||||||
claimId,
|
|
||||||
userId,
|
userId,
|
||||||
allowPreRoll,
|
|
||||||
internalFeatureEnabled, // for people on the team to test new features internally
|
|
||||||
shareTelemetry,
|
|
||||||
replay,
|
|
||||||
videoTheaterMode,
|
videoTheaterMode,
|
||||||
|
onPlayerReady,
|
||||||
playNext,
|
playNext,
|
||||||
playPrevious,
|
playPrevious,
|
||||||
|
toggleVideoTheaterMode,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
// will later store the videojs player
|
// will later store the videojs player
|
||||||
|
@ -152,27 +152,25 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
...VIDEO_JS_OPTIONS,
|
...VIDEO_JS_OPTIONS,
|
||||||
autoplay: autoplay,
|
autoplay: autoplay,
|
||||||
muted: startMuted,
|
muted: startMuted,
|
||||||
sources: [
|
sources: [{ src: source, type: sourceType }],
|
||||||
{
|
|
||||||
src: source,
|
|
||||||
type: sourceType,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
poster: poster, // thumb looks bad in app, and if autoplay, flashing poster is annoying
|
poster: poster, // thumb looks bad in app, and if autoplay, flashing poster is annoying
|
||||||
plugins: {
|
plugins: { eventTracking: true, overlay: OVERLAY.OVERLAY_DATA },
|
||||||
eventTracking: true,
|
|
||||||
overlay: OVERLAY.OVERLAY_DATA,
|
|
||||||
},
|
|
||||||
// fixes problem of errant CC button showing up on iOS
|
// fixes problem of errant CC button showing up on iOS
|
||||||
// the true fix here is to fix the m3u8 file, see: https://github.com/lbryio/lbry-desktop/pull/6315
|
// the true fix here is to fix the m3u8 file, see: https://github.com/lbryio/lbry-desktop/pull/6315
|
||||||
controlBar: {
|
controlBar: { subsCapsButton: false },
|
||||||
subsCapsButton: false,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const { detectFileType, createVideoPlayerDOM } = functions({ source, sourceType, videoJsOptions, isAudio });
|
const { detectFileType, createVideoPlayerDOM } = functions({ source, sourceType, videoJsOptions, isAudio });
|
||||||
|
|
||||||
const { unmuteAndHideHint, retryVideoAfterFailure, initializeEvents } = events({ tapToUnmuteRef, tapToRetryRef, setReload, videoTheaterMode, playerRef, autoplaySetting, replay });
|
const { unmuteAndHideHint, retryVideoAfterFailure, initializeEvents } = events({
|
||||||
|
tapToUnmuteRef,
|
||||||
|
tapToRetryRef,
|
||||||
|
setReload,
|
||||||
|
videoTheaterMode,
|
||||||
|
playerRef,
|
||||||
|
autoplaySetting,
|
||||||
|
replay,
|
||||||
|
});
|
||||||
|
|
||||||
// Initialize video.js
|
// Initialize video.js
|
||||||
function initializeVideoPlayer(el) {
|
function initializeVideoPlayer(el) {
|
||||||
|
@ -180,6 +178,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
|
|
||||||
const vjs = videojs(el, videoJsOptions, () => {
|
const vjs = videojs(el, videoJsOptions, () => {
|
||||||
const player = playerRef.current;
|
const player = playerRef.current;
|
||||||
|
const adapter = new playerjs.VideoJSAdapter(player);
|
||||||
|
|
||||||
// this seems like a weird thing to have to check for here
|
// this seems like a weird thing to have to check for here
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
|
@ -218,6 +217,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
const videoNode = containerRef.current && containerRef.current.querySelector('video, audio');
|
const videoNode = containerRef.current && containerRef.current.querySelector('video, audio');
|
||||||
|
|
||||||
onPlayerReady(player, videoNode);
|
onPlayerReady(player, videoNode);
|
||||||
|
adapter.ready();
|
||||||
});
|
});
|
||||||
|
|
||||||
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498)
|
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498)
|
||||||
|
@ -293,7 +293,6 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
}, [source, reload]);
|
}, [source, reload]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// $FlowFixMe
|
|
||||||
<div className={classnames('video-js-parent', { 'video-js-parent--ios': IS_IOS })} ref={containerRef}>
|
<div className={classnames('video-js-parent', { 'video-js-parent--ios': IS_IOS })} ref={containerRef}>
|
||||||
<Button
|
<Button
|
||||||
label={__('Tap to unmute')}
|
label={__('Tap to unmute')}
|
||||||
|
|
|
@ -12218,6 +12218,11 @@ pkg-up@^2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
find-up "^2.1.0"
|
find-up "^2.1.0"
|
||||||
|
|
||||||
|
player.js@^0.1.0:
|
||||||
|
version "0.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/player.js/-/player.js-0.1.0.tgz#38a2647f022dbbccf2e97e85e1fddccc9ef498e8"
|
||||||
|
integrity sha1-OKJkfwItu8zy6X6F4f3czJ70mOg=
|
||||||
|
|
||||||
please-upgrade-node@^3.0.2, please-upgrade-node@^3.2.0:
|
please-upgrade-node@^3.0.2, please-upgrade-node@^3.2.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
|
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
|
||||||
|
|
Loading…
Reference in a new issue