1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-03 09:49:20 +02:00

Upgrade to videojs v8

This commit is contained in:
Chocobozzz 2025-08-11 08:30:00 +02:00
parent 91afa1004e
commit 8c83592d89
No known key found for this signature in database
GPG key ID: 583A612D890159BE
57 changed files with 573 additions and 453 deletions

View file

@ -67,7 +67,6 @@
"@types/qrcode": "^1.5.5",
"@types/sanitize-html": "2.11.0",
"@types/sha.js": "^2.4.0",
"@types/video.js": "^7.3.40",
"@wdio/browserstack-service": "^9.12.7",
"@wdio/cli": "^9.12.7",
"@wdio/local-runner": "^9.12.7",
@ -109,7 +108,7 @@
"type-fest": "^4.37.0",
"typescript": "~5.7.3",
"ua-parser-js": "^2.0.3",
"video.js": "^7.19.2",
"video.js": "^8.23.4",
"vite": "^6.0.11",
"vite-plugin-checker": "^0.9.3",
"vite-plugin-node-polyfills": "^0.23.0",

View file

@ -52,7 +52,8 @@ import {
PeerTubePlayerConstructorOptions,
PeerTubePlayerLoadOptions,
PlayerMode,
videojs
videojs,
VideojsPlayer
} from '@peertube/player'
import { logger } from '@root-helpers/logger'
import { isP2PEnabled, videoRequiresFileToken, videoRequiresUserAuth } from '@root-helpers/video'
@ -885,7 +886,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
return loggedInOrAnonymousUser?.autoPlayNextVideo
},
isSuspended: (player: videojs.Player) => {
isSuspended: (player: VideojsPlayer) => {
return !isXPercentInViewport(player.el() as HTMLElement, 80)
},

View file

@ -5,7 +5,7 @@ import { TranslationsManager } from '@root-helpers/translations-manager'
import { copyToClipboard } from '@root-helpers/utils'
import { buildVideoOrPlaylistEmbed } from '@root-helpers/video'
import { isMobile } from '@root-helpers/web-browser'
import videojs, { VideoJsPlayer } from 'video.js'
import videojs from 'video.js'
import { saveAverageBandwidth } from './peertube-player-local-storage'
import './shared/bezels/bezels-plugin'
import './shared/context-menu'
@ -20,12 +20,12 @@ import './shared/control-bar/theater-button'
import './shared/control-bar/time-tooltip'
import './shared/dock/peertube-dock-component'
import './shared/dock/peertube-dock-plugin'
import './shared/nsfw/peertube-nsfw-info-component'
import './shared/nsfw/peertube-nsfw-plugin'
import './shared/hotkeys/peertube-hotkeys-plugin'
import './shared/metrics/metrics-plugin'
import './shared/mobile/peertube-mobile-buttons'
import './shared/mobile/peertube-mobile-plugin'
import './shared/nsfw/peertube-nsfw-info-component'
import './shared/nsfw/peertube-nsfw-plugin'
import './shared/p2p-media-loader/hls-plugin'
import './shared/p2p-media-loader/p2p-media-loader-plugin'
import './shared/peertube/peertube-plugin'
@ -45,7 +45,15 @@ import './shared/stats/stats-plugin'
import './shared/upnext/end-card'
import './shared/upnext/upnext-plugin'
import './shared/web-video/web-video-plugin'
import { PeerTubePlayerConstructorOptions, PeerTubePlayerLoadOptions, PlayerNetworkInfo, VideoJSPluginOptions } from './types'
import {
PeerTubePlayerConstructorOptions,
PeerTubePlayerLoadOptions,
PlayerNetworkInfo,
VideojsAutoplay,
VideojsPlayer,
VideojsPlayerOptions,
VideoJSPluginOptions
} from './types'
const CaptionsButton = videojs.getComponent('CaptionsButton') as any
// Change Captions to Subtitles/CC
@ -70,7 +78,7 @@ export class PeerTubePlayer {
private videojsDecodeErrors = 0
private player: VideoJsPlayer
private player: VideojsPlayer
private currentLoadOptions: PeerTubePlayerLoadOptions
@ -210,7 +218,7 @@ export class PeerTubePlayer {
this.getVideojsOptions()
)
this.player = videojs(this.options.playerElement(), videojsOptions)
this.player = videojs(this.options.playerElement(), videojsOptions) as VideojsPlayer
this.player.ready(() => {
if (!isNaN(+this.options.playbackRate)) {
@ -233,7 +241,7 @@ export class PeerTubePlayer {
this.player.on('video-change', () => alreadyFallback = false)
this.player.on('error', () => handleError())
this.player.on('network-info', (_, data: PlayerNetworkInfo) => {
this.player.on('network-info', (_: any, data: PlayerNetworkInfo) => {
if (data.source !== 'p2p-media-loader' || isNaN(data.bandwidthEstimate)) return
saveAverageBandwidth(data.bandwidthEstimate)
@ -366,7 +374,7 @@ export class PeerTubePlayer {
})
}
getVideojsOptions (): videojs.PlayerOptions {
getVideojsOptions (): VideojsPlayerOptions {
const html5 = {
preloadTextTracks: false,
// Prevent a bug on iOS where the text tracks added by peertube plugin are removed on play
@ -422,7 +430,7 @@ export class PeerTubePlayer {
html5,
// We don't use text track settings for now
textTrackSettings: false as any, // FIXME: typings
textTrackSettings: false,
controls: this.options.controls !== undefined ? this.options.controls : true,
loop: this.options.loop !== undefined ? this.options.loop : false,
@ -441,18 +449,20 @@ export class PeerTubePlayer {
plugins,
controlBar: {
children: controlBarOptionsBuilder.getChildrenOptions() as any // FIXME: typings
children: controlBarOptionsBuilder.getChildrenOptions()
},
language: this.options.language && !isDefaultLocale(this.options.language)
? this.options.language
: undefined
}
: undefined,
enableSmoothSeeking: true
} satisfies VideojsPlayerOptions
return videojsOptions
}
private getAutoPlayValue (autoplay: boolean): videojs.Autoplay {
private getAutoPlayValue (autoplay: boolean): VideojsAutoplay {
if (autoplay !== true) return false
return this.currentLoadOptions.forceAutoplay
@ -500,14 +510,14 @@ export class PeerTubePlayer {
const player = this.player
const shortUUID = self.currentLoadOptions.videoShortUUID
const isLoopEnabled = player.options_['loop']
const isLoopEnabled = player.options_.loop
const items = [
{
icon: 'repeat',
label: player.localize('Play in loop') + (isLoopEnabled ? '<span class="vjs-icon-tick-white"></span>' : ''),
listener: function () {
player.options_['loop'] = !isLoopEnabled
player.options_.loop = !isLoopEnabled
}
},
{

View file

@ -25,8 +25,8 @@ $context-menu-width: 350px;
cursor: pointer;
font-size: 1em;
padding: 8px 16px;
text-align: start;
text-transform: none;
justify-content: flex-start;
&:hover {
background-color: rgba(255, 255, 255, 0.2);

View file

@ -40,7 +40,6 @@ $setting-transition-easing: ease-out;
}
.vjs-settings-sub-menu-title {
text-align: start;
font-weight: $font-semibold;
}
@ -118,16 +117,19 @@ $setting-transition-easing: ease-out;
.vjs-menu-item {
outline: 0;
font-weight: $font-semibold;
text-align: end;
justify-content: flex-end;
padding: 8px 15px;
&.vjs-back-button {
padding: 12px 15px;
margin-bottom: 5px;
border-bottom: 1px solid #808080;
text-align: start;
justify-content: flex-start;
align-items: center;
&::before {
top: -1px;
@include chevron-left(9px, 2px);
@include margin-right(10px);
}

View file

@ -1,11 +1,11 @@
import videojs from 'video.js'
import type { VideojsComponentOptions, VideojsPlayer, VideojsPlugin } from '../../types/peertube-videojs-typings'
import { PauseBezel } from './pause-bezel'
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class BezelsPlugin extends Plugin {
constructor (player: videojs.Player, options?: videojs.ComponentOptions) {
constructor (player: VideojsPlayer, options?: VideojsComponentOptions) {
super(player)
this.player.ready(() => {

View file

@ -1,5 +1,6 @@
import videojs from 'video.js'
import { isMobile } from '@root-helpers/web-browser'
import videojs from 'video.js'
import { VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
function getPauseBezel () {
return `
@ -31,7 +32,8 @@ function getPlayBezel () {
`
}
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
export class PauseBezel extends Component {
declare container: HTMLDivElement
@ -42,7 +44,7 @@ export class PauseBezel extends Component {
declare private playerPlayHandler: () => void
declare private videoChangeHandler: () => void
constructor (player: videojs.Player, options?: videojs.ComponentOptions) {
constructor (player: VideojsPlayer, options?: VideojsComponentOptions) {
super(player, options)
// Hide bezels on mobile since we already have our mobile overlay

View file

@ -1,17 +1,17 @@
import videojs from 'video.js'
import { ContextMenuItemOptions } from '../../types'
import { ContextMenuItemOptions, VideojsComponentOptions, VideojsMenuItem, VideojsPlayer } from '../../types'
const MenuItem = videojs.getComponent('MenuItem')
const MenuItem = videojs.getComponent('MenuItem') as typeof VideojsMenuItem
class ContextMenuItem extends MenuItem {
declare options_: ContextMenuItemOptions
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor (player: videojs.Player, options: ContextMenuItemOptions) {
constructor (player: VideojsPlayer, options: VideojsComponentOptions & ContextMenuItemOptions) {
super(player, options)
}
handleClick (e: videojs.EventTarget.Event) {
handleClick (e: Event) {
super.handleClick(e)
this.options_.listener(e)

View file

@ -1,18 +1,18 @@
import videojs, { VideoJsPlayer } from 'video.js'
import { ContextMenuPluginOptions } from '../../types'
import videojs from 'video.js'
import { ContextMenuPluginOptions, VideojsMenuItemOptions, VideojsPlayer, VideojsPlugin } from '../../types'
import { ContextMenu } from './context-menu'
import { getPointerPosition } from './util'
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class ContextMenuPlugin extends Plugin {
declare options_: ContextMenuPluginOptions & videojs.MenuOptions
declare options_: ContextMenuPluginOptions & VideojsMenuItemOptions
declare menu: ContextMenu
declare private onContextMenuBind: (e: TouchEvent & MouseEvent) => void
constructor (player: videojs.Player, options: ContextMenuPluginOptions & videojs.MenuOptions) {
super(player, options)
constructor (player: VideojsPlayer, options: ContextMenuPluginOptions & VideojsMenuItemOptions) {
super(player)
this.options_ = options
@ -96,7 +96,7 @@ export { ContextMenuPlugin }
// Private
// ---------------------------------------------------------------------------
function hasMenu (player: VideoJsPlayer) {
function hasMenu (player: VideojsPlayer) {
if (!player.usingPlugin('contextMenu')) return false
return !!player.contextMenu().menu?.el()

View file

@ -1,33 +1,32 @@
import videojs from 'video.js'
import { ContextMenuPluginOptions, VideojsMenu, VideojsMenuOptions, VideojsPlayer } from '../../types'
import { ContextMenuItem } from './context-menu-item'
import { ContextMenuPluginOptions } from '../../types'
const Menu = videojs.getComponent('Menu')
const Menu = videojs.getComponent('Menu') as typeof VideojsMenu
type ContextMenuOptions = ContextMenuPluginOptions & { position: { left: number, top: number } }
class ContextMenu extends Menu {
declare options_: ContextMenuOptions & videojs.MenuOptions
declare options_: ContextMenuOptions & VideojsMenuOptions
constructor (player: videojs.Player, options: ContextMenuOptions) {
constructor (player: VideojsPlayer, options: ContextMenuOptions) {
super(player, { ...options, menuButton: undefined })
// Each menu component has its own `dispose` method that can be
// safely bound and unbound to events while maintaining its context.
this.dispose = videojs.bind(this, this.dispose)
// TODO: explain why we need this (I don't understand it)
this.dispose = this.dispose.bind(this)
for (const c of options.content()) {
this.addItem(
new ContextMenuItem(player, {
label: c.label,
listener: videojs.bind(player, c.listener)
listener: c.listener.bind(player)
})
)
}
}
createEl () {
const el = super.createEl()
const el = super.createEl() as HTMLElement
videojs.dom.addClass(el, 'vjs-contextmenu-ui-menu')
el.style.left = this.options_.position.left + 'px'

View file

@ -1,11 +1,11 @@
import videojs from 'video.js'
import { TheaterButtonOptions } from '../../types'
import { getStoredPreferredSubtitle } from '../../peertube-player-local-storage'
import { TheaterButtonOptions, VideojsButton, VideojsButtonOptions, VideojsPlayer } from '../../types'
const Button = videojs.getComponent('Button') as typeof VideojsButton
const Button = videojs.getComponent('Button')
class CaptionToggleButton extends Button {
constructor (player: videojs.Player, options: TheaterButtonOptions & videojs.ComponentOptions) {
constructor (player: VideojsPlayer, options: TheaterButtonOptions & VideojsButtonOptions) {
super(player, options)
player.on('texttrackchange', () => this.update())

View file

@ -1,9 +1,9 @@
import { VideoChapter } from '@peertube/peertube-models'
import videojs from 'video.js'
import { ChaptersOptions } from '../../types'
import { ChaptersOptions, VideojsPlayer, VideojsPlugin } from '../../types'
import { ProgressBarMarkerComponent } from './progress-bar-marker-component'
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class ChaptersPlugin extends Plugin {
declare private chapters: VideoChapter[]
@ -11,8 +11,8 @@ class ChaptersPlugin extends Plugin {
private activeChapter: VideoChapter
constructor (player: videojs.Player, options: videojs.ComponentOptions & ChaptersOptions) {
super(player, options)
constructor (player: VideojsPlayer, options: ChaptersOptions) {
super(player)
this.markers = []
this.chapters = options.chapters
@ -25,8 +25,13 @@ class ChaptersPlugin extends Plugin {
const marker = new ProgressBarMarkerComponent(player, { timecode: chapter.timecode })
marker.on('mouseenter', () => this.activeChapter = chapter)
marker.on('mouseleave', () => this.activeChapter = undefined)
marker.on('mouseenter', () => {
this.activeChapter = chapter
})
marker.on('mouseleave', () => {
this.activeChapter = undefined
})
this.markers.push(marker)
this.getSeekBar().addChild(marker)

View file

@ -1,12 +1,12 @@
import videojs from 'video.js'
import { NextPreviousVideoButtonOptions } from '../../types'
import { NextPreviousVideoButtonOptions, VideojsButton, VideojsButtonOptions, VideojsPlayer } from '../../types'
const Button = videojs.getComponent('Button')
const Button = videojs.getComponent('Button') as typeof VideojsButton
class NextPreviousVideoButton extends Button {
declare options_: NextPreviousVideoButtonOptions & videojs.ComponentOptions
declare options_: NextPreviousVideoButtonOptions & VideojsButtonOptions
constructor (player: videojs.Player, options?: NextPreviousVideoButtonOptions & videojs.ComponentOptions) {
constructor (player: VideojsPlayer, options?: NextPreviousVideoButtonOptions & VideojsButtonOptions) {
super(player, options)
this.player().on('video-change', () => {

View file

@ -1,8 +1,9 @@
import videojs from 'video.js'
import { PlayerNetworkInfo } from '../../types'
import { PlayerNetworkInfo, VideojsButton } from '../../types'
import { bytes } from '../common'
const Button = videojs.getComponent('Button')
const Button = videojs.getComponent('Button') as typeof VideojsButton
class P2PInfoButton extends Button {
createEl () {
const div = videojs.dom.createEl('div', { className: 'vjs-peertube' })
@ -87,7 +88,7 @@ class P2PInfoButton extends Button {
subDivP2P.className = 'vjs-peertube-displayed'
})
this.player_.on('network-info', (_event, data: PlayerNetworkInfo) => {
this.player_.on('network-info', (_event: any, data: PlayerNetworkInfo) => {
if (data.p2p) return
if (data.source === 'web-video') subDivHttpText.textContent = 'HTTP'

View file

@ -1,16 +1,16 @@
import videojs from 'video.js'
import { buildVideoLink, decorateVideoLink } from '@peertube/peertube-core-utils'
import { PeerTubeLinkButtonOptions } from '../../types'
import videojs from 'video.js'
import { PeerTubeLinkButtonOptions, VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
class PeerTubeLinkButton extends Component {
declare private mouseEnterHandler: () => void
declare private clickHandler: () => void
declare options_: PeerTubeLinkButtonOptions & videojs.ComponentOptions
declare options_: PeerTubeLinkButtonOptions & VideojsComponentOptions
constructor (player: videojs.Player, options?: PeerTubeLinkButtonOptions & videojs.ComponentOptions) {
constructor (player: VideojsPlayer, options?: PeerTubeLinkButtonOptions & VideojsComponentOptions) {
super(player, options)
this.updateShowing()

View file

@ -1,15 +1,15 @@
import videojs from 'video.js'
import { PeerTubeLinkButtonOptions } from '../../types'
import { PeerTubeLinkButtonOptions, VideojsClickableComponent, VideojsClickableComponentOptions, VideojsPlayer } from '../../types'
const ClickableComponent = videojs.getComponent('ClickableComponent')
const ClickableComponent = videojs.getComponent('ClickableComponent') as typeof VideojsClickableComponent
class PeerTubeLiveDisplay extends ClickableComponent {
declare private interval: any
declare private contentEl_: any
declare private contentEl_: HTMLElement
constructor (player: videojs.Player, options?: PeerTubeLinkButtonOptions) {
super(player, options as any)
constructor (player: VideojsPlayer, options?: VideojsClickableComponentOptions & PeerTubeLinkButtonOptions) {
super(player, options)
this.interval = this.setInterval(() => this.updateClass(), 1000)
@ -36,7 +36,7 @@ class PeerTubeLiveDisplay extends ClickableComponent {
className: 'vjs-live-display'
}, {
'aria-live': 'off'
})
}) as HTMLElement
this.contentEl_.appendChild(videojs.dom.createEl('span', {
className: 'vjs-control-text',

View file

@ -1,12 +1,12 @@
import videojs from 'video.js'
import { ProgressBarMarkerComponentOptions } from '../../types'
import { ProgressBarMarkerComponentOptions, VideojsClickableComponent, VideojsClickableComponentOptions, VideojsPlayer } from '../../types'
const ClickableComponent = videojs.getComponent('ClickableComponent')
const ClickableComponent = videojs.getComponent('ClickableComponent') as typeof VideojsClickableComponent
export class ProgressBarMarkerComponent extends ClickableComponent {
declare options_: ProgressBarMarkerComponentOptions & videojs.ComponentOptions
declare options_: ProgressBarMarkerComponentOptions & VideojsClickableComponentOptions
constructor (player: videojs.Player, options?: ProgressBarMarkerComponentOptions & videojs.ComponentOptions) {
constructor (player: VideojsPlayer, options?: ProgressBarMarkerComponentOptions & VideojsClickableComponentOptions) {
super(player, options)
const updateMarker = () => {

View file

@ -1,10 +1,11 @@
import videojs from 'video.js'
import { StoryboardOptions } from '../../types'
import { StoryboardOptions, VideojsPlayer, VideojsPlugin } from '../../types'
import Tech from 'video.js/dist/types/tech/tech'
// Big thanks to this beautiful plugin: https://github.com/phloxic/videojs-sprite-thumbnails
// Adapted to respect peertube player style
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class StoryboardPlugin extends Plugin {
declare private url: string
@ -14,9 +15,9 @@ class StoryboardPlugin extends Plugin {
declare private cached: boolean
declare private mouseTimeTooltip: videojs.MouseTimeDisplay
declare private seekBar: { el(): HTMLElement, mouseTimeDisplay: any, playProgressBar: any }
declare private progress: any
declare private mouseTimeTooltip: VideojsPlayer['controlBar']['progressControl']['seekBar']['mouseTimeDisplay']['timeTooltip']
declare private seekBar: VideojsPlayer['controlBar']['progressControl']['seekBar']
declare private progress: VideojsPlayer['controlBar']['progressControl']
declare private spritePlaceholder: HTMLElement
@ -26,8 +27,8 @@ class StoryboardPlugin extends Plugin {
declare private onReadyOrLoadstartHandler: (event: { type: 'ready' }) => void
constructor (player: videojs.Player, options: videojs.ComponentOptions & StoryboardOptions) {
super(player, options)
constructor (player: VideojsPlayer, options: StoryboardOptions) {
super(player)
this.url = options.url
this.height = options.height
@ -46,7 +47,7 @@ class StoryboardPlugin extends Plugin {
}
init () {
const controls = this.player.controlBar as any
const controls = this.player.controlBar
// default control bar component tree is expected
// https://docs.videojs.com/tutorial-components.html#default-component-tree
@ -60,7 +61,8 @@ class StoryboardPlugin extends Plugin {
this.onReadyOrLoadstartHandler = event => {
if (event.type !== 'ready') {
const spriteSource = this.player.currentSources().find(source => {
// FIXME: typings
const spriteSource = (this.player.currentSources() as unknown as Tech[]).find(source => {
return Object.prototype.hasOwnProperty.call(source, 'storyboard')
}) as any
const spriteOpts = spriteSource?.['storyboard'] as StoryboardOptions
@ -97,7 +99,7 @@ class StoryboardPlugin extends Plugin {
if (!this.cached) {
this.sprites[this.url] = videojs.dom.createEl('img', {
src: this.url
})
}) as HTMLImageElement
}
this.progress.on(spriteEvents, this.boundedHijackMouseTooltip)
} else {

View file

@ -1,15 +1,15 @@
import videojs from 'video.js'
import { getStoredTheater, saveTheaterInStore } from '../../peertube-player-local-storage'
import { TheaterButtonOptions } from '../../types'
import { TheaterButtonOptions, VideojsButton, VideojsButtonOptions, VideojsPlayer } from '../../types'
const Button = videojs.getComponent('Button') as typeof VideojsButton
const Button = videojs.getComponent('Button')
class TheaterButton extends Button {
private static readonly THEATER_MODE_CLASS = 'vjs-theater-enabled'
declare private theaterButtonOptions: TheaterButtonOptions
constructor (player: videojs.Player, options: TheaterButtonOptions & videojs.ComponentOptions) {
constructor (player: VideojsPlayer, options: TheaterButtonOptions & VideojsButtonOptions) {
super(player, options)
this.theaterButtonOptions = options

View file

@ -1,13 +1,14 @@
import { timeToInt } from '@peertube/peertube-core-utils'
import videojs, { VideoJsPlayer } from 'video.js'
import videojs from 'video.js'
import { VideojsTimeTooltip } from '../../types'
const TimeToolTip = videojs.getComponent('TimeTooltip') as any // FIXME: typings don't have write method
const TimeToolTip = videojs.getComponent('TimeTooltip') as typeof VideojsTimeTooltip
class TimeTooltip extends TimeToolTip {
declare private currentTimecode: string
write (timecode: string) {
const player: VideoJsPlayer = this.player()
const player = this.player()
if (player.usingPlugin('chapters')) {
if (timecode === this.currentTimecode) return

View file

@ -1,6 +1,7 @@
import videojs from 'video.js'
import { VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
export type PeerTubeDockComponentOptions = {
title?: string
@ -9,10 +10,10 @@ export type PeerTubeDockComponentOptions = {
}
class PeerTubeDockComponent extends Component {
declare options_: videojs.ComponentOptions & PeerTubeDockComponentOptions
declare options_: VideojsComponentOptions & PeerTubeDockComponentOptions
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor (player: videojs.Player, options: videojs.ComponentOptions & PeerTubeDockComponentOptions) {
constructor (player: VideojsPlayer, options: VideojsComponentOptions & PeerTubeDockComponentOptions) {
super(player, options)
}

View file

@ -1,7 +1,8 @@
import videojs from 'video.js'
import { VideojsPlayer, VideojsPlugin } from '../../types'
import { PeerTubeDockComponent } from './peertube-dock-component'
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
export type PeerTubeDockPluginOptions = {
title?: string
@ -12,8 +13,8 @@ export type PeerTubeDockPluginOptions = {
class PeerTubeDockPlugin extends Plugin {
declare private dockComponent: PeerTubeDockComponent
constructor (player: videojs.Player, options: videojs.PlayerOptions & PeerTubeDockPluginOptions) {
super(player, options)
constructor (player: VideojsPlayer, options: PeerTubeDockPluginOptions) {
super(player)
player.ready(() => {
player.addClass('peertube-dock')

View file

@ -1,8 +1,9 @@
import videojs from 'video.js'
import { VideojsPlayer, VideojsPlugin } from '../../types'
type KeyHandler = { accept: (event: KeyboardEvent) => boolean, cb: (e: KeyboardEvent) => void }
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
export type HotkeysOptions = {
isLive: boolean
@ -18,8 +19,8 @@ class PeerTubeHotkeysPlugin extends Plugin {
declare private readonly isLive: boolean
constructor (player: videojs.Player, options: videojs.PlayerOptions & HotkeysOptions) {
super(player, options)
constructor (player: VideojsPlayer, options: HotkeysOptions) {
super(player)
this.isLive = options.isLive

View file

@ -1,12 +1,12 @@
import debug from 'debug'
import videojs from 'video.js'
import { PlaybackMetricCreate, VideoResolutionType } from '@peertube/peertube-models'
import { logger } from '@root-helpers/logger'
import { MetricsPluginOptions, PlayerNetworkInfo } from '../../types'
import debug from 'debug'
import videojs from 'video.js'
import { MetricsPluginOptions, PlayerNetworkInfo, VideojsPlayer, VideojsPlugin } from '../../types'
const debugLogger = debug('peertube:player:metrics')
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class MetricsPlugin extends Plugin {
declare options_: MetricsPluginOptions
@ -27,7 +27,7 @@ class MetricsPlugin extends Plugin {
declare private metricsInterval: any
constructor (player: videojs.Player, options: MetricsPluginOptions) {
constructor (player: VideojsPlayer, options: MetricsPluginOptions) {
super(player)
this.options_ = options
@ -154,7 +154,7 @@ class MetricsPlugin extends Plugin {
}
private trackBytes () {
this.player.on('network-info', (_event, data: PlayerNetworkInfo) => {
this.player.on('network-info', (_event: any, data: PlayerNetworkInfo) => {
this.downloadedBytesHTTP += Math.max(Math.round(data.http.downloaded - (this.lastPlayerNetworkInfo?.http.downloaded || 0)), 0)
this.downloadedBytesP2P += Math.max(Math.round((data.p2p?.downloaded || 0) - (this.lastPlayerNetworkInfo?.p2p?.downloaded || 0)), 0)

View file

@ -1,6 +1,8 @@
import videojs from 'video.js'
import { VideojsComponent } from '../../types'
const Component = videojs.getComponent('Component') as typeof VideojsComponent
const Component = videojs.getComponent('Component')
class PeerTubeMobileButtons extends Component {
declare private mainButton: HTMLDivElement

View file

@ -1,11 +1,14 @@
import { logger } from '@root-helpers/logger'
import debug from 'debug'
import videojs from 'video.js'
import { logger } from '@root-helpers/logger'
import { VideojsPlayer, VideojsPlugin } from '../../types'
import { PeerTubeMobileButtons } from './peertube-mobile-buttons'
const debugLogger = debug('peertube:player:mobile')
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
type SeekBar = VideojsPlayer['controlBar']['progressControl']['seekBar']
class PeerTubeMobilePlugin extends Plugin {
private static readonly DOUBLE_TAP_DELAY_MS = 250
@ -29,10 +32,10 @@ class PeerTubeMobilePlugin extends Plugin {
declare private sliderActiveHandler: () => void
declare private sliderInactiveHandler: () => void
declare private seekBar: videojs.Component
declare private seekBar: SeekBar
constructor (player: videojs.Player, options: videojs.PlayerOptions) {
super(player, options)
constructor (player: VideojsPlayer) {
super(player)
this.seekAmount = 0
@ -45,16 +48,14 @@ class PeerTubeMobilePlugin extends Plugin {
this.peerTubeMobileButtons = player.addChild('PeerTubeMobileButtons', { reportTouchActivity: false }) as PeerTubeMobileButtons
if (!this.player.options_.userActions) this.player.options_.userActions = {};
// FIXME: typings
(this.player.options_.userActions as any).click = false
if (!this.player.options_.userActions) this.player.options_.userActions = {}
this.player.options_.userActions.click = false
this.player.options_.userActions.doubleClick = false
this.onPlayHandler = () => this.initTouchStartEvents()
this.player.one('play', this.onPlayHandler)
this.seekBar = this.player.getDescendant([ 'controlBar', 'progressControl', 'seekBar' ])
this.seekBar = this.player.getDescendant([ 'controlBar', 'progressControl', 'seekBar' ]) as SeekBar
this.sliderActiveHandler = () => this.player.addClass('vjs-mobile-sliding')
this.sliderInactiveHandler = () => this.player.removeClass('vjs-mobile-sliding')
@ -76,10 +77,9 @@ class PeerTubeMobilePlugin extends Plugin {
private handleFullscreenRotation () {
this.onFullScreenChangeHandler = () => {
if (!this.player.isFullscreen() || this.isPortraitVideo()) return;
// https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1615
(screen.orientation as any).lock('landscape')
if (!this.player.isFullscreen() || this.isPortraitVideo()) return
;(screen.orientation as any).lock('landscape')
.catch((err: Error) => logger.error('Cannot lock screen to landscape.', err))
}
@ -151,7 +151,7 @@ class PeerTubeMobilePlugin extends Plugin {
private onDoubleTap (event: TouchEvent) {
const playerWidth = this.player.currentWidth()
const rect = this.findPlayerTarget((event.target as HTMLElement)).getBoundingClientRect()
const rect = this.findPlayerTarget(event.target as HTMLElement).getBoundingClientRect()
const offsetX = event.targetTouches[0].pageX - rect.left
debugLogger('Calculating double tap zone (player width: %d, offset X: %d)', playerWidth, offsetX)

View file

@ -1,14 +1,15 @@
import { NSFWFlag } from '@peertube/peertube-models'
import videojs from 'video.js'
import { VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
import { type PeerTubeNSFWPluginOptions } from './peertube-nsfw-plugin'
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
class PeerTubeNSFWDetailsComponent extends Component {
declare options_: videojs.ComponentOptions & PeerTubeNSFWPluginOptions
declare options_: VideojsComponentOptions & PeerTubeNSFWPluginOptions
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor (player: videojs.Player, options: videojs.ComponentOptions & PeerTubeNSFWPluginOptions) {
constructor (player: VideojsPlayer, options: VideojsComponentOptions & PeerTubeNSFWPluginOptions) {
super(player, options)
}

View file

@ -1,13 +1,14 @@
import videojs from 'video.js'
import { VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
import { type PeerTubeNSFWPluginOptions } from './peertube-nsfw-plugin'
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
class PeerTubeNSFWInfoComponent extends Component {
declare options_: videojs.ComponentOptions & PeerTubeNSFWPluginOptions
declare options_: VideojsComponentOptions & PeerTubeNSFWPluginOptions
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor (player: videojs.Player, options: videojs.ComponentOptions & PeerTubeNSFWPluginOptions) {
constructor (player: VideojsPlayer, options: VideojsComponentOptions & PeerTubeNSFWPluginOptions) {
super(player, options)
}

View file

@ -1,8 +1,9 @@
import videojs from 'video.js'
import { PeerTubeNSFWInfoComponent } from './peertube-nsfw-info-component'
import { VideojsPlayer, VideojsPlugin } from '../../types'
import { PeerTubeNSFWDetailsComponent } from './peertube-nsfw-details-component'
import { PeerTubeNSFWInfoComponent } from './peertube-nsfw-info-component'
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
export type PeerTubeNSFWPluginOptions = {
summary: string
@ -13,8 +14,8 @@ class PeerTubeNSFWPlugin extends Plugin {
declare private nsfwInfoComponent: PeerTubeNSFWInfoComponent
declare private nsfwDetailsComponent: PeerTubeNSFWDetailsComponent
constructor (player: videojs.Player, options: videojs.PlayerOptions & PeerTubeNSFWPluginOptions) {
super(player, options)
constructor (player: VideojsPlayer, options: PeerTubeNSFWPluginOptions) {
super(player)
player.ready(() => {
player.addClass('peertube-nsfw')

View file

@ -1,12 +1,13 @@
// Thanks https://github.com/streamroot/videojs-hlsjs-plugin
// We duplicated this plugin to choose the hls.js version we want, because streamroot only provide a bundled file
import { omit } from '@peertube/peertube-core-utils'
import { logger } from '@root-helpers/logger'
import Hlsjs, { ErrorData, Level, LevelSwitchingData, ManifestParsedData } from 'hls.js'
import videojs from 'video.js'
import { HLSPluginOptions, HlsjsConfigHandlerOptions, PeerTubeResolution, VideoJSTechHLS } from '../../types'
import { HlsJsP2PEngine, HlsWithP2PInstance } from 'p2p-media-loader-hlsjs'
import { omit } from '@peertube/peertube-core-utils'
import videojs from 'video.js'
import Tech, { SourceObject } from 'video.js/dist/types/tech/tech'
import { HLSPluginOptions, HlsjsConfigHandlerOptions, PeerTubeResolution, VideoJSTechHLS, VideojsPlayer, VideojsPlugin } from '../../types'
const HlsWithP2P = HlsJsP2PEngine.injectMixin(Hlsjs)
@ -37,7 +38,7 @@ const registerSourceHandler = function (vjs: typeof videojs) {
alreadyRegistered = true // FIXME: typings
;(html5 as any).registerSourceHandler({
canHandleSource: function (source: videojs.Tech.SourceObject) {
canHandleSource: function (source: SourceObject) {
const hlsTypeRE = /^application\/x-mpegURL|application\/vnd\.apple\.mpegurl$/i
const hlsExtRE = /\.m3u8/i
@ -47,7 +48,7 @@ const registerSourceHandler = function (vjs: typeof videojs) {
return ''
},
handleSource: function (source: videojs.Tech.SourceObject, tech: VideoJSTechHLS) {
handleSource: function (source: SourceObject, tech: VideoJSTechHLS) {
if (tech.hlsProvider) {
tech.hlsProvider.dispose()
}
@ -64,11 +65,11 @@ const registerSourceHandler = function (vjs: typeof videojs) {
// HLS options plugin
// ---------------------------------------------------------------------------
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class HLSJSConfigHandler extends Plugin {
constructor (player: videojs.Player, options: HlsjsConfigHandlerOptions) {
super(player, options)
constructor (player: VideojsPlayer, options: HlsjsConfigHandlerOptions) {
super(player)
if (!options) return
@ -109,9 +110,9 @@ videojs.registerPlugin('hlsjs', HLSJSConfigHandler)
export class Html5Hlsjs {
private readonly videoElement: HTMLVideoElement
private readonly errorCounts: ErrorCounts = {}
private readonly player: videojs.Player
private readonly tech: videojs.Tech
private readonly source: videojs.Tech.SourceObject
private readonly player: VideojsPlayer
private readonly tech: Tech
private readonly source: SourceObject
private readonly vjs: typeof videojs
private maxNetworkErrorRecovery = 5
@ -134,7 +135,7 @@ export class Html5Hlsjs {
private audioMode = false
constructor (vjs: typeof videojs, source: videojs.Tech.SourceObject, tech: videojs.Tech) {
constructor (vjs: typeof videojs, source: SourceObject, tech: Tech) {
this.vjs = vjs
this.source = source
@ -142,7 +143,7 @@ export class Html5Hlsjs {
;(this.tech as any).name_ = 'Hlsjs'
this.videoElement = tech.el() as HTMLVideoElement
this.player = vjs((tech.options_ as any).playerId)
this.player = vjs(tech.options_.playerId) as VideojsPlayer
this.handlers.error = event => {
let errorTxt: string

View file

@ -5,12 +5,13 @@ import { FragLoadedData, default as Hlsjs } from 'hls.js'
import type { DownloadSource, SegmentErrorDetails, SegmentLoadDetails } from 'p2p-media-loader-core'
import type { HlsWithP2PInstance } from 'p2p-media-loader-hlsjs'
import videojs from 'video.js'
import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo } from '../../types'
import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo, VideojsPlayer, VideojsPlugin } from '../../types'
import { SettingsButton } from '../settings/settings-menu-button'
const debugLogger = debug('peertube:player:p2p-media-loader')
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class P2pMediaLoaderPlugin extends Plugin {
declare private readonly options: P2PMediaLoaderPluginOptions
@ -35,7 +36,7 @@ class P2pMediaLoaderPlugin extends Plugin {
declare private connectedPeers: Set<string>
declare private totalHTTPPeers: number
constructor (player: videojs.Player, options?: P2PMediaLoaderPluginOptions) {
constructor (player: VideojsPlayer, options?: P2PMediaLoaderPluginOptions) {
super(player)
this.options = options

View file

@ -5,6 +5,8 @@ import { isIOS, isMobile, isSafari } from '@root-helpers/web-browser'
import debug from 'debug'
import { UAParser } from 'ua-parser-js'
import videojs from 'video.js'
import type MediaError from 'video.js/dist/types/media-error'
import type ModalDialog from 'video.js/dist/types/modal-dialog'
import {
getPlayerSessionId,
getStoredLastSubtitle,
@ -16,19 +18,26 @@ import {
saveVideoWatchHistory,
saveVolumeInStore
} from '../../peertube-player-local-storage'
import { PeerTubePluginOptions } from '../../types'
import type {
PeerTubePluginOptions,
VideojsAutoplay,
VideojsCaptionsButton,
VideojsPlayer,
VideojsPlayerOptions,
VideojsPlugin
} from '../../types'
import { SettingsButton } from '../settings/settings-menu-button'
const debugLogger = debug('peertube:player:peertube')
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class PeerTubePlugin extends Plugin {
declare private readonly videoViewUrl: () => string
declare private readonly authorizationHeader: () => string
declare private readonly initialInactivityTimeout: number
declare private readonly hasAutoplay: () => videojs.Autoplay
declare private readonly hasAutoplay: () => VideojsAutoplay
declare private currentSubtitle: string
declare private currentPlaybackRate: number
@ -39,7 +48,7 @@ class PeerTubePlugin extends Plugin {
declare private mouseInControlBar: boolean
declare private mouseInSettings: boolean
declare private errorModal: videojs.ModalDialog
declare private errorModal: ModalDialog
declare private hasInitialSeek: boolean
@ -56,7 +65,7 @@ class PeerTubePlugin extends Plugin {
os: string
}
constructor (player: videojs.Player, private readonly options: PeerTubePluginOptions) {
constructor (player: VideojsPlayer, private readonly options: PeerTubePluginOptions) {
super(player)
this.setUserAgentInfo()
@ -99,7 +108,7 @@ class PeerTubePlugin extends Plugin {
})
this.player.one('canplay', () => {
const playerOptions = this.player.options_
const playerOptions = this.player.options_ as VideojsPlayerOptions
const volume = getStoredVolume()
if (volume !== undefined) this.player.volume(volume)
@ -298,7 +307,7 @@ class PeerTubePlugin extends Plugin {
this.player.on('video-change', () => tryToUpdateRatioFromOptions())
this.player.on('video-ratio-changed', (_event, data: { ratio: number }) => {
this.player.on('video-ratio-changed', (_event: any, data: { ratio: number }) => {
if (this.options.videoRatio()) return
this.adaptPlayerFromRatio({ ratio: data.ratio, defaultRatio })
@ -497,7 +506,7 @@ class PeerTubePlugin extends Plugin {
private listenControlBarMouse () {
const controlBar = this.player.controlBar
const settingsButton: SettingsButton = (controlBar as any).settingsButton
const settingsButton = controlBar.settingsButton
controlBar.on('mouseenter', () => {
this.mouseInControlBar = true
@ -635,24 +644,6 @@ class PeerTubePlugin extends Plugin {
// Thanks: https://github.com/videojs/video.js/issues/4460#issuecomment-312861657
private initSmoothProgressBar () {
const SeekBar = videojs.getComponent('SeekBar') as any
SeekBar.prototype.getPercent = function getPercent () {
// Allows for smooth scrubbing, when player can't keep up.
// const time = (this.player_.scrubbing()) ?
// this.player_.getCache().currentTime :
// this.player_.currentTime()
const time = this.player_.currentTime()
const percent = time / this.player_.duration()
return percent >= 1 ? 1 : percent
}
SeekBar.prototype.handleMouseMove = function handleMouseMove (event: any) {
let newTime = this.calculateDistance(event) * this.player_.duration()
if (newTime === this.player_.duration()) {
newTime = newTime - 0.1
}
this.player_.currentTime(newTime)
this.update()
}
}
private patchMenuEscapeKey () {
@ -688,7 +679,7 @@ class PeerTubePlugin extends Plugin {
private getCaptionsButton () {
const settingsButton = this.player.controlBar.getDescendant([ 'settingsButton' ]) as SettingsButton
return settingsButton.menu.getChild('captionsButton') as videojs.CaptionsButton
return settingsButton.menu.getChild('captionsButton') as unknown as VideojsCaptionsButton
}
private getPlaybackRateButton () {

View file

@ -7,8 +7,8 @@ import {
} from '../../types'
type ControlBarOptionsBuilderConstructorOptions =
Pick<PeerTubePlayerConstructorOptions, 'peertubeLink' | 'instanceName' | 'theaterButton'> &
{
& Pick<PeerTubePlayerConstructorOptions, 'peertubeLink' | 'instanceName' | 'theaterButton'>
& {
videoShortUUID: () => string
p2pEnabled: () => boolean
@ -17,7 +17,6 @@ type ControlBarOptionsBuilderConstructorOptions =
}
export class ControlBarOptionsBuilder {
constructor (private options: ControlBarOptionsBuilderConstructorOptions) {
}
@ -84,11 +83,7 @@ export class ControlBarOptionsBuilder {
progressControl: {
children: {
seekBar: {
children: {
loadProgressBar: {},
mouseTimeDisplay: {},
playProgressBar: {}
}
children: [ 'loadProgressBar', 'mouseTimeDisplay', 'playProgressBar' ]
}
}
}

View file

@ -7,7 +7,13 @@ import debug from 'debug'
import { Level } from 'hls.js'
import type { CoreConfig, StreamConfig } from 'p2p-media-loader-core'
import { getAverageBandwidthInStore } from '../../peertube-player-local-storage'
import { HLSPluginOptions, P2PMediaLoaderPluginOptions, PeerTubePlayerConstructorOptions, PeerTubePlayerLoadOptions } from '../../types'
import {
HLSPluginOptions,
P2PMediaLoaderPluginOptions,
PeerTubePlayerConstructorOptions,
PeerTubePlayerLoadOptions,
VideojsPlayer
} from '../../types'
import { getRtcConfig } from '../common'
import { RedundancyUrlManager } from '../p2p-media-loader/redundancy-url-manager'
import { SegmentValidator } from '../p2p-media-loader/segment-validator'
@ -67,7 +73,7 @@ export class HLSOptionsBuilder {
const hlsjs = {
hlsjsConfig: this.getHLSJSOptions(p2pMediaLoaderConfig),
levelLabelHandler: (level: Level, player: videojs.VideoJsPlayer) => {
levelLabelHandler: (level: Level, player: VideojsPlayer) => {
const resolution = Math.min(level.height || 0, level.width || 0)
const file = this.options.hls.videoFiles.find(f => f.resolution.id === resolution)

View file

@ -1,20 +1,20 @@
import videojs from 'video.js'
import { PlaylistPluginOptions } from '../../types'
import { PlaylistPluginOptions, VideojsClickableComponent, VideojsClickableComponentOptions, VideojsPlayer } from '../../types'
import { PlaylistMenu } from './playlist-menu'
const ClickableComponent = videojs.getComponent('ClickableComponent')
const ClickableComponent = videojs.getComponent('ClickableComponent') as typeof VideojsClickableComponent
class PlaylistButton extends ClickableComponent {
declare private playlistInfoElement: HTMLElement
declare private wrapper: HTMLElement
declare options_: PlaylistPluginOptions & { playlistMenu: PlaylistMenu } & videojs.ClickableComponentOptions
declare options_: PlaylistPluginOptions & { playlistMenu: PlaylistMenu } & VideojsClickableComponentOptions
// FIXME: eslint -> it's not a useless constructor, we need to extend constructor options typings
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor (
player: videojs.Player,
options?: PlaylistPluginOptions & { playlistMenu: PlaylistMenu } & videojs.ClickableComponentOptions
player: VideojsPlayer,
options?: PlaylistPluginOptions & { playlistMenu: PlaylistMenu } & VideojsClickableComponentOptions
) {
super(player, options)
}

View file

@ -1,9 +1,9 @@
import videojs from 'video.js'
import { secondsToTime } from '@peertube/peertube-core-utils'
import { VideoPlaylistElement } from '@peertube/peertube-models'
import { PlaylistItemOptions } from '../../types'
import videojs from 'video.js'
import { PlaylistItemOptions, VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
class PlaylistMenuItem extends Component {
declare private element: VideoPlaylistElement
@ -11,10 +11,10 @@ class PlaylistMenuItem extends Component {
declare private clickHandler: () => void
declare private keyDownHandler: (event: KeyboardEvent) => void
declare options_: videojs.ComponentOptions & PlaylistItemOptions
declare options_: VideojsComponentOptions & PlaylistItemOptions
constructor (player: videojs.Player, options?: PlaylistItemOptions) {
super(player, options as any)
constructor (player: VideojsPlayer, options?: VideojsComponentOptions & PlaylistItemOptions) {
super(player, options)
this.emitTapEvents()
@ -130,7 +130,8 @@ class PlaylistMenuItem extends Component {
li.appendChild(block)
}
private handleKeyDown (event: KeyboardEvent) {
// Can't put it private because it's public in parent component
handleKeyDown (event: KeyboardEvent) {
if (event.code === 'Space' || event.code === 'Enter') {
this.switchPlaylistItem()
}
@ -141,6 +142,6 @@ class PlaylistMenuItem extends Component {
}
}
Component.registerComponent('PlaylistMenuItem', PlaylistMenuItem)
videojs.registerComponent('PlaylistMenuItem', PlaylistMenuItem)
export { PlaylistMenuItem }

View file

@ -1,9 +1,9 @@
import videojs from 'video.js'
import { VideoPlaylistElement } from '@peertube/peertube-models'
import { PlaylistPluginOptions } from '../../types'
import videojs from 'video.js'
import { PlaylistPluginOptions, VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
import { PlaylistMenuItem } from './playlist-menu-item'
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
class PlaylistMenu extends Component {
declare private menuItems: PlaylistMenuItem[]
@ -14,9 +14,9 @@ class PlaylistMenu extends Component {
declare private readonly onPlayerCick: (event: Event) => void
declare options_: PlaylistPluginOptions & videojs.ComponentOptions
declare options_: PlaylistPluginOptions & VideojsComponentOptions
constructor (player: videojs.Player, options?: PlaylistPluginOptions & videojs.ComponentOptions) {
constructor (player: VideojsPlayer, options?: PlaylistPluginOptions & VideojsComponentOptions) {
super(player, options)
this.menuItems = []
@ -152,6 +152,6 @@ class PlaylistMenu extends Component {
}
}
Component.registerComponent('PlaylistMenu', PlaylistMenu)
videojs.registerComponent('PlaylistMenu', PlaylistMenu)
export { PlaylistMenu }

View file

@ -1,16 +1,16 @@
import videojs from 'video.js'
import { PlaylistPluginOptions } from '../../types'
import { PlaylistPluginOptions, VideojsPlayer, VideojsPlugin } from '../../types'
import { PlaylistButton } from './playlist-button'
import { PlaylistMenu } from './playlist-menu'
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class PlaylistPlugin extends Plugin {
declare private playlistMenu: PlaylistMenu
declare private playlistButton: PlaylistButton
constructor (player: videojs.Player, options?: PlaylistPluginOptions) {
super(player, options)
constructor (player: VideojsPlayer, options?: PlaylistPluginOptions) {
super(player)
this.player.addClass('vjs-playlist')

View file

@ -1,7 +1,7 @@
import videojs from 'video.js'
import { PeerTubeResolution } from '../../types'
import { PeerTubeResolution, VideojsPlayer, VideojsPlugin } from '../../types'
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class PeerTubeResolutionsPlugin extends Plugin {
declare private currentSelection: PeerTubeResolution
@ -9,7 +9,7 @@ class PeerTubeResolutionsPlugin extends Plugin {
declare private autoResolutionChosenId: number
constructor (player: videojs.Player) {
constructor (player: VideojsPlayer) {
super(player)
this.resolutions = []
@ -85,7 +85,6 @@ class PeerTubeResolutionsPlugin extends Plugin {
return 1
})
}
}
videojs.registerPlugin('peertubeResolutions', PeerTubeResolutionsPlugin)

View file

@ -1,12 +1,12 @@
import videojs from 'video.js'
import { VideojsMenu } from '../../types'
const Menu = videojs.getComponent('Menu')
const Component = videojs.getComponent('Component')
const Menu = videojs.getComponent('Menu') as typeof VideojsMenu
// Default menu doesn't check if the child is disabled/hidden
class MenuFocusFixed extends Menu {
declare private focusedChild_: number
declare focusedChild_: number
stepForward () {
let stepChild = 0
@ -72,5 +72,5 @@ class MenuFocusFixed extends Menu {
}
}
Component.registerComponent('MenuFocusFixed', MenuFocusFixed)
videojs.registerComponent('MenuFocusFixed', MenuFocusFixed)
export { MenuFocusFixed }

View file

@ -1,12 +1,14 @@
import videojs from 'video.js'
import { VideojsMenu, VideojsMenuButton, VideojsMenuButtonOptions, VideojsPlayer } from '../../types'
import { ResolutionMenuItem } from './resolution-menu-item'
const Menu = videojs.getComponent('Menu')
const MenuButton = videojs.getComponent('MenuButton')
const Menu = videojs.getComponent('Menu') as typeof VideojsMenu
const MenuButton = videojs.getComponent('MenuButton') as typeof VideojsMenuButton
class ResolutionMenuButton extends MenuButton {
declare labelEl_: HTMLElement
constructor (player: videojs.Player, options?: videojs.MenuButtonOptions) {
constructor (player: VideojsPlayer, options?: VideojsMenuButtonOptions) {
super(player, options)
this.controlText('Quality')
@ -37,7 +39,7 @@ class ResolutionMenuButton extends MenuButton {
}
createMenu () {
const menu: videojs.Menu = new Menu(this.player_, { menuButton: this })
const menu = new Menu(this.player_, { menuButton: this })
const resolutions = this.player().peertubeResolutions().getResolutions()
for (const r of resolutions) {

View file

@ -1,9 +1,10 @@
import videojs from 'video.js'
import { VideojsMenuItem, VideojsMenuItemOptions, VideojsPlayer } from '../../types'
const MenuItem = videojs.getComponent('MenuItem')
const MenuItem = videojs.getComponent('MenuItem') as typeof VideojsMenuItem
export interface ResolutionMenuItemOptions extends videojs.MenuItemOptions {
resolutionId: number
export interface ResolutionMenuItemOptions extends VideojsMenuItemOptions {
resolutionId?: number
}
class ResolutionMenuItem extends MenuItem {
@ -14,7 +15,7 @@ class ResolutionMenuItem extends MenuItem {
declare private updateSelectionHandler: () => void
constructor (player: videojs.Player, options?: ResolutionMenuItemOptions) {
constructor (player: VideojsPlayer, options?: ResolutionMenuItemOptions) {
super(player, { ...options, selectable: true })
this.autoResolutionChosen = ''

View file

@ -1,9 +1,10 @@
import videojs from 'video.js'
import { VideojsComponent, VideojsPlayer } from '../../types'
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
class SettingsDialog extends Component {
constructor (player: videojs.Player) {
constructor (player: VideojsPlayer) {
super(player)
this.hide()
@ -41,6 +42,6 @@ class SettingsDialog extends Component {
}
}
Component.registerComponent('SettingsDialog', SettingsDialog)
videojs.registerComponent('SettingsDialog', SettingsDialog)
export { SettingsDialog }

View file

@ -1,5 +1,6 @@
import debug from 'debug'
import videojs from 'video.js'
import { VideojsButton, VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
import { toTitleCase } from '../common'
import { MenuFocusFixed } from './menu-focus-fixed'
import { SettingsDialog } from './settings-dialog'
@ -9,10 +10,10 @@ import { SettingsPanelChild } from './settings-panel-child'
const debugLogger = debug('peertube:player:settings')
const Button = videojs.getComponent('Button')
const Component = videojs.getComponent('Component')
const Button = videojs.getComponent('Button') as typeof VideojsButton
const Component = videojs.getComponent('Component') as typeof VideojsComponent
export interface SettingsButtonOptions extends videojs.ComponentOptions {
export interface SettingsButtonOptions extends VideojsComponentOptions {
entries: any[]
setup?: {
maxHeightOffset: number
@ -33,18 +34,18 @@ class SettingsButton extends Button {
declare private settingsButtonOptions: SettingsButtonOptions
constructor (player: videojs.Player, options?: SettingsButtonOptions) {
constructor (player: VideojsPlayer, options?: SettingsButtonOptions) {
super(player, options)
this.settingsButtonOptions = options
this.controlText('Settings')
this.dialog = this.player().addChild('settingsDialog')
this.dialog = this.player().addChild('settingsDialog') as SettingsDialog
this.dialogEl = this.dialog.el() as HTMLElement
this.menu = null
this.panel = this.dialog.addChild('settingsPanel')
this.panelChild = this.panel.addChild('settingsPanelChild')
this.panel = this.dialog.addChild('settingsPanel') as SettingsPanel
this.panelChild = this.panel.addChild('settingsPanelChild') as SettingsPanelChild
this.addClass('vjs-settings')
this.setAttribute('aria-controls', 'vjs-settings-dialog-' + this.player().id())
@ -170,7 +171,7 @@ class SettingsButton extends Button {
this.resetChildren()
}
getComponentSize (element: videojs.Component | HTMLElement) {
getComponentSize (element: VideojsComponent | HTMLElement) {
let width: number = null
let height: number = null
@ -217,7 +218,7 @@ class SettingsButton extends Button {
this.focus()
})
this.menu.on('arrow-right', (_, el) => {
this.menu.on('arrow-right', (_: any, el: HTMLElement) => {
debugLogger('Detected arrow right on menu item', el)
el.click()
@ -257,7 +258,7 @@ class SettingsButton extends Button {
// Hide children to avoid sub menus stacking on top of each other
// or having multiple menus open
settingsMenuItem.on('click', videojs.bind(this, this.hideChildren))
settingsMenuItem.on('click', () => this.hideChildren())
// Whether to add or remove selected class on the settings sub menu element
settingsMenuItem.on('click', openSubMenu)
@ -288,6 +289,6 @@ class SettingsButton extends Button {
}
}
Component.registerComponent('SettingsButton', SettingsButton)
videojs.registerComponent('SettingsButton', SettingsButton)
export { SettingsButton }

View file

@ -1,37 +1,40 @@
import debug from 'debug'
import videojs from 'video.js'
import { VideojsComponent, VideojsMenu, VideojsMenuItem, VideojsMenuItemOptions, VideojsPlayer } from '../../types'
import { toTitleCase } from '../common'
import { SettingsDialog } from './settings-dialog'
import { SettingsButton } from './settings-menu-button'
import { SettingsPanel } from './settings-panel'
import { SettingsPanelChild } from './settings-panel-child'
import Button from 'video.js/dist/types/button'
import MenuButton from 'video.js/dist/types/menu/menu-button'
const debugLogger = debug('peertube:player:settings')
const MenuItem = videojs.getComponent('MenuItem')
const Component = videojs.getComponent('Component')
const MenuItem = videojs.getComponent('MenuItem') as typeof VideojsMenuItem
const Component = videojs.getComponent('Component') as typeof VideojsComponent
interface MenuItemExtended extends videojs.MenuItem {
interface MenuItemExtended extends VideojsMenuItem {
isSelected_: boolean
getLabel?: () => string
}
export interface SettingsMenuItemOptions extends videojs.MenuItemOptions {
entry: string
menuButton: SettingsButton
export interface SettingsMenuItemOptions extends VideojsMenuItemOptions {
entry?: string
menuButton?: SettingsButton
}
class SettingsMenuItem extends MenuItem {
declare settingsButton: SettingsButton
declare dialog: SettingsDialog
declare mainMenu: videojs.Menu
declare mainMenu: VideojsMenu
declare panel: SettingsPanel
declare panelChild: SettingsPanelChild
declare panelChildEl: HTMLElement
declare size: number[]
declare menuToLoad: string
declare subMenu: SettingsButton
declare subMenu: MenuButton
declare submenuClickHandler: typeof SettingsMenuItem.prototype.onSubmenuClick
declare transitionEndHandler: typeof SettingsMenuItem.prototype.onTransitionEnd
@ -40,14 +43,14 @@ class SettingsMenuItem extends MenuItem {
declare settingsSubMenuValueEl_: HTMLElement
declare settingsSubMenuEl_: HTMLElement
constructor (player: videojs.Player, options?: SettingsMenuItemOptions) {
constructor (player: VideojsPlayer, options?: SettingsMenuItemOptions) {
super(player, options)
this.settingsButton = options.menuButton
this.dialog = this.settingsButton.dialog
this.mainMenu = this.settingsButton.menu
this.panel = this.dialog.getChild('settingsPanel')
this.panelChild = this.panel.getChild('settingsPanelChild')
this.panel = this.dialog.getChild('settingsPanel') as SettingsPanel
this.panelChild = this.panel.getChild('settingsPanelChild') as SettingsPanelChild
this.panelChildEl = this.panelChild.el() as HTMLElement
this.size = null
@ -56,15 +59,15 @@ class SettingsMenuItem extends MenuItem {
this.menuToLoad = 'mainmenu'
const subMenuName = toTitleCase(options.entry)
const SubMenuComponent = videojs.getComponent(subMenuName)
const SubMenuComponent = videojs.getComponent(subMenuName) as typeof MenuButton
console.log(options.entry)
if (!SubMenuComponent) {
throw new Error(`Component ${subMenuName} does not exist`)
}
const newOptions = Object.assign({}, options, { entry: options.menuButton, menuButton: this })
this.subMenu = new SubMenuComponent(this.player(), newOptions) as SettingsButton
this.subMenu = new SubMenuComponent(this.player(), { ...options })
const subMenuClass = this.subMenu.buildCSSClass().split(' ')[0]
this.settingsSubMenuEl_.className += ' ' + subMenuClass
@ -174,7 +177,7 @@ class SettingsMenuItem extends MenuItem {
*
* @method handleClick
*/
handleClick (event: videojs.EventTarget.Event) {
handleClick (event: Event) {
this.menuToLoad = 'submenu'
// Remove open class to ensure only the open submenu gets this class
videojs.dom.removeClass(this.el(), 'open')
@ -239,8 +242,7 @@ class SettingsMenuItem extends MenuItem {
mainMenuEl.style.opacity = '0'
// back button will always take you to main menu, so set dialog sizes
const mainMenuAny = this.mainMenu
this.settingsButton.setDialogSize([ mainMenuAny.width() as number, mainMenuAny.height() as number ])
this.settingsButton.setDialogSize([ this.mainMenu.width(), this.mainMenu.height() ])
// animation not triggered without timeout (some async stuff ?!?)
setTimeout(() => {
@ -376,7 +378,6 @@ class SettingsMenuItem extends MenuItem {
}
}
;(SettingsMenuItem as any).prototype.contentElType = 'button'
videojs.registerComponent('SettingsMenuItem', SettingsMenuItem)
export { SettingsMenuItem }

View file

@ -1,9 +1,9 @@
import videojs from 'video.js'
import { VideojsComponent } from '../../types'
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
class SettingsPanelChild extends Component {
createEl () {
return super.createEl('div', {
className: 'vjs-settings-panel-child',
@ -12,6 +12,6 @@ class SettingsPanelChild extends Component {
}
}
Component.registerComponent('SettingsPanelChild', SettingsPanelChild)
videojs.registerComponent('SettingsPanelChild', SettingsPanelChild)
export { SettingsPanelChild }

View file

@ -1,9 +1,9 @@
import videojs from 'video.js'
import { VideojsComponent } from '../../types'
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
class SettingsPanel extends Component {
createEl () {
return super.createEl('div', {
className: 'vjs-settings-panel',
@ -12,6 +12,6 @@ class SettingsPanel extends Component {
}
}
Component.registerComponent('SettingsPanel', SettingsPanel)
videojs.registerComponent('SettingsPanel', SettingsPanel)
export { SettingsPanel }

View file

@ -1,10 +1,11 @@
import videojs from 'video.js'
import { logger } from '@root-helpers/logger'
import { secondsToTime } from '@peertube/peertube-core-utils'
import { PlayerNetworkInfo as EventPlayerNetworkInfo } from '../../types'
import { logger } from '@root-helpers/logger'
import videojs from 'video.js'
import { TimeRange } from 'video.js/dist/types/utils/time'
import { PlayerNetworkInfo as EventPlayerNetworkInfo, VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
import { bytes } from '../common'
interface StatsCardOptions extends videojs.ComponentOptions {
interface StatsCardOptions extends VideojsComponentOptions {
videoUUID: string
videoIsLive: boolean
mode: 'web-video' | 'p2p-media-loader'
@ -28,7 +29,8 @@ interface InfoElement {
value: HTMLElement
}
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
class StatsCard extends Component {
declare options_: StatsCardOptions
@ -65,7 +67,7 @@ class StatsCard extends Component {
declare private onNetworkInfoHandler: (_event: any, data: EventPlayerNetworkInfo) => void
constructor (player: videojs.Player, options?: StatsCardOptions) {
constructor (player: VideojsPlayer, options?: StatsCardOptions) {
super(player, options)
this.metadataStore = {}
@ -365,7 +367,7 @@ class StatsCard extends Component {
return { root, value }
}
private timeRangesToString (r: videojs.TimeRange) {
private timeRangesToString (r: TimeRange) {
let result = ''
for (let i = 0; i < r.length; i++) {

View file

@ -1,12 +1,13 @@
import videojs from 'video.js'
import { VideojsPlayer, VideojsPlugin } from '../../types'
import { StatsCard, StatsCardOptions } from './stats-card'
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class StatsForNerdsPlugin extends Plugin {
declare private statsCard: StatsCard
constructor (player: videojs.Player, options: StatsCardOptions) {
constructor (player: VideojsPlayer, options: StatsCardOptions) {
super(player)
this.player.ready(() => {

View file

@ -1,5 +1,5 @@
import videojs from 'video.js'
import { UpNextPluginOptions } from '../../types'
import { UpNextPluginOptions, VideojsComponent, VideojsComponentOptions, VideojsPlayer } from '../../types'
function getMainTemplate (options: EndCardOptions) {
return `
@ -24,13 +24,14 @@ function getMainTemplate (options: EndCardOptions) {
`
}
export interface EndCardOptions extends videojs.ComponentOptions, UpNextPluginOptions {
export interface EndCardOptions extends VideojsComponentOptions, UpNextPluginOptions {
cancelText: string
headText: string
suspendedText: string
}
const Component = videojs.getComponent('Component')
const Component = videojs.getComponent('Component') as typeof VideojsComponent
export class EndCard extends Component {
declare options_: EndCardOptions
@ -53,7 +54,7 @@ export class EndCard extends Component {
declare private onEndedHandler: () => void
declare private onPlayingHandler: () => void
constructor (player: videojs.Player, options: EndCardOptions) {
constructor (player: VideojsPlayer, options: EndCardOptions) {
super(player, options)
this.dashOffsetTotal = 586

View file

@ -1,12 +1,11 @@
import videojs from 'video.js'
import { UpNextPluginOptions } from '../../types'
import { UpNextPluginOptions, VideojsPlayer, VideojsPlugin } from '../../types'
import { EndCard, EndCardOptions } from './end-card'
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class UpNextPlugin extends Plugin {
constructor (player: videojs.Player, options: UpNextPluginOptions) {
constructor (player: VideojsPlayer, options: UpNextPluginOptions) {
super(player)
const settings: EndCardOptions = {

View file

@ -3,11 +3,11 @@ import { VideoFile } from '@peertube/peertube-models'
import { logger } from '@root-helpers/logger'
import debug from 'debug'
import videojs from 'video.js'
import { PeerTubeResolution, PlayerNetworkInfo, WebVideoPluginOptions } from '../../types'
import { PeerTubeResolution, PlayerNetworkInfo, VideojsPlayer, VideojsPlugin, WebVideoPluginOptions } from '../../types'
const debugLogger = debug('peertube:player:web-video-plugin')
const Plugin = videojs.getPlugin('plugin')
const Plugin = videojs.getPlugin('plugin') as typeof VideojsPlugin
class WebVideoPlugin extends Plugin {
declare private readonly videoFiles: VideoFile[]
@ -21,8 +21,8 @@ class WebVideoPlugin extends Plugin {
declare private onPlayHandler: () => void
declare private onLoadedMetadata: () => void
constructor (player: videojs.Player, options?: WebVideoPluginOptions) {
super(player, options)
constructor (player: VideojsPlayer, options?: WebVideoPluginOptions) {
super(player)
this.videoFiles = options.videoFiles
this.videoFileToken = options.videoFileToken
@ -109,7 +109,8 @@ class WebVideoPlugin extends Plugin {
.then(() => {
if (paused) this.player.pause()
this.player.autoplay(oldAutoplayValue)
// FIXME: typings
this.player.autoplay(oldAutoplayValue as any)
})
}
}

View file

@ -1,7 +1,7 @@
import { LiveVideoLatencyModeType, VideoChapter, VideoFile } from '@peertube/peertube-models'
import { PluginsManager } from '@root-helpers/plugins-manager'
import { PeerTubeDockPluginOptions } from '../shared/dock/peertube-dock-plugin'
import { PlaylistPluginOptions, VideoJSCaption, VideoJSStoryboard } from './peertube-videojs-typings'
import { PlaylistPluginOptions, VideoJSCaption, VideojsPlayer, VideoJSStoryboard } from './peertube-videojs-typings'
export type PlayerMode = 'web-video' | 'p2p-media-loader'
@ -106,7 +106,7 @@ export type PeerTubePlayerLoadOptions = {
upnext?: {
isEnabled: () => boolean
isSuspended: (player: videojs.VideoJsPlayer) => boolean
isSuspended: (player: VideojsPlayer) => boolean
timeout: number
}

View file

@ -3,6 +3,22 @@ import type { HlsConfig, Level, Loader, LoaderContext } from 'hls.js'
import type { CoreConfig } from 'p2p-media-loader-core'
import type { HlsJsP2PEngine } from 'p2p-media-loader-hlsjs'
import videojs from 'video.js'
import BigPlayButton from 'video.js/dist/types/big-play-button'
import Button from 'video.js/dist/types/button'
import ClickableComponent from 'video.js/dist/types/clickable-component'
import Component from 'video.js/dist/types/component'
import ControlBar from 'video.js/dist/types/control-bar/control-bar'
import MouseTimeDisplay from 'video.js/dist/types/control-bar/progress-control/mouse-time-display'
import ProgressControl from 'video.js/dist/types/control-bar/progress-control/progress-control'
import SeekBar from 'video.js/dist/types/control-bar/progress-control/seek-bar'
import TimeTooltip from 'video.js/dist/types/control-bar/progress-control/time-tooltip'
import type CaptionButton from 'video.js/dist/types/control-bar/text-track-controls/captions-button'
import LoadingSpinner from 'video.js/dist/types/loading-spinner'
import Menu from 'video.js/dist/types/menu/menu'
import MenuButton from 'video.js/dist/types/menu/menu-button'
import MenuItem from 'video.js/dist/types/menu/menu-item'
import type Plugin from 'video.js/dist/types/plugin'
import Tech from 'video.js/dist/types/tech/tech'
import { BezelsPlugin } from '../shared/bezels/bezels-plugin'
import { ContextMenuPlugin } from '../shared/context-menu'
import { ChaptersPlugin } from '../shared/control-bar/chapters-plugin'
@ -23,65 +39,28 @@ import { StatsForNerdsPlugin } from '../shared/stats/stats-plugin'
import { UpNextPlugin } from '../shared/upnext/upnext-plugin'
import { WebVideoPlugin } from '../shared/web-video/web-video-plugin'
import { PlayerMode } from './peertube-player-options'
import { SettingsButton } from '../shared/settings/settings-menu-button'
declare module 'video.js' {
export interface VideoJsPlayer {
srOptions_: HlsjsConfigHandlerOptions
theaterEnabled: boolean
// FIXME: add it to upstream typings
posterImage: {
show(): void
hide(): void
}
handleTechSeeked_(): void
textTracks(): TextTrackList & {
tracks_: (TextTrack & { id: string, label: string, src: string })[]
}
// Plugins
peertube(): PeerTubePlugin
webVideo(options?: any): WebVideoPlugin
p2pMediaLoader(options?: any): P2pMediaLoaderPlugin
hlsjs(options?: any): any
peertubeResolutions(): PeerTubeResolutionsPlugin
contextMenu(options?: ContextMenuPluginOptions): ContextMenuPlugin
bezels(): BezelsPlugin
peertubeMobile(): PeerTubeMobilePlugin
peerTubeHotkeysPlugin(options?: HotkeysOptions): PeerTubeHotkeysPlugin
stats(options?: StatsCardOptions): StatsForNerdsPlugin
storyboard(options?: StoryboardOptions): StoryboardPlugin
peertubeDock(options?: PeerTubeDockPluginOptions): PeerTubeDockPlugin
peertubeNSFW(options?: PeerTubeNSFWPluginOptions): PeerTubeNSFWPlugin
chapters(options?: ChaptersOptions): ChaptersPlugin
upnext(options?: UpNextPluginOptions): UpNextPlugin
playlist(options?: PlaylistPluginOptions): PlaylistPlugin
}
}
export interface VideoJSTechHLS extends videojs.Tech {
export interface VideoJSTechHLS extends Tech {
hlsProvider: Html5Hlsjs
}
export interface HlsjsConfigHandlerOptions {
hlsjsConfig?: HlsConfig
levelLabelHandler?: (level: Level, player: videojs.Player) => string
levelLabelHandler?: (level: Level, player: VideojsPlayer) => string
}
export type PeerTubeResolution = {
@ -116,7 +95,7 @@ export type PeerTubePluginOptions = {
cssPlayerPortraitModeVariable: string
}
hasAutoplay: () => videojs.Autoplay
hasAutoplay: () => VideojsAutoplay
videoViewUrl: () => string
videoViewIntervalMs: number
@ -154,7 +133,7 @@ export type ContextMenuPluginOptions = {
}
export type ContextMenuItemOptions = {
listener: (e: videojs.EventTarget.Event) => void
listener: (e?: Event) => void
label: string
}
@ -215,7 +194,7 @@ export type WebVideoPluginOptions = {
}
export type HLSLoaderClass = {
new(confg: HlsConfig): Loader<LoaderContext>
new(config: HlsConfig): Loader<LoaderContext>
getEngine(): HlsJsP2PEngine
}
@ -300,3 +279,150 @@ export type PlaylistItemOptions = {
onClicked: () => void
}
type EventHandler = (event: any, data: any) => void
export declare class VideojsPlugin extends Plugin {
player: VideojsPlayer
on (event: string, handler: EventHandler): this
one (event: string, handler: EventHandler): void
off (event: string, handler: EventHandler): void
}
export type VideojsPlayer = ReturnType<typeof videojs.getPlayer> & {
options_: ReturnType<typeof videojs.getPlayer>['options_'] & {
loop: boolean
userActions: {
click?: boolean
doubleClick?: boolean
}
}
posterImage: {
show(): void
hide(): void
}
error: (err?: MediaError | string | number) => MediaError
on(event: string, handler: EventHandler): void
loadingSpinner: LoadingSpinner
controlBar: ControlBar & {
settingsButton: SettingsButton
progressControl: ProgressControl & {
seekBar: SeekBar & {
mouseTimeDisplay: {
timeTooltip: MouseTimeDisplay
}
}
}
}
bigPlayButton: BigPlayButton
srOptions_: HlsjsConfigHandlerOptions
// ---------------------------------------------------------------------------
peertube(): PeerTubePlugin
webVideo(options?: any): WebVideoPlugin
p2pMediaLoader(options?: any): P2pMediaLoaderPlugin
hlsjs(options?: any): any
peertubeResolutions(): PeerTubeResolutionsPlugin
contextMenu(options?: ContextMenuPluginOptions): ContextMenuPlugin
bezels(): BezelsPlugin
peertubeMobile(): PeerTubeMobilePlugin
peerTubeHotkeysPlugin(options?: HotkeysOptions): PeerTubeHotkeysPlugin
stats(options?: StatsCardOptions): StatsForNerdsPlugin
storyboard(options?: StoryboardOptions): StoryboardPlugin
peertubeDock(options?: PeerTubeDockPluginOptions): PeerTubeDockPlugin
peertubeNSFW(options?: PeerTubeNSFWPluginOptions): PeerTubeNSFWPlugin
chapters(options?: ChaptersOptions): ChaptersPlugin
upnext(options?: UpNextPluginOptions): UpNextPlugin
playlist(options?: PlaylistPluginOptions): PlaylistPlugin
// ---------------------------------------------------------------------------
theaterEnabled: boolean
}
export declare class VideojsComponent extends Component {
player: () => VideojsPlayer
player_: VideojsPlayer
}
export declare class VideojsMenuItem extends MenuItem {
player: () => VideojsPlayer
player_: VideojsPlayer
}
export declare class VideojsMenu extends Menu {
player: () => VideojsPlayer
player_: VideojsPlayer
}
export declare class VideojsMenuButton extends MenuButton {
player: () => VideojsPlayer
player_: VideojsPlayer
// FIXME: typings
setIcon: Component['setIcon']
}
export declare class VideojsButton extends Button {
player: () => VideojsPlayer
player_: VideojsPlayer
}
export declare class VideojsClickableComponent extends ClickableComponent {
player: () => VideojsPlayer
player_: VideojsPlayer
}
export declare class VideojsTimeTooltip extends TimeTooltip {
player: () => VideojsPlayer
player_: VideojsPlayer
}
export type VideojsComponentOptions = ConstructorParameters<typeof Component>[1]
export type VideojsMenuItemOptions = ConstructorParameters<typeof MenuItem>[1]
export type VideojsMenuOptions = ConstructorParameters<typeof Menu>[1]
export type VideojsButtonOptions = ConstructorParameters<typeof Button>[1]
export type VideojsClickableComponentOptions = ConstructorParameters<typeof ClickableComponent>[1]
export type VideojsMenuButtonOptions = ConstructorParameters<typeof MenuButton>[1]
export type VideojsAutoplay = boolean | 'muted' | 'play' | 'any'
export type VideojsPlayerOptions = Partial<VideojsPlayer['options_']> & {
muted?: boolean
controls?: boolean
autoplay?: VideojsAutoplay
poster?: string
preload?: 'none'
plugins?: VideoJSPluginOptions
controlBar?: {
children: Record<string, any>
}
textTrackSettings?: boolean
}
export type VideojsCaptionsButton = CaptionButton & Component

View file

@ -7,7 +7,7 @@ import {
VideoPlaylistElement,
VideoState
} from '@peertube/peertube-models'
import type { PeerTubePlayer } from '@peertube/player'
import type { PeerTubePlayer, VideojsPlayer } from '@peertube/player'
import { TranslationsManager } from '@root-helpers/translations-manager'
import { PeerTubeServerError } from 'src/types'
import type videojs from 'video.js'
@ -29,7 +29,7 @@ import {
import { PlayerHTML } from './shared/player-html'
export class PeerTubeEmbed {
player: videojs.Player
player: VideojsPlayer
api: PeerTubeEmbedApi = null
config: HTMLServerConfig

View file

@ -2265,11 +2265,6 @@
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
"@types/video.js@^7.3.40":
version "7.3.58"
resolved "https://registry.yarnpkg.com/@types/video.js/-/video.js-7.3.58.tgz#7e8cdafee25c75d6eb18f530b93ac52edff53c03"
integrity sha512-1CQjuSrgbv1/dhmcfQ83eVyYbvGyqhTvb2Opxr0QCV+iJ4J6/J+XWQ3Om59WiwCd1MN3rDUHasx5XRrpUtewYQ==
"@types/which@^2.0.1":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@types/which/-/which-2.0.2.tgz#54541d02d6b1daee5ec01ac0d1b37cecf37db1ae"
@ -2387,33 +2382,41 @@
"@typescript-eslint/types" "8.32.0"
eslint-visitor-keys "^4.2.0"
"@videojs/http-streaming@2.16.3":
version "2.16.3"
resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-2.16.3.tgz#d9b460c3716436327dbab4b1faeb2a767f05dcef"
integrity sha512-91CJv5PnFBzNBvyEjt+9cPzTK/xoVixARj2g7ZAvItA+5bx8VKdk5RxCz/PP2kdzz9W+NiDUMPkdmTsosmy69Q==
"@videojs/http-streaming@^3.17.2":
version "3.17.2"
resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-3.17.2.tgz#264eaf23980f4f0e3ad918a665ac60f178f01ff8"
integrity sha512-VBQ3W4wnKnVKb/limLdtSD2rAd5cmHN70xoMf4OmuDd0t2kfJX04G+sfw6u2j8oOm2BXYM9E1f4acHruqKnM1g==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/vhs-utils" "3.0.5"
aes-decrypter "3.1.3"
"@videojs/vhs-utils" "^4.1.1"
aes-decrypter "^4.0.2"
global "^4.4.0"
m3u8-parser "4.8.0"
mpd-parser "^0.22.1"
mux.js "6.0.1"
video.js "^6 || ^7"
m3u8-parser "^7.2.0"
mpd-parser "^1.3.1"
mux.js "7.1.0"
video.js "^7 || ^8"
"@videojs/vhs-utils@3.0.5", "@videojs/vhs-utils@^3.0.4", "@videojs/vhs-utils@^3.0.5":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz#665ba70d78258ba1ab977364e2fe9f4d4799c46c"
integrity sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==
"@videojs/vhs-utils@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-4.0.0.tgz#4d4dbf5d61a9fbd2da114b84ec747c3a483bc60d"
integrity sha512-xJp7Yd4jMLwje2vHCUmi8MOUU76nxiwII3z4Eg3Ucb+6rrkFVGosrXlMgGnaLjq724j3wzNElRZ71D/CKrTtxg==
dependencies:
"@babel/runtime" "^7.12.5"
global "^4.4.0"
url-toolkit "^2.2.1"
"@videojs/xhr@2.6.0":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@videojs/xhr/-/xhr-2.6.0.tgz#cd897e0ad54faf497961bcce3fa16dc15a26bb80"
integrity sha512-7J361GiN1tXpm+gd0xz2QWr3xNWBE+rytvo8J3KuggFaLg+U37gZQ2BuPLcnkfGffy2e+ozY70RHC8jt7zjA6Q==
"@videojs/vhs-utils@^4.1.1":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-4.1.1.tgz#44226fc5993f577490b5e08951ddc083714405cc"
integrity sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA==
dependencies:
"@babel/runtime" "^7.12.5"
global "^4.4.0"
"@videojs/xhr@2.7.0":
version "2.7.0"
resolved "https://registry.yarnpkg.com/@videojs/xhr/-/xhr-2.7.0.tgz#e272af6e2b5448aeb400905a5c6f4818f6b6ad47"
integrity sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==
dependencies:
"@babel/runtime" "^7.5.5"
global "~4.4.0"
@ -2709,13 +2712,13 @@ addressparser@^1.0.1:
resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746"
integrity sha512-aQX7AISOMM7HFE0iZ3+YnD07oIeJqWGVnJ+ZIKaBZAk03ftmVYVqsGas/rbXKR21n4D/hKCSHypvcyOkds/xzg==
aes-decrypter@3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/aes-decrypter/-/aes-decrypter-3.1.3.tgz#65ff5f2175324d80c41083b0e135d1464b12ac35"
integrity sha512-VkG9g4BbhMBy+N5/XodDeV6F02chEk9IpgRTq/0bS80y4dzy79VH2Gtms02VXomf3HmyRe3yyJYkJ990ns+d6A==
aes-decrypter@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/aes-decrypter/-/aes-decrypter-4.0.2.tgz#90648181c68878f54093920a3b44776ec2dc4914"
integrity sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/vhs-utils" "^3.0.5"
"@videojs/vhs-utils" "^4.1.1"
global "^4.4.0"
pkcs7 "^1.0.4"
@ -5402,7 +5405,7 @@ global-prefix@^3.0.0:
kind-of "^6.0.2"
which "^1.3.1"
global@^4.3.1, global@^4.4.0, global@~4.4.0:
global@4.4.0, global@^4.3.1, global@^4.4.0, global@~4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
@ -5745,11 +5748,6 @@ imurmurhash@^0.1.4:
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
individual@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/individual/-/individual-2.0.0.tgz#833b097dad23294e76117a98fb38e0d9ad61bb97"
integrity sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g==
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@ -6322,11 +6320,6 @@ jszip@^3.10.1:
readable-stream "~2.3.6"
setimmediate "^1.0.5"
keycode@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.1.tgz#09c23b2be0611d26117ea2501c2c391a01f39eff"
integrity sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==
keyv@^4.5.4:
version "4.5.4"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
@ -6575,13 +6568,13 @@ lru@^3.1.0:
dependencies:
inherits "^2.0.1"
m3u8-parser@4.8.0:
version "4.8.0"
resolved "https://registry.yarnpkg.com/m3u8-parser/-/m3u8-parser-4.8.0.tgz#4a2d591fdf6f2579d12a327081198df8af83083d"
integrity sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA==
m3u8-parser@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/m3u8-parser/-/m3u8-parser-7.2.0.tgz#9e2eb50abb8349d248cd58842367da4acabdf297"
integrity sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/vhs-utils" "^3.0.5"
"@videojs/vhs-utils" "^4.1.1"
global "^4.4.0"
magic-string@0.30.17, magic-string@^0.30.12, magic-string@^0.30.3:
@ -6921,13 +6914,13 @@ mocha@^10.3.0:
yargs-parser "^20.2.9"
yargs-unparser "^2.0.0"
mpd-parser@0.22.1, mpd-parser@^0.22.1:
version "0.22.1"
resolved "https://registry.yarnpkg.com/mpd-parser/-/mpd-parser-0.22.1.tgz#bc2bf7d3e56368e4b0121035b055675401871521"
integrity sha512-fwBebvpyPUU8bOzvhX0VQZgSohncbgYwUyJJoTSNpmy7ccD2ryiCvM7oRkn/xQH5cv73/xU7rJSNCLjdGFor0Q==
mpd-parser@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/mpd-parser/-/mpd-parser-1.3.1.tgz#557b6ac27411c2c177bb01e46e14440703a414a3"
integrity sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/vhs-utils" "^3.0.5"
"@videojs/vhs-utils" "^4.0.0"
"@xmldom/xmldom" "^0.8.3"
global "^4.4.0"
@ -6972,10 +6965,10 @@ mute-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b"
integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==
mux.js@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-6.0.1.tgz#65ce0f7a961d56c006829d024d772902d28c7755"
integrity sha512-22CHb59rH8pWGcPGW5Og7JngJ9s+z4XuSlYvnxhLuc58cA1WqGDQPzuG8I+sPm1/p0CdgpzVTaKW408k5DNn8w==
mux.js@7.1.0, mux.js@^7.0.1:
version "7.1.0"
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-7.1.0.tgz#aba5ed55a39cb790ef4b30b2c3ea0d2630b0264e"
integrity sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==
dependencies:
"@babel/runtime" "^7.11.2"
global "^4.4.0"
@ -8311,13 +8304,6 @@ run-series@^1.1.9:
resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.9.tgz#15ba9cb90e6a6c054e67c98e1dc063df0ecc113a"
integrity sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==
rust-result@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/rust-result/-/rust-result-1.0.0.tgz#34c75b2e6dc39fe5875e5bdec85b5e0f91536f72"
integrity sha512-6cJzSBU+J/RJCF063onnQf0cDUOHs9uZI1oroSGnHOph+CQTIJ5Pp2hK5kEQq1+7yE/EEWfulSNXAQ2jikPthA==
dependencies:
individual "^2.0.0"
rxjs@7.8.1:
version "7.8.1"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
@ -8358,13 +8344,6 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-json-parse@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-4.0.0.tgz#7c0f578cfccd12d33a71c0e05413e2eca171eaac"
integrity sha512-RjZPPHugjK0TOzFrLZ8inw44s9bKox99/0AZW9o/BEQVrJfhI+fIHMErnPyRa89/yRXUUr93q+tiN6zhoVV4wQ==
dependencies:
rust-result "^1.0.0"
safe-push-apply@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5"
@ -8946,16 +8925,7 @@ strict-event-emitter@^0.1.0:
resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.1.0.tgz#fd742c1fb7e3852f0b964ecdae2d7666a6fb7ef8"
integrity sha512-8hSYfU+WKLdNcHVXJ0VxRXiPESalzRe7w1l8dg9+/22Ry+iZQUoQuoJ27R30GMD1TiyYINWsIEGY05WrskhSKw==
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -9036,14 +9006,7 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -9747,31 +9710,37 @@ vary@^1, vary@^1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
"video.js@^6 || ^7", video.js@^7.19.2:
version "7.21.7"
resolved "https://registry.yarnpkg.com/video.js/-/video.js-7.21.7.tgz#8feccac174c5f202144b2f84138352a81f263dcd"
integrity sha512-T2s3WFAht7Zjr2OSJamND9x9Dn2O+Z5WuHGdh8jI5SYh5mkMdVTQ7vSRmA5PYpjXJ2ycch6jpMjkJEIEU2xxqw==
"video.js@^7 || ^8", video.js@^8.23.4:
version "8.23.4"
resolved "https://registry.yarnpkg.com/video.js/-/video.js-8.23.4.tgz#65876174dfcee1057102a03a847fdaa8cf346c66"
integrity sha512-qI0VTlYmKzEqRsz1Nppdfcaww4RSxZAq77z2oNSl3cNg2h6do5C8Ffl0KqWQ1OpD8desWXsCrde7tKJ9gGTEyQ==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/http-streaming" "2.16.3"
"@videojs/vhs-utils" "^3.0.4"
"@videojs/xhr" "2.6.0"
aes-decrypter "3.1.3"
"@videojs/http-streaming" "^3.17.2"
"@videojs/vhs-utils" "^4.1.1"
"@videojs/xhr" "2.7.0"
aes-decrypter "^4.0.2"
global "4.4.0"
m3u8-parser "^7.2.0"
mpd-parser "^1.3.1"
mux.js "^7.0.1"
videojs-contrib-quality-levels "4.1.0"
videojs-font "4.2.0"
videojs-vtt.js "0.15.5"
videojs-contrib-quality-levels@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz#44c2d2167114a5c8418548b10a25cb409d6cba51"
integrity sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==
dependencies:
global "^4.4.0"
keycode "^2.2.0"
m3u8-parser "4.8.0"
mpd-parser "0.22.1"
mux.js "6.0.1"
safe-json-parse "4.0.0"
videojs-font "3.2.0"
videojs-vtt.js "^0.15.5"
videojs-font@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-3.2.0.tgz#212c9d3f4e4ec3fa7345167d64316add35e92232"
integrity sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==
videojs-font@4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-4.2.0.tgz#fbce803d347c565816e296f527e208dc65c9f235"
integrity sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==
videojs-vtt.js@^0.15.5:
videojs-vtt.js@0.15.5:
version "0.15.5"
resolved "https://registry.yarnpkg.com/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz#567776eaf2a7a928d88b148a8b401ade2406f2ca"
integrity sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==
@ -10058,7 +10027,7 @@ workerpool@^6.5.1:
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544"
integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@ -10076,15 +10045,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"

View file