aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/assets/player/peertube-videojs-plugin.ts
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/assets/player/peertube-videojs-plugin.ts')
-rw-r--r--client/src/assets/player/peertube-videojs-plugin.ts109
1 files changed, 80 insertions, 29 deletions
diff --git a/client/src/assets/player/peertube-videojs-plugin.ts b/client/src/assets/player/peertube-videojs-plugin.ts
index 01a630cb6..618d77cbe 100644
--- a/client/src/assets/player/peertube-videojs-plugin.ts
+++ b/client/src/assets/player/peertube-videojs-plugin.ts
@@ -1,6 +1,5 @@
1// Big thanks to: https://github.com/kmoskwiak/videojs-resolution-switcher 1// Big thanks to: https://github.com/kmoskwiak/videojs-resolution-switcher
2 2
3import { VideoService } from '@app/shared/video/video.service'
4import * as videojs from 'video.js' 3import * as videojs from 'video.js'
5import * as WebTorrent from 'webtorrent' 4import * as WebTorrent from 'webtorrent'
6import { VideoFile } from '../../../../shared/models/videos/video.model' 5import { VideoFile } from '../../../../shared/models/videos/video.model'
@@ -147,12 +146,12 @@ Button.registerComponent('PeerTubeLinkButton', PeertubeLinkButton)
147class WebTorrentButton extends Button { 146class WebTorrentButton extends Button {
148 createEl () { 147 createEl () {
149 const div = document.createElement('div') 148 const div = document.createElement('div')
150 const subDiv = document.createElement('div') 149 const subDivWebtorrent = document.createElement('div')
151 div.appendChild(subDiv) 150 div.appendChild(subDivWebtorrent)
152 151
153 const downloadIcon = document.createElement('span') 152 const downloadIcon = document.createElement('span')
154 downloadIcon.classList.add('icon', 'icon-download') 153 downloadIcon.classList.add('icon', 'icon-download')
155 subDiv.appendChild(downloadIcon) 154 subDivWebtorrent.appendChild(downloadIcon)
156 155
157 const downloadSpeedText = document.createElement('span') 156 const downloadSpeedText = document.createElement('span')
158 downloadSpeedText.classList.add('download-speed-text') 157 downloadSpeedText.classList.add('download-speed-text')
@@ -161,11 +160,11 @@ class WebTorrentButton extends Button {
161 const downloadSpeedUnit = document.createElement('span') 160 const downloadSpeedUnit = document.createElement('span')
162 downloadSpeedText.appendChild(downloadSpeedNumber) 161 downloadSpeedText.appendChild(downloadSpeedNumber)
163 downloadSpeedText.appendChild(downloadSpeedUnit) 162 downloadSpeedText.appendChild(downloadSpeedUnit)
164 subDiv.appendChild(downloadSpeedText) 163 subDivWebtorrent.appendChild(downloadSpeedText)
165 164
166 const uploadIcon = document.createElement('span') 165 const uploadIcon = document.createElement('span')
167 uploadIcon.classList.add('icon', 'icon-upload') 166 uploadIcon.classList.add('icon', 'icon-upload')
168 subDiv.appendChild(uploadIcon) 167 subDivWebtorrent.appendChild(uploadIcon)
169 168
170 const uploadSpeedText = document.createElement('span') 169 const uploadSpeedText = document.createElement('span')
171 uploadSpeedText.classList.add('upload-speed-text') 170 uploadSpeedText.classList.add('upload-speed-text')
@@ -174,34 +173,56 @@ class WebTorrentButton extends Button {
174 const uploadSpeedUnit = document.createElement('span') 173 const uploadSpeedUnit = document.createElement('span')
175 uploadSpeedText.appendChild(uploadSpeedNumber) 174 uploadSpeedText.appendChild(uploadSpeedNumber)
176 uploadSpeedText.appendChild(uploadSpeedUnit) 175 uploadSpeedText.appendChild(uploadSpeedUnit)
177 subDiv.appendChild(uploadSpeedText) 176 subDivWebtorrent.appendChild(uploadSpeedText)
178 177
179 const peersText = document.createElement('span') 178 const peersText = document.createElement('span')
180 peersText.textContent = ' peers'
181 peersText.classList.add('peers-text') 179 peersText.classList.add('peers-text')
182 const peersNumber = document.createElement('span') 180 const peersNumber = document.createElement('span')
183 peersNumber.classList.add('peers-number') 181 peersNumber.classList.add('peers-number')
184 subDiv.appendChild(peersNumber) 182 subDivWebtorrent.appendChild(peersNumber)
185 subDiv.appendChild(peersText) 183 subDivWebtorrent.appendChild(peersText)
186 184
187 div.className = 'vjs-webtorrent' 185 div.className = 'vjs-peertube'
188 // Hide the stats before we get the info 186 // Hide the stats before we get the info
189 subDiv.className = 'vjs-webtorrent-hidden' 187 subDivWebtorrent.className = 'vjs-peertube-hidden'
188
189 const subDivHttp = document.createElement('div')
190 subDivHttp.className = 'vjs-peertube-hidden'
191 const subDivHttpText = document.createElement('span')
192 subDivHttpText.classList.add('peers-number')
193 subDivHttpText.textContent = 'HTTP'
194 const subDivFallbackText = document.createElement('span')
195 subDivFallbackText.classList.add('peers-text')
196 subDivFallbackText.textContent = ' fallback'
197
198 subDivHttp.appendChild(subDivHttpText)
199 subDivHttp.appendChild(subDivFallbackText)
200 div.appendChild(subDivHttp)
190 201
191 this.player_.peertube().on('torrentInfo', (event, data) => { 202 this.player_.peertube().on('torrentInfo', (event, data) => {
203 // We are in HTTP fallback
204 if (!data) {
205 subDivHttp.className = 'vjs-peertube-displayed'
206 subDivWebtorrent.className = 'vjs-peertube-hidden'
207
208 return
209 }
210
192 const downloadSpeed = bytes(data.downloadSpeed) 211 const downloadSpeed = bytes(data.downloadSpeed)
193 const uploadSpeed = bytes(data.uploadSpeed) 212 const uploadSpeed = bytes(data.uploadSpeed)
194 const numPeers = data.numPeers 213 const numPeers = data.numPeers
195 214
196 downloadSpeedNumber.textContent = downloadSpeed[0] 215 downloadSpeedNumber.textContent = downloadSpeed[ 0 ]
197 downloadSpeedUnit.textContent = ' ' + downloadSpeed[1] 216 downloadSpeedUnit.textContent = ' ' + downloadSpeed[ 1 ]
198 217
199 uploadSpeedNumber.textContent = uploadSpeed[0] 218 uploadSpeedNumber.textContent = uploadSpeed[ 0 ]
200 uploadSpeedUnit.textContent = ' ' + uploadSpeed[1] 219 uploadSpeedUnit.textContent = ' ' + uploadSpeed[ 1 ]
201 220
202 peersNumber.textContent = numPeers 221 peersNumber.textContent = numPeers
222 peersText.textContent = ' peers'
203 223
204 subDiv.className = 'vjs-webtorrent-displayed' 224 subDivHttp.className = 'vjs-peertube-hidden'
225 subDivWebtorrent.className = 'vjs-peertube-displayed'
205 }) 226 })
206 227
207 return div 228 return div
@@ -225,6 +246,7 @@ class PeerTubePlugin extends Plugin {
225 private videoDuration: number 246 private videoDuration: number
226 private videoViewInterval 247 private videoViewInterval
227 private torrentInfoInterval 248 private torrentInfoInterval
249 private savePlayerSrcFunction: Function
228 250
229 constructor (player: videojs.Player, options: PeertubePluginOptions) { 251 constructor (player: videojs.Player, options: PeertubePluginOptions) {
230 super(player, options) 252 super(player, options)
@@ -237,12 +259,11 @@ class PeerTubePlugin extends Plugin {
237 this.videoViewUrl = options.videoViewUrl 259 this.videoViewUrl = options.videoViewUrl
238 this.videoDuration = options.videoDuration 260 this.videoDuration = options.videoDuration
239 261
262 this.savePlayerSrcFunction = this.player.src
240 // Hack to "simulate" src link in video.js >= 6 263 // Hack to "simulate" src link in video.js >= 6
241 // Without this, we can't play the video after pausing it 264 // Without this, we can't play the video after pausing it
242 // https://github.com/videojs/video.js/blob/master/src/js/player.js#L1633 265 // https://github.com/videojs/video.js/blob/master/src/js/player.js#L1633
243 this.player.src = function () { 266 this.player.src = () => true
244 return true
245 }
246 267
247 this.playerElement = options.playerElement 268 this.playerElement = options.playerElement
248 269
@@ -284,6 +305,10 @@ class PeerTubePlugin extends Plugin {
284 return 305 return
285 } 306 }
286 307
308 // Do not display error to user because we will have multiple fallbacks
309 this.disableErrorDisplay()
310 this.player.src = () => true
311
287 const previousVideoFile = this.currentVideoFile 312 const previousVideoFile = this.currentVideoFile
288 this.currentVideoFile = videoFile 313 this.currentVideoFile = videoFile
289 314
@@ -295,7 +320,7 @@ class PeerTubePlugin extends Plugin {
295 320
296 const options = { autoplay: true, controls: true } 321 const options = { autoplay: true, controls: true }
297 renderVideo(torrent.files[0], this.playerElement, options,(err, renderer) => { 322 renderVideo(torrent.files[0], this.playerElement, options,(err, renderer) => {
298 if (err) return this.handleError(err) 323 if (err) return this.fallbackToHttp()
299 324
300 this.renderer = renderer 325 this.renderer = renderer
301 if (!this.player.paused()) { 326 if (!this.player.paused()) {
@@ -347,7 +372,8 @@ class PeerTubePlugin extends Plugin {
347 372
348 flushVideoFile (videoFile: VideoFile, destroyRenderer = true) { 373 flushVideoFile (videoFile: VideoFile, destroyRenderer = true) {
349 if (videoFile !== undefined && webtorrent.get(videoFile.magnetUri)) { 374 if (videoFile !== undefined && webtorrent.get(videoFile.magnetUri)) {
350 if (destroyRenderer === true) this.renderer.destroy() 375 if (destroyRenderer === true && this.renderer && this.renderer.destroy) this.renderer.destroy()
376
351 webtorrent.remove(videoFile.magnetUri) 377 webtorrent.remove(videoFile.magnetUri)
352 console.log('Removed ' + videoFile.magnetUri) 378 console.log('Removed ' + videoFile.magnetUri)
353 } 379 }
@@ -390,13 +416,17 @@ class PeerTubePlugin extends Plugin {
390 416
391 private runTorrentInfoScheduler () { 417 private runTorrentInfoScheduler () {
392 this.torrentInfoInterval = setInterval(() => { 418 this.torrentInfoInterval = setInterval(() => {
393 if (this.torrent !== undefined) { 419 // Not initialized yet
394 this.trigger('torrentInfo', { 420 if (this.torrent === undefined) return
395 downloadSpeed: this.torrent.downloadSpeed, 421
396 numPeers: this.torrent.numPeers, 422 // Http fallback
397 uploadSpeed: this.torrent.uploadSpeed 423 if (this.torrent === null) return this.trigger('torrentInfo', false)
398 }) 424
399 } 425 return this.trigger('torrentInfo', {
426 downloadSpeed: this.torrent.downloadSpeed,
427 numPeers: this.torrent.numPeers,
428 uploadSpeed: this.torrent.uploadSpeed
429 })
400 }, 1000) 430 }, 1000)
401 } 431 }
402 432
@@ -433,8 +463,29 @@ class PeerTubePlugin extends Plugin {
433 return fetch(this.videoViewUrl, { method: 'POST' }) 463 return fetch(this.videoViewUrl, { method: 'POST' })
434 } 464 }
435 465
466 private fallbackToHttp () {
467 this.flushVideoFile(this.currentVideoFile, true)
468 this.torrent = null
469
470 // Enable error display now this is our last fallback
471 this.player.one('error', () => this.enableErrorDisplay())
472
473 const httpUrl = this.currentVideoFile.fileUrl
474 this.player.src = this.savePlayerSrcFunction
475 this.player.src(httpUrl)
476 this.player.play()
477 }
478
436 private handleError (err: Error | string) { 479 private handleError (err: Error | string) {
437 return this.player.trigger('customError', { err }) 480 return this.player.trigger('customError', { err })
438 } 481 }
482
483 private enableErrorDisplay () {
484 this.player.addClass('vjs-error-display-enabled')
485 }
486
487 private disableErrorDisplay () {
488 this.player.removeClass('vjs-error-display-enabled')
489 }
439} 490}
440videojsUntyped.registerPlugin('peertube', PeerTubePlugin) 491videojsUntyped.registerPlugin('peertube', PeerTubePlugin)