]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/assets/player/shared/manager-options/manager-options-builder.ts
Fix missing p2p media loader config for hls
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / shared / manager-options / manager-options-builder.ts
1 import videojs from 'video.js'
2 import { copyToClipboard } from '@root-helpers/utils'
3 import { buildVideoOrPlaylistEmbed } from '@root-helpers/video'
4 import { isIOS, isSafari } from '@root-helpers/web-browser'
5 import { buildVideoLink, decorateVideoLink, pick } from '@shared/core-utils'
6 import { isDefaultLocale } from '@shared/core-utils/i18n'
7 import { VideoJSPluginOptions } from '../../types'
8 import { CommonOptions, PeertubePlayerManagerOptions, PlayerMode } from '../../types/manager-options'
9 import { ControlBarOptionsBuilder } from './control-bar-options-builder'
10 import { HLSOptionsBuilder } from './hls-options-builder'
11 import { WebTorrentOptionsBuilder } from './webtorrent-options-builder'
12
13 export class ManagerOptionsBuilder {
14
15 constructor (
16 private mode: PlayerMode,
17 private options: PeertubePlayerManagerOptions,
18 private p2pMediaLoaderModule?: any
19 ) {
20
21 }
22
23 getVideojsOptions (alreadyPlayed: boolean): videojs.PlayerOptions {
24 const commonOptions = this.options.common
25
26 let autoplay = this.getAutoPlayValue(commonOptions.autoplay, alreadyPlayed)
27 const html5 = {
28 preloadTextTracks: false
29 }
30
31 const plugins: VideoJSPluginOptions = {
32 peertube: {
33 mode: this.mode,
34 autoplay, // Use peertube plugin autoplay because we could get the file by webtorrent
35 videoViewUrl: commonOptions.videoViewUrl,
36 videoDuration: commonOptions.videoDuration,
37 userWatching: commonOptions.userWatching,
38 subtitle: commonOptions.subtitle,
39 videoCaptions: commonOptions.videoCaptions,
40 stopTime: commonOptions.stopTime,
41 isLive: commonOptions.isLive,
42 videoUUID: commonOptions.videoUUID
43 }
44 }
45
46 if (commonOptions.playlist) {
47 plugins.playlist = commonOptions.playlist
48 }
49
50 if (this.mode === 'p2p-media-loader') {
51 const hlsOptionsBuilder = new HLSOptionsBuilder(this.options, this.p2pMediaLoaderModule)
52 const options = hlsOptionsBuilder.getPluginOptions()
53
54 Object.assign(plugins, pick(options, [ 'hlsjs', 'p2pMediaLoader' ]))
55 Object.assign(html5, options.html5)
56 } else if (this.mode === 'webtorrent') {
57 const webtorrentOptionsBuilder = new WebTorrentOptionsBuilder(this.options, this.getAutoPlayValue(autoplay, alreadyPlayed))
58
59 Object.assign(plugins, webtorrentOptionsBuilder.getPluginOptions())
60
61 // WebTorrent plugin handles autoplay, because we do some hackish stuff in there
62 autoplay = false
63 }
64
65 const controlBarOptionsBuilder = new ControlBarOptionsBuilder(this.options, this.mode)
66
67 const videojsOptions = {
68 html5,
69
70 // We don't use text track settings for now
71 textTrackSettings: false as any, // FIXME: typings
72 controls: commonOptions.controls !== undefined ? commonOptions.controls : true,
73 loop: commonOptions.loop !== undefined ? commonOptions.loop : false,
74
75 muted: commonOptions.muted !== undefined
76 ? commonOptions.muted
77 : undefined, // Undefined so the player knows it has to check the local storage
78
79 autoplay: this.getAutoPlayValue(autoplay, alreadyPlayed),
80
81 poster: commonOptions.poster,
82 inactivityTimeout: commonOptions.inactivityTimeout,
83 playbackRates: [ 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2 ],
84
85 plugins,
86
87 controlBar: {
88 children: controlBarOptionsBuilder.getChildrenOptions() as any // FIXME: typings
89 }
90 }
91
92 if (commonOptions.language && !isDefaultLocale(commonOptions.language)) {
93 Object.assign(videojsOptions, { language: commonOptions.language })
94 }
95
96 return videojsOptions
97 }
98
99 private getAutoPlayValue (autoplay: any, alreadyPlayed: boolean) {
100 if (autoplay !== true) return autoplay
101
102 // On first play, disable autoplay to avoid issues
103 // But if the player already played videos, we can safely autoplay next ones
104 if (isIOS() || isSafari()) {
105 return alreadyPlayed ? 'play' : false
106 }
107
108 return 'play'
109 }
110
111 getContextMenuOptions (player: videojs.Player, commonOptions: CommonOptions) {
112 const content = () => {
113 const isLoopEnabled = player.options_['loop']
114
115 const items = [
116 {
117 icon: 'repeat',
118 label: player.localize('Play in loop') + (isLoopEnabled ? '<span class="vjs-icon-tick-white"></span>' : ''),
119 listener: function () {
120 player.options_['loop'] = !isLoopEnabled
121 }
122 },
123 {
124 label: player.localize('Copy the video URL'),
125 listener: function () {
126 copyToClipboard(buildVideoLink({ shortUUID: commonOptions.videoShortUUID }))
127 }
128 },
129 {
130 label: player.localize('Copy the video URL at the current time'),
131 listener: function (this: videojs.Player) {
132 const url = buildVideoLink({ shortUUID: commonOptions.videoShortUUID })
133
134 copyToClipboard(decorateVideoLink({ url, startTime: this.currentTime() }))
135 }
136 },
137 {
138 icon: 'code',
139 label: player.localize('Copy embed code'),
140 listener: () => {
141 copyToClipboard(buildVideoOrPlaylistEmbed(commonOptions.embedUrl, commonOptions.embedTitle))
142 }
143 }
144 ]
145
146 if (this.mode === 'webtorrent') {
147 items.push({
148 label: player.localize('Copy magnet URI'),
149 listener: function (this: videojs.Player) {
150 copyToClipboard(this.webtorrent().getCurrentVideoFile().magnetUri)
151 }
152 })
153 }
154
155 items.push({
156 icon: 'info',
157 label: player.localize('Stats for nerds'),
158 listener: () => {
159 player.stats().show()
160 }
161 })
162
163 return items.map(i => ({
164 ...i,
165 label: `<span class="vjs-icon-${i.icon || 'link-2'}"></span>` + i.label
166 }))
167 }
168
169 return { content }
170 }
171 }