1 // FIXME: something weird with our path definition in tsconfig and typings
3 import * as videojs from 'video.js'
4 import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo, VideoJSComponentInterface } from './peertube-videojs-typings'
6 // videojs-hlsjs-plugin needs videojs in window
7 window['videojs'] = videojs
8 import '@streamroot/videojs-hlsjs-plugin'
10 import { Engine, initVideoJsContribHlsJsPlayer } from 'p2p-media-loader-hlsjs'
11 import * as Hls from 'hls.js'
12 import { Events } from 'p2p-media-loader-core'
14 const Plugin: VideoJSComponentInterface = videojs.getPlugin('plugin')
15 class P2pMediaLoaderPlugin extends Plugin {
17 private readonly CONSTANTS = {
18 INFO_SCHEDULER: 1000 // Don't change this
22 private p2pEngine: Engine
23 private statsP2PBytes = {
24 pendingDownload: [] as number[],
25 pendingUpload: [] as number[],
31 private networkInfoInterval: any
33 constructor (player: videojs.Player, options: P2PMediaLoaderPluginOptions) {
34 super(player, options)
36 videojs.Html5Hlsjs.addHook('beforeinitialize', (videojsPlayer: any, hlsjs: Hls) => {
42 initVideoJsContribHlsJsPlayer(player)
51 clearInterval(this.networkInfoInterval)
54 private initialize () {
55 this.p2pEngine = this.player.tech_.options_.hlsjsConfig.loader.getEngine()
57 this.hlsjs.on(Hls.Events.LEVEL_SWITCHING, (_, data: Hls.levelSwitchingData) => {
58 this.trigger('resolutionChange', { auto: this.hlsjs.autoLevelEnabled, resolutionId: data.height })
65 this.p2pEngine.on(Events.PieceBytesDownloaded, (method: string, size: number) => {
66 if (method === 'p2p') {
67 this.statsP2PBytes.pendingDownload.push(size)
68 this.statsP2PBytes.totalDownload += size
72 this.p2pEngine.on(Events.PieceBytesUploaded, (method: string, size: number) => {
73 if (method === 'p2p') {
74 this.statsP2PBytes.pendingUpload.push(size)
75 this.statsP2PBytes.totalUpload += size
79 this.p2pEngine.on(Events.PeerConnect, () => this.statsP2PBytes.numPeers++)
80 this.p2pEngine.on(Events.PeerClose, () => this.statsP2PBytes.numPeers--)
82 this.networkInfoInterval = setInterval(() => {
83 let downloadSpeed = this.statsP2PBytes.pendingDownload.reduce((a: number, b: number) => a + b, 0)
84 let uploadSpeed = this.statsP2PBytes.pendingUpload.reduce((a: number, b: number) => a + b, 0)
86 this.statsP2PBytes.pendingDownload = []
87 this.statsP2PBytes.pendingUpload = []
89 return this.player.trigger('p2pInfo', {
93 numPeers: this.statsP2PBytes.numPeers,
94 downloaded: this.statsP2PBytes.totalDownload,
95 uploaded: this.statsP2PBytes.totalUpload
97 } as PlayerNetworkInfo)
98 }, this.CONSTANTS.INFO_SCHEDULER)
102 videojs.registerPlugin('p2pMediaLoader', P2pMediaLoaderPlugin)
103 export { P2pMediaLoaderPlugin }