]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/assets/player/shared/manager-options/hls-options-builder.ts
Force autoplay when live starts
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / shared / manager-options / hls-options-builder.ts
CommitLineData
9597920e
C
1import { HybridLoaderSettings } from '@peertube/p2p-media-loader-core'
2import { HlsJsEngineSettings } from '@peertube/p2p-media-loader-hlsjs'
42b40636 3import { logger } from '@root-helpers/logger'
9597920e 4import { LiveVideoLatencyMode } from '@shared/models'
57d65032
C
5import { getAverageBandwidthInStore } from '../../peertube-player-local-storage'
6import { P2PMediaLoader, P2PMediaLoaderPluginOptions } from '../../types'
7import { PeertubePlayerManagerOptions } from '../../types/manager-options'
3545e72c 8import { getRtcConfig, isSameOrigin } from '../common'
9597920e
C
9import { RedundancyUrlManager } from '../p2p-media-loader/redundancy-url-manager'
10import { segmentUrlBuilderFactory } from '../p2p-media-loader/segment-url-builder'
11import { segmentValidatorFactory } from '../p2p-media-loader/segment-validator'
9597920e
C
12
13export class HLSOptionsBuilder {
14
15 constructor (
16 private options: PeertubePlayerManagerOptions,
17 private p2pMediaLoaderModule?: any
18 ) {
19
20 }
21
9866921c 22 async getPluginOptions () {
9597920e
C
23 const commonOptions = this.options.common
24
25 const redundancyUrlManager = new RedundancyUrlManager(this.options.p2pMediaLoader.redundancyBaseUrls)
26
9866921c 27 const p2pMediaLoaderConfig = await this.options.pluginsManager.runHook(
28 'filter:internal.player.p2p-media-loader.options.result',
29 this.getP2PMediaLoaderOptions(redundancyUrlManager)
30 )
9597920e
C
31 const loader = new this.p2pMediaLoaderModule.Engine(p2pMediaLoaderConfig).createLoaderClass() as P2PMediaLoader
32
33 const p2pMediaLoader: P2PMediaLoaderPluginOptions = {
326f3692
C
34 requiresAuth: commonOptions.requiresAuth,
35
9597920e
C
36 redundancyUrlManager,
37 type: 'application/x-mpegURL',
38 startTime: commonOptions.startTime,
39 src: this.options.p2pMediaLoader.playlistUrl,
40 loader
41 }
42
43 const hlsjs = {
44 levelLabelHandler: (level: { height: number, width: number }) => {
45 const resolution = Math.min(level.height || 0, level.width || 0)
46
47 const file = this.options.p2pMediaLoader.videoFiles.find(f => f.resolution.id === resolution)
48 // We don't have files for live videos
49 if (!file) return level.height
50
51 let label = file.resolution.label
52 if (file.fps >= 50) label += file.fps
53
54 return label
9597920e
C
55 }
56 }
57
e71e2d8a
C
58 const html5 = {
59 hlsjsConfig: this.getHLSJSOptions(loader)
60 }
61
62 return { p2pMediaLoader, hlsjs, html5 }
9597920e
C
63 }
64
65 // ---------------------------------------------------------------------------
66
67 private getP2PMediaLoaderOptions (redundancyUrlManager: RedundancyUrlManager): HlsJsEngineSettings {
68 let consumeOnly = false
69 if ((navigator as any)?.connection?.type === 'cellular') {
42b40636 70 logger.info('We are on a cellular connection: disabling seeding.')
9597920e
C
71 consumeOnly = true
72 }
73
74 const trackerAnnounce = this.options.p2pMediaLoader.trackerAnnounce
75 .filter(t => t.startsWith('ws'))
76
77 const specificLiveOrVODOptions = this.options.common.isLive
78 ? this.getP2PMediaLoaderLiveOptions()
79 : this.getP2PMediaLoaderVODOptions()
80
81 return {
82 loader: {
9597920e
C
83 trackerAnnounce,
84 rtcConfig: getRtcConfig(),
85
86 simultaneousHttpDownloads: 1,
87 httpFailedSegmentTimeout: 1000,
88
3545e72c
C
89 xhrSetup: (xhr, url) => {
90 if (!this.options.common.requiresAuth) return
91 if (!isSameOrigin(this.options.common.serverUrl, url)) return
92
93 xhr.setRequestHeader('Authorization', this.options.common.authorizationHeader())
94 },
95
96 segmentValidator: segmentValidatorFactory({
97 segmentsSha256Url: this.options.p2pMediaLoader.segmentsSha256Url,
98 isLive: this.options.common.isLive,
99 authorizationHeader: this.options.common.authorizationHeader,
100 requiresAuth: this.options.common.requiresAuth,
101 serverUrl: this.options.common.serverUrl
102 }),
103
a77c5ff3 104 segmentUrlBuilder: segmentUrlBuilderFactory(redundancyUrlManager),
9597920e
C
105
106 useP2P: this.options.common.p2pEnabled,
107 consumeOnly,
108
109 ...specificLiveOrVODOptions
110 },
111 segments: {
112 swarmId: this.options.p2pMediaLoader.playlistUrl,
023c3ca2 113 forwardSegmentCount: specificLiveOrVODOptions.p2pDownloadMaxPriority ?? 20
9597920e
C
114 }
115 }
116 }
117
118 private getP2PMediaLoaderLiveOptions (): Partial<HybridLoaderSettings> {
119 const base = {
120 requiredSegmentsPriority: 1
121 }
122
123 const latencyMode = this.options.common.liveOptions.latencyMode
124
125 switch (latencyMode) {
126 case LiveVideoLatencyMode.SMALL_LATENCY:
127 return {
128 ...base,
129
130 useP2P: false,
131 httpDownloadProbability: 1
132 }
133
134 case LiveVideoLatencyMode.HIGH_LATENCY:
135 return base
136
137 default:
138 return base
139 }
140 }
141
142 private getP2PMediaLoaderVODOptions (): Partial<HybridLoaderSettings> {
143 return {
144 requiredSegmentsPriority: 3,
a77c5ff3 145 skipSegmentBuilderPriority: 1,
9597920e
C
146
147 cachedSegmentExpiration: 86400000,
148 cachedSegmentsCount: 100,
149
150 httpDownloadMaxPriority: 9,
151 httpDownloadProbability: 0.06,
152 httpDownloadProbabilitySkipIfNoPeers: true,
153
154 p2pDownloadMaxPriority: 50
155 }
156 }
157
158 // ---------------------------------------------------------------------------
159
160 private getHLSJSOptions (loader: P2PMediaLoader) {
161 const specificLiveOrVODOptions = this.options.common.isLive
162 ? this.getHLSLiveOptions()
163 : this.getHLSVODOptions()
164
165 const base = {
166 capLevelToPlayerSize: true,
167 autoStartLoad: false,
168
169 loader,
170
171 ...specificLiveOrVODOptions
172 }
173
174 const averageBandwidth = getAverageBandwidthInStore()
175 if (!averageBandwidth) return base
176
177 return {
178 ...base,
179
180 abrEwmaDefaultEstimate: averageBandwidth * 8, // We want bit/s
a77c5ff3 181 backBufferLength: 90,
9597920e
C
182 startLevel: -1,
183 testBandwidth: false,
184 debug: false
185 }
186 }
187
188 private getHLSLiveOptions () {
189 const latencyMode = this.options.common.liveOptions.latencyMode
190
191 switch (latencyMode) {
192 case LiveVideoLatencyMode.SMALL_LATENCY:
193 return {
194 liveSyncDurationCount: 2
195 }
196
197 case LiveVideoLatencyMode.HIGH_LATENCY:
198 return {
199 liveSyncDurationCount: 10
200 }
201
202 default:
203 return {
204 liveSyncDurationCount: 5
205 }
206 }
207 }
208
209 private getHLSVODOptions () {
210 return {
211 liveSyncDurationCount: 5
212 }
213 }
214}