diff options
Diffstat (limited to 'client/src/assets/player/peertube-player-manager.ts')
-rw-r--r-- | client/src/assets/player/peertube-player-manager.ts | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/client/src/assets/player/peertube-player-manager.ts b/client/src/assets/player/peertube-player-manager.ts index d9e02cd7d..4e6387a53 100644 --- a/client/src/assets/player/peertube-player-manager.ts +++ b/client/src/assets/player/peertube-player-manager.ts | |||
@@ -1,21 +1,26 @@ | |||
1 | import { VideoFile } from '../../../../shared/models/videos' | 1 | import { VideoFile } from '../../../../shared/models/videos' |
2 | // @ts-ignore | 2 | import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js' |
3 | import * as videojs from 'video.js' | ||
4 | import 'videojs-hotkeys' | 3 | import 'videojs-hotkeys' |
5 | import 'videojs-dock' | 4 | import 'videojs-dock' |
6 | import 'videojs-contextmenu-ui' | 5 | import 'videojs-contextmenu-ui' |
7 | import 'videojs-contrib-quality-levels' | 6 | import 'videojs-contrib-quality-levels' |
7 | import './upnext/end-card' | ||
8 | import './upnext/upnext-plugin' | 8 | import './upnext/upnext-plugin' |
9 | import './bezels/bezels-plugin' | 9 | import './bezels/bezels-plugin' |
10 | import './peertube-plugin' | 10 | import './peertube-plugin' |
11 | import './videojs-components/next-video-button' | 11 | import './videojs-components/next-video-button' |
12 | import './videojs-components/p2p-info-button' | ||
12 | import './videojs-components/peertube-link-button' | 13 | import './videojs-components/peertube-link-button' |
14 | import './videojs-components/peertube-load-progress-bar' | ||
13 | import './videojs-components/resolution-menu-button' | 15 | import './videojs-components/resolution-menu-button' |
16 | import './videojs-components/resolution-menu-item' | ||
17 | import './videojs-components/settings-dialog' | ||
14 | import './videojs-components/settings-menu-button' | 18 | import './videojs-components/settings-menu-button' |
15 | import './videojs-components/p2p-info-button' | 19 | import './videojs-components/settings-menu-item' |
16 | import './videojs-components/peertube-load-progress-bar' | 20 | import './videojs-components/settings-panel' |
21 | import './videojs-components/settings-panel-child' | ||
17 | import './videojs-components/theater-button' | 22 | import './videojs-components/theater-button' |
18 | import { P2PMediaLoaderPluginOptions, UserWatching, VideoJSCaption, VideoJSPluginOptions, videojsUntyped } from './peertube-videojs-typings' | 23 | import { P2PMediaLoaderPluginOptions, UserWatching, VideoJSCaption, VideoJSPluginOptions } from './peertube-videojs-typings' |
19 | import { buildVideoEmbed, buildVideoLink, copyToClipboard, getRtcConfig } from './utils' | 24 | import { buildVideoEmbed, buildVideoLink, copyToClipboard, getRtcConfig } from './utils' |
20 | import { isDefaultLocale } from '../../../../shared/models/i18n/i18n' | 25 | import { isDefaultLocale } from '../../../../shared/models/i18n/i18n' |
21 | import { segmentValidatorFactory } from './p2p-media-loader/segment-validator' | 26 | import { segmentValidatorFactory } from './p2p-media-loader/segment-validator' |
@@ -24,12 +29,17 @@ import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager' | |||
24 | import { getStoredP2PEnabled } from './peertube-player-local-storage' | 29 | import { getStoredP2PEnabled } from './peertube-player-local-storage' |
25 | import { TranslationsManager } from './translations-manager' | 30 | import { TranslationsManager } from './translations-manager' |
26 | 31 | ||
32 | // For VideoJS | ||
33 | (window as any).WebVTT = require('vtt.js/lib/vtt.js').WebVTT; | ||
34 | |||
27 | // Change 'Playback Rate' to 'Speed' (smaller for our settings menu) | 35 | // Change 'Playback Rate' to 'Speed' (smaller for our settings menu) |
28 | videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed' | 36 | (videojs.getComponent('PlaybackRateMenuButton') as any).prototype.controlText_ = 'Speed' |
37 | |||
38 | const CaptionsButton = videojs.getComponent('CaptionsButton') as any | ||
29 | // Change Captions to Subtitles/CC | 39 | // Change Captions to Subtitles/CC |
30 | videojsUntyped.getComponent('CaptionsButton').prototype.controlText_ = 'Subtitles/CC' | 40 | CaptionsButton.prototype.controlText_ = 'Subtitles/CC' |
31 | // We just want to display 'Off' instead of 'captions off', keep a space so the variable == true (hacky I know) | 41 | // We just want to display 'Off' instead of 'captions off', keep a space so the variable == true (hacky I know) |
32 | videojsUntyped.getComponent('CaptionsButton').prototype.label_ = ' ' | 42 | CaptionsButton.prototype.label_ = ' ' |
33 | 43 | ||
34 | export type PlayerMode = 'webtorrent' | 'p2p-media-loader' | 44 | export type PlayerMode = 'webtorrent' | 'p2p-media-loader' |
35 | 45 | ||
@@ -92,9 +102,9 @@ export type PeertubePlayerManagerOptions = { | |||
92 | 102 | ||
93 | export class PeertubePlayerManager { | 103 | export class PeertubePlayerManager { |
94 | private static playerElementClassName: string | 104 | private static playerElementClassName: string |
95 | private static onPlayerChange: (player: any) => void | 105 | private static onPlayerChange: (player: VideoJsPlayer) => void |
96 | 106 | ||
97 | static async initialize (mode: PlayerMode, options: PeertubePlayerManagerOptions, onPlayerChange: (player: any) => void) { | 107 | static async initialize (mode: PlayerMode, options: PeertubePlayerManagerOptions, onPlayerChange: (player: VideoJsPlayer) => void) { |
98 | let p2pMediaLoader: any | 108 | let p2pMediaLoader: any |
99 | 109 | ||
100 | this.onPlayerChange = onPlayerChange | 110 | this.onPlayerChange = onPlayerChange |
@@ -114,12 +124,12 @@ export class PeertubePlayerManager { | |||
114 | 124 | ||
115 | const self = this | 125 | const self = this |
116 | return new Promise(res => { | 126 | return new Promise(res => { |
117 | videojs(options.common.playerElement, videojsOptions, function (this: any) { | 127 | videojs(options.common.playerElement, videojsOptions, function (this: VideoJsPlayer) { |
118 | const player = this | 128 | const player = this |
119 | 129 | ||
120 | let alreadyFallback = false | 130 | let alreadyFallback = false |
121 | 131 | ||
122 | player.tech_.one('error', () => { | 132 | player.tech(true).one('error', () => { |
123 | if (!alreadyFallback) self.maybeFallbackToWebTorrent(mode, player, options) | 133 | if (!alreadyFallback) self.maybeFallbackToWebTorrent(mode, player, options) |
124 | alreadyFallback = true | 134 | alreadyFallback = true |
125 | }) | 135 | }) |
@@ -164,7 +174,7 @@ export class PeertubePlayerManager { | |||
164 | const videojsOptions = this.getVideojsOptions(mode, options) | 174 | const videojsOptions = this.getVideojsOptions(mode, options) |
165 | 175 | ||
166 | const self = this | 176 | const self = this |
167 | videojs(newVideoElement, videojsOptions, function (this: any) { | 177 | videojs(newVideoElement, videojsOptions, function (this: VideoJsPlayer) { |
168 | const player = this | 178 | const player = this |
169 | 179 | ||
170 | self.addContextMenu(mode, player, options.common.embedUrl) | 180 | self.addContextMenu(mode, player, options.common.embedUrl) |
@@ -173,7 +183,11 @@ export class PeertubePlayerManager { | |||
173 | }) | 183 | }) |
174 | } | 184 | } |
175 | 185 | ||
176 | private static getVideojsOptions (mode: PlayerMode, options: PeertubePlayerManagerOptions, p2pMediaLoaderModule?: any) { | 186 | private static getVideojsOptions ( |
187 | mode: PlayerMode, | ||
188 | options: PeertubePlayerManagerOptions, | ||
189 | p2pMediaLoaderModule?: any | ||
190 | ): VideoJsPlayerOptions { | ||
177 | const commonOptions = options.common | 191 | const commonOptions = options.common |
178 | 192 | ||
179 | let autoplay = commonOptions.autoplay | 193 | let autoplay = commonOptions.autoplay |
@@ -213,7 +227,7 @@ export class PeertubePlayerManager { | |||
213 | html5, | 227 | html5, |
214 | 228 | ||
215 | // We don't use text track settings for now | 229 | // We don't use text track settings for now |
216 | textTrackSettings: false, | 230 | textTrackSettings: false as any, // FIXME: typings |
217 | controls: commonOptions.controls !== undefined ? commonOptions.controls : true, | 231 | controls: commonOptions.controls !== undefined ? commonOptions.controls : true, |
218 | loop: commonOptions.loop !== undefined ? commonOptions.loop : false, | 232 | loop: commonOptions.loop !== undefined ? commonOptions.loop : false, |
219 | 233 | ||
@@ -237,7 +251,7 @@ export class PeertubePlayerManager { | |||
237 | peertubeLink: commonOptions.peertubeLink, | 251 | peertubeLink: commonOptions.peertubeLink, |
238 | theaterButton: commonOptions.theaterButton, | 252 | theaterButton: commonOptions.theaterButton, |
239 | nextVideo: commonOptions.nextVideo | 253 | nextVideo: commonOptions.nextVideo |
240 | }) | 254 | }) as any // FIXME: typings |
241 | } | 255 | } |
242 | } | 256 | } |
243 | 257 | ||
@@ -406,7 +420,7 @@ export class PeertubePlayerManager { | |||
406 | return children | 420 | return children |
407 | } | 421 | } |
408 | 422 | ||
409 | private static addContextMenu (mode: PlayerMode, player: any, videoEmbedUrl: string) { | 423 | private static addContextMenu (mode: PlayerMode, player: VideoJsPlayer, videoEmbedUrl: string) { |
410 | const content = [ | 424 | const content = [ |
411 | { | 425 | { |
412 | label: player.localize('Copy the video URL'), | 426 | label: player.localize('Copy the video URL'), |
@@ -416,9 +430,8 @@ export class PeertubePlayerManager { | |||
416 | }, | 430 | }, |
417 | { | 431 | { |
418 | label: player.localize('Copy the video URL at the current time'), | 432 | label: player.localize('Copy the video URL at the current time'), |
419 | listener: function () { | 433 | listener: function (this: VideoJsPlayer) { |
420 | const player = this as videojs.Player | 434 | copyToClipboard(buildVideoLink({ startTime: this.currentTime() })) |
421 | copyToClipboard(buildVideoLink({ startTime: player.currentTime() })) | ||
422 | } | 435 | } |
423 | }, | 436 | }, |
424 | { | 437 | { |
@@ -432,9 +445,8 @@ export class PeertubePlayerManager { | |||
432 | if (mode === 'webtorrent') { | 445 | if (mode === 'webtorrent') { |
433 | content.push({ | 446 | content.push({ |
434 | label: player.localize('Copy magnet URI'), | 447 | label: player.localize('Copy magnet URI'), |
435 | listener: function () { | 448 | listener: function (this: VideoJsPlayer) { |
436 | const player = this as videojs.Player | 449 | copyToClipboard(this.webtorrent().getCurrentVideoFile().magnetUri) |
437 | copyToClipboard(player.webtorrent().getCurrentVideoFile().magnetUri) | ||
438 | } | 450 | } |
439 | }) | 451 | }) |
440 | } | 452 | } |
@@ -472,7 +484,8 @@ export class PeertubePlayerManager { | |||
472 | return event.key === '>' | 484 | return event.key === '>' |
473 | }, | 485 | }, |
474 | handler: function (player: videojs.Player) { | 486 | handler: function (player: videojs.Player) { |
475 | player.playbackRate((player.playbackRate() + 0.1).toFixed(2)) | 487 | const newValue = Math.min(player.playbackRate() + 0.1, 5) |
488 | player.playbackRate(parseFloat(newValue.toFixed(2))) | ||
476 | } | 489 | } |
477 | }, | 490 | }, |
478 | decreasePlaybackRateKey: { | 491 | decreasePlaybackRateKey: { |
@@ -480,7 +493,8 @@ export class PeertubePlayerManager { | |||
480 | return event.key === '<' | 493 | return event.key === '<' |
481 | }, | 494 | }, |
482 | handler: function (player: videojs.Player) { | 495 | handler: function (player: videojs.Player) { |
483 | player.playbackRate((player.playbackRate() - 0.1).toFixed(2)) | 496 | const newValue = Math.max(player.playbackRate() - 0.1, 0.10) |
497 | player.playbackRate(parseFloat(newValue.toFixed(2))) | ||
484 | } | 498 | } |
485 | }, | 499 | }, |
486 | frameByFrame: { | 500 | frameByFrame: { |