import 'videojs-hotkeys/videojs.hotkeys'
import 'videojs-dock'
-import 'videojs-contextmenu-pt'
-import 'videojs-contrib-quality-levels'
+import '@peertube/videojs-contextmenu'
import './upnext/end-card'
import './upnext/upnext-plugin'
import './stats/stats-card'
import './stats/stats-plugin'
import './bezels/bezels-plugin'
import './peertube-plugin'
+import './peertube-resolutions-plugin'
import './videojs-components/next-previous-video-button'
import './videojs-components/p2p-info-button'
import './videojs-components/peertube-link-button'
import './videojs-components/theater-button'
import './playlist/playlist-plugin'
import videojs from 'video.js'
+import { HlsJsEngineSettings } from '@peertube/p2p-media-loader-hlsjs'
import { PluginsManager } from '@root-helpers/plugins-manager'
import { buildVideoLink, decorateVideoLink } from '@shared/core-utils'
import { isDefaultLocale } from '@shared/core-utils/i18n'
import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager'
import { segmentUrlBuilderFactory } from './p2p-media-loader/segment-url-builder'
import { segmentValidatorFactory } from './p2p-media-loader/segment-validator'
-import { getStoredP2PEnabled } from './peertube-player-local-storage'
+import { getAverageBandwidthInStore, getStoredP2PEnabled, saveAverageBandwidth } from './peertube-player-local-storage'
import {
NextPreviousVideoButtonOptions,
P2PMediaLoaderPluginOptions,
PeerTubeLinkButtonOptions,
+ PlayerNetworkInfo,
PlaylistPluginOptions,
UserWatching,
VideoJSCaption,
if (mode === 'webtorrent') await import('./webtorrent/webtorrent-plugin')
if (mode === 'p2p-media-loader') {
[ p2pMediaLoader ] = await Promise.all([
- import('p2p-media-loader-hlsjs'),
+ import('@peertube/p2p-media-loader-hlsjs'),
import('./p2p-media-loader/p2p-media-loader-plugin')
])
}
mode
})
+ player.on('p2pInfo', (_, data: PlayerNetworkInfo) => {
+ if (data.source !== 'p2p-media-loader' || isNaN(data.bandwidthEstimate)) return
+
+ saveAverageBandwidth(data.bandwidthEstimate)
+ })
+
return res(player)
})
})
}
let consumeOnly = false
- // FIXME: typings
- if (navigator && (navigator as any).connection && (navigator as any).connection.type === 'cellular') {
+ if ((navigator as any)?.connection?.type === 'cellular') {
console.log('We are on a cellular connection: disabling seeding.')
consumeOnly = true
}
- const p2pMediaLoaderConfig = {
+ const p2pMediaLoaderConfig: HlsJsEngineSettings = {
loader: {
trackerAnnounce,
segmentValidator: segmentValidatorFactory(options.p2pMediaLoader.segmentsSha256Url, options.common.isLive),
rtcConfig: getRtcConfig(),
requiredSegmentsPriority: 1,
- segmentUrlBuilder: segmentUrlBuilderFactory(redundancyUrlManager),
+ simultaneousHttpDownloads: 1,
+ segmentUrlBuilder: segmentUrlBuilderFactory(redundancyUrlManager, 1),
useP2P: getStoredP2PEnabled(),
consumeOnly
},
swarmId: p2pMediaLoaderOptions.playlistUrl
}
}
+
const hlsjs = {
levelLabelHandler: (level: { height: number, width: number }) => {
const resolution = Math.min(level.height || 0, level.width || 0)
return label
},
html5: {
- hlsjsConfig: {
- capLevelToPlayerSize: true,
- autoStartLoad: false,
- liveSyncDurationCount: 5,
- loader: new p2pMediaLoaderModule.Engine(p2pMediaLoaderConfig).createLoaderClass()
- }
+ hlsjsConfig: this.getHLSOptions(p2pMediaLoaderModule, p2pMediaLoaderConfig)
}
}
return toAssign
}
+ private static getHLSOptions (p2pMediaLoaderModule: any, p2pMediaLoaderConfig: HlsJsEngineSettings) {
+ const base = {
+ capLevelToPlayerSize: true,
+ autoStartLoad: false,
+ liveSyncDurationCount: 5,
+
+ loader: new p2pMediaLoaderModule.Engine(p2pMediaLoaderConfig).createLoaderClass()
+ }
+
+ const averageBandwidth = getAverageBandwidthInStore()
+ if (!averageBandwidth) return base
+
+ return {
+ ...base,
+
+ abrEwmaDefaultEstimate: averageBandwidth * 8, // We want bit/s
+ startLevel: -1,
+ testBandwidth: false,
+ debug: false
+ }
+ }
+
private static addWebTorrentOptions (plugins: VideoJSPluginOptions, options: PeertubePlayerManagerOptions) {
const commonOptions = options.common
const webtorrentOptions = options.webtorrent
const p2pMediaLoaderOptions = options.p2pMediaLoader
const autoplay = this.getAutoPlayValue(commonOptions.autoplay) === 'play'
- ? true
- : false
const webtorrent = {
autoplay,
theaterButton: boolean
captions: boolean
- nextVideo?: Function
+ nextVideo?: () => void
hasNextVideo?: () => boolean
- previousVideo?: Function
+ previousVideo?: () => void
hasPreviousVideo?: () => boolean
}) {
const settingEntries = []
}
Object.assign(children, {
- 'previousVideoButton': buttonOptions
+ previousVideoButton: buttonOptions
})
}
}
Object.assign(children, {
- 'nextVideoButton': buttonOptions
+ nextVideoButton: buttonOptions
})
}
Object.assign(children, {
- 'currentTimeDisplay': {},
- 'timeDivider': {},
- 'durationDisplay': {},
- 'liveDisplay': {},
+ currentTimeDisplay: {},
+ timeDivider: {},
+ durationDisplay: {},
+ liveDisplay: {},
- 'flexibleWidthSpacer': {},
- 'progressControl': {
+ flexibleWidthSpacer: {},
+ progressControl: {
children: {
- 'seekBar': {
+ seekBar: {
children: {
[loadProgressBar]: {},
- 'mouseTimeDisplay': {},
- 'playProgressBar': {}
+ mouseTimeDisplay: {},
+ playProgressBar: {}
}
}
}
},
- 'p2PInfoButton': {},
+ p2PInfoButton: {},
- 'muteToggle': {},
- 'volumeControl': {},
+ muteToggle: {},
+ volumeControl: {},
- 'settingsButton': {
+ settingsButton: {
setup: {
maxHeightOffset: 40
},
if (options.peertubeLink === true) {
Object.assign(children, {
- 'peerTubeLinkButton': { shortUUID: options.videoShortUUID } as PeerTubeLinkButtonOptions
+ peerTubeLinkButton: { shortUUID: options.videoShortUUID } as PeerTubeLinkButtonOptions
})
}
if (options.theaterButton === true) {
Object.assign(children, {
- 'theaterButton': {}
+ theaterButton: {}
})
}
Object.assign(children, {
- 'fullscreenToggle': {}
+ fullscreenToggle: {}
})
return children