1 import { peertubeTranslate } from '../../../../../shared/core-utils/i18n'
9 VideoStreamingPlaylistType
10 } from '../../../../../shared/models'
11 import { P2PMediaLoaderOptions, PeertubePlayerManagerOptions, PlayerMode, VideoJSCaption } from '../../../assets/player'
19 } from '../../../root-helpers'
20 import { PeerTubePlugin } from './peertube-plugin'
21 import { PlayerHTML } from './player-html'
22 import { PlaylistTracker } from './playlist-tracker'
23 import { Translations } from './translations'
24 import { VideoFetcher } from './video-fetcher'
26 export class PlayerManagerOptions {
27 private autoplay: boolean
29 private controls: boolean
30 private controlBar: boolean
32 private muted: boolean
34 private subtitle: string
35 private enableApi = false
36 private startTime: number | string = 0
37 private stopTime: number | string
39 private title: boolean
40 private warningTitle: boolean
41 private peertubeLink: boolean
42 private p2pEnabled: boolean
43 private bigPlayBackgroundColor: string
44 private foregroundColor: string
46 private mode: PlayerMode
47 private scope = 'peertube'
50 private readonly playerHTML: PlayerHTML,
51 private readonly videoFetcher: VideoFetcher,
52 private readonly peertubePlugin: PeerTubePlugin
72 return this.warningTitle
76 return !!this.p2pEnabled
79 hasBigPlayBackgroundColor () {
80 return !!this.bigPlayBackgroundColor
83 getBigPlayBackgroundColor () {
84 return this.bigPlayBackgroundColor
87 hasForegroundColor () {
88 return !!this.foregroundColor
91 getForegroundColor () {
92 return this.foregroundColor
103 // ---------------------------------------------------------------------------
105 loadParams (config: HTMLServerConfig, video: VideoDetails) {
107 const params = new URL(window.location.toString()).searchParams
109 this.autoplay = getParamToggle(params, 'autoplay', false)
111 this.controls = getParamToggle(params, 'controls', true)
112 this.controlBar = getParamToggle(params, 'controlBar', true)
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))
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')
127 this.bigPlayBackgroundColor = getParamString(params, 'bigPlayBackgroundColor')
128 this.foregroundColor = getParamString(params, 'foregroundColor')
130 const modeParam = getParamString(params, 'mode')
133 if (modeParam === 'p2p-media-loader') this.mode = 'p2p-media-loader'
134 else this.mode = 'webtorrent'
136 if (Array.isArray(video.streamingPlaylists) && video.streamingPlaylists.length !== 0) this.mode = 'p2p-media-loader'
137 else this.mode = 'webtorrent'
140 console.error('Cannot get params from URL.', err)
144 // ---------------------------------------------------------------------------
146 async getPlayerOptions (options: {
148 captionsResponse: Response
151 alreadyHadPlayer: boolean
153 translations: Translations
155 playlistTracker?: PlaylistTracker
156 playNextPlaylistVideo?: () => any
157 playPreviousPlaylistVideo?: () => any
158 onVideoUpdate?: (uuid: string) => any
169 const videoCaptions = await this.buildCaptions(captionsResponse, translations)
171 const playerOptions: PeertubePlayerManagerOptions = {
173 // Autoplay in playlist mode
174 autoplay: alreadyHadPlayer ? true : this.autoplay,
176 controls: this.controls,
177 controlBar: this.controlBar,
182 p2pEnabled: this.p2pEnabled,
184 captions: videoCaptions.length !== 0,
185 subtitle: this.subtitle,
187 startTime: playlistTracker
188 ? playlistTracker.getCurrentElement().startTimestamp
190 stopTime: playlistTracker
191 ? playlistTracker.getCurrentElement().stopTimestamp
195 inactivityTimeout: 2500,
196 videoViewUrl: this.videoFetcher.getVideoViewsUrl(video.uuid),
198 videoShortUUID: video.shortUUID,
199 videoUUID: video.uuid,
201 playerElement: this.playerHTML.getPlayerElement(),
202 onPlayerElementChange: (element: HTMLVideoElement) => {
203 this.playerHTML.setPlayerElement(element)
206 videoDuration: video.duration,
208 peertubeLink: this.peertubeLink,
209 poster: window.location.origin + video.previewPath,
210 theaterButton: false,
212 serverUrl: window.location.origin,
213 language: navigator.language,
214 embedUrl: window.location.origin + video.embedPath,
215 embedTitle: video.name,
217 errorNotifier: () => {
218 // Empty, we don't have a notifier in the embed
221 ...this.buildLiveOptions(video, live),
223 ...this.buildPlaylistOptions(options)
227 videoFiles: video.files
230 ...this.buildP2PMediaLoaderOptions(video),
232 pluginsManager: this.peertubePlugin.getPluginsManager()
238 private buildLiveOptions (video: VideoDetails, live: LiveVideo) {
239 if (!video.isLive) return { isLive: false }
244 latencyMode: live.latencyMode
249 private buildPlaylistOptions (options: {
250 playlistTracker?: PlaylistTracker
251 playNextPlaylistVideo?: () => any
252 playPreviousPlaylistVideo?: () => any
253 onVideoUpdate?: (uuid: string) => any
255 const { playlistTracker, playNextPlaylistVideo, playPreviousPlaylistVideo, onVideoUpdate } = options
257 if (!playlistTracker) return {}
261 elements: playlistTracker.getPlaylistElements(),
262 playlist: playlistTracker.getPlaylist(),
264 getCurrentPosition: () => playlistTracker.getCurrentPosition(),
266 onItemClicked: (videoPlaylistElement: VideoPlaylistElement) => {
267 playlistTracker.setCurrentElement(videoPlaylistElement)
269 onVideoUpdate(videoPlaylistElement.video.uuid)
273 nextVideo: () => playNextPlaylistVideo(),
274 hasNextVideo: () => playlistTracker.hasNextPlaylistElement(),
276 previousVideo: () => playPreviousPlaylistVideo(),
277 hasPreviousVideo: () => playlistTracker.hasPreviousPlaylistElement()
281 private buildP2PMediaLoaderOptions (video: VideoDetails) {
282 if (this.mode !== 'p2p-media-loader') return {}
284 const hlsPlaylist = video.streamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
288 playlistUrl: hlsPlaylist.playlistUrl,
289 segmentsSha256Url: hlsPlaylist.segmentsSha256Url,
290 redundancyBaseUrls: hlsPlaylist.redundancies.map(r => r.baseUrl),
291 trackerAnnounce: video.trackerUrls,
292 videoFiles: hlsPlaylist.files
293 } as P2PMediaLoaderOptions
297 // ---------------------------------------------------------------------------
299 private async buildCaptions (captionsResponse: Response, translations: Translations): Promise<VideoJSCaption[]> {
300 if (captionsResponse.ok) {
301 const { data } = await captionsResponse.json()
303 return data.map((c: VideoCaption) => ({
304 label: peertubeTranslate(c.language.label, translations),
305 language: c.language.id,
306 src: window.location.origin + c.captionPath
313 // ---------------------------------------------------------------------------
315 private isP2PEnabled (config: HTMLServerConfig, video: Video) {
316 const userP2PEnabled = getBoolOrDefault(
317 peertubeLocalStorage.getItem(UserLocalStorageKeys.P2P_ENABLED),
318 config.defaults.p2p.embed.enabled
321 return isP2PEnabled(video, config, userP2PEnabled)