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:
saltrafael 2021-11-30 17:46:03 -03:00 committed by GitHub
parent a7b991efb1
commit 4fd4309829
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 68 deletions

View file

@ -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",

View file

@ -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')}

View file

@ -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"