aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/assets/player
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/assets/player')
-rw-r--r--client/src/assets/player/peertube-player-local-storage.ts12
-rw-r--r--client/src/assets/player/peertube-player.ts44
-rw-r--r--client/src/assets/player/peertube-videojs-plugin.ts49
-rw-r--r--client/src/assets/player/peertube-videojs-typings.ts1
-rw-r--r--client/src/assets/player/settings-menu-item.ts13
-rw-r--r--client/src/assets/player/utils.ts1
6 files changed, 92 insertions, 28 deletions
diff --git a/client/src/assets/player/peertube-player-local-storage.ts b/client/src/assets/player/peertube-player-local-storage.ts
index 7e3813570..059fca308 100644
--- a/client/src/assets/player/peertube-player-local-storage.ts
+++ b/client/src/assets/player/peertube-player-local-storage.ts
@@ -60,6 +60,14 @@ function getAverageBandwidthInStore () {
60 return undefined 60 return undefined
61} 61}
62 62
63function saveLastSubtitle (language: string) {
64 return setLocalStorage('last-subtitle', language)
65}
66
67function getStoredLastSubtitle () {
68 return getLocalStorage('last-subtitle')
69}
70
63// --------------------------------------------------------------------------- 71// ---------------------------------------------------------------------------
64 72
65export { 73export {
@@ -71,7 +79,9 @@ export {
71 saveMuteInStore, 79 saveMuteInStore,
72 saveTheaterInStore, 80 saveTheaterInStore,
73 saveAverageBandwidth, 81 saveAverageBandwidth,
74 getAverageBandwidthInStore 82 getAverageBandwidthInStore,
83 saveLastSubtitle,
84 getStoredLastSubtitle
75} 85}
76 86
77// --------------------------------------------------------------------------- 87// ---------------------------------------------------------------------------
diff --git a/client/src/assets/player/peertube-player.ts b/client/src/assets/player/peertube-player.ts
index aaa1170b6..2de6d7fef 100644
--- a/client/src/assets/player/peertube-player.ts
+++ b/client/src/assets/player/peertube-player.ts
@@ -26,23 +26,24 @@ videojsUntyped.getComponent('CaptionsButton').prototype.controlText_ = 'Subtitle
26videojsUntyped.getComponent('CaptionsButton').prototype.label_ = ' ' 26videojsUntyped.getComponent('CaptionsButton').prototype.label_ = ' '
27 27
28function getVideojsOptions (options: { 28function getVideojsOptions (options: {
29 autoplay: boolean, 29 autoplay: boolean
30 playerElement: HTMLVideoElement, 30 playerElement: HTMLVideoElement
31 videoViewUrl: string, 31 videoViewUrl: string
32 videoDuration: number, 32 videoDuration: number
33 videoFiles: VideoFile[], 33 videoFiles: VideoFile[]
34 enableHotkeys: boolean, 34 enableHotkeys: boolean
35 inactivityTimeout: number, 35 inactivityTimeout: number
36 peertubeLink: boolean, 36 peertubeLink: boolean
37 poster: string, 37 poster: string
38 startTime: number | string 38 startTime: number | string
39 theaterMode: boolean, 39 theaterMode: boolean
40 videoCaptions: VideoJSCaption[], 40 videoCaptions: VideoJSCaption[]
41 41
42 language?: string, 42 language?: string
43 controls?: boolean, 43 controls?: boolean
44 muted?: boolean, 44 muted?: boolean
45 loop?: boolean 45 loop?: boolean
46 subtitle?: string
46 47
47 userWatching?: UserWatching 48 userWatching?: UserWatching
48}) { 49}) {
@@ -50,8 +51,10 @@ function getVideojsOptions (options: {
50 // We don't use text track settings for now 51 // We don't use text track settings for now
51 textTrackSettings: false, 52 textTrackSettings: false,
52 controls: options.controls !== undefined ? options.controls : true, 53 controls: options.controls !== undefined ? options.controls : true,
53 muted: options.controls !== undefined ? options.muted : false,
54 loop: options.loop !== undefined ? options.loop : false, 54 loop: options.loop !== undefined ? options.loop : false,
55
56 muted: options.muted !== undefined ? options.muted : undefined, // Undefined so the player knows it has to check the local storage
57
55 poster: options.poster, 58 poster: options.poster,
56 autoplay: false, 59 autoplay: false,
57 inactivityTimeout: options.inactivityTimeout, 60 inactivityTimeout: options.inactivityTimeout,
@@ -65,7 +68,8 @@ function getVideojsOptions (options: {
65 videoViewUrl: options.videoViewUrl, 68 videoViewUrl: options.videoViewUrl,
66 videoDuration: options.videoDuration, 69 videoDuration: options.videoDuration,
67 startTime: options.startTime, 70 startTime: options.startTime,
68 userWatching: options.userWatching 71 userWatching: options.userWatching,
72 subtitle: options.subtitle
69 } 73 }
70 }, 74 },
71 controlBar: { 75 controlBar: {
@@ -250,6 +254,10 @@ function loadLocaleInVideoJS (serverUrl: string, videojs: any, locale: string) {
250 loadLocaleInVideoJS.cache[path] = json 254 loadLocaleInVideoJS.cache[path] = json
251 return json 255 return json
252 }) 256 })
257 .catch(err => {
258 console.error('Cannot get player translations', err)
259 return undefined
260 })
253 } 261 }
254 262
255 const completeLocale = getCompleteLocale(locale) 263 const completeLocale = getCompleteLocale(locale)
@@ -266,6 +274,10 @@ function getServerTranslations (serverUrl: string, locale: string) {
266 274
267 return fetch(path + '/server.json') 275 return fetch(path + '/server.json')
268 .then(res => res.json()) 276 .then(res => res.json())
277 .catch(err => {
278 console.error('Cannot get server translations', err)
279 return undefined
280 })
269} 281}
270 282
271// ############################################################################ 283// ############################################################################
diff --git a/client/src/assets/player/peertube-videojs-plugin.ts b/client/src/assets/player/peertube-videojs-plugin.ts
index 4fd5a9be2..e9fb90c61 100644
--- a/client/src/assets/player/peertube-videojs-plugin.ts
+++ b/client/src/assets/player/peertube-videojs-plugin.ts
@@ -11,10 +11,12 @@ import { isMobile, timeToInt, videoFileMaxByResolution, videoFileMinByResolution
11import { PeertubeChunkStore } from './peertube-chunk-store' 11import { PeertubeChunkStore } from './peertube-chunk-store'
12import { 12import {
13 getAverageBandwidthInStore, 13 getAverageBandwidthInStore,
14 getStoredLastSubtitle,
14 getStoredMute, 15 getStoredMute,
15 getStoredVolume, 16 getStoredVolume,
16 getStoredWebTorrentEnabled, 17 getStoredWebTorrentEnabled,
17 saveAverageBandwidth, 18 saveAverageBandwidth,
19 saveLastSubtitle,
18 saveMuteInStore, 20 saveMuteInStore,
19 saveVolumeInStore 21 saveVolumeInStore
20} from './peertube-player-local-storage' 22} from './peertube-player-local-storage'
@@ -67,10 +69,11 @@ class PeerTubePlugin extends Plugin {
67 private currentVideoFile: VideoFile 69 private currentVideoFile: VideoFile
68 private torrent: WebTorrent.Torrent 70 private torrent: WebTorrent.Torrent
69 private videoCaptions: VideoJSCaption[] 71 private videoCaptions: VideoJSCaption[]
72 private defaultSubtitle: string
70 73
71 private renderer: any 74 private renderer: any
72 private fakeRenderer: any 75 private fakeRenderer: any
73 private destoyingFakeRenderer = false 76 private destroyingFakeRenderer = false
74 77
75 private autoResolution = true 78 private autoResolution = true
76 private forbidAutoResolution = false 79 private forbidAutoResolution = false
@@ -106,11 +109,34 @@ class PeerTubePlugin extends Plugin {
106 if (this.autoplay === true) this.player.addClass('vjs-has-autoplay') 109 if (this.autoplay === true) this.player.addClass('vjs-has-autoplay')
107 110
108 this.player.ready(() => { 111 this.player.ready(() => {
112 const playerOptions = this.player.options_
113
109 const volume = getStoredVolume() 114 const volume = getStoredVolume()
110 if (volume !== undefined) this.player.volume(volume) 115 if (volume !== undefined) this.player.volume(volume)
111 const muted = getStoredMute() 116
117 const muted = playerOptions.muted !== undefined ? playerOptions.muted : getStoredMute()
112 if (muted !== undefined) this.player.muted(muted) 118 if (muted !== undefined) this.player.muted(muted)
113 119
120 this.defaultSubtitle = options.subtitle || getStoredLastSubtitle()
121
122 this.player.on('volumechange', () => {
123 saveVolumeInStore(this.player.volume())
124 saveMuteInStore(this.player.muted())
125 })
126
127 this.player.textTracks().on('change', () => {
128 const showing = this.player.textTracks().tracks_.find((t: { kind: string, mode: string }) => {
129 return t.kind === 'captions' && t.mode === 'showing'
130 })
131
132 if (!showing) {
133 saveLastSubtitle('off')
134 return
135 }
136
137 saveLastSubtitle(showing.language)
138 })
139
114 this.player.duration(options.videoDuration) 140 this.player.duration(options.videoDuration)
115 141
116 this.initializePlayer() 142 this.initializePlayer()
@@ -124,11 +150,6 @@ class PeerTubePlugin extends Plugin {
124 this.runAutoQualitySchedulerTimer = setTimeout(() => this.runAutoQualityScheduler(), this.CONSTANTS.AUTO_QUALITY_SCHEDULER) 150 this.runAutoQualitySchedulerTimer = setTimeout(() => this.runAutoQualityScheduler(), this.CONSTANTS.AUTO_QUALITY_SCHEDULER)
125 }) 151 })
126 }) 152 })
127
128 this.player.on('volumechange', () => {
129 saveVolumeInStore(this.player.volume())
130 saveMuteInStore(this.player.muted())
131 })
132 } 153 }
133 154
134 dispose () { 155 dispose () {
@@ -599,6 +620,9 @@ class PeerTubePlugin extends Plugin {
599 this.player.src = this.savePlayerSrcFunction 620 this.player.src = this.savePlayerSrcFunction
600 this.player.src(httpUrl) 621 this.player.src(httpUrl)
601 622
623 // We changed the source, so reinit captions
624 this.initCaptions()
625
602 return this.tryToPlay(err => { 626 return this.tryToPlay(err => {
603 if (err && done) return done(err) 627 if (err && done) return done(err)
604 628
@@ -657,14 +681,14 @@ class PeerTubePlugin extends Plugin {
657 } 681 }
658 682
659 private renderFileInFakeElement (file: WebTorrent.TorrentFile, delay: number) { 683 private renderFileInFakeElement (file: WebTorrent.TorrentFile, delay: number) {
660 this.destoyingFakeRenderer = false 684 this.destroyingFakeRenderer = false
661 685
662 const fakeVideoElem = document.createElement('video') 686 const fakeVideoElem = document.createElement('video')
663 renderVideo(file, fakeVideoElem, { autoplay: false, controls: false }, (err, renderer) => { 687 renderVideo(file, fakeVideoElem, { autoplay: false, controls: false }, (err, renderer) => {
664 this.fakeRenderer = renderer 688 this.fakeRenderer = renderer
665 689
666 // The renderer returns an error when we destroy it, so skip them 690 // The renderer returns an error when we destroy it, so skip them
667 if (this.destoyingFakeRenderer === false && err) { 691 if (this.destroyingFakeRenderer === false && err) {
668 console.error('Cannot render new torrent in fake video element.', err) 692 console.error('Cannot render new torrent in fake video element.', err)
669 } 693 }
670 694
@@ -675,7 +699,7 @@ class PeerTubePlugin extends Plugin {
675 699
676 private destroyFakeRenderer () { 700 private destroyFakeRenderer () {
677 if (this.fakeRenderer) { 701 if (this.fakeRenderer) {
678 this.destoyingFakeRenderer = true 702 this.destroyingFakeRenderer = true
679 703
680 if (this.fakeRenderer.destroy) { 704 if (this.fakeRenderer.destroy) {
681 try { 705 try {
@@ -695,9 +719,12 @@ class PeerTubePlugin extends Plugin {
695 label: caption.label, 719 label: caption.label,
696 language: caption.language, 720 language: caption.language,
697 id: caption.language, 721 id: caption.language,
698 src: caption.src 722 src: caption.src,
723 default: this.defaultSubtitle === caption.language
699 }, false) 724 }, false)
700 } 725 }
726
727 this.player.trigger('captionsChanged')
701 } 728 }
702 729
703 // Thanks: https://github.com/videojs/video.js/issues/4460#issuecomment-312861657 730 // Thanks: https://github.com/videojs/video.js/issues/4460#issuecomment-312861657
diff --git a/client/src/assets/player/peertube-videojs-typings.ts b/client/src/assets/player/peertube-videojs-typings.ts
index d127230fa..634c7fdc9 100644
--- a/client/src/assets/player/peertube-videojs-typings.ts
+++ b/client/src/assets/player/peertube-videojs-typings.ts
@@ -39,6 +39,7 @@ type PeertubePluginOptions = {
39 autoplay: boolean, 39 autoplay: boolean,
40 videoCaptions: VideoJSCaption[] 40 videoCaptions: VideoJSCaption[]
41 41
42 subtitle?: string
42 userWatching?: UserWatching 43 userWatching?: UserWatching
43} 44}
44 45
diff --git a/client/src/assets/player/settings-menu-item.ts b/client/src/assets/player/settings-menu-item.ts
index 698f4627a..2a3460ae5 100644
--- a/client/src/assets/player/settings-menu-item.ts
+++ b/client/src/assets/player/settings-menu-item.ts
@@ -48,6 +48,19 @@ class SettingsMenuItem extends MenuItem {
48 // Update on rate change 48 // Update on rate change
49 player.on('ratechange', this.submenuClickHandler) 49 player.on('ratechange', this.submenuClickHandler)
50 50
51 if (subMenuName === 'CaptionsButton') {
52 // Hack to regenerate captions on HTTP fallback
53 player.on('captionsChanged', () => {
54 setTimeout(() => {
55 this.settingsSubMenuEl_.innerHTML = ''
56 this.settingsSubMenuEl_.appendChild(this.subMenu.menu.el_)
57 this.update()
58 this.bindClickEvents()
59
60 }, 0)
61 })
62 }
63
51 this.reset() 64 this.reset()
52 }, 0) 65 }, 0)
53 }) 66 })
diff --git a/client/src/assets/player/utils.ts b/client/src/assets/player/utils.ts
index c87287482..8b9f34b99 100644
--- a/client/src/assets/player/utils.ts
+++ b/client/src/assets/player/utils.ts
@@ -39,6 +39,7 @@ function buildVideoLink (time?: number, url?: string) {
39} 39}
40 40
41function timeToInt (time: number | string) { 41function timeToInt (time: number | string) {
42 if (!time) return 0
42 if (typeof time === 'number') return time 43 if (typeof time === 'number') return time
43 44
44 const reg = /^((\d+)h)?((\d+)m)?((\d+)s?)?$/ 45 const reg = /^((\d+)h)?((\d+)m)?((\d+)s?)?$/