@livepeer-frameworks/player-core 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. package/README.md +11 -9
  2. package/dist/cjs/core/ABRController.js +456 -0
  3. package/dist/cjs/core/ABRController.js.map +1 -0
  4. package/dist/cjs/core/CodecUtils.js +195 -0
  5. package/dist/cjs/core/CodecUtils.js.map +1 -0
  6. package/dist/cjs/core/ErrorClassifier.js +410 -0
  7. package/dist/cjs/core/ErrorClassifier.js.map +1 -0
  8. package/dist/cjs/core/EventEmitter.js +108 -0
  9. package/dist/cjs/core/EventEmitter.js.map +1 -0
  10. package/dist/cjs/core/GatewayClient.js +342 -0
  11. package/dist/cjs/core/GatewayClient.js.map +1 -0
  12. package/dist/cjs/core/InteractionController.js +606 -0
  13. package/dist/cjs/core/InteractionController.js.map +1 -0
  14. package/dist/cjs/core/LiveDurationProxy.js +186 -0
  15. package/dist/cjs/core/LiveDurationProxy.js.map +1 -0
  16. package/dist/cjs/core/MetaTrackManager.js +624 -0
  17. package/dist/cjs/core/MetaTrackManager.js.map +1 -0
  18. package/dist/cjs/core/MistReporter.js +449 -0
  19. package/dist/cjs/core/MistReporter.js.map +1 -0
  20. package/dist/cjs/core/MistSignaling.js +264 -0
  21. package/dist/cjs/core/MistSignaling.js.map +1 -0
  22. package/dist/cjs/core/PlayerController.js +2658 -0
  23. package/dist/cjs/core/PlayerController.js.map +1 -0
  24. package/dist/cjs/core/PlayerInterface.js +269 -0
  25. package/dist/cjs/core/PlayerInterface.js.map +1 -0
  26. package/dist/cjs/core/PlayerManager.js +806 -0
  27. package/dist/cjs/core/PlayerManager.js.map +1 -0
  28. package/dist/cjs/core/PlayerRegistry.js +270 -0
  29. package/dist/cjs/core/PlayerRegistry.js.map +1 -0
  30. package/dist/cjs/core/QualityMonitor.js +474 -0
  31. package/dist/cjs/core/QualityMonitor.js.map +1 -0
  32. package/dist/cjs/core/SeekingUtils.js +292 -0
  33. package/dist/cjs/core/SeekingUtils.js.map +1 -0
  34. package/dist/cjs/core/StreamStateClient.js +381 -0
  35. package/dist/cjs/core/StreamStateClient.js.map +1 -0
  36. package/dist/cjs/core/SubtitleManager.js +227 -0
  37. package/dist/cjs/core/SubtitleManager.js.map +1 -0
  38. package/dist/cjs/core/TelemetryReporter.js +258 -0
  39. package/dist/cjs/core/TelemetryReporter.js.map +1 -0
  40. package/dist/cjs/core/TimeFormat.js +176 -0
  41. package/dist/cjs/core/TimeFormat.js.map +1 -0
  42. package/dist/cjs/core/TimerManager.js +176 -0
  43. package/dist/cjs/core/TimerManager.js.map +1 -0
  44. package/dist/cjs/core/UrlUtils.js +160 -0
  45. package/dist/cjs/core/UrlUtils.js.map +1 -0
  46. package/dist/cjs/core/detector.js +293 -0
  47. package/dist/cjs/core/detector.js.map +1 -0
  48. package/dist/cjs/core/scorer.js +443 -0
  49. package/dist/cjs/core/scorer.js.map +1 -0
  50. package/dist/cjs/index.js +121 -20134
  51. package/dist/cjs/index.js.map +1 -1
  52. package/dist/cjs/lib/utils.js +11 -0
  53. package/dist/cjs/lib/utils.js.map +1 -0
  54. package/dist/cjs/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.js +6 -0
  55. package/dist/cjs/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.js.map +1 -0
  56. package/dist/cjs/node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/bundle-mjs.js +3042 -0
  57. package/dist/cjs/node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  58. package/dist/cjs/players/DashJsPlayer.js +638 -0
  59. package/dist/cjs/players/DashJsPlayer.js.map +1 -0
  60. package/dist/cjs/players/HlsJsPlayer.js +482 -0
  61. package/dist/cjs/players/HlsJsPlayer.js.map +1 -0
  62. package/dist/cjs/players/MewsWsPlayer/SourceBufferManager.js +522 -0
  63. package/dist/cjs/players/MewsWsPlayer/SourceBufferManager.js.map +1 -0
  64. package/dist/cjs/players/MewsWsPlayer/WebSocketManager.js +215 -0
  65. package/dist/cjs/players/MewsWsPlayer/WebSocketManager.js.map +1 -0
  66. package/dist/cjs/players/MewsWsPlayer/index.js +987 -0
  67. package/dist/cjs/players/MewsWsPlayer/index.js.map +1 -0
  68. package/dist/cjs/players/MistPlayer.js +185 -0
  69. package/dist/cjs/players/MistPlayer.js.map +1 -0
  70. package/dist/cjs/players/MistWebRTCPlayer/index.js +635 -0
  71. package/dist/cjs/players/MistWebRTCPlayer/index.js.map +1 -0
  72. package/dist/cjs/players/NativePlayer.js +762 -0
  73. package/dist/cjs/players/NativePlayer.js.map +1 -0
  74. package/dist/cjs/players/VideoJsPlayer.js +585 -0
  75. package/dist/cjs/players/VideoJsPlayer.js.map +1 -0
  76. package/dist/cjs/players/WebCodecsPlayer/JitterBuffer.js +236 -0
  77. package/dist/cjs/players/WebCodecsPlayer/JitterBuffer.js.map +1 -0
  78. package/dist/cjs/players/WebCodecsPlayer/LatencyProfiles.js +143 -0
  79. package/dist/cjs/players/WebCodecsPlayer/LatencyProfiles.js.map +1 -0
  80. package/dist/cjs/players/WebCodecsPlayer/RawChunkParser.js +96 -0
  81. package/dist/cjs/players/WebCodecsPlayer/RawChunkParser.js.map +1 -0
  82. package/dist/cjs/players/WebCodecsPlayer/SyncController.js +359 -0
  83. package/dist/cjs/players/WebCodecsPlayer/SyncController.js.map +1 -0
  84. package/dist/cjs/players/WebCodecsPlayer/WebSocketController.js +460 -0
  85. package/dist/cjs/players/WebCodecsPlayer/WebSocketController.js.map +1 -0
  86. package/dist/cjs/players/WebCodecsPlayer/index.js +1467 -0
  87. package/dist/cjs/players/WebCodecsPlayer/index.js.map +1 -0
  88. package/dist/cjs/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.js +320 -0
  89. package/dist/cjs/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.js.map +1 -0
  90. package/dist/cjs/styles/index.js +57 -0
  91. package/dist/cjs/styles/index.js.map +1 -0
  92. package/dist/cjs/vanilla/FrameWorksPlayer.js +269 -0
  93. package/dist/cjs/vanilla/FrameWorksPlayer.js.map +1 -0
  94. package/dist/cjs/vanilla.js +11 -0
  95. package/dist/cjs/vanilla.js.map +1 -0
  96. package/dist/esm/core/ABRController.js +454 -0
  97. package/dist/esm/core/ABRController.js.map +1 -0
  98. package/dist/esm/core/CodecUtils.js +193 -0
  99. package/dist/esm/core/CodecUtils.js.map +1 -0
  100. package/dist/esm/core/ErrorClassifier.js +408 -0
  101. package/dist/esm/core/ErrorClassifier.js.map +1 -0
  102. package/dist/esm/core/EventEmitter.js +106 -0
  103. package/dist/esm/core/EventEmitter.js.map +1 -0
  104. package/dist/esm/core/GatewayClient.js +340 -0
  105. package/dist/esm/core/GatewayClient.js.map +1 -0
  106. package/dist/esm/core/InteractionController.js +604 -0
  107. package/dist/esm/core/InteractionController.js.map +1 -0
  108. package/dist/esm/core/LiveDurationProxy.js +184 -0
  109. package/dist/esm/core/LiveDurationProxy.js.map +1 -0
  110. package/dist/esm/core/MetaTrackManager.js +622 -0
  111. package/dist/esm/core/MetaTrackManager.js.map +1 -0
  112. package/dist/esm/core/MistReporter.js +447 -0
  113. package/dist/esm/core/MistReporter.js.map +1 -0
  114. package/dist/esm/core/MistSignaling.js +262 -0
  115. package/dist/esm/core/MistSignaling.js.map +1 -0
  116. package/dist/esm/core/PlayerController.js +2651 -0
  117. package/dist/esm/core/PlayerController.js.map +1 -0
  118. package/dist/esm/core/PlayerInterface.js +267 -0
  119. package/dist/esm/core/PlayerInterface.js.map +1 -0
  120. package/dist/esm/core/PlayerManager.js +804 -0
  121. package/dist/esm/core/PlayerManager.js.map +1 -0
  122. package/dist/esm/core/PlayerRegistry.js +264 -0
  123. package/dist/esm/core/PlayerRegistry.js.map +1 -0
  124. package/dist/esm/core/QualityMonitor.js +471 -0
  125. package/dist/esm/core/QualityMonitor.js.map +1 -0
  126. package/dist/esm/core/SeekingUtils.js +280 -0
  127. package/dist/esm/core/SeekingUtils.js.map +1 -0
  128. package/dist/esm/core/StreamStateClient.js +379 -0
  129. package/dist/esm/core/StreamStateClient.js.map +1 -0
  130. package/dist/esm/core/SubtitleManager.js +225 -0
  131. package/dist/esm/core/SubtitleManager.js.map +1 -0
  132. package/dist/esm/core/TelemetryReporter.js +256 -0
  133. package/dist/esm/core/TelemetryReporter.js.map +1 -0
  134. package/dist/esm/core/TimeFormat.js +169 -0
  135. package/dist/esm/core/TimeFormat.js.map +1 -0
  136. package/dist/esm/core/TimerManager.js +174 -0
  137. package/dist/esm/core/TimerManager.js.map +1 -0
  138. package/dist/esm/core/UrlUtils.js +151 -0
  139. package/dist/esm/core/UrlUtils.js.map +1 -0
  140. package/dist/esm/core/detector.js +279 -0
  141. package/dist/esm/core/detector.js.map +1 -0
  142. package/dist/esm/core/scorer.js +422 -0
  143. package/dist/esm/core/scorer.js.map +1 -0
  144. package/dist/esm/index.js +26 -20043
  145. package/dist/esm/index.js.map +1 -1
  146. package/dist/esm/lib/utils.js +9 -0
  147. package/dist/esm/lib/utils.js.map +1 -0
  148. package/dist/esm/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.js +4 -0
  149. package/dist/esm/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.js.map +1 -0
  150. package/dist/esm/node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/bundle-mjs.js +3036 -0
  151. package/dist/esm/node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  152. package/dist/esm/players/DashJsPlayer.js +636 -0
  153. package/dist/esm/players/DashJsPlayer.js.map +1 -0
  154. package/dist/esm/players/HlsJsPlayer.js +480 -0
  155. package/dist/esm/players/HlsJsPlayer.js.map +1 -0
  156. package/dist/esm/players/MewsWsPlayer/SourceBufferManager.js +520 -0
  157. package/dist/esm/players/MewsWsPlayer/SourceBufferManager.js.map +1 -0
  158. package/dist/esm/players/MewsWsPlayer/WebSocketManager.js +213 -0
  159. package/dist/esm/players/MewsWsPlayer/WebSocketManager.js.map +1 -0
  160. package/dist/esm/players/MewsWsPlayer/index.js +985 -0
  161. package/dist/esm/players/MewsWsPlayer/index.js.map +1 -0
  162. package/dist/esm/players/MistPlayer.js +183 -0
  163. package/dist/esm/players/MistPlayer.js.map +1 -0
  164. package/dist/esm/players/MistWebRTCPlayer/index.js +633 -0
  165. package/dist/esm/players/MistWebRTCPlayer/index.js.map +1 -0
  166. package/dist/esm/players/NativePlayer.js +759 -0
  167. package/dist/esm/players/NativePlayer.js.map +1 -0
  168. package/dist/esm/players/VideoJsPlayer.js +583 -0
  169. package/dist/esm/players/VideoJsPlayer.js.map +1 -0
  170. package/dist/esm/players/WebCodecsPlayer/JitterBuffer.js +233 -0
  171. package/dist/esm/players/WebCodecsPlayer/JitterBuffer.js.map +1 -0
  172. package/dist/esm/players/WebCodecsPlayer/LatencyProfiles.js +134 -0
  173. package/dist/esm/players/WebCodecsPlayer/LatencyProfiles.js.map +1 -0
  174. package/dist/esm/players/WebCodecsPlayer/RawChunkParser.js +91 -0
  175. package/dist/esm/players/WebCodecsPlayer/RawChunkParser.js.map +1 -0
  176. package/dist/esm/players/WebCodecsPlayer/SyncController.js +357 -0
  177. package/dist/esm/players/WebCodecsPlayer/SyncController.js.map +1 -0
  178. package/dist/esm/players/WebCodecsPlayer/WebSocketController.js +458 -0
  179. package/dist/esm/players/WebCodecsPlayer/WebSocketController.js.map +1 -0
  180. package/dist/esm/players/WebCodecsPlayer/index.js +1458 -0
  181. package/dist/esm/players/WebCodecsPlayer/index.js.map +1 -0
  182. package/dist/esm/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.js +315 -0
  183. package/dist/esm/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.js.map +1 -0
  184. package/dist/esm/styles/index.js +54 -0
  185. package/dist/esm/styles/index.js.map +1 -0
  186. package/dist/esm/vanilla/FrameWorksPlayer.js +264 -0
  187. package/dist/esm/vanilla/FrameWorksPlayer.js.map +1 -0
  188. package/dist/esm/vanilla.js +2 -0
  189. package/dist/esm/vanilla.js.map +1 -0
  190. package/dist/player.css +185 -42
  191. package/dist/types/core/ABRController.d.ts +4 -4
  192. package/dist/types/core/CodecUtils.d.ts +1 -1
  193. package/dist/types/core/ErrorClassifier.d.ts +77 -0
  194. package/dist/types/core/GatewayClient.d.ts +4 -4
  195. package/dist/types/core/MetaTrackManager.d.ts +2 -2
  196. package/dist/types/core/MistReporter.d.ts +3 -3
  197. package/dist/types/core/MistSignaling.d.ts +12 -12
  198. package/dist/types/core/PlayerController.d.ts +19 -14
  199. package/dist/types/core/PlayerInterface.d.ts +100 -2
  200. package/dist/types/core/PlayerManager.d.ts +36 -9
  201. package/dist/types/core/PlayerRegistry.d.ts +11 -11
  202. package/dist/types/core/QualityMonitor.d.ts +2 -2
  203. package/dist/types/core/SeekingUtils.d.ts +2 -2
  204. package/dist/types/core/StreamStateClient.d.ts +2 -2
  205. package/dist/types/core/TelemetryReporter.d.ts +1 -1
  206. package/dist/types/core/TimerManager.d.ts +1 -1
  207. package/dist/types/core/detector.d.ts +1 -1
  208. package/dist/types/core/index.d.ts +44 -44
  209. package/dist/types/core/scorer.d.ts +1 -1
  210. package/dist/types/core/selector.d.ts +2 -2
  211. package/dist/types/index.d.ts +35 -34
  212. package/dist/types/players/DashJsPlayer.d.ts +3 -3
  213. package/dist/types/players/HlsJsPlayer.d.ts +3 -3
  214. package/dist/types/players/MewsWsPlayer/SourceBufferManager.d.ts +1 -1
  215. package/dist/types/players/MewsWsPlayer/WebSocketManager.d.ts +1 -1
  216. package/dist/types/players/MewsWsPlayer/index.d.ts +2 -2
  217. package/dist/types/players/MewsWsPlayer/types.d.ts +15 -15
  218. package/dist/types/players/MistPlayer.d.ts +2 -2
  219. package/dist/types/players/MistWebRTCPlayer/index.d.ts +3 -3
  220. package/dist/types/players/NativePlayer.d.ts +3 -3
  221. package/dist/types/players/VideoJsPlayer.d.ts +3 -3
  222. package/dist/types/players/WebCodecsPlayer/JitterBuffer.d.ts +3 -3
  223. package/dist/types/players/WebCodecsPlayer/LatencyProfiles.d.ts +1 -1
  224. package/dist/types/players/WebCodecsPlayer/RawChunkParser.d.ts +2 -2
  225. package/dist/types/players/WebCodecsPlayer/SyncController.d.ts +2 -2
  226. package/dist/types/players/WebCodecsPlayer/WebSocketController.d.ts +3 -3
  227. package/dist/types/players/WebCodecsPlayer/index.d.ts +9 -9
  228. package/dist/types/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.d.ts +1 -1
  229. package/dist/types/players/WebCodecsPlayer/types.d.ts +49 -49
  230. package/dist/types/players/WebCodecsPlayer/worker/types.d.ts +31 -31
  231. package/dist/types/players/index.d.ts +5 -8
  232. package/dist/types/types.d.ts +15 -15
  233. package/dist/types/vanilla/FrameWorksPlayer.d.ts +2 -2
  234. package/dist/types/vanilla/index.d.ts +4 -4
  235. package/dist/workers/decoder.worker.js +129 -122
  236. package/dist/workers/decoder.worker.js.map +1 -1
  237. package/package.json +31 -15
  238. package/src/core/ABRController.ts +38 -36
  239. package/src/core/CodecUtils.ts +49 -46
  240. package/src/core/Disposable.ts +4 -4
  241. package/src/core/ErrorClassifier.ts +499 -0
  242. package/src/core/EventEmitter.ts +1 -1
  243. package/src/core/GatewayClient.ts +41 -39
  244. package/src/core/InteractionController.ts +89 -82
  245. package/src/core/LiveDurationProxy.ts +14 -15
  246. package/src/core/MetaTrackManager.ts +73 -65
  247. package/src/core/MistReporter.ts +72 -45
  248. package/src/core/MistSignaling.ts +59 -56
  249. package/src/core/PlayerController.ts +542 -384
  250. package/src/core/PlayerInterface.ts +192 -59
  251. package/src/core/PlayerManager.ts +354 -164
  252. package/src/core/PlayerRegistry.ts +238 -87
  253. package/src/core/QualityMonitor.ts +38 -31
  254. package/src/core/ScreenWakeLockManager.ts +8 -9
  255. package/src/core/SeekingUtils.ts +31 -22
  256. package/src/core/StreamStateClient.ts +74 -68
  257. package/src/core/SubtitleManager.ts +24 -22
  258. package/src/core/TelemetryReporter.ts +38 -32
  259. package/src/core/TimeFormat.ts +13 -17
  260. package/src/core/TimerManager.ts +24 -8
  261. package/src/core/UrlUtils.ts +20 -17
  262. package/src/core/detector.ts +44 -44
  263. package/src/core/index.ts +57 -48
  264. package/src/core/scorer.ts +136 -141
  265. package/src/core/selector.ts +2 -6
  266. package/src/global.d.ts +1 -1
  267. package/src/index.ts +56 -36
  268. package/src/players/DashJsPlayer.ts +164 -115
  269. package/src/players/HlsJsPlayer.ts +132 -78
  270. package/src/players/MewsWsPlayer/SourceBufferManager.ts +41 -36
  271. package/src/players/MewsWsPlayer/WebSocketManager.ts +9 -9
  272. package/src/players/MewsWsPlayer/index.ts +192 -152
  273. package/src/players/MewsWsPlayer/types.ts +21 -21
  274. package/src/players/MistPlayer.ts +45 -26
  275. package/src/players/MistWebRTCPlayer/index.ts +175 -129
  276. package/src/players/NativePlayer.ts +203 -143
  277. package/src/players/VideoJsPlayer.ts +170 -118
  278. package/src/players/WebCodecsPlayer/JitterBuffer.ts +6 -7
  279. package/src/players/WebCodecsPlayer/LatencyProfiles.ts +43 -43
  280. package/src/players/WebCodecsPlayer/RawChunkParser.ts +10 -10
  281. package/src/players/WebCodecsPlayer/SyncController.ts +45 -53
  282. package/src/players/WebCodecsPlayer/WebSocketController.ts +66 -68
  283. package/src/players/WebCodecsPlayer/index.ts +265 -223
  284. package/src/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.ts +12 -17
  285. package/src/players/WebCodecsPlayer/types.ts +56 -56
  286. package/src/players/WebCodecsPlayer/worker/decoder.worker.ts +238 -182
  287. package/src/players/WebCodecsPlayer/worker/types.ts +31 -31
  288. package/src/players/index.ts +5 -16
  289. package/src/styles/animations.css +2 -1
  290. package/src/styles/player.css +185 -42
  291. package/src/styles/tailwind.css +473 -159
  292. package/src/types.ts +43 -43
  293. package/src/vanilla/FrameWorksPlayer.ts +26 -14
  294. package/src/vanilla/index.ts +4 -4
@@ -1,110 +1,262 @@
1
1
  /**
2
2
  * Player Registry
3
3
  *
4
- * Central registration of all available player implementations
4
+ * Lazy registration of player implementations. Capabilities are declared
5
+ * statically so MIME-based filtering happens without importing any player
6
+ * modules. Only the players matching the stream's source types are loaded.
5
7
  */
6
8
 
7
- import { PlayerManager } from './PlayerManager';
8
- import type { IPlayer } from './PlayerInterface';
9
+ import { PlayerManager } from "./PlayerManager";
10
+ import type { IPlayer, PlayerCapability } from "./PlayerInterface";
11
+
12
+ // ============================================================================
13
+ // Lazy Player Entry
14
+ // ============================================================================
15
+
16
+ interface LazyPlayerEntry {
17
+ capability: PlayerCapability;
18
+ load: () => Promise<IPlayer>;
19
+ }
9
20
 
10
21
  /**
11
- * Shared registration state per manager instance. Ensures that we only
12
- * dynamically import and attach transport adapters once per manager.
22
+ * Static capability registry. Each entry declares its capabilities (MIME types,
23
+ * priority) and a lazy loader that dynamically imports the implementation.
24
+ * No player code is loaded until `load()` is called.
13
25
  */
14
- const managerRegistrationPromises = new WeakMap<PlayerManager, Promise<void>>();
26
+ const PLAYER_ENTRIES: LazyPlayerEntry[] = [
27
+ {
28
+ capability: {
29
+ name: "Native Player",
30
+ shortname: "native",
31
+ priority: 1,
32
+ mimes: [
33
+ "html5/video/mp4",
34
+ "html5/video/webm",
35
+ "html5/video/ogg",
36
+ "html5/audio/mp3",
37
+ "html5/audio/webm",
38
+ "html5/audio/ogg",
39
+ "html5/audio/wav",
40
+ "html5/application/vnd.apple.mpegurl",
41
+ "html5/application/vnd.apple.mpegurl;version=7",
42
+ "whep",
43
+ ],
44
+ },
45
+ load: () => import("../players/NativePlayer").then((m) => new m.NativePlayerImpl()),
46
+ },
47
+ {
48
+ capability: {
49
+ name: "WebCodecs Player",
50
+ shortname: "webcodecs",
51
+ priority: 0,
52
+ mimes: ["ws/video/raw", "wss/video/raw", "ws/video/h264", "wss/video/h264"],
53
+ },
54
+ load: () => import("../players/WebCodecsPlayer").then((m) => new m.WebCodecsPlayerImpl()),
55
+ },
56
+ {
57
+ capability: {
58
+ name: "MistServer WebRTC",
59
+ shortname: "mist-webrtc",
60
+ priority: 2,
61
+ mimes: ["webrtc", "mist/webrtc"],
62
+ },
63
+ load: () => import("../players/MistWebRTCPlayer").then((m) => new m.MistWebRTCPlayerImpl()),
64
+ },
65
+ {
66
+ capability: {
67
+ name: "Video.js Player",
68
+ shortname: "videojs",
69
+ priority: 2,
70
+ mimes: [
71
+ "html5/application/vnd.apple.mpegurl",
72
+ "html5/application/vnd.apple.mpegurl;version=7",
73
+ ],
74
+ },
75
+ load: () => import("../players/VideoJsPlayer").then((m) => new m.VideoJsPlayerImpl()),
76
+ },
77
+ {
78
+ capability: {
79
+ name: "HLS.js Player",
80
+ shortname: "hlsjs",
81
+ priority: 3,
82
+ mimes: [
83
+ "html5/application/vnd.apple.mpegurl",
84
+ "html5/application/vnd.apple.mpegurl;version=7",
85
+ ],
86
+ },
87
+ load: () => import("../players/HlsJsPlayer").then((m) => new m.HlsJsPlayerImpl()),
88
+ },
89
+ {
90
+ capability: {
91
+ name: "Dash.js Player",
92
+ shortname: "dashjs",
93
+ priority: 100,
94
+ mimes: ["dash/video/mp4"],
95
+ },
96
+ load: () => import("../players/DashJsPlayer").then((m) => new m.DashJsPlayerImpl()),
97
+ },
98
+ {
99
+ capability: {
100
+ name: "Legacy",
101
+ shortname: "mist-legacy",
102
+ priority: 99,
103
+ mimes: ["mist/legacy"],
104
+ },
105
+ load: () => import("../players/MistPlayer").then((m) => new m.MistPlayerImpl()),
106
+ },
107
+ {
108
+ capability: {
109
+ name: "MEWS WebSocket Player",
110
+ shortname: "mews",
111
+ priority: 2,
112
+ mimes: ["ws/video/mp4", "wss/video/mp4", "ws/video/webm", "wss/video/webm"],
113
+ },
114
+ load: () => import("../players/MewsWsPlayer").then((m) => new m.MewsWsPlayerImpl()),
115
+ },
116
+ ];
117
+
118
+ // ============================================================================
119
+ // Loading State
120
+ // ============================================================================
121
+
122
+ /** Track which players have been loaded per manager */
123
+ const loadedPlayersMap = new WeakMap<PlayerManager, Set<string>>();
15
124
 
16
- async function registerPlayersForManager(manager: PlayerManager): Promise<void> {
17
- console.log('[PlayerRegistry] registerPlayersForManager starting...');
18
- if (manager.getRegisteredPlayers().length > 0) {
19
- console.log('[PlayerRegistry] Players already registered');
20
- return;
125
+ function getLoadedSet(manager: PlayerManager): Set<string> {
126
+ let set = loadedPlayersMap.get(manager);
127
+ if (!set) {
128
+ set = new Set();
129
+ loadedPlayersMap.set(manager, set);
21
130
  }
131
+ return set;
132
+ }
133
+
134
+ /**
135
+ * Load only players whose capabilities match the given source MIME types.
136
+ * Already-loaded players are skipped. Safe to call multiple times with
137
+ * different MIME types — new players are added incrementally.
138
+ */
139
+ async function loadMatchingPlayers(manager: PlayerManager, sourceMimes: string[]): Promise<void> {
140
+ const loaded = getLoadedSet(manager);
141
+
142
+ const toLoad = PLAYER_ENTRIES.filter((entry) => {
143
+ if (loaded.has(entry.capability.shortname)) return false;
144
+ return entry.capability.mimes.some((m) => sourceMimes.includes(m));
145
+ });
146
+
147
+ if (toLoad.length === 0) return;
22
148
 
23
- console.log('[PlayerRegistry] Dynamically importing player modules...');
24
- const [
25
- nativeModule,
26
- videoModule,
27
- hlsModule,
28
- dashModule,
29
- mistModule,
30
- mewsModule,
31
- mistWebRTCModule,
32
- webCodecsModule
33
- ] = await Promise.all([
34
- import('../players/NativePlayer'),
35
- import('../players/VideoJsPlayer'),
36
- import('../players/HlsJsPlayer'),
37
- import('../players/DashJsPlayer'),
38
- import('../players/MistPlayer'),
39
- import('../players/MewsWsPlayer'),
40
- import('../players/MistWebRTCPlayer'),
41
- import('../players/WebCodecsPlayer')
42
- ]);
43
-
44
- console.log('[PlayerRegistry] All player modules imported, instantiating...');
45
- const instantiatedPlayers: IPlayer[] = [
46
- new nativeModule.NativePlayerImpl(),
47
- new webCodecsModule.WebCodecsPlayerImpl(), // Priority 1 - lowest latency
48
- new mistWebRTCModule.MistWebRTCPlayerImpl(), // Priority 2
49
- new videoModule.VideoJsPlayerImpl(),
50
- new hlsModule.HlsJsPlayerImpl(),
51
- new dashModule.DashJsPlayerImpl(),
52
- new mistModule.MistPlayerImpl(),
53
- new mewsModule.MewsWsPlayerImpl()
54
- ];
55
-
56
- for (const player of instantiatedPlayers) {
149
+ const players = await Promise.all(toLoad.map((e) => e.load()));
150
+ for (const player of players) {
151
+ loaded.add(player.capability.shortname);
57
152
  const alreadyRegistered = manager
58
153
  .getRegisteredPlayers()
59
- .some(existing => existing.capability.shortname === player.capability.shortname);
60
-
154
+ .some((p) => p.capability.shortname === player.capability.shortname);
61
155
  if (!alreadyRegistered) {
62
156
  manager.registerPlayer(player);
63
157
  }
64
158
  }
65
- console.log(`[PlayerRegistry] Registration complete. ${manager.getRegisteredPlayers().length} players registered.`);
66
159
  }
67
160
 
68
- export function ensurePlayersRegistered(manager: PlayerManager = globalPlayerManager): Promise<void> {
69
- console.log('[PlayerRegistry] ensurePlayersRegistered called');
70
- if (manager.getRegisteredPlayers().length > 0) {
71
- console.log('[PlayerRegistry] Already registered, returning');
72
- return Promise.resolve();
161
+ /**
162
+ * Load a specific player by shortname. Used for forcePlayer support.
163
+ */
164
+ async function loadPlayerByShortname(manager: PlayerManager, shortname: string): Promise<void> {
165
+ const loaded = getLoadedSet(manager);
166
+ if (loaded.has(shortname)) return;
167
+
168
+ const entry = PLAYER_ENTRIES.find((e) => e.capability.shortname === shortname);
169
+ if (!entry) return;
170
+
171
+ const player = await entry.load();
172
+ loaded.add(player.capability.shortname);
173
+ const alreadyRegistered = manager
174
+ .getRegisteredPlayers()
175
+ .some((p) => p.capability.shortname === player.capability.shortname);
176
+ if (!alreadyRegistered) {
177
+ manager.registerPlayer(player);
73
178
  }
179
+ }
180
+
181
+ /**
182
+ * Load all players. Used for backwards compatibility (createPlayerManager,
183
+ * registerAllPlayers) and when no MIME filter is available.
184
+ */
185
+ async function loadAllPlayers(manager: PlayerManager): Promise<void> {
186
+ const allMimes = PLAYER_ENTRIES.flatMap((e) => e.capability.mimes);
187
+ return loadMatchingPlayers(manager, allMimes);
188
+ }
189
+
190
+ // ============================================================================
191
+ // Public API
192
+ // ============================================================================
193
+
194
+ /** Deduplication promises for full registration (loadAllPlayers) */
195
+ const fullRegistrationPromises = new WeakMap<PlayerManager, Promise<void>>();
74
196
 
75
- const existing = managerRegistrationPromises.get(manager);
76
- if (existing) {
77
- console.log('[PlayerRegistry] Using existing registration promise');
78
- return existing;
197
+ /**
198
+ * Ensure all players are registered. Backwards-compatible API that loads
199
+ * every player module. Prefer the MIME-filtered path via initializePlayer.
200
+ */
201
+ export function ensurePlayersRegistered(
202
+ manager: PlayerManager = globalPlayerManager
203
+ ): Promise<void> {
204
+ const loaded = getLoadedSet(manager);
205
+ if (loaded.size === PLAYER_ENTRIES.length) {
206
+ return Promise.resolve();
79
207
  }
80
208
 
81
- console.log('[PlayerRegistry] Starting new registration...');
82
- const registrationPromise = registerPlayersForManager(manager).catch(error => {
83
- console.error('[PlayerRegistry] Registration failed:', error);
84
- managerRegistrationPromises.delete(manager);
209
+ const existing = fullRegistrationPromises.get(manager);
210
+ if (existing) return existing;
211
+
212
+ const promise = loadAllPlayers(manager).catch((error) => {
213
+ console.error("[PlayerRegistry] Registration failed:", error);
214
+ fullRegistrationPromises.delete(manager);
85
215
  throw error;
86
216
  });
87
217
 
88
- managerRegistrationPromises.set(manager, registrationPromise);
89
- return registrationPromise;
218
+ fullRegistrationPromises.set(manager, promise);
219
+ return promise;
90
220
  }
91
221
 
222
+ /**
223
+ * Monkey-patch initializePlayer to lazily load only matching players.
224
+ * Extracts source MIME types from streamInfo and loads the subset of
225
+ * player modules that can handle those types.
226
+ */
92
227
  const originalInitialize = PlayerManager.prototype.initializePlayer;
93
- PlayerManager.prototype.initializePlayer = async function (...args: Parameters<PlayerManager['initializePlayer']>) {
94
- console.log('[PlayerRegistry] initializePlayer wrapper - calling ensurePlayersRegistered...');
95
- await ensurePlayersRegistered(this);
96
- console.log('[PlayerRegistry] ensurePlayersRegistered done, calling original initializePlayer...');
228
+ PlayerManager.prototype.initializePlayer = async function (
229
+ ...args: Parameters<PlayerManager["initializePlayer"]>
230
+ ) {
231
+ const [_container, streamInfo, _playerOptions, managerOptions] = args;
232
+ const sourceMimes = streamInfo?.source?.map((s) => s.type) ?? [];
233
+
234
+ if (sourceMimes.length > 0) {
235
+ // Load only players matching the stream's source types
236
+ await loadMatchingPlayers(this, sourceMimes);
237
+
238
+ // Also load a forced player if specified
239
+ if (managerOptions?.forcePlayer) {
240
+ await loadPlayerByShortname(this, managerOptions.forcePlayer);
241
+ }
242
+ } else {
243
+ // No source info — fall back to loading all
244
+ await ensurePlayersRegistered(this);
245
+ }
246
+
97
247
  return originalInitialize.apply(this, args);
98
248
  };
99
249
 
100
- /**
101
- * Global PlayerManager instance with deferred registration
102
- */
250
+ // ============================================================================
251
+ // Global Instance
252
+ // ============================================================================
253
+
103
254
  const isDev = (() => {
104
255
  try {
105
- // In browser builds, process may be undefined; guard access
106
- // @ts-ignore
107
- return typeof process !== 'undefined' && process && process.env && process.env.NODE_ENV === 'development';
256
+ const g = globalThis as Record<string, unknown>;
257
+ const p = g.process as Record<string, unknown> | undefined;
258
+ const env = p?.env as Record<string, unknown> | undefined;
259
+ return env?.NODE_ENV === "development";
108
260
  } catch {
109
261
  return false;
110
262
  }
@@ -113,37 +265,36 @@ const isDev = (() => {
113
265
  export const globalPlayerManager = new PlayerManager({
114
266
  debug: isDev,
115
267
  autoFallback: true,
116
- maxFallbackAttempts: 3
268
+ maxFallbackAttempts: 3,
117
269
  });
118
270
 
119
271
  /**
120
272
  * Register all available players (async for backwards compatibility)
121
273
  */
122
- export async function registerAllPlayers(manager: PlayerManager = globalPlayerManager): Promise<void> {
274
+ export async function registerAllPlayers(
275
+ manager: PlayerManager = globalPlayerManager
276
+ ): Promise<void> {
123
277
  await ensurePlayersRegistered(manager);
124
278
  }
125
279
 
126
280
  /**
127
281
  * Create a new PlayerManager instance with all players registered
128
282
  */
129
- export function createPlayerManager(options?: ConstructorParameters<typeof PlayerManager>[0]): PlayerManager {
283
+ export function createPlayerManager(
284
+ options?: ConstructorParameters<typeof PlayerManager>[0]
285
+ ): PlayerManager {
130
286
  const manager = new PlayerManager(options);
131
- ensurePlayersRegistered(manager).catch(error => {
287
+ ensurePlayersRegistered(manager).catch((error) => {
132
288
  if (isDev) {
133
- console.warn('Player registration failed:', error);
289
+ console.warn("Player registration failed:", error);
134
290
  }
135
291
  });
136
292
  return manager;
137
293
  }
138
294
 
139
295
  /**
140
- * Export individual player classes for direct use
296
+ * Get the static capability registry (for UI display without loading modules)
141
297
  */
142
- export { NativePlayerImpl, DirectPlaybackPlayerImpl } from '../players/NativePlayer';
143
- export { HlsJsPlayerImpl } from '../players/HlsJsPlayer';
144
- export { DashJsPlayerImpl } from '../players/DashJsPlayer';
145
- export { VideoJsPlayerImpl } from '../players/VideoJsPlayer';
146
- export { MistPlayerImpl } from '../players/MistPlayer';
147
- export { MewsWsPlayerImpl } from '../players/MewsWsPlayer';
148
- export { MistWebRTCPlayerImpl } from '../players/MistWebRTCPlayer';
149
- export { WebCodecsPlayerImpl } from '../players/WebCodecsPlayer';
298
+ export function getAvailablePlayerCapabilities(): PlayerCapability[] {
299
+ return PLAYER_ENTRIES.map((e) => e.capability);
300
+ }
@@ -1,5 +1,5 @@
1
- import type { PlaybackQuality, QualityThresholds } from '../types';
2
- import { TimerManager } from './TimerManager';
1
+ import type { PlaybackQuality, QualityThresholds } from "../types";
2
+ import { TimerManager } from "./TimerManager";
3
3
 
4
4
  /**
5
5
  * Default quality thresholds
@@ -19,21 +19,21 @@ const ROLLING_WINDOW_SIZE = 20;
19
19
  * Playback score history entry (for MistPlayer-style 0-2.0 score)
20
20
  */
21
21
  interface PlaybackScoreEntry {
22
- clock: number; // Wall clock time in seconds
23
- video: number; // Video currentTime
24
- score: number; // Calculated score for this sample
22
+ clock: number; // Wall clock time in seconds
23
+ video: number; // Video currentTime
24
+ score: number; // Calculated score for this sample
25
25
  }
26
26
 
27
27
  /** Protocol type for threshold selection */
28
- export type PlayerProtocol = 'webrtc' | 'hls' | 'dash' | 'html5' | 'unknown';
28
+ export type PlayerProtocol = "webrtc" | "hls" | "dash" | "html5" | "unknown";
29
29
 
30
30
  /** Protocol-specific playback score thresholds (MistMetaPlayer reference) */
31
31
  export const PROTOCOL_THRESHOLDS: Record<PlayerProtocol, number> = {
32
- webrtc: 0.95, // Very strict for low-latency
33
- hls: 0.75, // More lenient for adaptive streaming
34
- dash: 0.75, // More lenient for adaptive streaming
35
- html5: 0.75, // Standard threshold
36
- unknown: 0.75, // Default
32
+ webrtc: 0.95, // Very strict for low-latency
33
+ hls: 0.75, // More lenient for adaptive streaming
34
+ dash: 0.75, // More lenient for adaptive streaming
35
+ html5: 0.75, // Standard threshold
36
+ unknown: 0.75, // Default
37
37
  };
38
38
 
39
39
  export interface QualityMonitorOptions {
@@ -82,7 +82,7 @@ export interface QualityMonitorState {
82
82
  */
83
83
  export class QualityMonitor {
84
84
  private videoElement: HTMLVideoElement | null = null;
85
- private options: Required<Omit<QualityMonitorOptions, 'protocol' | 'playbackScoreThreshold'>> & {
85
+ private options: Required<Omit<QualityMonitorOptions, "protocol" | "playbackScoreThreshold">> & {
86
86
  protocol: PlayerProtocol;
87
87
  playbackScoreThreshold: number | null;
88
88
  };
@@ -112,7 +112,7 @@ export class QualityMonitor {
112
112
  thresholds: options.thresholds ?? {},
113
113
  onQualityDegraded: options.onQualityDegraded ?? (() => {}),
114
114
  onSample: options.onSample ?? (() => {}),
115
- protocol: options.protocol ?? 'unknown',
115
+ protocol: options.protocol ?? "unknown",
116
116
  playbackScoreThreshold: options.playbackScoreThreshold ?? null,
117
117
  onFallbackRequest: options.onFallbackRequest ?? (() => {}),
118
118
  poorSamplesBeforeFallback: options.poorSamplesBeforeFallback ?? 5,
@@ -190,18 +190,18 @@ export class QualityMonitor {
190
190
  }
191
191
  };
192
192
 
193
- videoElement.addEventListener('waiting', onWaiting);
194
- videoElement.addEventListener('playing', onPlaying);
195
- videoElement.addEventListener('canplay', onCanPlay);
193
+ videoElement.addEventListener("waiting", onWaiting);
194
+ videoElement.addEventListener("playing", onPlaying);
195
+ videoElement.addEventListener("canplay", onCanPlay);
196
196
 
197
197
  this.listeners = [
198
- () => videoElement.removeEventListener('waiting', onWaiting),
199
- () => videoElement.removeEventListener('playing', onPlaying),
200
- () => videoElement.removeEventListener('canplay', onCanPlay),
198
+ () => videoElement.removeEventListener("waiting", onWaiting),
199
+ () => videoElement.removeEventListener("playing", onPlaying),
200
+ () => videoElement.removeEventListener("canplay", onCanPlay),
201
201
  ];
202
202
 
203
203
  // Start sampling interval
204
- this.timers.startInterval(() => this.sample(), this.options.sampleInterval, 'sampling');
204
+ this.timers.startInterval(() => this.sample(), this.options.sampleInterval, "sampling");
205
205
 
206
206
  // Take initial sample
207
207
  this.sample();
@@ -213,7 +213,7 @@ export class QualityMonitor {
213
213
  stop(): void {
214
214
  this.timers.destroy();
215
215
 
216
- this.listeners.forEach(cleanup => cleanup());
216
+ this.listeners.forEach((cleanup) => cleanup());
217
217
  this.listeners = [];
218
218
 
219
219
  this.videoElement = null;
@@ -241,9 +241,11 @@ export class QualityMonitor {
241
241
  this.options.onSample(quality);
242
242
 
243
243
  // Check for quality degradation
244
- if (quality.score < this.thresholds.minScore ||
245
- quality.stallCount > this.thresholds.maxStalls ||
246
- quality.bufferedAhead < this.thresholds.minBuffer) {
244
+ if (
245
+ quality.score < this.thresholds.minScore ||
246
+ quality.stallCount > this.thresholds.maxStalls ||
247
+ quality.bufferedAhead < this.thresholds.minBuffer
248
+ ) {
247
249
  this.options.onQualityDegraded(quality);
248
250
  }
249
251
 
@@ -254,13 +256,15 @@ export class QualityMonitor {
254
256
 
255
257
  // Trigger fallback after sustained poor quality
256
258
  // Only trigger once until quality improves or reset
257
- if (!this.fallbackTriggered &&
258
- this.consecutivePoorSamples >= this.options.poorSamplesBeforeFallback) {
259
+ if (
260
+ !this.fallbackTriggered &&
261
+ this.consecutivePoorSamples >= this.options.poorSamplesBeforeFallback
262
+ ) {
259
263
  this.fallbackTriggered = true;
260
264
  console.warn(
261
265
  `[QualityMonitor] Poor playback detected: ${Math.round(this.playbackScore * 100)}% ` +
262
- `(threshold: ${Math.round(this.getPlaybackScoreThreshold() * 100)}%, ` +
263
- `protocol: ${this.options.protocol})`
266
+ `(threshold: ${Math.round(this.getPlaybackScoreThreshold() * 100)}%, ` +
267
+ `protocol: ${this.options.protocol})`
264
268
  );
265
269
  this.options.onFallbackRequest({
266
270
  score: this.playbackScore,
@@ -284,7 +288,10 @@ export class QualityMonitor {
284
288
  let bufferedAhead = 0;
285
289
  if (video.buffered.length > 0) {
286
290
  for (let i = 0; i < video.buffered.length; i++) {
287
- if (video.buffered.start(i) <= video.currentTime && video.buffered.end(i) > video.currentTime) {
291
+ if (
292
+ video.buffered.start(i) <= video.currentTime &&
293
+ video.buffered.end(i) > video.currentTime
294
+ ) {
288
295
  bufferedAhead = video.buffered.end(i) - video.currentTime;
289
296
  break;
290
297
  }
@@ -296,7 +303,7 @@ export class QualityMonitor {
296
303
  let framesDropped = 0;
297
304
  let frameDropRate = 0;
298
305
 
299
- if ('getVideoPlaybackQuality' in video) {
306
+ if ("getVideoPlaybackQuality" in video) {
300
307
  const stats = video.getVideoPlaybackQuality();
301
308
  framesDecoded = stats.totalVideoFrames;
302
309
  framesDropped = stats.droppedVideoFrames;
@@ -505,7 +512,7 @@ export class QualityMonitor {
505
512
 
506
513
  if (clockDelta <= 0) return 1.0;
507
514
 
508
- return (videoDelta / clockDelta) / rate;
515
+ return videoDelta / clockDelta / rate;
509
516
  }
510
517
 
511
518
  /**
@@ -32,13 +32,13 @@ export class ScreenWakeLockManager {
32
32
 
33
33
  constructor(config: ScreenWakeLockConfig = {}) {
34
34
  this.config = config;
35
- this.isSupported = 'wakeLock' in navigator;
35
+ this.isSupported = "wakeLock" in navigator;
36
36
 
37
37
  this.boundVisibilityChange = this.handleVisibilityChange.bind(this);
38
38
 
39
39
  // Re-acquire wake lock when page becomes visible again
40
40
  if (this.isSupported) {
41
- document.addEventListener('visibilitychange', this.boundVisibilityChange);
41
+ document.addEventListener("visibilitychange", this.boundVisibilityChange);
42
42
  }
43
43
  }
44
44
 
@@ -46,7 +46,7 @@ export class ScreenWakeLockManager {
46
46
  * Check if Screen Wake Lock API is supported
47
47
  */
48
48
  static isSupported(): boolean {
49
- return 'wakeLock' in navigator;
49
+ return "wakeLock" in navigator;
50
50
  }
51
51
 
52
52
  /**
@@ -85,8 +85,8 @@ export class ScreenWakeLockManager {
85
85
  if (this.wakeLock) return;
86
86
 
87
87
  try {
88
- this.wakeLock = await navigator.wakeLock.request('screen');
89
- this.wakeLock.addEventListener('release', this.handleRelease.bind(this));
88
+ this.wakeLock = await navigator.wakeLock.request("screen");
89
+ this.wakeLock.addEventListener("release", this.handleRelease.bind(this));
90
90
  this.config.onAcquire?.();
91
91
  } catch (err) {
92
92
  // Wake lock request can fail if:
@@ -119,7 +119,7 @@ export class ScreenWakeLockManager {
119
119
  this.release();
120
120
 
121
121
  if (this.isSupported) {
122
- document.removeEventListener('visibilitychange', this.boundVisibilityChange);
122
+ document.removeEventListener("visibilitychange", this.boundVisibilityChange);
123
123
  }
124
124
  }
125
125
 
@@ -127,8 +127,7 @@ export class ScreenWakeLockManager {
127
127
  * Update wake lock based on current state
128
128
  */
129
129
  private updateWakeLock(): void {
130
- const shouldHold =
131
- this.isPlaying && (this.isFullscreen || this.config.acquireOnPlay);
130
+ const shouldHold = this.isPlaying && (this.isFullscreen || this.config.acquireOnPlay);
132
131
 
133
132
  if (shouldHold && !this.wakeLock) {
134
133
  this.acquire();
@@ -154,7 +153,7 @@ export class ScreenWakeLockManager {
154
153
  * Handle visibility change - re-acquire if page becomes visible
155
154
  */
156
155
  private handleVisibilityChange(): void {
157
- if (document.visibilityState === 'visible' && !this.wakeLock) {
156
+ if (document.visibilityState === "visible" && !this.wakeLock) {
158
157
  this.updateWakeLock();
159
158
  }
160
159
  }