]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - client/src/assets/player/peertube-videojs-plugin.ts
add webtorrent opt-out settings
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / peertube-videojs-plugin.ts
index 36b80bd72b543b636cd54f99931552e8cf13de02..90ca8f9faaeb2df12956cc1b74f6a69c6d3f5dbd 100644 (file)
@@ -3,11 +3,12 @@ import * as WebTorrent from 'webtorrent'
 import { VideoFile } from '../../../../shared/models/videos/video.model'
 import { renderVideo } from './video-renderer'
 import './settings-menu-button'
-import { PeertubePluginOptions, VideoJSCaption, VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
+import { PeertubePluginOptions, UserWatching, VideoJSCaption, VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
 import { isMobile, timeToInt, videoFileMaxByResolution, videoFileMinByResolution } from './utils'
 import * as CacheChunkStore from 'cache-chunk-store'
 import { PeertubeChunkStore } from './peertube-chunk-store'
 import {
+  getStoredWebTorrentPolicy,
   getAverageBandwidthInStore,
   getStoredMute,
   getStoredVolume,
@@ -32,7 +33,8 @@ class PeerTubePlugin extends Plugin {
     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
+    BANDWIDTH_AVERAGE_NUMBER_OF_VALUES: 5, // Last 5 seconds to build average bandwidth
+    USER_WATCHING_VIDEO_INTERVAL: 5000 // Every 5 seconds, notify the user is watching the video
   }
 
   private readonly webtorrent = new WebTorrent({
@@ -55,15 +57,20 @@ class PeerTubePlugin extends Plugin {
   private currentVideoFile: VideoFile
   private torrent: WebTorrent.Torrent
   private videoCaptions: VideoJSCaption[]
+
   private renderer
   private fakeRenderer
+  private destoyingFakeRenderer = false
+
   private autoResolution = true
   private forbidAutoResolution = false
   private isAutoResolutionObservation = false
+  private playerRefusedP2P = false
 
   private videoViewInterval
   private torrentInfoInterval
   private autoQualityInterval
+  private userWatchingVideoInterval
   private addTorrentDelay
   private qualityObservationTimer
   private runAutoQualitySchedulerTimer
@@ -92,11 +99,14 @@ class PeerTubePlugin extends Plugin {
       if (volume !== undefined) this.player.volume(volume)
       const muted = getStoredMute()
       if (muted !== undefined) this.player.muted(muted)
+      this.playerRefusedP2P = getStoredWebTorrentPolicy() || false
 
       this.initializePlayer()
       this.runTorrentInfoScheduler()
       this.runViewAdd()
 
+      if (options.userWatching) this.runUserWatchVideo(options.userWatching)
+
       this.player.one('play', () => {
         // Don't run immediately scheduler, wait some seconds the TCP connections are made
         this.runAutoQualitySchedulerTimer = setTimeout(() => this.runAutoQualityScheduler(), this.CONSTANTS.AUTO_QUALITY_SCHEDULER)
@@ -118,6 +128,8 @@ class PeerTubePlugin extends Plugin {
     clearInterval(this.torrentInfoInterval)
     clearInterval(this.autoQualityInterval)
 
+    if (this.userWatchingVideoInterval) clearInterval(this.userWatchingVideoInterval)
+
     // Don't need to destroy renderer, video player will be destroyed
     this.flushVideoFile(this.currentVideoFile, false)
 
@@ -279,7 +291,8 @@ class PeerTubePlugin extends Plugin {
         renderVideo(torrent.files[ 0 ], this.playerElement, renderVideoOptions, (err, renderer) => {
           this.renderer = renderer
 
-          if (err) return this.fallbackToHttp(done)
+          console.log('value this.playerRefusedP2P', this.playerRefusedP2P)
+          if (err || this.playerRefusedP2P) return this.fallbackToHttp(done)
 
           return this.tryToPlay(err => {
             if (err) return done(err)
@@ -521,6 +534,21 @@ class PeerTubePlugin extends Plugin {
     }, 1000)
   }
 
+  private runUserWatchVideo (options: UserWatching) {
+    let lastCurrentTime = 0
+
+    this.userWatchingVideoInterval = setInterval(() => {
+      const currentTime = Math.floor(this.player.currentTime())
+
+      if (currentTime - lastCurrentTime >= 1) {
+        lastCurrentTime = currentTime
+
+        this.notifyUserIsWatching(currentTime, options.url, options.authorizationHeader)
+          .catch(err => console.error('Cannot notify user is watching.', err))
+      }
+    }, this.CONSTANTS.USER_WATCHING_VIDEO_INTERVAL)
+  }
+
   private clearVideoViewInterval () {
     if (this.videoViewInterval !== undefined) {
       clearInterval(this.videoViewInterval)
@@ -534,6 +562,15 @@ class PeerTubePlugin extends Plugin {
     return fetch(this.videoViewUrl, { method: 'POST' })
   }
 
+  private notifyUserIsWatching (currentTime: number, url: string, authorizationHeader: string) {
+    const body = new URLSearchParams()
+    body.append('currentTime', currentTime.toString())
+
+    const headers = new Headers({ 'Authorization': authorizationHeader })
+
+    return fetch(url, { method: 'PUT', body, headers })
+  }
+
   private fallbackToHttp (done?: Function, play = true) {
     this.disableAutoResolution(true)
 
@@ -599,11 +636,16 @@ class PeerTubePlugin extends Plugin {
   }
 
   private renderFileInFakeElement (file: WebTorrent.TorrentFile, delay: number) {
+    this.destoyingFakeRenderer = false
+
     const fakeVideoElem = document.createElement('video')
     renderVideo(file, fakeVideoElem, { autoplay: false, controls: false }, (err, renderer) => {
       this.fakeRenderer = renderer
 
-      if (err) console.error('Cannot render new torrent in fake video element.', err)
+      // The renderer returns an error when we destroy it, so skip them
+      if (this.destoyingFakeRenderer === false && err) {
+        console.error('Cannot render new torrent in fake video element.', err)
+      }
 
       // Load the future file at the correct time (in delay MS - 2 seconds)
       fakeVideoElem.currentTime = this.player.currentTime() + (delay - 2000)
@@ -612,6 +654,8 @@ class PeerTubePlugin extends Plugin {
 
   private destroyFakeRenderer () {
     if (this.fakeRenderer) {
+      this.destoyingFakeRenderer = true
+
       if (this.fakeRenderer.destroy) {
         try {
           this.fakeRenderer.destroy()