From 4fd43098297fe96049bef197518d02698387e76f Mon Sep 17 00:00:00 2001 From: saltrafael <76502841+saltrafael@users.noreply.github.com> Date: Tue, 30 Nov 2021 17:46:03 -0300 Subject: [PATCH] add Player.js Support (#378) * Reorder video.js imports and props * Install player.js * Add player.js adapter for video.js --- package.json | 1 + .../viewers/videoViewer/internal/videojs.jsx | 135 +++++++++--------- yarn.lock | 5 + 3 files changed, 73 insertions(+), 68 deletions(-) diff --git a/package.json b/package.json index 8b84fc9f7..d7c49d198 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "if-env": "^1.0.4", "match-sorter": "^6.3.0", "parse-duration": "^1.0.0", + "player.js": "^0.1.0", "proxy-polyfill": "0.1.6", "re-reselect": "^4.0.0", "react-datetime-picker": "^3.2.1", diff --git a/ui/component/viewers/videoViewer/internal/videojs.jsx b/ui/component/viewers/videoViewer/internal/videojs.jsx index c1d3cf730..144d1e326 100644 --- a/ui/component/viewers/videoViewer/internal/videojs.jsx +++ b/ui/component/viewers/videoViewer/internal/videojs.jsx @@ -1,72 +1,72 @@ // @flow -import React, { useEffect, useRef, useState } from 'react'; -// import { SIMPLE_SITE } from 'config'; -import Button from 'component/button'; -import * as ICONS from 'constants/icons'; -import classnames from 'classnames'; -import videojs from 'video.js'; + +import './plugins/videojs-mobile-ui/plugin'; import 'videojs-contrib-ads'; // must be loaded in this order import 'videojs-ima'; // loads directly after contrib-ads 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 './plugins/videojs-mobile-ui/plugin'; -import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin'; -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 Button from 'component/button'; +import classnames from 'classnames'; import events from './videojs-events'; +import eventTracking from 'videojs-event-tracking'; 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 = { - on: (string, (any) => void) => void, - one: (string, (any) => void) => void, - isFullscreen: () => boolean, - exitFullscreen: () => boolean, - requestFullscreen: () => boolean, - play: () => Promise, - volume: (?number) => number, - muted: (?boolean) => boolean, - dispose: () => void, + controlBar: { addChild: (string, any) => void }, + loadingSpinner: any, + autoplay: (any) => boolean, currentTime: (?number) => number, + dispose: () => void, ended: () => boolean, error: () => any, - loadingSpinner: any, + exitFullscreen: () => boolean, 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, playbackRate: (?number) => number, readyState: () => number, + requestFullscreen: () => boolean, userActive: (?boolean) => boolean, - overlay: (any) => void, - mobileUi: (any) => void, - controlBar: { - addChild: (string, any) => void, - }, - autoplay: (any) => boolean, + volume: (?number) => number, }; type Props = { - source: string, - sourceType: string, - poster: ?string, - onPlayerReady: (Player, any) => void, - isAudio: boolean, - startMuted: boolean, + adUrl: ?string, + allowPreRoll: ?boolean, autoplay: boolean, autoplaySetting: boolean, - embedded: boolean, - toggleVideoTheaterMode: () => void, - adUrl: ?string, claimId: ?string, - userId: ?number, - allowPreRoll: ?boolean, + embedded: boolean, internalFeatureEnabled: ?boolean, - shareTelemetry: boolean, + isAudio: boolean, + poster: ?string, replay: boolean, + shareTelemetry: boolean, + source: string, + sourceType: string, + startMuted: boolean, + userId: ?number, videoTheaterMode: boolean, + onPlayerReady: (Player, any) => void, playNext: () => void, playPrevious: () => void, + toggleVideoTheaterMode: () => void, }; 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(function VideoJs(props: Props) { const { + // adUrl, // TODO: this ad functionality isn't used, can be pulled out + allowPreRoll, autoplay, autoplaySetting, + claimId, embedded, - startMuted, + internalFeatureEnabled, // for people on the team to test new features internally + isAudio, + poster, + replay, + shareTelemetry, source, sourceType, - poster, - isAudio, - onPlayerReady, - toggleVideoTheaterMode, - // adUrl, // TODO: this ad functionality isn't used, can be pulled out - claimId, + startMuted, userId, - allowPreRoll, - internalFeatureEnabled, // for people on the team to test new features internally - shareTelemetry, - replay, videoTheaterMode, + onPlayerReady, playNext, playPrevious, + toggleVideoTheaterMode, } = props; // will later store the videojs player @@ -152,27 +152,25 @@ export default React.memo(function VideoJs(props: Props) { ...VIDEO_JS_OPTIONS, autoplay: autoplay, muted: startMuted, - sources: [ - { - src: source, - type: sourceType, - }, - ], + sources: [{ src: source, type: sourceType }], poster: poster, // thumb looks bad in app, and if autoplay, flashing poster is annoying - plugins: { - eventTracking: true, - overlay: OVERLAY.OVERLAY_DATA, - }, + plugins: { eventTracking: true, overlay: OVERLAY.OVERLAY_DATA }, // 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 - controlBar: { - subsCapsButton: false, - }, + controlBar: { subsCapsButton: false }, }; 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 function initializeVideoPlayer(el) { @@ -180,6 +178,7 @@ export default React.memo(function VideoJs(props: Props) { const vjs = videojs(el, videoJsOptions, () => { const player = playerRef.current; + const adapter = new playerjs.VideoJSAdapter(player); // this seems like a weird thing to have to check for here if (!player) return; @@ -218,6 +217,7 @@ export default React.memo(function VideoJs(props: Props) { const videoNode = containerRef.current && containerRef.current.querySelector('video, audio'); onPlayerReady(player, videoNode); + adapter.ready(); }); // fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498) @@ -293,7 +293,6 @@ export default React.memo(function VideoJs(props: Props) { }, [source, reload]); return ( - // $FlowFixMe