@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
@@ -0,0 +1,636 @@
1
+ import { BasePlayer } from '../core/PlayerInterface.js';
2
+ import { checkProtocolMismatch, isFileProtocol, getBrowserInfo } from '../core/detector.js';
3
+ import { translateCodec } from '../core/CodecUtils.js';
4
+
5
+ // Player implementation class
6
+ class DashJsPlayerImpl extends BasePlayer {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.capability = {
10
+ name: "Dash.js Player",
11
+ shortname: "dashjs",
12
+ priority: 100, // Below legacy (99) - DASH support is experimental
13
+ mimes: ["dash/video/mp4"],
14
+ };
15
+ this.dashPlayer = null;
16
+ this.container = null;
17
+ this.destroyed = false;
18
+ this.debugging = false;
19
+ // Live duration proxy state (ported from reference dashjs.js:81-122)
20
+ this.lastProgress = Date.now();
21
+ this.videoProxy = null;
22
+ this.streamType = "unknown";
23
+ // Subtitle deferred loading (ported from reference dashjs.js:173-197)
24
+ this.subsLoaded = false;
25
+ this.pendingSubtitleId = null;
26
+ }
27
+ isMimeSupported(mimetype) {
28
+ return this.capability.mimes.includes(mimetype);
29
+ }
30
+ isBrowserSupported(mimetype, source, streamInfo) {
31
+ // Check protocol mismatch
32
+ if (checkProtocolMismatch(source.url)) {
33
+ return false;
34
+ }
35
+ // Don't use DASH.js if loaded via file://
36
+ if (isFileProtocol()) {
37
+ return false;
38
+ }
39
+ const browser = getBrowserInfo();
40
+ // Check MediaSource support (required for DASH.js)
41
+ if (!browser.supportsMediaSource) {
42
+ return false;
43
+ }
44
+ // Check codec compatibility
45
+ const playableTracks = [];
46
+ const tracksByType = {};
47
+ // Group tracks by type
48
+ for (const track of streamInfo.meta.tracks) {
49
+ if (track.type === "meta") {
50
+ if (track.codec === "subtitle") {
51
+ // Check for WebVTT subtitle support
52
+ for (const src of streamInfo.source) {
53
+ if (src.type === "html5/text/vtt") {
54
+ playableTracks.push("subtitle");
55
+ break;
56
+ }
57
+ }
58
+ }
59
+ continue;
60
+ }
61
+ if (!tracksByType[track.type]) {
62
+ tracksByType[track.type] = [];
63
+ }
64
+ tracksByType[track.type].push(track);
65
+ }
66
+ // DASH-incompatible audio codecs for fMP4 segments (even if browser MSE supports them)
67
+ // Standard DASH audio: AAC, MP3, AC-3/E-AC-3. OPUS only works in WebM DASH (not fMP4)
68
+ const DASH_INCOMPATIBLE_AUDIO = ["OPUS", "Opus", "opus", "VORBIS", "Vorbis"];
69
+ // Test codec support for video/audio tracks
70
+ for (const [trackType, tracks] of Object.entries(tracksByType)) {
71
+ let hasPlayableTrack = false;
72
+ for (const track of tracks) {
73
+ // Explicit DASH codec filtering - OPUS in fMP4 DASH doesn't work reliably
74
+ if (trackType === "audio" && DASH_INCOMPATIBLE_AUDIO.includes(track.codec)) {
75
+ console.debug(`[DashJS] Codec incompatible with DASH fMP4: ${track.codec}`);
76
+ continue;
77
+ }
78
+ const codecString = translateCodec(track);
79
+ // Use correct container type for audio vs video tracks
80
+ const container = trackType === "audio" ? "audio/mp4" : "video/mp4";
81
+ const mimeType = `${container};codecs="${codecString}"`;
82
+ if (MediaSource.isTypeSupported && MediaSource.isTypeSupported(mimeType)) {
83
+ hasPlayableTrack = true;
84
+ break;
85
+ }
86
+ else {
87
+ console.debug(`[DashJS] Codec not supported: ${mimeType}`);
88
+ }
89
+ }
90
+ if (hasPlayableTrack) {
91
+ playableTracks.push(trackType);
92
+ }
93
+ }
94
+ return playableTracks.length > 0 ? playableTracks : false;
95
+ }
96
+ /**
97
+ * Check if current stream is live.
98
+ * Ported from reference dashjs.js live detection.
99
+ */
100
+ isLiveStream() {
101
+ if (this.streamType === "live")
102
+ return true;
103
+ if (this.streamType === "vod")
104
+ return false;
105
+ // Fallback: check video duration
106
+ const v = this.videoElement;
107
+ if (v && (v.duration === Infinity || !isFinite(v.duration))) {
108
+ return true;
109
+ }
110
+ return false;
111
+ }
112
+ /**
113
+ * Create a Proxy wrapper for the video element that intercepts duration for live streams.
114
+ * Ported from reference dashjs.js:81-122.
115
+ *
116
+ * For live streams, returns synthetic duration = buffer_end + time_since_last_progress
117
+ * This makes the seek bar usable for live content.
118
+ */
119
+ createVideoProxy(video) {
120
+ if (!("Proxy" in window)) {
121
+ // Fallback for older browsers
122
+ return video;
123
+ }
124
+ // Track buffer progress for duration extrapolation
125
+ video.addEventListener("progress", () => {
126
+ this.lastProgress = Date.now();
127
+ });
128
+ const self = this;
129
+ return new Proxy(video, {
130
+ get(target, key, receiver) {
131
+ // Override duration for live streams (reference dashjs.js:108-116)
132
+ if (key === "duration" && self.isLiveStream()) {
133
+ const buffered = target.buffered;
134
+ if (buffered.length > 0) {
135
+ const bufferEnd = buffered.end(buffered.length - 1);
136
+ const timeSinceBuffer = (Date.now() - self.lastProgress) / 1000;
137
+ return bufferEnd + timeSinceBuffer;
138
+ }
139
+ }
140
+ const value = Reflect.get(target, key, receiver);
141
+ // Bind functions to the original target
142
+ if (typeof value === "function") {
143
+ return value.bind(target);
144
+ }
145
+ return value;
146
+ },
147
+ set(target, key, value) {
148
+ return Reflect.set(target, key, value);
149
+ },
150
+ });
151
+ }
152
+ /**
153
+ * Set up comprehensive event logging.
154
+ * Ported from reference dashjs.js:152-160.
155
+ */
156
+ setupEventLogging(dashjs) {
157
+ const skipEvents = [
158
+ "METRIC_ADDED",
159
+ "METRIC_UPDATED",
160
+ "METRIC_CHANGED",
161
+ "METRICS_CHANGED",
162
+ "FRAGMENT_LOADING_STARTED",
163
+ "FRAGMENT_LOADING_COMPLETED",
164
+ "LOG",
165
+ "PLAYBACK_TIME_UPDATED",
166
+ "PLAYBACK_PROGRESS",
167
+ ];
168
+ const events = dashjs.MediaPlayer?.events || {};
169
+ for (const eventKey of Object.keys(events)) {
170
+ if (!skipEvents.includes(eventKey)) {
171
+ this.dashPlayer.on(events[eventKey], (e) => {
172
+ if (this.destroyed)
173
+ return;
174
+ if (this.debugging) {
175
+ console.log("DASH event:", e.type);
176
+ }
177
+ });
178
+ }
179
+ }
180
+ }
181
+ /**
182
+ * Set up subtitle deferred loading.
183
+ * Ported from reference dashjs.js:173-197.
184
+ */
185
+ setupSubtitleHandling() {
186
+ this.dashPlayer.on("allTextTracksAdded", () => {
187
+ if (this.destroyed)
188
+ return;
189
+ this.subsLoaded = true;
190
+ if (this.pendingSubtitleId !== null) {
191
+ this.selectTextTrack(this.pendingSubtitleId);
192
+ this.pendingSubtitleId = null;
193
+ }
194
+ });
195
+ }
196
+ /**
197
+ * Set up stalled indicator handling.
198
+ * Ported from reference dashjs.js:207-211.
199
+ */
200
+ setupStalledHandling() {
201
+ this.videoElement?.addEventListener("progress", () => {
202
+ // Clear any stalled state when buffer advances
203
+ // This integrates with the loading indicator system
204
+ });
205
+ }
206
+ async initialize(container, source, options) {
207
+ this.destroyed = false;
208
+ this.container = container;
209
+ this.subsLoaded = false;
210
+ this.pendingSubtitleId = null;
211
+ container.classList.add("fw-player-container");
212
+ // Detect stream type from source if available (reference dashjs.js live detection)
213
+ const sourceType = source.type;
214
+ if (sourceType === "live") {
215
+ this.streamType = "live";
216
+ }
217
+ else if (sourceType === "vod") {
218
+ this.streamType = "vod";
219
+ }
220
+ else {
221
+ this.streamType = "unknown";
222
+ }
223
+ // Create video element
224
+ const video = document.createElement("video");
225
+ video.classList.add("fw-player-video");
226
+ video.setAttribute("playsinline", "");
227
+ video.setAttribute("crossorigin", "anonymous");
228
+ // Apply options (ported from reference dashjs.js:129-142)
229
+ if (options.autoplay)
230
+ video.autoplay = true;
231
+ if (options.muted)
232
+ video.muted = true;
233
+ video.controls = options.controls === true;
234
+ // Loop only for VoD (reference dashjs.js: live streams don't loop)
235
+ if (options.loop && this.streamType !== "live")
236
+ video.loop = true;
237
+ if (options.poster)
238
+ video.poster = options.poster;
239
+ // Create proxy for live duration handling (reference dashjs.js:81-122)
240
+ this.videoProxy = this.createVideoProxy(video);
241
+ this.videoElement = video;
242
+ container.appendChild(video);
243
+ // Set up event listeners
244
+ this.setupVideoEventListeners(video, options);
245
+ this.setupStalledHandling();
246
+ try {
247
+ // Dynamic import of DASH.js
248
+ console.debug("[DashJS] Importing dashjs module...");
249
+ const mod = await import('dashjs');
250
+ const dashjs = mod.default || mod;
251
+ console.debug("[DashJS] Module imported:", dashjs);
252
+ this.dashPlayer = dashjs.MediaPlayer().create();
253
+ console.debug("[DashJS] MediaPlayer created");
254
+ // Set up event logging (reference dashjs.js:152-160)
255
+ this.setupEventLogging(dashjs);
256
+ // Set up subtitle handling (reference dashjs.js:173-197)
257
+ this.setupSubtitleHandling();
258
+ this.dashPlayer.on("error", (e) => {
259
+ if (this.destroyed)
260
+ return;
261
+ const error = `DASH error: ${e?.event?.message || e?.message || "unknown"}`;
262
+ console.error("[DashJS] Error event:", e);
263
+ this.emit("error", error);
264
+ });
265
+ // Log key dashjs events for debugging
266
+ this.dashPlayer.on("manifestLoaded", (e) => {
267
+ console.debug("[DashJS] manifestLoaded:", e);
268
+ });
269
+ this.dashPlayer.on("canPlay", () => {
270
+ console.debug("[DashJS] canPlay event");
271
+ });
272
+ // Log stream initialization for debugging
273
+ this.dashPlayer.on("streamInitialized", () => {
274
+ if (this.destroyed)
275
+ return;
276
+ const isDynamic = this.dashPlayer.isDynamic?.() ?? false;
277
+ console.debug("[DashJS v5] streamInitialized - isDynamic:", isDynamic);
278
+ });
279
+ // Configure dashjs v5 streaming settings BEFORE initialization
280
+ // AGGRESSIVE settings for fastest startup and low latency
281
+ this.dashPlayer.updateSettings({
282
+ streaming: {
283
+ // AGGRESSIVE: Minimal buffers for fastest startup
284
+ buffer: {
285
+ fastSwitchEnabled: true,
286
+ stableBufferTime: 4, // Reduced from 16 (aggressive!)
287
+ bufferTimeAtTopQuality: 8, // Reduced from 30
288
+ bufferTimeAtTopQualityLongForm: 15, // Reduced from 60
289
+ bufferToKeep: 10, // Reduced from 30
290
+ bufferPruningInterval: 10, // Reduced from 30
291
+ },
292
+ // Gaps/stall handling
293
+ gaps: {
294
+ jumpGaps: true,
295
+ jumpLargeGaps: true,
296
+ smallGapLimit: 1.5,
297
+ threshold: 0.3,
298
+ },
299
+ // AGGRESSIVE: ABR with high initial bitrate estimate
300
+ abr: {
301
+ autoSwitchBitrate: { video: true, audio: true },
302
+ limitBitrateByPortal: false,
303
+ useDefaultABRRules: true,
304
+ initialBitrate: { video: 5000000, audio: 128000 }, // 5Mbps initial (was -1)
305
+ },
306
+ // LIVE CATCHUP - critical for maintaining live edge (was missing!)
307
+ liveCatchup: {
308
+ enabled: true,
309
+ maxDrift: 1.5, // Seek to live if drift > 1.5s
310
+ playbackRate: {
311
+ max: 0.15, // Speed up by max 15%
312
+ min: -0.15, // Slow down by max 15%
313
+ },
314
+ playbackBufferMin: 0.3, // Min buffer before catchup
315
+ mode: "liveCatchupModeDefault",
316
+ },
317
+ // Retry settings - more aggressive
318
+ retryAttempts: {
319
+ MPD: 5,
320
+ MediaSegment: 5,
321
+ InitializationSegment: 5,
322
+ BitstreamSwitchingSegment: 5,
323
+ IndexSegment: 5,
324
+ XLinkExpansion: 3,
325
+ other: 3,
326
+ },
327
+ retryIntervals: {
328
+ MPD: 1000,
329
+ MediaSegment: 1000,
330
+ InitializationSegment: 1000,
331
+ BitstreamSwitchingSegment: 1000,
332
+ IndexSegment: 1000,
333
+ XLinkExpansion: 1000,
334
+ other: 1000,
335
+ },
336
+ // Timeout settings - faster abandonment of slow segments
337
+ timeoutAttempts: {
338
+ MPD: 2,
339
+ MediaSegment: 2, // Abandon after 2 timeout attempts
340
+ InitializationSegment: 2,
341
+ BitstreamSwitchingSegment: 2,
342
+ IndexSegment: 2,
343
+ XLinkExpansion: 1,
344
+ other: 1,
345
+ },
346
+ // Abandon slow segment downloads more quickly
347
+ abandonLoadTimeout: 5000, // 5 seconds instead of default 10
348
+ xhrWithCredentials: false,
349
+ text: { defaultEnabled: false },
350
+ // AGGRESSIVE: Tighter live delay
351
+ delay: {
352
+ liveDelay: 2, // Reduced from 4 (2s behind live edge)
353
+ liveDelayFragmentCount: null,
354
+ useSuggestedPresentationDelay: false, // Ignore manifest suggestions
355
+ },
356
+ },
357
+ debug: {
358
+ logLevel: 4, // Always debug for now to see what's happening
359
+ },
360
+ });
361
+ // Add fragment loading event listeners to debug the pending issue
362
+ this.dashPlayer.on("fragmentLoadingStarted", (e) => {
363
+ console.debug("[DashJS] Fragment loading started:", e.request?.url?.split("/").pop());
364
+ });
365
+ this.dashPlayer.on("fragmentLoadingCompleted", (e) => {
366
+ console.debug("[DashJS] Fragment loading completed:", e.request?.url?.split("/").pop());
367
+ });
368
+ this.dashPlayer.on("fragmentLoadingAbandoned", (e) => {
369
+ console.warn("[DashJS] Fragment loading ABANDONED:", e.request?.url?.split("/").pop(), e);
370
+ });
371
+ this.dashPlayer.on("fragmentLoadingFailed", (e) => {
372
+ console.error("[DashJS] Fragment loading FAILED:", e.request?.url?.split("/").pop(), e);
373
+ });
374
+ // dashjs v5: Initialize with URL
375
+ console.debug("[DashJS v5] Initializing with URL:", source.url);
376
+ this.dashPlayer.initialize(video, source.url, options.autoplay ?? false);
377
+ console.debug("[DashJS v5] Initialize called");
378
+ // Optional subtitle tracks helper from source extras (external tracks)
379
+ try {
380
+ const subs = source.subtitles;
381
+ if (Array.isArray(subs)) {
382
+ subs.forEach((s, idx) => {
383
+ const track = document.createElement("track");
384
+ track.kind = "subtitles";
385
+ track.label = s.label;
386
+ track.srclang = s.lang;
387
+ track.src = s.src;
388
+ if (idx === 0)
389
+ track.default = true;
390
+ video.appendChild(track);
391
+ });
392
+ }
393
+ }
394
+ catch { }
395
+ return video;
396
+ }
397
+ catch (error) {
398
+ this.emit("error", error.message || String(error));
399
+ throw error;
400
+ }
401
+ }
402
+ /**
403
+ * Get DASH.js-specific stats for ABR and playback monitoring
404
+ * Updated for dashjs v5 API
405
+ */
406
+ async getStats() {
407
+ if (!this.dashPlayer || !this.videoElement)
408
+ return undefined;
409
+ try {
410
+ // dashjs v5: getCurrentRepresentationForType returns Representation object
411
+ const currentRep = this.dashPlayer.getCurrentRepresentationForType?.("video");
412
+ // dashjs v5: getRepresentationsByType returns Representation[] (bandwidth instead of bitrate)
413
+ const representations = this.dashPlayer.getRepresentationsByType?.("video") || [];
414
+ const bufferLevel = this.dashPlayer.getBufferLength("video") || 0;
415
+ // Find current quality index
416
+ const currentIndex = currentRep
417
+ ? representations.findIndex((r) => r.id === currentRep.id)
418
+ : 0;
419
+ return {
420
+ type: "dash",
421
+ currentQuality: currentIndex >= 0 ? currentIndex : 0,
422
+ bufferLevel,
423
+ bitrateInfoList: representations.map((r) => ({
424
+ bitrate: r.bandwidth || 0, // v5 uses 'bandwidth' not 'bitrate'
425
+ width: r.width || 0,
426
+ height: r.height || 0,
427
+ })),
428
+ currentBitrate: currentRep?.bandwidth || 0,
429
+ playbackRate: this.videoElement.playbackRate,
430
+ };
431
+ }
432
+ catch {
433
+ return undefined;
434
+ }
435
+ }
436
+ /**
437
+ * Set playback rate
438
+ */
439
+ setPlaybackRate(rate) {
440
+ if (this.videoElement) {
441
+ this.videoElement.playbackRate = rate;
442
+ }
443
+ }
444
+ /**
445
+ * Set source URL for seamless source switching.
446
+ * Ported from reference dashjs.js:166-168.
447
+ */
448
+ setSource(url) {
449
+ if (this.dashPlayer) {
450
+ this.dashPlayer.attachSource(url);
451
+ }
452
+ }
453
+ /**
454
+ * Get duration using proxy for live streams.
455
+ * Returns synthetic growing duration for live content.
456
+ */
457
+ getDuration() {
458
+ // Use proxy if available for live duration handling
459
+ if (this.videoProxy && this.isLiveStream()) {
460
+ return this.videoProxy.duration ?? 0;
461
+ }
462
+ return this.videoElement?.duration ?? 0;
463
+ }
464
+ /**
465
+ * Jump to live edge for live streams.
466
+ * Uses DASH.js seekToLive API when available.
467
+ */
468
+ jumpToLive() {
469
+ const video = this.videoElement;
470
+ if (!video || !this.isLiveStream())
471
+ return;
472
+ // DASH.js has a seekToLive method for live streams
473
+ if (this.dashPlayer && typeof this.dashPlayer.seekToLive === "function") {
474
+ console.debug("[DashJS] jumpToLive using seekToLive()");
475
+ this.dashPlayer.seekToLive();
476
+ return;
477
+ }
478
+ // Fallback: seek to end of seekable range
479
+ if (video.seekable && video.seekable.length > 0) {
480
+ const liveEdge = video.seekable.end(video.seekable.length - 1);
481
+ if (isFinite(liveEdge) && liveEdge > 0) {
482
+ console.debug("[DashJS] jumpToLive using seekable.end:", liveEdge);
483
+ video.currentTime = liveEdge;
484
+ }
485
+ }
486
+ }
487
+ /**
488
+ * Get latency from live edge (for live streams)
489
+ */
490
+ getLiveLatency() {
491
+ const video = this.videoElement;
492
+ if (!video || !this.isLiveStream())
493
+ return 0;
494
+ // DASH.js provides live delay metrics
495
+ if (this.dashPlayer && typeof this.dashPlayer.getCurrentLiveLatency === "function") {
496
+ return this.dashPlayer.getCurrentLiveLatency() * 1000;
497
+ }
498
+ // Fallback: calculate from seekable end
499
+ if (video.seekable && video.seekable.length > 0) {
500
+ const liveEdge = video.seekable.end(video.seekable.length - 1);
501
+ if (isFinite(liveEdge)) {
502
+ return Math.max(0, (liveEdge - video.currentTime) * 1000);
503
+ }
504
+ }
505
+ return 0;
506
+ }
507
+ async destroy() {
508
+ this.destroyed = true;
509
+ this.subsLoaded = false;
510
+ this.pendingSubtitleId = null;
511
+ this.videoProxy = null;
512
+ if (this.dashPlayer) {
513
+ try {
514
+ this.dashPlayer.reset();
515
+ }
516
+ catch (e) {
517
+ console.warn("Error destroying DASH.js:", e);
518
+ }
519
+ this.dashPlayer = null;
520
+ }
521
+ if (this.videoElement && this.container) {
522
+ try {
523
+ this.container.removeChild(this.videoElement);
524
+ }
525
+ catch { }
526
+ }
527
+ this.videoElement = null;
528
+ this.container = null;
529
+ this.listeners.clear();
530
+ }
531
+ getQualities() {
532
+ const out = [];
533
+ const v = this.videoElement;
534
+ if (!this.dashPlayer || !v)
535
+ return out;
536
+ try {
537
+ // dashjs v5: getRepresentationsByType returns Representation[] (bandwidth instead of bitrate)
538
+ const representations = this.dashPlayer.getRepresentationsByType?.("video") || [];
539
+ const settings = this.dashPlayer.getSettings?.();
540
+ const isAutoEnabled = settings?.streaming?.abr?.autoSwitchBitrate?.video !== false;
541
+ out.push({ id: "auto", label: "Auto", isAuto: true, active: isAutoEnabled });
542
+ representations.forEach((rep, i) => {
543
+ out.push({
544
+ id: String(i),
545
+ label: rep.height ? `${rep.height}p` : `${Math.round((rep.bandwidth || 0) / 1000)}kbps`,
546
+ bitrate: rep.bandwidth, // v5 uses 'bandwidth'
547
+ width: rep.width,
548
+ height: rep.height,
549
+ });
550
+ });
551
+ }
552
+ catch { }
553
+ return out;
554
+ }
555
+ selectQuality(id) {
556
+ if (!this.dashPlayer)
557
+ return;
558
+ if (id === "auto") {
559
+ this.dashPlayer.updateSettings({
560
+ streaming: { abr: { autoSwitchBitrate: { video: true } } },
561
+ });
562
+ return;
563
+ }
564
+ const idx = parseInt(id, 10);
565
+ if (!isNaN(idx)) {
566
+ this.dashPlayer.updateSettings({
567
+ streaming: { abr: { autoSwitchBitrate: { video: false } } },
568
+ });
569
+ // dashjs v5: setRepresentationForTypeByIndex instead of setQualityFor
570
+ try {
571
+ this.dashPlayer.setRepresentationForTypeByIndex?.("video", idx);
572
+ }
573
+ catch { }
574
+ }
575
+ }
576
+ // Captions via native text tracks or dash.js API
577
+ getTextTracks() {
578
+ const v = this.videoElement;
579
+ if (!this.dashPlayer || !v)
580
+ return [];
581
+ const out = [];
582
+ try {
583
+ const textTracks = (v.textTracks || []);
584
+ for (let i = 0; i < textTracks.length; i++) {
585
+ const tt = textTracks[i];
586
+ out.push({
587
+ id: String(i),
588
+ label: tt.label || `CC ${i + 1}`,
589
+ lang: tt.language,
590
+ active: tt.mode === "showing",
591
+ });
592
+ }
593
+ }
594
+ catch { }
595
+ return out;
596
+ }
597
+ selectTextTrack(id) {
598
+ const v = this.videoElement;
599
+ if (!this.dashPlayer || !v)
600
+ return;
601
+ // Deferred loading: wait for allTextTracksAdded (reference dashjs.js:180-186)
602
+ if (!this.subsLoaded) {
603
+ this.pendingSubtitleId = id;
604
+ return;
605
+ }
606
+ // Try dash.js API first (reference dashjs.js:193-197)
607
+ try {
608
+ const dashTracks = this.dashPlayer.getTracksFor("text");
609
+ if (dashTracks && dashTracks.length > 0) {
610
+ const idx = id === null ? -1 : parseInt(id, 10);
611
+ if (idx >= 0 && idx < dashTracks.length) {
612
+ this.dashPlayer.setTextTrack(idx);
613
+ return;
614
+ }
615
+ else if (id === null || idx < 0) {
616
+ // Disable all dash.js text tracks
617
+ this.dashPlayer.setTextTrack(-1);
618
+ return;
619
+ }
620
+ }
621
+ }
622
+ catch { }
623
+ // Fallback to native text tracks
624
+ const list = v.textTracks;
625
+ for (let i = 0; i < list.length; i++) {
626
+ const tt = list[i];
627
+ if (id !== null && String(i) === id)
628
+ tt.mode = "showing";
629
+ else
630
+ tt.mode = "disabled";
631
+ }
632
+ }
633
+ }
634
+
635
+ export { DashJsPlayerImpl };
636
+ //# sourceMappingURL=DashJsPlayer.js.map