]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - client/src/assets/player/peertube-videojs-plugin.ts
Add title in player peers info to show total downloaded/uploaded data
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / peertube-videojs-plugin.ts
index b54f096b26770cee9886c8b28e88d0df637f91a6..fc07c35d61eca44fdead9fb29d2d9b21bd8720ec 100644 (file)
@@ -4,36 +4,19 @@ import { VideoFile } from '../../../../shared/models/videos/video.model'
 import { renderVideo } from './video-renderer'
 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 {
-  getAverageBandwidth,
+  getAverageBandwidthInStore,
   getStoredMute,
   getStoredVolume,
   saveAverageBandwidth,
   saveMuteInStore,
-  saveVolumeInStore,
-  videoFileMaxByResolution,
-  videoFileMinByResolution
-} from './utils'
-import * as CacheChunkStore from 'cache-chunk-store'
-import { PeertubeChunkStore } from './peertube-chunk-store'
-
-const webtorrent = new WebTorrent({
-  tracker: {
-    rtcConfig: {
-      iceServers: [
-        {
-          urls: 'stun:stun.stunprotocol.org'
-        },
-        {
-          urls: 'stun:stun.framasoft.org'
-        }
-      ]
-    }
-  },
-  dht: false
-})
+  saveVolumeInStore
+} from './peertube-player-local-storage'
 
-const Plugin: VideoJSComponentInterface = videojsUntyped.getPlugin('plugin')
+const Plugin: VideoJSComponentInterface = videojs.getPlugin('plugin')
 class PeerTubePlugin extends Plugin {
   private readonly playerElement: HTMLVideoElement
 
@@ -52,9 +35,27 @@ class PeerTubePlugin extends Plugin {
     BANDWIDTH_AVERAGE_NUMBER_OF_VALUES: 5 // Last 5 seconds to build average bandwidth
   }
 
+  private readonly webtorrent = new WebTorrent({
+    tracker: {
+      rtcConfig: {
+        iceServers: [
+          {
+            urls: 'stun:stun.stunprotocol.org'
+          },
+          {
+            urls: 'stun:stun.framasoft.org'
+          }
+        ]
+      }
+    },
+    dht: false
+  })
+
   private player: any
   private currentVideoFile: VideoFile
   private torrent: WebTorrent.Torrent
+  private renderer
+  private fakeRenderer
   private autoResolution = true
   private isAutoResolutionObservation = false
 
@@ -123,6 +124,8 @@ class PeerTubePlugin extends Plugin {
 
     // Don't need to destroy renderer, video player will be destroyed
     this.flushVideoFile(this.currentVideoFile, false)
+
+    this.destroyFakeRenderer()
   }
 
   getCurrentResolutionId () {
@@ -144,10 +147,10 @@ class PeerTubePlugin extends Plugin {
   ) {
     // Automatically choose the adapted video file
     if (videoFile === undefined) {
-      const savedAverageBandwidth = getAverageBandwidth()
+      const savedAverageBandwidth = getAverageBandwidthInStore()
       videoFile = savedAverageBandwidth
         ? this.getAppropriateFile(savedAverageBandwidth)
-        : this.videoFiles[0]
+        : this.pickAverageVideoFile()
     }
 
     // Don't add the same video file once again
@@ -191,18 +194,33 @@ class PeerTubePlugin extends Plugin {
       })
     }
 
-    this.torrent = webtorrent.add(magnetOrTorrentUrl, torrentOptions, torrent => {
+    this.torrent = this.webtorrent.add(magnetOrTorrentUrl, torrentOptions, torrent => {
       console.log('Added ' + magnetOrTorrentUrl + '.')
 
-      // Pause the old torrent
       if (oldTorrent) {
+        // Pause the old torrent
         oldTorrent.pause()
         // Pause does not remove actual peers (in particular the webseed peer)
         oldTorrent.removePeer(oldTorrent['ws'])
+
+        // We use a fake renderer so we download correct pieces of the next file
+        if (options.delay) {
+          const fakeVideoElem = document.createElement('video')
+          renderVideo(torrent.files[0], fakeVideoElem, { autoplay: false, controls: false }, (err, renderer) => {
+            this.fakeRenderer = renderer
+
+            if (err) console.error('Cannot render new torrent in fake video element.', err)
+
+            // Load the future file at the correct time
+            fakeVideoElem.currentTime = this.player.currentTime() + (options.delay / 2000)
+          })
+        }
       }
 
       // Render the video in a few seconds? (on resolution change for example, we wait some seconds of the new video resolution)
       this.addTorrentDelay = setTimeout(() => {
+        this.destroyFakeRenderer()
+
         const paused = this.player.paused()
 
         this.flushVideoFile(previousVideoFile)
@@ -263,16 +281,16 @@ class PeerTubePlugin extends Plugin {
     const options = {
       forcePlay: false,
       delay,
-      seek: currentTime
+      seek: currentTime + (delay / 1000)
     }
     this.updateVideoFile(newVideoFile, options)
   }
 
   flushVideoFile (videoFile: VideoFile, destroyRenderer = true) {
-    if (videoFile !== undefined && webtorrent.get(videoFile.magnetUri)) {
+    if (videoFile !== undefined && this.webtorrent.get(videoFile.magnetUri)) {
       if (destroyRenderer === true && this.renderer && this.renderer.destroy) this.renderer.destroy()
 
-      webtorrent.remove(videoFile.magnetUri)
+      this.webtorrent.remove(videoFile.magnetUri)
       console.log('Removed ' + videoFile.magnetUri)
     }
   }
@@ -310,6 +328,7 @@ class PeerTubePlugin extends Plugin {
                           this.player.pause()
                           this.player.posterImage.show()
                           this.player.removeClass('vjs-has-autoplay')
+                          this.player.removeClass('vjs-has-big-play-button-clicked')
 
                           return done()
                         })
@@ -366,6 +385,8 @@ class PeerTubePlugin extends Plugin {
   }
 
   private initializePlayer () {
+    if (isMobile()) this.player.addClass('vjs-is-mobile')
+
     this.initSmoothProgressBar()
 
     this.alterInactivity()
@@ -377,7 +398,7 @@ class PeerTubePlugin extends Plugin {
     } else {
       // Don't try on iOS that does not support MediaSource
       if (this.isIOS()) {
-        this.currentVideoFile = this.videoFiles[0]
+        this.currentVideoFile = this.pickAverageVideoFile()
         return this.fallbackToHttp(undefined, false)
       }
 
@@ -439,13 +460,15 @@ class PeerTubePlugin extends Plugin {
       // Http fallback
       if (this.torrent === null) return this.trigger('torrentInfo', false)
 
-      // webtorrent.downloadSpeed because we need to take into account the potential old torrent too
-      if (webtorrent.downloadSpeed !== 0) this.downloadSpeeds.push(webtorrent.downloadSpeed)
+      // this.webtorrent.downloadSpeed because we need to take into account the potential old torrent too
+      if (this.webtorrent.downloadSpeed !== 0) this.downloadSpeeds.push(this.webtorrent.downloadSpeed)
 
       return this.trigger('torrentInfo', {
         downloadSpeed: this.torrent.downloadSpeed,
         numPeers: this.torrent.numPeers,
-        uploadSpeed: this.torrent.uploadSpeed
+        uploadSpeed: this.torrent.uploadSpeed,
+        downloaded: this.torrent.downloaded,
+        uploaded: this.torrent.uploaded
       })
     }, this.CONSTANTS.INFO_SCHEDULER)
   }
@@ -480,6 +503,8 @@ class PeerTubePlugin extends Plugin {
   }
 
   private addViewToVideo () {
+    if (!this.videoViewUrl) return Promise.resolve(undefined)
+
     return fetch(this.videoViewUrl, { method: 'POST' })
   }
 
@@ -533,6 +558,25 @@ class PeerTubePlugin extends Plugin {
     settingsDialog.on('mouseleave', () => enableInactivity())
   }
 
+  private pickAverageVideoFile () {
+    if (this.videoFiles.length === 1) return this.videoFiles[0]
+
+    return this.videoFiles[Math.floor(this.videoFiles.length / 2)]
+  }
+
+  private destroyFakeRenderer () {
+    if (this.fakeRenderer) {
+      if (this.fakeRenderer.destroy) {
+        try {
+          this.fakeRenderer.destroy()
+        } catch (err) {
+          console.log('Cannot destroy correctly fake renderer.', err)
+        }
+      }
+      this.fakeRenderer = undefined
+    }
+  }
+
   // Thanks: https://github.com/videojs/video.js/issues/4460#issuecomment-312861657
   private initSmoothProgressBar () {
     const SeekBar = videojsUntyped.getComponent('SeekBar')
@@ -556,5 +600,5 @@ class PeerTubePlugin extends Plugin {
   }
 }
 
-videojsUntyped.registerPlugin('peertube', PeerTubePlugin)
+videojs.registerPlugin('peertube', PeerTubePlugin)
 export { PeerTubePlugin }