]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - client/src/assets/player/peertube-videojs-plugin.ts
Fix ios player playback/subtitles menu
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / peertube-videojs-plugin.ts
index 4b0677faba6dc43f9a85e8e22277371bf919c7a5..36b80bd72b543b636cd54f99931552e8cf13de02 100644 (file)
@@ -4,7 +4,7 @@ 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 { isMobile, videoFileMaxByResolution, videoFileMinByResolution, timeToInt } from './utils'
+import { isMobile, timeToInt, videoFileMaxByResolution, videoFileMinByResolution } from './utils'
 import * as CacheChunkStore from 'cache-chunk-store'
 import { PeertubeChunkStore } from './peertube-chunk-store'
 import {
@@ -83,11 +83,6 @@ class PeerTubePlugin extends Plugin {
     this.videoCaptions = options.videoCaptions
 
     this.savePlayerSrcFunction = this.player.src
-    // Hack to "simulate" src link in video.js >= 6
-    // Without this, we can't play the video after pausing it
-    // https://github.com/videojs/video.js/blob/master/src/js/player.js#L1633
-    this.player.src = () => true
-
     this.playerElement = options.playerElement
 
     if (this.autoplay === true) this.player.addClass('vjs-has-autoplay')
@@ -104,9 +99,7 @@ class PeerTubePlugin extends Plugin {
 
       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)
+        this.runAutoQualitySchedulerTimer = setTimeout(() => this.runAutoQualityScheduler(), this.CONSTANTS.AUTO_QUALITY_SCHEDULER)
       })
     })
 
@@ -167,6 +160,9 @@ class PeerTubePlugin extends Plugin {
     // Do not display error to user because we will have multiple fallback
     this.disableErrorDisplay()
 
+    // Hack to "simulate" src link in video.js >= 6
+    // Without this, we can't play the video after pausing it
+    // https://github.com/videojs/video.js/blob/master/src/js/player.js#L1633
     this.player.src = () => true
     const oldPlaybackRate = this.player.playbackRate()
 
@@ -181,7 +177,66 @@ class PeerTubePlugin extends Plugin {
     this.trigger('videoFileUpdate')
   }
 
-  addTorrent (
+  updateResolution (resolutionId: number, delay = 0) {
+    // Remember player state
+    const currentTime = this.player.currentTime()
+    const isPaused = this.player.paused()
+
+    // Remove poster to have black background
+    this.playerElement.poster = ''
+
+    // Hide bigPlayButton
+    if (!isPaused) {
+      this.player.bigPlayButton.hide()
+    }
+
+    const newVideoFile = this.videoFiles.find(f => f.resolution.id === resolutionId)
+    const options = {
+      forcePlay: false,
+      delay,
+      seek: currentTime + (delay / 1000)
+    }
+    this.updateVideoFile(newVideoFile, options)
+  }
+
+  flushVideoFile (videoFile: VideoFile, destroyRenderer = true) {
+    if (videoFile !== undefined && this.webtorrent.get(videoFile.magnetUri)) {
+      if (destroyRenderer === true && this.renderer && this.renderer.destroy) this.renderer.destroy()
+
+      this.webtorrent.remove(videoFile.magnetUri)
+      console.log('Removed ' + videoFile.magnetUri)
+    }
+  }
+
+  isAutoResolutionOn () {
+    return this.autoResolution
+  }
+
+  enableAutoResolution () {
+    this.autoResolution = true
+    this.trigger('autoResolutionUpdate')
+  }
+
+  disableAutoResolution (forbid = false) {
+    if (forbid === true) this.forbidAutoResolution = true
+
+    this.autoResolution = false
+    this.trigger('autoResolutionUpdate')
+  }
+
+  isAutoResolutionForbidden () {
+    return this.forbidAutoResolution === true
+  }
+
+  getCurrentVideoFile () {
+    return this.currentVideoFile
+  }
+
+  getTorrent () {
+    return this.torrent
+  }
+
+  private addTorrent (
     magnetOrTorrentUrl: string,
     previousVideoFile: VideoFile,
     options: {
@@ -205,26 +260,15 @@ class PeerTubePlugin extends Plugin {
 
       if (oldTorrent) {
         // Pause the old torrent
-        oldTorrent.pause()
-        // Pause does not remove actual peers (in particular the webseed peer)
-        oldTorrent.removePeer(oldTorrent['ws'])
+        this.stopTorrent(oldTorrent)
 
         // 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)
-          })
-        }
+        if (options.delay) this.renderFileInFakeElement(torrent.files[ 0 ], options.delay)
       }
 
       // Render the video in a few seconds? (on resolution change for example, we wait some seconds of the new video resolution)
       this.addTorrentDelay = setTimeout(() => {
+        // We don't need the fake renderer anymore
         this.destroyFakeRenderer()
 
         const paused = this.player.paused()
@@ -232,7 +276,7 @@ class PeerTubePlugin extends Plugin {
         this.flushVideoFile(previousVideoFile)
 
         const renderVideoOptions = { autoplay: false, controls: true }
-        renderVideo(torrent.files[0], this.playerElement, renderVideoOptions,(err, renderer) => {
+        renderVideo(torrent.files[ 0 ], this.playerElement, renderVideoOptions, (err, renderer) => {
           this.renderer = renderer
 
           if (err) return this.fallbackToHttp(done)
@@ -265,7 +309,7 @@ class PeerTubePlugin extends Plugin {
       if (err.message.indexOf('incorrect info hash') !== -1) {
         console.error('Incorrect info hash detected, falling back to torrent file.')
         const newOptions = { forcePlay: true, seek: options.seek }
-        return this.addTorrent(this.torrent['xs'], previousVideoFile, newOptions, done)
+        return this.addTorrent(this.torrent[ 'xs' ], previousVideoFile, newOptions, done)
       }
 
       // Remote instance is down
@@ -277,65 +321,6 @@ class PeerTubePlugin extends Plugin {
     })
   }
 
-  updateResolution (resolutionId: number, delay = 0) {
-    // Remember player state
-    const currentTime = this.player.currentTime()
-    const isPaused = this.player.paused()
-
-    // Remove poster to have black background
-    this.playerElement.poster = ''
-
-    // Hide bigPlayButton
-    if (!isPaused) {
-      this.player.bigPlayButton.hide()
-    }
-
-    const newVideoFile = this.videoFiles.find(f => f.resolution.id === resolutionId)
-    const options = {
-      forcePlay: false,
-      delay,
-      seek: currentTime + (delay / 1000)
-    }
-    this.updateVideoFile(newVideoFile, options)
-  }
-
-  flushVideoFile (videoFile: VideoFile, destroyRenderer = true) {
-    if (videoFile !== undefined && this.webtorrent.get(videoFile.magnetUri)) {
-      if (destroyRenderer === true && this.renderer && this.renderer.destroy) this.renderer.destroy()
-
-      this.webtorrent.remove(videoFile.magnetUri)
-      console.log('Removed ' + videoFile.magnetUri)
-    }
-  }
-
-  isAutoResolutionOn () {
-    return this.autoResolution
-  }
-
-  enableAutoResolution () {
-    this.autoResolution = true
-    this.trigger('autoResolutionUpdate')
-  }
-
-  disableAutoResolution (forbid = false) {
-    if (forbid === true) this.forbidAutoResolution = true
-
-    this.autoResolution = false
-    this.trigger('autoResolutionUpdate')
-  }
-
-  isAutoResolutionForbidden () {
-    return this.forbidAutoResolution === true
-  }
-
-  getCurrentVideoFile () {
-    return this.currentVideoFile
-  }
-
-  getTorrent () {
-    return this.torrent
-  }
-
   private tryToPlay (done?: Function) {
     if (!done) done = function () { /* empty */ }
 
@@ -435,22 +420,22 @@ class PeerTubePlugin extends Plugin {
     if (this.autoplay === true) {
       this.player.posterImage.hide()
 
-      this.updateVideoFile(undefined, { forcePlay: true, seek: this.startTime })
-    } else {
-      // Don't try on iOS that does not support MediaSource
-      if (this.isIOS()) {
-        this.currentVideoFile = this.pickAverageVideoFile()
-        return this.fallbackToHttp(undefined, false)
-      }
+      return this.updateVideoFile(undefined, { forcePlay: true, seek: this.startTime })
+    }
 
-      // Proxy first play
-      const oldPlay = this.player.play.bind(this.player)
-      this.player.play = () => {
-        this.player.addClass('vjs-has-big-play-button-clicked')
-        this.player.play = oldPlay
+    // Don't try on iOS that does not support MediaSource
+    if (this.isIOS()) {
+      this.currentVideoFile = this.pickAverageVideoFile()
+      return this.fallbackToHttp(undefined, false)
+    }
 
-        this.updateVideoFile(undefined, { forcePlay: true, seek: this.startTime })
-      }
+    // Proxy first play
+    const oldPlay = this.player.play.bind(this.player)
+    this.player.play = () => {
+      this.player.addClass('vjs-has-big-play-button-clicked')
+      this.player.play = oldPlay
+
+      this.updateVideoFile(undefined, { forcePlay: true, seek: this.startTime })
     }
   }
 
@@ -607,6 +592,24 @@ class PeerTubePlugin extends Plugin {
     return this.videoFiles[Math.floor(this.videoFiles.length / 2)]
   }
 
+  private stopTorrent (torrent: WebTorrent.Torrent) {
+    torrent.pause()
+    // Pause does not remove actual peers (in particular the webseed peer)
+    torrent.removePeer(torrent[ 'ws' ])
+  }
+
+  private renderFileInFakeElement (file: WebTorrent.TorrentFile, delay: number) {
+    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)
+
+      // Load the future file at the correct time (in delay MS - 2 seconds)
+      fakeVideoElem.currentTime = this.player.currentTime() + (delay - 2000)
+    })
+  }
+
   private destroyFakeRenderer () {
     if (this.fakeRenderer) {
       if (this.fakeRenderer.destroy) {