diff options
author | Chocobozzz <me@florianbigard.com> | 2022-03-14 11:16:54 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2022-03-14 11:36:38 +0100 |
commit | 9597920ee3d4ac99803e7107983ddf98a9dfb3c4 (patch) | |
tree | 62c98909b4eb30ece3c0f58c26c8555e6bef1e31 /client/src/assets/player/manager-options | |
parent | 9af2accee68082e4e1160a4e4a7036451262be02 (diff) | |
download | PeerTube-9597920ee3d4ac99803e7107983ddf98a9dfb3c4.tar.gz PeerTube-9597920ee3d4ac99803e7107983ddf98a9dfb3c4.tar.zst PeerTube-9597920ee3d4ac99803e7107983ddf98a9dfb3c4.zip |
Reorganize player manager options builder
Diffstat (limited to 'client/src/assets/player/manager-options')
5 files changed, 612 insertions, 0 deletions
diff --git a/client/src/assets/player/manager-options/control-bar-options-builder.ts b/client/src/assets/player/manager-options/control-bar-options-builder.ts new file mode 100644 index 000000000..54e61c5d0 --- /dev/null +++ b/client/src/assets/player/manager-options/control-bar-options-builder.ts | |||
@@ -0,0 +1,132 @@ | |||
1 | import { NextPreviousVideoButtonOptions, PeerTubeLinkButtonOptions } from '../peertube-videojs-typings' | ||
2 | import { CommonOptions, PeertubePlayerManagerOptions, PlayerMode } from './manager-options.model' | ||
3 | |||
4 | export class ControlBarOptionsBuilder { | ||
5 | private options: CommonOptions | ||
6 | |||
7 | constructor ( | ||
8 | globalOptions: PeertubePlayerManagerOptions, | ||
9 | private mode: PlayerMode | ||
10 | ) { | ||
11 | this.options = globalOptions.common | ||
12 | } | ||
13 | |||
14 | getChildrenOptions () { | ||
15 | const children = {} | ||
16 | |||
17 | if (this.options.previousVideo) { | ||
18 | Object.assign(children, this.getPreviousVideo()) | ||
19 | } | ||
20 | |||
21 | Object.assign(children, { playToggle: {} }) | ||
22 | |||
23 | if (this.options.nextVideo) { | ||
24 | Object.assign(children, this.getNextVideo()) | ||
25 | } | ||
26 | |||
27 | Object.assign(children, { | ||
28 | currentTimeDisplay: {}, | ||
29 | timeDivider: {}, | ||
30 | durationDisplay: {}, | ||
31 | liveDisplay: {}, | ||
32 | |||
33 | flexibleWidthSpacer: {}, | ||
34 | |||
35 | ...this.getProgressControl(), | ||
36 | |||
37 | p2PInfoButton: { | ||
38 | p2pEnabled: this.options.p2pEnabled | ||
39 | }, | ||
40 | |||
41 | muteToggle: {}, | ||
42 | volumeControl: {}, | ||
43 | |||
44 | settingsButton: this.getSettingsButton() | ||
45 | }) | ||
46 | |||
47 | if (this.options.peertubeLink === true) { | ||
48 | Object.assign(children, { | ||
49 | peerTubeLinkButton: { shortUUID: this.options.videoShortUUID } as PeerTubeLinkButtonOptions | ||
50 | }) | ||
51 | } | ||
52 | |||
53 | if (this.options.theaterButton === true) { | ||
54 | Object.assign(children, { | ||
55 | theaterButton: {} | ||
56 | }) | ||
57 | } | ||
58 | |||
59 | Object.assign(children, { | ||
60 | fullscreenToggle: {} | ||
61 | }) | ||
62 | |||
63 | return children | ||
64 | } | ||
65 | |||
66 | private getSettingsButton () { | ||
67 | const settingEntries: string[] = [] | ||
68 | |||
69 | settingEntries.push('playbackRateMenuButton') | ||
70 | |||
71 | if (this.options.captions === true) settingEntries.push('captionsButton') | ||
72 | |||
73 | settingEntries.push('resolutionMenuButton') | ||
74 | |||
75 | return { | ||
76 | settingsButton: { | ||
77 | setup: { | ||
78 | maxHeightOffset: 40 | ||
79 | }, | ||
80 | entries: settingEntries | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | |||
85 | private getProgressControl () { | ||
86 | const loadProgressBar = this.mode === 'webtorrent' | ||
87 | ? 'peerTubeLoadProgressBar' | ||
88 | : 'loadProgressBar' | ||
89 | |||
90 | return { | ||
91 | progressControl: { | ||
92 | children: { | ||
93 | seekBar: { | ||
94 | children: { | ||
95 | [loadProgressBar]: {}, | ||
96 | mouseTimeDisplay: {}, | ||
97 | playProgressBar: {} | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | private getPreviousVideo () { | ||
106 | const buttonOptions: NextPreviousVideoButtonOptions = { | ||
107 | type: 'previous', | ||
108 | handler: this.options.previousVideo, | ||
109 | isDisabled: () => { | ||
110 | if (!this.options.hasPreviousVideo) return false | ||
111 | |||
112 | return !this.options.hasPreviousVideo() | ||
113 | } | ||
114 | } | ||
115 | |||
116 | return { previousVideoButton: buttonOptions } | ||
117 | } | ||
118 | |||
119 | private getNextVideo () { | ||
120 | const buttonOptions: NextPreviousVideoButtonOptions = { | ||
121 | type: 'next', | ||
122 | handler: this.options.nextVideo, | ||
123 | isDisabled: () => { | ||
124 | if (!this.options.hasNextVideo) return false | ||
125 | |||
126 | return !this.options.hasNextVideo() | ||
127 | } | ||
128 | } | ||
129 | |||
130 | return { nextVideoButton: buttonOptions } | ||
131 | } | ||
132 | } | ||
diff --git a/client/src/assets/player/manager-options/hls-options-builder.ts b/client/src/assets/player/manager-options/hls-options-builder.ts new file mode 100644 index 000000000..9de23561b --- /dev/null +++ b/client/src/assets/player/manager-options/hls-options-builder.ts | |||
@@ -0,0 +1,192 @@ | |||
1 | import { HybridLoaderSettings } from '@peertube/p2p-media-loader-core' | ||
2 | import { HlsJsEngineSettings } from '@peertube/p2p-media-loader-hlsjs' | ||
3 | import { LiveVideoLatencyMode } from '@shared/models' | ||
4 | import { RedundancyUrlManager } from '../p2p-media-loader/redundancy-url-manager' | ||
5 | import { segmentUrlBuilderFactory } from '../p2p-media-loader/segment-url-builder' | ||
6 | import { segmentValidatorFactory } from '../p2p-media-loader/segment-validator' | ||
7 | import { getAverageBandwidthInStore } from '../peertube-player-local-storage' | ||
8 | import { P2PMediaLoader, P2PMediaLoaderPluginOptions } from '../peertube-videojs-typings' | ||
9 | import { getRtcConfig } from '../utils' | ||
10 | import { PeertubePlayerManagerOptions } from './manager-options.model' | ||
11 | |||
12 | export class HLSOptionsBuilder { | ||
13 | |||
14 | constructor ( | ||
15 | private options: PeertubePlayerManagerOptions, | ||
16 | private p2pMediaLoaderModule?: any | ||
17 | ) { | ||
18 | |||
19 | } | ||
20 | |||
21 | getPluginOptions () { | ||
22 | const commonOptions = this.options.common | ||
23 | |||
24 | const redundancyUrlManager = new RedundancyUrlManager(this.options.p2pMediaLoader.redundancyBaseUrls) | ||
25 | |||
26 | const p2pMediaLoaderConfig = this.getP2PMediaLoaderOptions(redundancyUrlManager) | ||
27 | const loader = new this.p2pMediaLoaderModule.Engine(p2pMediaLoaderConfig).createLoaderClass() as P2PMediaLoader | ||
28 | |||
29 | const p2pMediaLoader: P2PMediaLoaderPluginOptions = { | ||
30 | redundancyUrlManager, | ||
31 | type: 'application/x-mpegURL', | ||
32 | startTime: commonOptions.startTime, | ||
33 | src: this.options.p2pMediaLoader.playlistUrl, | ||
34 | loader | ||
35 | } | ||
36 | |||
37 | const hlsjs = { | ||
38 | levelLabelHandler: (level: { height: number, width: number }) => { | ||
39 | const resolution = Math.min(level.height || 0, level.width || 0) | ||
40 | |||
41 | const file = this.options.p2pMediaLoader.videoFiles.find(f => f.resolution.id === resolution) | ||
42 | // We don't have files for live videos | ||
43 | if (!file) return level.height | ||
44 | |||
45 | let label = file.resolution.label | ||
46 | if (file.fps >= 50) label += file.fps | ||
47 | |||
48 | return label | ||
49 | }, | ||
50 | html5: { | ||
51 | hlsjsConfig: this.getHLSJSOptions(loader) | ||
52 | } | ||
53 | } | ||
54 | |||
55 | return { p2pMediaLoader, hlsjs } | ||
56 | } | ||
57 | |||
58 | // --------------------------------------------------------------------------- | ||
59 | |||
60 | private getP2PMediaLoaderOptions (redundancyUrlManager: RedundancyUrlManager): HlsJsEngineSettings { | ||
61 | let consumeOnly = false | ||
62 | if ((navigator as any)?.connection?.type === 'cellular') { | ||
63 | console.log('We are on a cellular connection: disabling seeding.') | ||
64 | consumeOnly = true | ||
65 | } | ||
66 | |||
67 | const trackerAnnounce = this.options.p2pMediaLoader.trackerAnnounce | ||
68 | .filter(t => t.startsWith('ws')) | ||
69 | |||
70 | const specificLiveOrVODOptions = this.options.common.isLive | ||
71 | ? this.getP2PMediaLoaderLiveOptions() | ||
72 | : this.getP2PMediaLoaderVODOptions() | ||
73 | |||
74 | return { | ||
75 | loader: { | ||
76 | |||
77 | trackerAnnounce, | ||
78 | rtcConfig: getRtcConfig(), | ||
79 | |||
80 | simultaneousHttpDownloads: 1, | ||
81 | httpFailedSegmentTimeout: 1000, | ||
82 | |||
83 | segmentValidator: segmentValidatorFactory(this.options.p2pMediaLoader.segmentsSha256Url, this.options.common.isLive), | ||
84 | segmentUrlBuilder: segmentUrlBuilderFactory(redundancyUrlManager, 1), | ||
85 | |||
86 | useP2P: this.options.common.p2pEnabled, | ||
87 | consumeOnly, | ||
88 | |||
89 | ...specificLiveOrVODOptions | ||
90 | }, | ||
91 | segments: { | ||
92 | swarmId: this.options.p2pMediaLoader.playlistUrl, | ||
93 | forwardSegmentCount: specificLiveOrVODOptions.p2pDownloadMaxPriority | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | private getP2PMediaLoaderLiveOptions (): Partial<HybridLoaderSettings> { | ||
99 | const base = { | ||
100 | requiredSegmentsPriority: 1 | ||
101 | } | ||
102 | |||
103 | const latencyMode = this.options.common.liveOptions.latencyMode | ||
104 | |||
105 | switch (latencyMode) { | ||
106 | case LiveVideoLatencyMode.SMALL_LATENCY: | ||
107 | return { | ||
108 | ...base, | ||
109 | |||
110 | useP2P: false, | ||
111 | httpDownloadProbability: 1 | ||
112 | } | ||
113 | |||
114 | case LiveVideoLatencyMode.HIGH_LATENCY: | ||
115 | return base | ||
116 | |||
117 | default: | ||
118 | return base | ||
119 | } | ||
120 | } | ||
121 | |||
122 | private getP2PMediaLoaderVODOptions (): Partial<HybridLoaderSettings> { | ||
123 | return { | ||
124 | requiredSegmentsPriority: 3, | ||
125 | |||
126 | cachedSegmentExpiration: 86400000, | ||
127 | cachedSegmentsCount: 100, | ||
128 | |||
129 | httpDownloadMaxPriority: 9, | ||
130 | httpDownloadProbability: 0.06, | ||
131 | httpDownloadProbabilitySkipIfNoPeers: true, | ||
132 | |||
133 | p2pDownloadMaxPriority: 50 | ||
134 | } | ||
135 | } | ||
136 | |||
137 | // --------------------------------------------------------------------------- | ||
138 | |||
139 | private getHLSJSOptions (loader: P2PMediaLoader) { | ||
140 | const specificLiveOrVODOptions = this.options.common.isLive | ||
141 | ? this.getHLSLiveOptions() | ||
142 | : this.getHLSVODOptions() | ||
143 | |||
144 | const base = { | ||
145 | capLevelToPlayerSize: true, | ||
146 | autoStartLoad: false, | ||
147 | |||
148 | loader, | ||
149 | |||
150 | ...specificLiveOrVODOptions | ||
151 | } | ||
152 | |||
153 | const averageBandwidth = getAverageBandwidthInStore() | ||
154 | if (!averageBandwidth) return base | ||
155 | |||
156 | return { | ||
157 | ...base, | ||
158 | |||
159 | abrEwmaDefaultEstimate: averageBandwidth * 8, // We want bit/s | ||
160 | startLevel: -1, | ||
161 | testBandwidth: false, | ||
162 | debug: false | ||
163 | } | ||
164 | } | ||
165 | |||
166 | private getHLSLiveOptions () { | ||
167 | const latencyMode = this.options.common.liveOptions.latencyMode | ||
168 | |||
169 | switch (latencyMode) { | ||
170 | case LiveVideoLatencyMode.SMALL_LATENCY: | ||
171 | return { | ||
172 | liveSyncDurationCount: 2 | ||
173 | } | ||
174 | |||
175 | case LiveVideoLatencyMode.HIGH_LATENCY: | ||
176 | return { | ||
177 | liveSyncDurationCount: 10 | ||
178 | } | ||
179 | |||
180 | default: | ||
181 | return { | ||
182 | liveSyncDurationCount: 5 | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | private getHLSVODOptions () { | ||
188 | return { | ||
189 | liveSyncDurationCount: 5 | ||
190 | } | ||
191 | } | ||
192 | } | ||
diff --git a/client/src/assets/player/manager-options/manager-options-builder.ts b/client/src/assets/player/manager-options/manager-options-builder.ts new file mode 100644 index 000000000..14bdb5d96 --- /dev/null +++ b/client/src/assets/player/manager-options/manager-options-builder.ts | |||
@@ -0,0 +1,168 @@ | |||
1 | import videojs from 'video.js' | ||
2 | import { buildVideoLink, decorateVideoLink } from '@shared/core-utils' | ||
3 | import { isDefaultLocale } from '@shared/core-utils/i18n' | ||
4 | import { copyToClipboard } from '../../../root-helpers/utils' | ||
5 | import { VideoJSPluginOptions } from '../peertube-videojs-typings' | ||
6 | import { buildVideoOrPlaylistEmbed, isIOS, isSafari } from '../utils' | ||
7 | import { ControlBarOptionsBuilder } from './control-bar-options-builder' | ||
8 | import { HLSOptionsBuilder } from './hls-options-builder' | ||
9 | import { CommonOptions, PeertubePlayerManagerOptions, PlayerMode } from './manager-options.model' | ||
10 | import { WebTorrentOptionsBuilder } from './webtorrent-options-builder' | ||
11 | |||
12 | export class ManagerOptionsBuilder { | ||
13 | |||
14 | constructor ( | ||
15 | private mode: PlayerMode, | ||
16 | private options: PeertubePlayerManagerOptions, | ||
17 | private p2pMediaLoaderModule?: any | ||
18 | ) { | ||
19 | |||
20 | } | ||
21 | |||
22 | getVideojsOptions (alreadyPlayed: boolean): videojs.PlayerOptions { | ||
23 | const commonOptions = this.options.common | ||
24 | |||
25 | let autoplay = this.getAutoPlayValue(commonOptions.autoplay, alreadyPlayed) | ||
26 | const html5 = { | ||
27 | preloadTextTracks: false | ||
28 | } | ||
29 | |||
30 | const plugins: VideoJSPluginOptions = { | ||
31 | peertube: { | ||
32 | mode: this.mode, | ||
33 | autoplay, // Use peertube plugin autoplay because we could get the file by webtorrent | ||
34 | videoViewUrl: commonOptions.videoViewUrl, | ||
35 | videoDuration: commonOptions.videoDuration, | ||
36 | userWatching: commonOptions.userWatching, | ||
37 | subtitle: commonOptions.subtitle, | ||
38 | videoCaptions: commonOptions.videoCaptions, | ||
39 | stopTime: commonOptions.stopTime, | ||
40 | isLive: commonOptions.isLive, | ||
41 | videoUUID: commonOptions.videoUUID | ||
42 | } | ||
43 | } | ||
44 | |||
45 | if (commonOptions.playlist) { | ||
46 | plugins.playlist = commonOptions.playlist | ||
47 | } | ||
48 | |||
49 | if (this.mode === 'p2p-media-loader') { | ||
50 | const hlsOptionsBuilder = new HLSOptionsBuilder(this.options, this.p2pMediaLoaderModule) | ||
51 | |||
52 | Object.assign(plugins, hlsOptionsBuilder.getPluginOptions()) | ||
53 | } else if (this.mode === 'webtorrent') { | ||
54 | const webtorrentOptionsBuilder = new WebTorrentOptionsBuilder(this.options, this.getAutoPlayValue(autoplay, alreadyPlayed)) | ||
55 | |||
56 | Object.assign(plugins, webtorrentOptionsBuilder.getPluginOptions()) | ||
57 | |||
58 | // WebTorrent plugin handles autoplay, because we do some hackish stuff in there | ||
59 | autoplay = false | ||
60 | } | ||
61 | |||
62 | const controlBarOptionsBuilder = new ControlBarOptionsBuilder(this.options, this.mode) | ||
63 | |||
64 | const videojsOptions = { | ||
65 | html5, | ||
66 | |||
67 | // We don't use text track settings for now | ||
68 | textTrackSettings: false as any, // FIXME: typings | ||
69 | controls: commonOptions.controls !== undefined ? commonOptions.controls : true, | ||
70 | loop: commonOptions.loop !== undefined ? commonOptions.loop : false, | ||
71 | |||
72 | muted: commonOptions.muted !== undefined | ||
73 | ? commonOptions.muted | ||
74 | : undefined, // Undefined so the player knows it has to check the local storage | ||
75 | |||
76 | autoplay: this.getAutoPlayValue(autoplay, alreadyPlayed), | ||
77 | |||
78 | poster: commonOptions.poster, | ||
79 | inactivityTimeout: commonOptions.inactivityTimeout, | ||
80 | playbackRates: [ 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2 ], | ||
81 | |||
82 | plugins, | ||
83 | |||
84 | controlBar: { | ||
85 | children: controlBarOptionsBuilder.getChildrenOptions() as any // FIXME: typings | ||
86 | } | ||
87 | } | ||
88 | |||
89 | if (commonOptions.language && !isDefaultLocale(commonOptions.language)) { | ||
90 | Object.assign(videojsOptions, { language: commonOptions.language }) | ||
91 | } | ||
92 | |||
93 | return videojsOptions | ||
94 | } | ||
95 | |||
96 | private getAutoPlayValue (autoplay: any, alreadyPlayed: boolean) { | ||
97 | if (autoplay !== true) return autoplay | ||
98 | |||
99 | // On first play, disable autoplay to avoid issues | ||
100 | // But if the player already played videos, we can safely autoplay next ones | ||
101 | if (isIOS() || isSafari()) { | ||
102 | return alreadyPlayed ? 'play' : false | ||
103 | } | ||
104 | |||
105 | return 'play' | ||
106 | } | ||
107 | |||
108 | getContextMenuOptions (player: videojs.Player, commonOptions: CommonOptions) { | ||
109 | const content = () => { | ||
110 | const isLoopEnabled = player.options_['loop'] | ||
111 | |||
112 | const items = [ | ||
113 | { | ||
114 | icon: 'repeat', | ||
115 | label: player.localize('Play in loop') + (isLoopEnabled ? '<span class="vjs-icon-tick-white"></span>' : ''), | ||
116 | listener: function () { | ||
117 | player.options_['loop'] = !isLoopEnabled | ||
118 | } | ||
119 | }, | ||
120 | { | ||
121 | label: player.localize('Copy the video URL'), | ||
122 | listener: function () { | ||
123 | copyToClipboard(buildVideoLink({ shortUUID: commonOptions.videoShortUUID })) | ||
124 | } | ||
125 | }, | ||
126 | { | ||
127 | label: player.localize('Copy the video URL at the current time'), | ||
128 | listener: function (this: videojs.Player) { | ||
129 | const url = buildVideoLink({ shortUUID: commonOptions.videoShortUUID }) | ||
130 | |||
131 | copyToClipboard(decorateVideoLink({ url, startTime: this.currentTime() })) | ||
132 | } | ||
133 | }, | ||
134 | { | ||
135 | icon: 'code', | ||
136 | label: player.localize('Copy embed code'), | ||
137 | listener: () => { | ||
138 | copyToClipboard(buildVideoOrPlaylistEmbed(commonOptions.embedUrl, commonOptions.embedTitle)) | ||
139 | } | ||
140 | } | ||
141 | ] | ||
142 | |||
143 | if (this.mode === 'webtorrent') { | ||
144 | items.push({ | ||
145 | label: player.localize('Copy magnet URI'), | ||
146 | listener: function (this: videojs.Player) { | ||
147 | copyToClipboard(this.webtorrent().getCurrentVideoFile().magnetUri) | ||
148 | } | ||
149 | }) | ||
150 | } | ||
151 | |||
152 | items.push({ | ||
153 | icon: 'info', | ||
154 | label: player.localize('Stats for nerds'), | ||
155 | listener: () => { | ||
156 | player.stats().show() | ||
157 | } | ||
158 | }) | ||
159 | |||
160 | return items.map(i => ({ | ||
161 | ...i, | ||
162 | label: `<span class="vjs-icon-${i.icon || 'link-2'}"></span>` + i.label | ||
163 | })) | ||
164 | } | ||
165 | |||
166 | return { content } | ||
167 | } | ||
168 | } | ||
diff --git a/client/src/assets/player/manager-options/manager-options.model.ts b/client/src/assets/player/manager-options/manager-options.model.ts new file mode 100644 index 000000000..0b0f8b435 --- /dev/null +++ b/client/src/assets/player/manager-options/manager-options.model.ts | |||
@@ -0,0 +1,84 @@ | |||
1 | import { PluginsManager } from '@root-helpers/plugins-manager' | ||
2 | import { LiveVideoLatencyMode, VideoFile } from '@shared/models' | ||
3 | import { PlaylistPluginOptions, UserWatching, VideoJSCaption } from '../peertube-videojs-typings' | ||
4 | |||
5 | export type PlayerMode = 'webtorrent' | 'p2p-media-loader' | ||
6 | |||
7 | export type WebtorrentOptions = { | ||
8 | videoFiles: VideoFile[] | ||
9 | } | ||
10 | |||
11 | export type P2PMediaLoaderOptions = { | ||
12 | playlistUrl: string | ||
13 | segmentsSha256Url: string | ||
14 | trackerAnnounce: string[] | ||
15 | redundancyBaseUrls: string[] | ||
16 | videoFiles: VideoFile[] | ||
17 | } | ||
18 | |||
19 | export interface CustomizationOptions { | ||
20 | startTime: number | string | ||
21 | stopTime: number | string | ||
22 | |||
23 | controls?: boolean | ||
24 | muted?: boolean | ||
25 | loop?: boolean | ||
26 | subtitle?: string | ||
27 | resume?: string | ||
28 | |||
29 | peertubeLink: boolean | ||
30 | } | ||
31 | |||
32 | export interface CommonOptions extends CustomizationOptions { | ||
33 | playerElement: HTMLVideoElement | ||
34 | onPlayerElementChange: (element: HTMLVideoElement) => void | ||
35 | |||
36 | autoplay: boolean | ||
37 | p2pEnabled: boolean | ||
38 | |||
39 | nextVideo?: () => void | ||
40 | hasNextVideo?: () => boolean | ||
41 | |||
42 | previousVideo?: () => void | ||
43 | hasPreviousVideo?: () => boolean | ||
44 | |||
45 | playlist?: PlaylistPluginOptions | ||
46 | |||
47 | videoDuration: number | ||
48 | enableHotkeys: boolean | ||
49 | inactivityTimeout: number | ||
50 | poster: string | ||
51 | |||
52 | theaterButton: boolean | ||
53 | captions: boolean | ||
54 | |||
55 | videoViewUrl: string | ||
56 | embedUrl: string | ||
57 | embedTitle: string | ||
58 | |||
59 | isLive: boolean | ||
60 | liveOptions?: { | ||
61 | latencyMode: LiveVideoLatencyMode | ||
62 | } | ||
63 | |||
64 | language?: string | ||
65 | |||
66 | videoCaptions: VideoJSCaption[] | ||
67 | |||
68 | videoUUID: string | ||
69 | videoShortUUID: string | ||
70 | |||
71 | userWatching?: UserWatching | ||
72 | |||
73 | serverUrl: string | ||
74 | |||
75 | errorNotifier: (message: string) => void | ||
76 | } | ||
77 | |||
78 | export type PeertubePlayerManagerOptions = { | ||
79 | common: CommonOptions | ||
80 | webtorrent: WebtorrentOptions | ||
81 | p2pMediaLoader?: P2PMediaLoaderOptions | ||
82 | |||
83 | pluginsManager: PluginsManager | ||
84 | } | ||
diff --git a/client/src/assets/player/manager-options/webtorrent-options-builder.ts b/client/src/assets/player/manager-options/webtorrent-options-builder.ts new file mode 100644 index 000000000..303940b29 --- /dev/null +++ b/client/src/assets/player/manager-options/webtorrent-options-builder.ts | |||
@@ -0,0 +1,36 @@ | |||
1 | import { PeertubePlayerManagerOptions } from './manager-options.model' | ||
2 | |||
3 | export class WebTorrentOptionsBuilder { | ||
4 | |||
5 | constructor ( | ||
6 | private options: PeertubePlayerManagerOptions, | ||
7 | private autoPlayValue: any | ||
8 | ) { | ||
9 | |||
10 | } | ||
11 | |||
12 | getPluginOptions () { | ||
13 | const commonOptions = this.options.common | ||
14 | const webtorrentOptions = this.options.webtorrent | ||
15 | const p2pMediaLoaderOptions = this.options.p2pMediaLoader | ||
16 | |||
17 | const autoplay = this.autoPlayValue === 'play' | ||
18 | |||
19 | const webtorrent = { | ||
20 | autoplay, | ||
21 | |||
22 | playerRefusedP2P: commonOptions.p2pEnabled === false, | ||
23 | videoDuration: commonOptions.videoDuration, | ||
24 | playerElement: commonOptions.playerElement, | ||
25 | |||
26 | videoFiles: webtorrentOptions.videoFiles.length !== 0 | ||
27 | ? webtorrentOptions.videoFiles | ||
28 | // The WebTorrent plugin won't be able to play these files, but it will fallback to HTTP mode | ||
29 | : p2pMediaLoaderOptions?.videoFiles || [], | ||
30 | |||
31 | startTime: commonOptions.startTime | ||
32 | } | ||
33 | |||
34 | return { webtorrent } | ||
35 | } | ||
36 | } | ||