-
-declare module 'video.js' {
- interface Player {
- peertube (): PeerTubePlugin
- }
-}
-
-interface VideoJSComponentInterface {
- _player: videojs.Player
-
- new (player: videojs.Player, options?: any)
-
- registerComponent (name: string, obj: any)
-}
-
-type PeertubePluginOptions = {
- videoFiles: VideoFile[]
- playerElement: HTMLVideoElement
- videoViewUrl: string
- videoDuration: number
-}
-
-// https://github.com/danrevah/ngx-pipes/blob/master/src/pipes/math/bytes.ts
-// Don't import all Angular stuff, just copy the code with shame
-const dictionaryBytes: Array<{max: number, type: string}> = [
- { max: 1024, type: 'B' },
- { max: 1048576, type: 'KB' },
- { max: 1073741824, type: 'MB' },
- { max: 1.0995116e12, type: 'GB' }
-]
-function bytes (value) {
- const format = dictionaryBytes.find(d => value < d.max) || dictionaryBytes[dictionaryBytes.length - 1]
- const calc = Math.floor(value / (format.max / 1024)).toString()
-
- return [ calc, format.type ]
-}
-
-// videojs typings don't have some method we need
-const videojsUntyped = videojs as any
-const webtorrent = new WebTorrent({
- tracker: {
- rtcConfig: {
- iceServers: [
- {
- urls: 'stun:stun.stunprotocol.org'
- },
- {
- urls: 'stun:stun.framasoft.org'
- },
- {
- urls: 'stun:stun.l.google.com:19302'
- }
- ]
- }
- },
- dht: false
-})
-
-const MenuItem: VideoJSComponentInterface = videojsUntyped.getComponent('MenuItem')
-class ResolutionMenuItem extends MenuItem {
-
- constructor (player: videojs.Player, options) {
- options.selectable = true
- super(player, options)
-
- const currentResolutionId = this.player_.peertube().getCurrentResolutionId()
- this.selected(this.options_.id === currentResolutionId)
- }
-
- handleClick (event) {
- super.handleClick(event)
-
- this.player_.peertube().updateResolution(this.options_.id)
- }
-}
-MenuItem.registerComponent('ResolutionMenuItem', ResolutionMenuItem)
-
-const MenuButton: VideoJSComponentInterface = videojsUntyped.getComponent('MenuButton')
-class ResolutionMenuButton extends MenuButton {
- label: HTMLElement
-
- constructor (player: videojs.Player, options) {
- options.label = 'Quality'
- super(player, options)
-
- this.label = document.createElement('span')
-
- this.el().setAttribute('aria-label', 'Quality')
- this.controlText('Quality')
-
- videojsUntyped.dom.addClass(this.label, 'vjs-resolution-button-label')
- this.el().appendChild(this.label)
-
- player.peertube().on('videoFileUpdate', () => this.update())
- }
-
- createItems () {
- const menuItems = []
- for (const videoFile of this.player_.peertube().videoFiles) {
- menuItems.push(new ResolutionMenuItem(
- this.player_,
- {
- id: videoFile.resolution.id,
- label: videoFile.resolution.label,
- src: videoFile.magnetUri,
- selected: videoFile.resolution.id === this.currentSelectionId
- })
- )
- }
-
- return menuItems
- }
-
- update () {
- if (!this.label) return
-
- this.label.innerHTML = this.player_.peertube().getCurrentResolutionLabel()
- this.hide()
- return super.update()
- }
-
- buildCSSClass () {
- return super.buildCSSClass() + ' vjs-resolution-button'
- }
-}
-MenuButton.registerComponent('ResolutionMenuButton', ResolutionMenuButton)
-
-const Button: VideoJSComponentInterface = videojsUntyped.getComponent('Button')
-class PeerTubeLinkButton extends Button {
-
- createEl () {
- const link = document.createElement('a')
- link.href = window.location.href.replace('embed', 'watch')
- link.innerHTML = 'PeerTube'
- link.title = 'Go to the video page'
- link.className = 'vjs-peertube-link'
- link.target = '_blank'
-
- return link
- }
-
- handleClick () {
- this.player_.pause()
+import './settings-menu-button'
+import { PeertubePluginOptions, VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
+import { isMobile, videoFileMaxByResolution, videoFileMinByResolution } from './utils'
+import * as CacheChunkStore from 'cache-chunk-store'
+import { PeertubeChunkStore } from './peertube-chunk-store'
+import {
+ getAverageBandwidthInStore,
+ getStoredMute,
+ getStoredVolume,
+ saveAverageBandwidth,
+ saveMuteInStore,
+ saveVolumeInStore
+} from './peertube-player-local-storage'
+
+const Plugin: VideoJSComponentInterface = videojs.getPlugin('plugin')
+class PeerTubePlugin extends Plugin {
+ private readonly playerElement: HTMLVideoElement
+
+ private readonly autoplay: boolean = false
+ private readonly startTime: number = 0
+ private readonly savePlayerSrcFunction: Function
+ private readonly videoFiles: VideoFile[]
+ private readonly videoViewUrl: string
+ private readonly videoDuration: number
+ private readonly CONSTANTS = {
+ INFO_SCHEDULER: 1000, // Don't change this
+ AUTO_QUALITY_SCHEDULER: 3000, // Check quality every 3 seconds
+ AUTO_QUALITY_THRESHOLD_PERCENT: 30, // Bandwidth should be 30% more important than a resolution bitrate to change to it
+ AUTO_QUALITY_OBSERVATION_TIME: 10000, // Wait 10 seconds after having change the resolution before another check
+ AUTO_QUALITY_HIGHER_RESOLUTION_DELAY: 5000, // Buffering higher resolution during 5 seconds
+ BANDWIDTH_AVERAGE_NUMBER_OF_VALUES: 5 // Last 5 seconds to build average bandwidth