mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-03 17:59:37 +02:00
Upgrade to videojs v8
This commit is contained in:
parent
91afa1004e
commit
8c83592d89
57 changed files with 573 additions and 453 deletions
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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 = () => {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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' ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 = ''
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
190
client/yarn.lock
190
client/yarn.lock
|
@ -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"
|
||||
|
|
0
locales/fr-FR/translation.json
Normal file
0
locales/fr-FR/translation.json
Normal file
Loading…
Add table
Add a link
Reference in a new issue