X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=client%2Fsrc%2Fassets%2Fplayer%2Fp2p-media-loader%2Fp2p-media-loader-plugin.ts;h=2eb849d2b157f34849c35b878458a0f705c4d291;hb=15a7eafb892441957ba7dd6fcbf556086fe5b2b3;hp=c44c184d5bb80ab646d22058788f18ea02c6ebae;hpb=b82df0a39910e2cb079bf7f9f92de3ec2b0b09aa;p=github%2FChocobozzz%2FPeerTube.git diff --git a/client/src/assets/player/p2p-media-loader/p2p-media-loader-plugin.ts b/client/src/assets/player/p2p-media-loader/p2p-media-loader-plugin.ts index c44c184d5..2eb849d2b 100644 --- a/client/src/assets/player/p2p-media-loader/p2p-media-loader-plugin.ts +++ b/client/src/assets/player/p2p-media-loader/p2p-media-loader-plugin.ts @@ -1,16 +1,15 @@ -// FIXME: something weird with our path definition in tsconfig and typings -// @ts-ignore -import * as videojs from 'video.js' -import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo, VideoJSComponentInterface } from '../peertube-videojs-typings' -import { Engine, initHlsJsPlayer, initVideoJsContribHlsJsPlayer } from 'p2p-media-loader-hlsjs' +import * as Hlsjs from 'hls.js/dist/hls.light.js' import { Events, Segment } from 'p2p-media-loader-core' -import { timeToInt } from '../utils' +import { Engine, initHlsJsPlayer, initVideoJsContribHlsJsPlayer } from 'p2p-media-loader-hlsjs' +import videojs from 'video.js' +import { timeToInt } from '@shared/core-utils' +import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo } from '../peertube-videojs-typings' +import { registerConfigPlugin, registerSourceHandler } from './hls-plugin' -// videojs-hlsjs-plugin needs videojs in window -window['videojs'] = videojs -require('@streamroot/videojs-hlsjs-plugin') +registerConfigPlugin(videojs) +registerSourceHandler(videojs) -const Plugin: VideoJSComponentInterface = videojs.getPlugin('plugin') +const Plugin = videojs.getPlugin('plugin') class P2pMediaLoaderPlugin extends Plugin { private readonly CONSTANTS = { @@ -18,7 +17,7 @@ class P2pMediaLoaderPlugin extends Plugin { } private readonly options: P2PMediaLoaderPluginOptions - private hlsjs: any // Don't type hlsjs to not bundle the module + private hlsjs: Hlsjs private p2pEngine: Engine private statsP2PBytes = { pendingDownload: [] as number[], @@ -37,24 +36,33 @@ class P2pMediaLoaderPlugin extends Plugin { private networkInfoInterval: any - constructor (player: videojs.Player, options: P2PMediaLoaderPluginOptions) { - super(player, options) + private hlsjsCurrentLevel: number + private hlsjsLevels: Hlsjs.Level[] + + constructor (player: videojs.Player, options?: P2PMediaLoaderPluginOptions) { + super(player) this.options = options - if (!videojs.Html5Hlsjs) { - const message = 'HLS.js does not seem to be supported.' - console.warn(message) + // FIXME: typings https://github.com/Microsoft/TypeScript/issues/14080 + if (!(videojs as any).Html5Hlsjs) { + console.warn('HLS.js does not seem to be supported. Try to fallback to built in HLS.') - player.ready(() => player.trigger('error', new Error(message))) - return - } + if (!player.canPlayType('application/vnd.apple.mpegurl')) { + const message = 'Cannot fallback to built-in HLS' + console.warn(message) - videojs.Html5Hlsjs.addHook('beforeinitialize', (videojsPlayer: any, hlsjs: any) => { - this.hlsjs = hlsjs - }) + player.ready(() => player.trigger('error', new Error(message))) + return + } + } else { + // FIXME: typings https://github.com/Microsoft/TypeScript/issues/14080 + (videojs as any).Html5Hlsjs.addHook('beforeinitialize', (videojsPlayer: any, hlsjs: any) => { + this.hlsjs = hlsjs + }) - initVideoJsContribHlsJsPlayer(player) + initVideoJsContribHlsJsPlayer(player) + } this.startTime = timeToInt(options.startTime) @@ -63,11 +71,13 @@ class P2pMediaLoaderPlugin extends Plugin { src: options.src }) - player.one('play', () => { - player.addClass('vjs-has-big-play-button-clicked') - }) + player.ready(() => { + this.initializeCore() - player.ready(() => this.initialize()) + if ((videojs as any).Html5Hlsjs) { + this.initializePlugin() + } + }) } dispose () { @@ -77,18 +87,47 @@ class P2pMediaLoaderPlugin extends Plugin { clearInterval(this.networkInfoInterval) } - private initialize () { + getCurrentLevel () { + return this.hlsjsLevels.find(l => l.level === this.hlsjsCurrentLevel) + } + + getLiveLatency () { + return undefined as number + // FIXME: Use latency when hls >= V1 + // return this.hlsjs.latency + } + + getHLSJS () { + return this.hlsjs + } + + private initializeCore () { + this.player.one('play', () => { + this.player.addClass('vjs-has-big-play-button-clicked') + }) + + this.player.one('canplay', () => { + if (this.startTime) { + this.player.currentTime(this.startTime) + } + }) + } + + private initializePlugin () { initHlsJsPlayer(this.hlsjs) - const tech = this.player.tech_ - this.p2pEngine = tech.options_.hlsjsConfig.loader.getEngine() + // FIXME: typings + const options = this.player.tech(true).options_ as any + this.p2pEngine = options.hlsjsConfig.loader.getEngine() - // Avoid using constants to not import hls.hs - // https://github.com/video-dev/hls.js/blob/master/src/events.js#L37 - this.hlsjs.on('hlsLevelSwitching', (_: any, data: any) => { + this.hlsjs.on(Hlsjs.Events.LEVEL_SWITCHING, (_: any, data: any) => { this.trigger('resolutionChange', { auto: this.hlsjs.autoLevelEnabled, resolutionId: data.height }) }) + this.hlsjs.on(Hlsjs.Events.MANIFEST_LOADED, (_: any, data: any) => { + this.trigger('resolutionsLoaded') + }) + this.p2pEngine.on(Events.SegmentError, (segment: Segment, err) => { console.error('Segment error.', segment, err) @@ -98,12 +137,6 @@ class P2pMediaLoaderPlugin extends Plugin { this.statsP2PBytes.numPeers = 1 + this.options.redundancyUrlManager.countBaseUrls() this.runStats() - - this.player.one('canplay', () => { - if (this.startTime) { - this.player.currentTime(this.startTime) - } - }) } private runStats () { @@ -124,6 +157,14 @@ class P2pMediaLoaderPlugin extends Plugin { this.p2pEngine.on(Events.PeerConnect, () => this.statsP2PBytes.numPeers++) this.p2pEngine.on(Events.PeerClose, () => this.statsP2PBytes.numPeers--) + this.hlsjs.on(Hlsjs.Events.MANIFEST_PARSED, (_e, manifest) => { + this.hlsjsCurrentLevel = manifest.firstLevel + this.hlsjsLevels = manifest.levels + }) + this.hlsjs.on(Hlsjs.Events.LEVEL_LOADED, (_e, level) => { + this.hlsjsCurrentLevel = level.levelId || (level as any).id + }) + this.networkInfoInterval = setInterval(() => { const p2pDownloadSpeed = this.arraySum(this.statsP2PBytes.pendingDownload) const p2pUploadSpeed = this.arraySum(this.statsP2PBytes.pendingUpload) @@ -137,6 +178,7 @@ class P2pMediaLoaderPlugin extends Plugin { this.statsHTTPBytes.pendingUpload = [] return this.player.trigger('p2pInfo', { + source: 'p2p-media-loader', http: { downloadSpeed: httpDownloadSpeed, uploadSpeed: httpUploadSpeed, @@ -149,7 +191,8 @@ class P2pMediaLoaderPlugin extends Plugin { numPeers: this.statsP2PBytes.numPeers, downloaded: this.statsP2PBytes.totalDownload, uploaded: this.statsP2PBytes.totalUpload - } + }, + bandwidthEstimate: (this.hlsjs as any).bandwidthEstimate / 8 } as PlayerNetworkInfo) }, this.CONSTANTS.INFO_SCHEDULER) }