]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/standalone/videos/shared/player-manager-options.ts
Correctly handle actors without follow counters
[github/Chocobozzz/PeerTube.git] / client / src / standalone / videos / shared / player-manager-options.ts
CommitLineData
f1a0f3b7
C
1import { peertubeTranslate } from '../../../../../shared/core-utils/i18n'
2import {
3 HTMLServerConfig,
4 LiveVideo,
5 Video,
6 VideoCaption,
7 VideoDetails,
8 VideoPlaylistElement,
9 VideoStreamingPlaylistType
10} from '../../../../../shared/models'
11import { P2PMediaLoaderOptions, PeertubePlayerManagerOptions, PlayerMode, VideoJSCaption } from '../../../assets/player'
12import {
13 getBoolOrDefault,
14 getParamString,
15 getParamToggle,
16 isP2PEnabled,
17 peertubeLocalStorage,
18 UserLocalStorageKeys
19} from '../../../root-helpers'
20import { PeerTubePlugin } from './peertube-plugin'
21import { PlayerHTML } from './player-html'
22import { PlaylistTracker } from './playlist-tracker'
23import { Translations } from './translations'
24import { VideoFetcher } from './video-fetcher'
25
26export class PlayerManagerOptions {
27 private autoplay: boolean
28
29 private controls: boolean
30 private controlBar: boolean
31
32 private muted: boolean
33 private loop: boolean
34 private subtitle: string
35 private enableApi = false
36 private startTime: number | string = 0
37 private stopTime: number | string
38
39 private title: boolean
40 private warningTitle: boolean
41 private peertubeLink: boolean
42 private p2pEnabled: boolean
43 private bigPlayBackgroundColor: string
44 private foregroundColor: string
45
46 private mode: PlayerMode
47 private scope = 'peertube'
48
49 constructor (
50 private readonly playerHTML: PlayerHTML,
51 private readonly videoFetcher: VideoFetcher,
52 private readonly peertubePlugin: PeerTubePlugin
53 ) {}
54
55 hasAPIEnabled () {
56 return this.enableApi
57 }
58
59 hasAutoplay () {
60 return this.autoplay
61 }
62
63 hasControls () {
64 return this.controls
65 }
66
67 hasTitle () {
68 return this.title
69 }
70
71 hasWarningTitle () {
72 return this.warningTitle
73 }
74
75 hasP2PEnabled () {
76 return !!this.p2pEnabled
77 }
78
79 hasBigPlayBackgroundColor () {
80 return !!this.bigPlayBackgroundColor
81 }
82
83 getBigPlayBackgroundColor () {
84 return this.bigPlayBackgroundColor
85 }
86
87 hasForegroundColor () {
88 return !!this.foregroundColor
89 }
90
91 getForegroundColor () {
92 return this.foregroundColor
93 }
94
95 getMode () {
96 return this.mode
97 }
98
99 getScope () {
100 return this.scope
101 }
102
103 // ---------------------------------------------------------------------------
104
105 loadParams (config: HTMLServerConfig, video: VideoDetails) {
106 try {
107 const params = new URL(window.location.toString()).searchParams
108
109 this.autoplay = getParamToggle(params, 'autoplay', false)
110
111 this.controls = getParamToggle(params, 'controls', true)
112 this.controlBar = getParamToggle(params, 'controlBar', true)
113
114 this.muted = getParamToggle(params, 'muted', undefined)
115 this.loop = getParamToggle(params, 'loop', false)
116 this.title = getParamToggle(params, 'title', true)
117 this.enableApi = getParamToggle(params, 'api', this.enableApi)
118 this.warningTitle = getParamToggle(params, 'warningTitle', true)
119 this.peertubeLink = getParamToggle(params, 'peertubeLink', true)
120 this.p2pEnabled = getParamToggle(params, 'p2p', this.isP2PEnabled(config, video))
121
122 this.scope = getParamString(params, 'scope', this.scope)
123 this.subtitle = getParamString(params, 'subtitle')
124 this.startTime = getParamString(params, 'start')
125 this.stopTime = getParamString(params, 'stop')
126
127 this.bigPlayBackgroundColor = getParamString(params, 'bigPlayBackgroundColor')
128 this.foregroundColor = getParamString(params, 'foregroundColor')
129
130 const modeParam = getParamString(params, 'mode')
131
132 if (modeParam) {
133 if (modeParam === 'p2p-media-loader') this.mode = 'p2p-media-loader'
134 else this.mode = 'webtorrent'
135 } else {
136 if (Array.isArray(video.streamingPlaylists) && video.streamingPlaylists.length !== 0) this.mode = 'p2p-media-loader'
137 else this.mode = 'webtorrent'
138 }
139 } catch (err) {
140 console.error('Cannot get params from URL.', err)
141 }
142 }
143
144 // ---------------------------------------------------------------------------
145
146 async getPlayerOptions (options: {
147 video: VideoDetails
148 captionsResponse: Response
149 live?: LiveVideo
150
bd2b51be
C
151 serverConfig: HTMLServerConfig
152
f1a0f3b7
C
153 alreadyHadPlayer: boolean
154
155 translations: Translations
156
157 playlistTracker?: PlaylistTracker
158 playNextPlaylistVideo?: () => any
159 playPreviousPlaylistVideo?: () => any
160 onVideoUpdate?: (uuid: string) => any
161 }) {
162 const {
163 video,
164 captionsResponse,
165 alreadyHadPlayer,
166 translations,
167 playlistTracker,
bd2b51be
C
168 live,
169 serverConfig
f1a0f3b7
C
170 } = options
171
172 const videoCaptions = await this.buildCaptions(captionsResponse, translations)
173
174 const playerOptions: PeertubePlayerManagerOptions = {
175 common: {
176 // Autoplay in playlist mode
177 autoplay: alreadyHadPlayer ? true : this.autoplay,
178
179 controls: this.controls,
180 controlBar: this.controlBar,
181
182 muted: this.muted,
183 loop: this.loop,
184
185 p2pEnabled: this.p2pEnabled,
186
187 captions: videoCaptions.length !== 0,
188 subtitle: this.subtitle,
189
190 startTime: playlistTracker
191 ? playlistTracker.getCurrentElement().startTimestamp
192 : this.startTime,
193 stopTime: playlistTracker
194 ? playlistTracker.getCurrentElement().stopTimestamp
195 : this.stopTime,
196
197 videoCaptions,
198 inactivityTimeout: 2500,
199 videoViewUrl: this.videoFetcher.getVideoViewsUrl(video.uuid),
200
201 videoShortUUID: video.shortUUID,
202 videoUUID: video.uuid,
203
204 playerElement: this.playerHTML.getPlayerElement(),
205 onPlayerElementChange: (element: HTMLVideoElement) => {
206 this.playerHTML.setPlayerElement(element)
207 },
208
209 videoDuration: video.duration,
210 enableHotkeys: true,
bd2b51be 211
f1a0f3b7 212 peertubeLink: this.peertubeLink,
bd2b51be
C
213 instanceName: serverConfig.instance.name,
214
f1a0f3b7
C
215 poster: window.location.origin + video.previewPath,
216 theaterButton: false,
217
218 serverUrl: window.location.origin,
219 language: navigator.language,
220 embedUrl: window.location.origin + video.embedPath,
221 embedTitle: video.name,
222
223 errorNotifier: () => {
224 // Empty, we don't have a notifier in the embed
225 },
226
227 ...this.buildLiveOptions(video, live),
228
229 ...this.buildPlaylistOptions(options)
230 },
231
232 webtorrent: {
233 videoFiles: video.files
234 },
235
236 ...this.buildP2PMediaLoaderOptions(video),
237
238 pluginsManager: this.peertubePlugin.getPluginsManager()
239 }
240
241 return playerOptions
242 }
243
244 private buildLiveOptions (video: VideoDetails, live: LiveVideo) {
245 if (!video.isLive) return { isLive: false }
246
247 return {
248 isLive: true,
249 liveOptions: {
250 latencyMode: live.latencyMode
251 }
252 }
253 }
254
255 private buildPlaylistOptions (options: {
256 playlistTracker?: PlaylistTracker
257 playNextPlaylistVideo?: () => any
258 playPreviousPlaylistVideo?: () => any
259 onVideoUpdate?: (uuid: string) => any
260 }) {
261 const { playlistTracker, playNextPlaylistVideo, playPreviousPlaylistVideo, onVideoUpdate } = options
262
263 if (!playlistTracker) return {}
264
265 return {
266 playlist: {
267 elements: playlistTracker.getPlaylistElements(),
268 playlist: playlistTracker.getPlaylist(),
269
270 getCurrentPosition: () => playlistTracker.getCurrentPosition(),
271
272 onItemClicked: (videoPlaylistElement: VideoPlaylistElement) => {
273 playlistTracker.setCurrentElement(videoPlaylistElement)
274
275 onVideoUpdate(videoPlaylistElement.video.uuid)
276 }
277 },
278
279 nextVideo: () => playNextPlaylistVideo(),
280 hasNextVideo: () => playlistTracker.hasNextPlaylistElement(),
281
282 previousVideo: () => playPreviousPlaylistVideo(),
283 hasPreviousVideo: () => playlistTracker.hasPreviousPlaylistElement()
284 }
285 }
286
287 private buildP2PMediaLoaderOptions (video: VideoDetails) {
288 if (this.mode !== 'p2p-media-loader') return {}
289
290 const hlsPlaylist = video.streamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
291
292 return {
293 p2pMediaLoader: {
294 playlistUrl: hlsPlaylist.playlistUrl,
295 segmentsSha256Url: hlsPlaylist.segmentsSha256Url,
296 redundancyBaseUrls: hlsPlaylist.redundancies.map(r => r.baseUrl),
297 trackerAnnounce: video.trackerUrls,
298 videoFiles: hlsPlaylist.files
299 } as P2PMediaLoaderOptions
300 }
301 }
302
303 // ---------------------------------------------------------------------------
304
305 private async buildCaptions (captionsResponse: Response, translations: Translations): Promise<VideoJSCaption[]> {
306 if (captionsResponse.ok) {
307 const { data } = await captionsResponse.json()
308
309 return data.map((c: VideoCaption) => ({
310 label: peertubeTranslate(c.language.label, translations),
311 language: c.language.id,
312 src: window.location.origin + c.captionPath
313 }))
314 }
315
316 return []
317 }
318
319 // ---------------------------------------------------------------------------
320
321 private isP2PEnabled (config: HTMLServerConfig, video: Video) {
322 const userP2PEnabled = getBoolOrDefault(
323 peertubeLocalStorage.getItem(UserLocalStorageKeys.P2P_ENABLED),
324 config.defaults.p2p.embed.enabled
325 )
326
327 return isP2PEnabled(video, config, userP2PEnabled)
328 }
329}