diff options
Diffstat (limited to 'client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts')
-rw-r--r-- | client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts | 89 |
1 files changed, 60 insertions, 29 deletions
diff --git a/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts b/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts index d05d6193c..d83ec625a 100644 --- a/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts +++ b/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts | |||
@@ -14,6 +14,10 @@ type Metadata = { | |||
14 | levels: Level[] | 14 | levels: Level[] |
15 | } | 15 | } |
16 | 16 | ||
17 | // --------------------------------------------------------------------------- | ||
18 | // Source handler registration | ||
19 | // --------------------------------------------------------------------------- | ||
20 | |||
17 | type HookFn = (player: videojs.Player, hljs: Hlsjs) => void | 21 | type HookFn = (player: videojs.Player, hljs: Hlsjs) => void |
18 | 22 | ||
19 | const registerSourceHandler = function (vjs: typeof videojs) { | 23 | const registerSourceHandler = function (vjs: typeof videojs) { |
@@ -25,10 +29,13 @@ const registerSourceHandler = function (vjs: typeof videojs) { | |||
25 | const html5 = vjs.getTech('Html5') | 29 | const html5 = vjs.getTech('Html5') |
26 | 30 | ||
27 | if (!html5) { | 31 | if (!html5) { |
28 | logger.error('No Hml5 tech found in videojs') | 32 | logger.error('No "Html5" tech found in videojs') |
29 | return | 33 | return |
30 | } | 34 | } |
31 | 35 | ||
36 | // Already registered | ||
37 | if ((html5 as any).canPlaySource({ type: 'application/x-mpegURL' })) return | ||
38 | |||
32 | // FIXME: typings | 39 | // FIXME: typings |
33 | (html5 as any).registerSourceHandler({ | 40 | (html5 as any).registerSourceHandler({ |
34 | canHandleSource: function (source: videojs.Tech.SourceObject) { | 41 | canHandleSource: function (source: videojs.Tech.SourceObject) { |
@@ -56,32 +63,55 @@ const registerSourceHandler = function (vjs: typeof videojs) { | |||
56 | (vjs as any).Html5Hlsjs = Html5Hlsjs | 63 | (vjs as any).Html5Hlsjs = Html5Hlsjs |
57 | } | 64 | } |
58 | 65 | ||
59 | function hlsjsConfigHandler (this: videojs.Player, options: HlsjsConfigHandlerOptions) { | 66 | // --------------------------------------------------------------------------- |
60 | const player = this | 67 | // HLS options plugin |
68 | // --------------------------------------------------------------------------- | ||
61 | 69 | ||
62 | if (!options) return | 70 | const Plugin = videojs.getPlugin('plugin') |
63 | 71 | ||
64 | if (!player.srOptions_) { | 72 | class HLSJSConfigHandler extends Plugin { |
65 | player.srOptions_ = {} | 73 | |
66 | } | 74 | constructor (player: videojs.Player, options: HlsjsConfigHandlerOptions) { |
75 | super(player, options) | ||
76 | |||
77 | if (!options) return | ||
78 | |||
79 | if (!player.srOptions_) { | ||
80 | player.srOptions_ = {} | ||
81 | } | ||
82 | |||
83 | if (!player.srOptions_.hlsjsConfig) { | ||
84 | player.srOptions_.hlsjsConfig = options.hlsjsConfig | ||
85 | } | ||
67 | 86 | ||
68 | if (!player.srOptions_.hlsjsConfig) { | 87 | if (options.levelLabelHandler && !player.srOptions_.levelLabelHandler) { |
69 | player.srOptions_.hlsjsConfig = options.hlsjsConfig | 88 | player.srOptions_.levelLabelHandler = options.levelLabelHandler |
89 | } | ||
90 | |||
91 | registerSourceHandler(videojs) | ||
70 | } | 92 | } |
71 | 93 | ||
72 | if (options.levelLabelHandler && !player.srOptions_.levelLabelHandler) { | 94 | dispose () { |
73 | player.srOptions_.levelLabelHandler = options.levelLabelHandler | 95 | this.player.srOptions_ = undefined |
96 | |||
97 | const tech = this.player.tech(true) as any | ||
98 | if (tech.hlsProvider) { | ||
99 | tech.hlsProvider.dispose() | ||
100 | tech.hlsProvider = undefined | ||
101 | } | ||
102 | |||
103 | super.dispose() | ||
74 | } | 104 | } |
75 | } | 105 | } |
76 | 106 | ||
77 | const registerConfigPlugin = function (vjs: typeof videojs) { | 107 | videojs.registerPlugin('hlsjs', HLSJSConfigHandler) |
78 | // Used in Brightcove since we don't pass options directly there | 108 | |
79 | const registerVjsPlugin = vjs.registerPlugin || vjs.plugin | 109 | // --------------------------------------------------------------------------- |
80 | registerVjsPlugin('hlsjs', hlsjsConfigHandler) | 110 | // HLS JS source handler |
81 | } | 111 | // --------------------------------------------------------------------------- |
82 | 112 | ||
83 | class Html5Hlsjs { | 113 | export class Html5Hlsjs { |
84 | private static readonly hooks: { [id: string]: HookFn[] } = {} | 114 | private static hooks: { [id: string]: HookFn[] } = {} |
85 | 115 | ||
86 | private readonly videoElement: HTMLVideoElement | 116 | private readonly videoElement: HTMLVideoElement |
87 | private readonly errorCounts: ErrorCounts = {} | 117 | private readonly errorCounts: ErrorCounts = {} |
@@ -101,8 +131,9 @@ class Html5Hlsjs { | |||
101 | private dvrDuration: number = null | 131 | private dvrDuration: number = null |
102 | private edgeMargin: number = null | 132 | private edgeMargin: number = null |
103 | 133 | ||
104 | private handlers: { [ id in 'play' ]: EventListener } = { | 134 | private handlers: { [ id in 'play' | 'error' ]: EventListener } = { |
105 | play: null | 135 | play: null, |
136 | error: null | ||
106 | } | 137 | } |
107 | 138 | ||
108 | constructor (vjs: typeof videojs, source: videojs.Tech.SourceObject, tech: videojs.Tech) { | 139 | constructor (vjs: typeof videojs, source: videojs.Tech.SourceObject, tech: videojs.Tech) { |
@@ -115,7 +146,7 @@ class Html5Hlsjs { | |||
115 | this.videoElement = tech.el() as HTMLVideoElement | 146 | this.videoElement = tech.el() as HTMLVideoElement |
116 | this.player = vjs((tech.options_ as any).playerId) | 147 | this.player = vjs((tech.options_ as any).playerId) |
117 | 148 | ||
118 | this.videoElement.addEventListener('error', event => { | 149 | this.handlers.error = event => { |
119 | let errorTxt: string | 150 | let errorTxt: string |
120 | const mediaError = ((event.currentTarget || event.target) as HTMLVideoElement).error | 151 | const mediaError = ((event.currentTarget || event.target) as HTMLVideoElement).error |
121 | 152 | ||
@@ -143,7 +174,8 @@ class Html5Hlsjs { | |||
143 | } | 174 | } |
144 | 175 | ||
145 | logger.error(`MEDIA_ERROR: ${errorTxt}`) | 176 | logger.error(`MEDIA_ERROR: ${errorTxt}`) |
146 | }) | 177 | } |
178 | this.videoElement.addEventListener('error', this.handlers.error) | ||
147 | 179 | ||
148 | this.initialize() | 180 | this.initialize() |
149 | } | 181 | } |
@@ -174,6 +206,7 @@ class Html5Hlsjs { | |||
174 | // See comment for `initialize` method. | 206 | // See comment for `initialize` method. |
175 | dispose () { | 207 | dispose () { |
176 | this.videoElement.removeEventListener('play', this.handlers.play) | 208 | this.videoElement.removeEventListener('play', this.handlers.play) |
209 | this.videoElement.removeEventListener('error', this.handlers.error) | ||
177 | 210 | ||
178 | // FIXME: https://github.com/video-dev/hls.js/issues/4092 | 211 | // FIXME: https://github.com/video-dev/hls.js/issues/4092 |
179 | const untypedHLS = this.hls as any | 212 | const untypedHLS = this.hls as any |
@@ -200,6 +233,10 @@ class Html5Hlsjs { | |||
200 | return true | 233 | return true |
201 | } | 234 | } |
202 | 235 | ||
236 | static removeAllHooks () { | ||
237 | Html5Hlsjs.hooks = {} | ||
238 | } | ||
239 | |||
203 | private _executeHooksFor (type: string) { | 240 | private _executeHooksFor (type: string) { |
204 | if (Html5Hlsjs.hooks[type] === undefined) { | 241 | if (Html5Hlsjs.hooks[type] === undefined) { |
205 | return | 242 | return |
@@ -421,7 +458,7 @@ class Html5Hlsjs { | |||
421 | ? data.level | 458 | ? data.level |
422 | : -1 | 459 | : -1 |
423 | 460 | ||
424 | this.player.peertubeResolutions().select({ id: resolutionId, autoResolutionChosenId, byEngine: true }) | 461 | this.player.peertubeResolutions().select({ id: resolutionId, autoResolutionChosenId, fireCallback: false }) |
425 | }) | 462 | }) |
426 | 463 | ||
427 | this.hls.attachMedia(this.videoElement) | 464 | this.hls.attachMedia(this.videoElement) |
@@ -433,9 +470,3 @@ class Html5Hlsjs { | |||
433 | this._initHlsjs() | 470 | this._initHlsjs() |
434 | } | 471 | } |
435 | } | 472 | } |
436 | |||
437 | export { | ||
438 | Html5Hlsjs, | ||
439 | registerSourceHandler, | ||
440 | registerConfigPlugin | ||
441 | } | ||