From aa8b6df4a51c82eb91e6fd71a090b2128098af6b Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 6 Oct 2017 10:40:09 +0200 Subject: Client: handle multiple file resolutions --- client/src/app/videos/shared/video.model.ts | 15 ++- client/src/app/videos/video-watch/index.ts | 1 - .../videos/video-watch/video-magnet.component.html | 5 +- .../videos/video-watch/video-watch.component.ts | 121 ++++++--------------- .../app/videos/video-watch/webtorrent.service.ts | 29 ----- client/src/app/videos/videos.module.ts | 6 +- 6 files changed, 50 insertions(+), 127 deletions(-) delete mode 100644 client/src/app/videos/video-watch/webtorrent.service.ts (limited to 'client/src/app') diff --git a/client/src/app/videos/shared/video.model.ts b/client/src/app/videos/shared/video.model.ts index 17f41059d..b315e59b1 100644 --- a/client/src/app/videos/shared/video.model.ts +++ b/client/src/app/videos/shared/video.model.ts @@ -1,5 +1,6 @@ import { Video as VideoServerModel, VideoFile } from '../../../../../shared' import { User } from '../../shared' +import { VideoResolution } from '../../../../../shared/models/videos/video-resolution.enum' export class Video implements VideoServerModel { author: string @@ -116,11 +117,19 @@ export class Video implements VideoServerModel { return (this.nsfw && (!user || user.displayNSFW === false)) } - getDefaultMagnetUri () { + getAppropriateMagnetUri (actualDownloadSpeed = 0) { if (this.files === undefined || this.files.length === 0) return '' + if (this.files.length === 1) return this.files[0].magnetUri - // TODO: choose the original file - return this.files[0].magnetUri + // Find first video that is good for our download speed (remember they are sorted) + let betterResolutionFile = this.files.find(f => actualDownloadSpeed > (f.size / this.duration)) + + // If the download speed is too bad, return the lowest resolution we have + if (betterResolutionFile === undefined) { + betterResolutionFile = this.files.find(f => f.resolution === VideoResolution.H_240P) + } + + return betterResolutionFile.magnetUri } patch (values: Object) { diff --git a/client/src/app/videos/video-watch/index.ts b/client/src/app/videos/video-watch/index.ts index 6e35262d3..105872469 100644 --- a/client/src/app/videos/video-watch/index.ts +++ b/client/src/app/videos/video-watch/index.ts @@ -2,4 +2,3 @@ export * from './video-magnet.component' export * from './video-share.component' export * from './video-report.component' export * from './video-watch.component' -export * from './webtorrent.service' diff --git a/client/src/app/videos/video-watch/video-magnet.component.html b/client/src/app/videos/video-watch/video-magnet.component.html index 5b0324e37..484280c45 100644 --- a/client/src/app/videos/video-watch/video-magnet.component.html +++ b/client/src/app/videos/video-watch/video-magnet.component.html @@ -10,7 +10,10 @@ diff --git a/client/src/app/videos/video-watch/video-watch.component.ts b/client/src/app/videos/video-watch/video-watch.component.ts index f5a47199d..dbe391fff 100644 --- a/client/src/app/videos/video-watch/video-watch.component.ts +++ b/client/src/app/videos/video-watch/video-watch.component.ts @@ -4,6 +4,8 @@ import { Observable } from 'rxjs/Observable' import { Subscription } from 'rxjs/Subscription' import videojs from 'video.js' +import '../../../assets/player/peertube-videojs-plugin' + import { MetaService } from '@ngx-meta/core' import { NotificationsService } from 'angular2-notifications' @@ -13,7 +15,7 @@ import { VideoShareComponent } from './video-share.component' import { VideoReportComponent } from './video-report.component' import { Video, VideoService } from '../shared' import { WebTorrentService } from './webtorrent.service' -import { UserVideoRateType, VideoRateType, UserVideoRate } from '../../../../../shared' +import { UserVideoRateType, VideoRateType } from '../../../../../shared' @Component({ selector: 'my-video-watch', @@ -21,8 +23,6 @@ import { UserVideoRateType, VideoRateType, UserVideoRate } from '../../../../../ styleUrls: [ './video-watch.component.scss' ] }) export class VideoWatchComponent implements OnInit, OnDestroy { - private static LOADTIME_TOO_LONG = 20000 - @ViewChild('videoMagnetModal') videoMagnetModal: VideoMagnetComponent @ViewChild('videoShareModal') videoShareModal: VideoShareComponent @ViewChild('videoReportModal') videoReportModal: VideoReportComponent @@ -38,20 +38,15 @@ export class VideoWatchComponent implements OnInit, OnDestroy { video: Video = null videoNotFound = false - private errorTimer: number private paramsSub: Subscription - private errorsSub: Subscription - private torrentInfosInterval: number constructor ( private elementRef: ElementRef, - private ngZone: NgZone, private route: ActivatedRoute, private router: Router, private videoService: VideoService, private confirmService: ConfirmService, private metaService: MetaService, - private webTorrentService: WebTorrentService, private authService: AuthService, private notificationsService: NotificationsService ) {} @@ -68,81 +63,17 @@ export class VideoWatchComponent implements OnInit, OnDestroy { } ) }) - - this.playerElement = this.elementRef.nativeElement.querySelector('#video-container') - - const videojsOptions = { - controls: true, - autoplay: true - } - - const self = this - videojs(this.playerElement, videojsOptions, function () { - self.player = this - }) - - this.errorsSub = this.webTorrentService.errors.subscribe(err => this.handleError(err)) } ngOnDestroy () { // Remove WebTorrent stuff console.log('Removing video from webtorrent.') - window.clearInterval(this.torrentInfosInterval) - window.clearTimeout(this.errorTimer) - - if (this.video !== null && this.webTorrentService.has(this.video.getDefaultMagnetUri())) { - this.webTorrentService.remove(this.video.getDefaultMagnetUri()) - } // Remove player videojs(this.playerElement).dispose() // Unsubscribe subscriptions this.paramsSub.unsubscribe() - this.errorsSub.unsubscribe() - } - - loadVideo () { - // Reset the error - this.error = false - // We are loading the video - this.loading = true - - console.log('Adding ' + this.video.getDefaultMagnetUri() + '.') - - // The callback might never return if there are network issues - // So we create a timer to inform the user the load is abnormally long - this.errorTimer = window.setTimeout(() => this.loadTooLong(), VideoWatchComponent.LOADTIME_TOO_LONG) - - const torrent = this.webTorrentService.add(this.video.getDefaultMagnetUri(), torrent => { - // Clear the error timer - window.clearTimeout(this.errorTimer) - // Maybe the error was fired by the timer, so reset it - this.error = false - - // We are not loading the video anymore - this.loading = false - - console.log('Added ' + this.video.getDefaultMagnetUri() + '.') - torrent.files[0].renderTo(this.playerElement, (err) => { - if (err) { - this.notificationsService.error('Error', 'Cannot append the file in the video element.') - console.error(err) - } - - // Hack to "simulate" src link in video.js >= 6 - // If no, we can't play the video after pausing it - // https://github.com/videojs/video.js/blob/master/src/js/player.js#L1633 - (this.player as any).src = () => true - - this.player.play() - }) - - this.runInProgress(torrent) - }) - - torrent.on('error', err => this.handleError(err)) - torrent.on('warning', err => this.handleError(err)) } setLike () { @@ -295,8 +226,36 @@ export class VideoWatchComponent implements OnInit, OnDestroy { return this.router.navigate([ '/videos/list' ]) } + this.playerElement = this.elementRef.nativeElement.querySelector('#video-container') + + const videojsOptions = { + controls: true, + autoplay: true, + plugins: { + peertube: { + videoFiles: this.video.files, + playerElement: this.playerElement, + autoplay: true, + peerTubeLink: false + } + } + } + + const self = this + videojs(this.playerElement, videojsOptions, function () { + self.player = this + this.on('customError', (event, data) => { + self.handleError(data.err) + }) + + this.on('torrentInfo', (event, data) => { + self.downloadSpeed = data.downloadSpeed + self.numPeers = data.numPeers + self.uploadSpeed = data.uploadSpeed + }) + }) + this.setOpenGraphTags() - this.loadVideo() this.checkUserRating() } ) @@ -318,11 +277,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { this.video.dislikes += dislikesToIncrement } - private loadTooLong () { - this.error = true - console.error('The video load seems to be abnormally long.') - } - private setOpenGraphTags () { this.metaService.setTitle(this.video.name) @@ -343,15 +297,4 @@ export class VideoWatchComponent implements OnInit, OnDestroy { this.metaService.setTag('og:url', window.location.href) this.metaService.setTag('url', window.location.href) } - - private runInProgress (torrent: any) { - // Refresh each second - this.torrentInfosInterval = window.setInterval(() => { - this.ngZone.run(() => { - this.downloadSpeed = torrent.downloadSpeed - this.numPeers = torrent.numPeers - this.uploadSpeed = torrent.uploadSpeed - }) - }, 1000) - } } diff --git a/client/src/app/videos/video-watch/webtorrent.service.ts b/client/src/app/videos/video-watch/webtorrent.service.ts deleted file mode 100644 index 8819e17d4..000000000 --- a/client/src/app/videos/video-watch/webtorrent.service.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Injectable } from '@angular/core' -import { Subject } from 'rxjs/Subject' - -import * as WebTorrent from 'webtorrent' - -@Injectable() -export class WebTorrentService { - errors = new Subject() - - private client: WebTorrent.Instance - - constructor () { - this.client = new WebTorrent({ dht: false }) - - this.client.on('error', err => this.errors.next(err)) - } - - add (magnetUri: string, callback: (torrent: WebTorrent.Torrent) => any) { - return this.client.add(magnetUri, callback) - } - - remove (magnetUri: string) { - return this.client.remove(magnetUri) - } - - has (magnetUri: string) { - return this.client.get(magnetUri) !== null - } -} diff --git a/client/src/app/videos/videos.module.ts b/client/src/app/videos/videos.module.ts index 7d2451de7..bc86118cc 100644 --- a/client/src/app/videos/videos.module.ts +++ b/client/src/app/videos/videos.module.ts @@ -10,8 +10,7 @@ import { VideoWatchComponent, VideoMagnetComponent, VideoReportComponent, - VideoShareComponent, - WebTorrentService + VideoShareComponent } from './video-watch' import { VideoService } from './shared' import { SharedModule } from '../shared' @@ -47,8 +46,7 @@ import { SharedModule } from '../shared' ], providers: [ - VideoService, - WebTorrentService + VideoService ] }) export class VideosModule { } -- cgit v1.2.3