@therealtinhtute/baroiplayer 1.2.0 → 2.0.0-beta.1

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 (305) hide show
  1. package/README.md +91 -73
  2. package/dist/components/icons/index.d.ts +36 -0
  3. package/dist/components/icons/index.d.ts.map +1 -0
  4. package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts +4 -0
  5. package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts.map +1 -0
  6. package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts +5 -0
  7. package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts.map +1 -0
  8. package/dist/components/icons/svg-icons/AudioIcon.d.ts +5 -0
  9. package/dist/components/icons/svg-icons/AudioIcon.d.ts.map +1 -0
  10. package/dist/components/icons/svg-icons/BackwardIcon.d.ts +5 -0
  11. package/dist/components/icons/svg-icons/BackwardIcon.d.ts.map +1 -0
  12. package/dist/components/icons/svg-icons/CameraIcon.d.ts +5 -0
  13. package/dist/components/icons/svg-icons/CameraIcon.d.ts.map +1 -0
  14. package/dist/components/icons/svg-icons/CheckIcon.d.ts +5 -0
  15. package/dist/components/icons/svg-icons/CheckIcon.d.ts.map +1 -0
  16. package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts +4 -0
  17. package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts.map +1 -0
  18. package/dist/components/icons/svg-icons/ForwardIcon.d.ts +5 -0
  19. package/dist/components/icons/svg-icons/ForwardIcon.d.ts.map +1 -0
  20. package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts +5 -0
  21. package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts.map +1 -0
  22. package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts +5 -0
  23. package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts.map +1 -0
  24. package/dist/components/icons/svg-icons/LoadingIcon.d.ts +5 -0
  25. package/dist/components/icons/svg-icons/LoadingIcon.d.ts.map +1 -0
  26. package/dist/components/icons/svg-icons/PauseIcon.d.ts +5 -0
  27. package/dist/components/icons/svg-icons/PauseIcon.d.ts.map +1 -0
  28. package/dist/components/icons/svg-icons/PlayIcon.d.ts +5 -0
  29. package/dist/components/icons/svg-icons/PlayIcon.d.ts.map +1 -0
  30. package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts +5 -0
  31. package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts.map +1 -0
  32. package/dist/components/icons/svg-icons/QualityIcon.d.ts +5 -0
  33. package/dist/components/icons/svg-icons/QualityIcon.d.ts.map +1 -0
  34. package/dist/components/icons/svg-icons/SettingsIcon.d.ts +5 -0
  35. package/dist/components/icons/svg-icons/SettingsIcon.d.ts.map +1 -0
  36. package/dist/components/icons/svg-icons/SliderIcon.d.ts +5 -0
  37. package/dist/components/icons/svg-icons/SliderIcon.d.ts.map +1 -0
  38. package/dist/components/icons/svg-icons/SubtitleIcon.d.ts +5 -0
  39. package/dist/components/icons/svg-icons/SubtitleIcon.d.ts.map +1 -0
  40. package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts +5 -0
  41. package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts.map +1 -0
  42. package/dist/components/icons/svg-icons/UnPiPIcon.d.ts +4 -0
  43. package/dist/components/icons/svg-icons/UnPiPIcon.d.ts.map +1 -0
  44. package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts +5 -0
  45. package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts.map +1 -0
  46. package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts +5 -0
  47. package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts.map +1 -0
  48. package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts +5 -0
  49. package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts.map +1 -0
  50. package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts +5 -0
  51. package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts.map +1 -0
  52. package/dist/components/variants/gradient/gradient-audio.d.ts +13 -0
  53. package/dist/components/variants/gradient/gradient-audio.d.ts.map +1 -0
  54. package/dist/components/variants/gradient/gradient-controls.d.ts +4 -0
  55. package/dist/components/variants/gradient/gradient-controls.d.ts.map +1 -0
  56. package/dist/components/variants/gradient/gradient-glyphs.d.ts +30 -0
  57. package/dist/components/variants/gradient/gradient-glyphs.d.ts.map +1 -0
  58. package/dist/components/variants/gradient/gradient-video.d.ts +16 -0
  59. package/dist/components/variants/gradient/gradient-video.d.ts.map +1 -0
  60. package/dist/index.css +1 -1
  61. package/dist/index.d.ts +5 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +2 -112
  64. package/dist/index.js.map +1 -1
  65. package/dist/index.mjs +786 -6271
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/package.json +3 -0
  68. package/package.json +110 -108
  69. package/src/components/variants/gradient/gradient-audio.tsx +47 -0
  70. package/src/components/variants/gradient/gradient-controls.tsx +254 -0
  71. package/src/components/variants/gradient/gradient-glyphs.test.tsx +69 -0
  72. package/src/components/variants/gradient/gradient-glyphs.tsx +129 -0
  73. package/src/components/variants/gradient/gradient-skin.css +211 -0
  74. package/src/components/variants/gradient/gradient-video.tsx +70 -0
  75. package/src/index.ts +5 -198
  76. package/src/test/accessibility-utils.ts +0 -59
  77. package/dist/context/media.js +0 -2
  78. package/dist/context/media.js.map +0 -1
  79. package/dist/context/media.mjs +0 -15
  80. package/dist/context/media.mjs.map +0 -1
  81. package/dist/context/store.js +0 -2
  82. package/dist/context/store.js.map +0 -1
  83. package/dist/context/store.mjs +0 -5
  84. package/dist/context/store.mjs.map +0 -1
  85. package/dist/context-BYwDoSRX.js +0 -1172
  86. package/dist/context-BYwDoSRX.js.map +0 -1
  87. package/dist/context-eNS62_ac.cjs +0 -23
  88. package/dist/context-eNS62_ac.cjs.map +0 -1
  89. package/dist/core-events-B1iM2F46.cjs +0 -2
  90. package/dist/core-events-B1iM2F46.cjs.map +0 -1
  91. package/dist/core-events-DunPHKRE.js +0 -484
  92. package/dist/core-events-DunPHKRE.js.map +0 -1
  93. package/dist/core-plugins-By-4-kGs.cjs +0 -2
  94. package/dist/core-plugins-By-4-kGs.cjs.map +0 -1
  95. package/dist/core-plugins-DSBWcTuX.js +0 -821
  96. package/dist/core-plugins-DSBWcTuX.js.map +0 -1
  97. package/dist/core.js +0 -37
  98. package/dist/core.js.map +0 -1
  99. package/dist/core.mjs +0 -1233
  100. package/dist/core.mjs.map +0 -1
  101. package/dist/enhanced-components-B_l3cist.js +0 -1142
  102. package/dist/enhanced-components-B_l3cist.js.map +0 -1
  103. package/dist/enhanced-components-BspFs9OO.cjs +0 -2
  104. package/dist/enhanced-components-BspFs9OO.cjs.map +0 -1
  105. package/dist/hooks-BXwI8QG6.cjs +0 -4
  106. package/dist/hooks-BXwI8QG6.cjs.map +0 -1
  107. package/dist/hooks-Bpi-jDiO.js +0 -1816
  108. package/dist/hooks-Bpi-jDiO.js.map +0 -1
  109. package/dist/minimal-components-C4z900Ro.js +0 -1926
  110. package/dist/minimal-components-C4z900Ro.js.map +0 -1
  111. package/dist/minimal-components-v4qBp6jv.cjs +0 -2
  112. package/dist/minimal-components-v4qBp6jv.cjs.map +0 -1
  113. package/dist/minimal-components.css +0 -1
  114. package/dist/mona-loading.gif +0 -0
  115. package/dist/performance-monitor-C5k6FDXw.js +0 -301
  116. package/dist/performance-monitor-C5k6FDXw.js.map +0 -1
  117. package/dist/performance-monitor-lJmuUjQQ.cjs +0 -2
  118. package/dist/performance-monitor-lJmuUjQQ.cjs.map +0 -1
  119. package/dist/utils-CFOue_9K.cjs +0 -9
  120. package/dist/utils-CFOue_9K.cjs.map +0 -1
  121. package/dist/utils-Dzpl2ArK.js +0 -2844
  122. package/dist/utils-Dzpl2ArK.js.map +0 -1
  123. package/dist/utils.js +0 -2
  124. package/dist/utils.js.map +0 -1
  125. package/dist/utils.mjs +0 -11
  126. package/dist/utils.mjs.map +0 -1
  127. package/src/adapters/videojs-adapter.tsx +0 -470
  128. package/src/assets/mona-loading.gif +0 -0
  129. package/src/components/AnimateLoading.tsx +0 -107
  130. package/src/components/LoadingState.tsx +0 -239
  131. package/src/components/__tests__/media-player-accessibility.test.tsx +0 -510
  132. package/src/components/__tests__/media-player-react19.test.tsx +0 -457
  133. package/src/components/accessibility/keyboard-help-overlay.tsx +0 -207
  134. package/src/components/audio-player.tsx +0 -85
  135. package/src/components/basic/index.ts +0 -37
  136. package/src/components/enhanced/advanced-features.tsx +0 -311
  137. package/src/components/enhanced/debug-panel.tsx +0 -448
  138. package/src/components/enhanced/enhanced-controls.tsx +0 -597
  139. package/src/components/enhanced/enhanced-media-player.tsx +0 -566
  140. package/src/components/enhanced/error-handling.tsx +0 -338
  141. package/src/components/enhanced/index.ts +0 -39
  142. package/src/components/enhanced/media-player-enhanced.tsx +0 -383
  143. package/src/components/examples/basic-video-player.tsx +0 -50
  144. package/src/components/examples/custom-controls-example.tsx +0 -63
  145. package/src/components/examples/enhanced-controls-example.tsx +0 -100
  146. package/src/components/examples/enhanced-media-player-example.tsx +0 -302
  147. package/src/components/examples/loading-states-demo.tsx +0 -142
  148. package/src/components/examples/react-19-demo.tsx +0 -353
  149. package/src/components/examples/volume-orientation-demo.tsx +0 -106
  150. package/src/components/icon-demo.tsx +0 -196
  151. package/src/components/legacy.tsx +0 -87
  152. package/src/components/media-metadata-display.tsx +0 -99
  153. package/src/components/media-player-audio.tsx +0 -39
  154. package/src/components/media-player-controls.tsx +0 -223
  155. package/src/components/media-player-error.tsx +0 -163
  156. package/src/components/media-player-fullscreen.tsx +0 -109
  157. package/src/components/media-player-hls.tsx +0 -111
  158. package/src/components/media-player-loading.tsx +0 -76
  159. package/src/components/media-player-play.tsx +0 -75
  160. package/src/components/media-player-root.tsx +0 -338
  161. package/src/components/media-player-seek.tsx +0 -168
  162. package/src/components/media-player-time.tsx +0 -99
  163. package/src/components/media-player-tooltip.tsx +0 -58
  164. package/src/components/media-player-video.tsx +0 -54
  165. package/src/components/media-player-volume.tsx +0 -155
  166. package/src/components/media-player.tsx +0 -292
  167. package/src/components/media-suspense.tsx +0 -344
  168. package/src/components/player-settings-form.tsx +0 -158
  169. package/src/components/react-player-wrapper.tsx +0 -651
  170. package/src/components/simple-video-player.tsx +0 -62
  171. package/src/components/ui/blur-poster.tsx +0 -93
  172. package/src/components/ui/empty-state.tsx +0 -91
  173. package/src/components/ui/enhanced-seek-bar.tsx +0 -254
  174. package/src/components/ui/error-state.tsx +0 -124
  175. package/src/components/ui/fullscreen-button.tsx +0 -81
  176. package/src/components/ui/loading-skeleton.tsx +0 -107
  177. package/src/components/ui/media-resource-preloader.tsx +0 -458
  178. package/src/components/ui/offline-message.tsx +0 -98
  179. package/src/components/ui/play-button.tsx +0 -99
  180. package/src/components/ui/seek-bar.tsx +0 -191
  181. package/src/components/ui/time-display.tsx +0 -61
  182. package/src/components/ui/volume-control.tsx +0 -190
  183. package/src/components/unified/base-media-player.tsx +0 -252
  184. package/src/components/unified/media-player.tsx +0 -75
  185. package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +0 -587
  186. package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +0 -573
  187. package/src/components/variants/minimal/MinimalControls.tsx +0 -124
  188. package/src/components/variants/minimal/MinimalLoading.tsx +0 -28
  189. package/src/components/variants/minimal/MinimalMediaPlayer.tsx +0 -318
  190. package/src/components/variants/minimal/MinimalOverlay.tsx +0 -58
  191. package/src/components/variants/minimal/MinimalPlayButton.tsx +0 -56
  192. package/src/components/variants/minimal/MinimalSeekBar.tsx +0 -140
  193. package/src/components/variants/minimal/MinimalVolumeControl.tsx +0 -75
  194. package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +0 -206
  195. package/src/components/variants/minimal/components/CenterPlayButton.tsx +0 -22
  196. package/src/components/variants/minimal/components/ControlBar.tsx +0 -142
  197. package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +0 -412
  198. package/src/components/variants/minimal/components/PlaybackControls.tsx +0 -46
  199. package/src/components/variants/minimal/components/RightControls.tsx +0 -164
  200. package/src/components/variants/minimal/components/SeekBar.tsx +0 -127
  201. package/src/components/variants/minimal/components/SettingsDropdown.tsx +0 -68
  202. package/src/components/variants/minimal/components/SubtitleDisplay.tsx +0 -21
  203. package/src/components/variants/minimal/components/TimeDisplay.tsx +0 -15
  204. package/src/components/variants/minimal/components/VideoElement.tsx +0 -33
  205. package/src/components/variants/minimal/components/VolumeControl.tsx +0 -220
  206. package/src/components/variants/minimal/index.ts +0 -23
  207. package/src/components/video-player.tsx +0 -100
  208. package/src/context/__tests__/media-store.test.ts +0 -509
  209. package/src/context/error-handling.ts +0 -398
  210. package/src/context/media-context.tsx +0 -254
  211. package/src/context/media-provider.tsx +0 -264
  212. package/src/context/media-store.ts +0 -387
  213. package/src/context/persistence.ts +0 -462
  214. package/src/core/events/event-system.ts +0 -448
  215. package/src/core/events/hooks.ts +0 -325
  216. package/src/core/events/index.ts +0 -22
  217. package/src/core/events/middleware.ts +0 -286
  218. package/src/core/index.ts +0 -22
  219. package/src/core/optimization/bundle-optimizer.tsx +0 -312
  220. package/src/core/performance/cicd.ts +0 -98
  221. package/src/core/performance/index.ts +0 -38
  222. package/src/core/performance/media-loading-optimizer.ts +0 -544
  223. package/src/core/performance/performance-budgets.ts +0 -437
  224. package/src/core/performance/performance-monitor.tsx +0 -488
  225. package/src/core/performance/performance-testing.ts +0 -461
  226. package/src/core/plugins/__tests__/registry.test.ts +0 -595
  227. package/src/core/plugins/base-plugin.ts +0 -225
  228. package/src/core/plugins/enhanced-plugin-system.ts +0 -435
  229. package/src/core/plugins/examples/analytics-plugin.ts +0 -241
  230. package/src/core/plugins/index.ts +0 -39
  231. package/src/core/plugins/registry.ts +0 -546
  232. package/src/core/plugins/types.ts +0 -169
  233. package/src/core/plugins/utils.ts +0 -317
  234. package/src/core/progressive-loading.tsx +0 -331
  235. package/src/core/providers/enhanced-hls-provider.ts +0 -307
  236. package/src/core/providers/lazy-provider.tsx +0 -14
  237. package/src/core/providers/service-provider.tsx +0 -164
  238. package/src/core/utils.tsx +0 -34
  239. package/src/features/media-session/media-session-manager.ts +0 -411
  240. package/src/features/picture-in-picture/pip-manager.ts +0 -428
  241. package/src/features/playlist/playlist-manager.ts +0 -626
  242. package/src/features/subtitles/subtitle-manager.ts +0 -435
  243. package/src/features/subtitles/subtitle-parser.ts +0 -284
  244. package/src/features/thumbnails/thumbnail-generator.ts +0 -528
  245. package/src/hooks/__tests__/currentTime-fix.test.ts +0 -149
  246. package/src/hooks/__tests__/use-media-player.test.ts +0 -712
  247. package/src/hooks/__tests__/use-media-state.test.tsx +0 -316
  248. package/src/hooks/accessibility/index.ts +0 -27
  249. package/src/hooks/accessibility/use-accessibility-preferences.ts +0 -190
  250. package/src/hooks/accessibility/use-focus-management.ts +0 -183
  251. package/src/hooks/accessibility/use-keyboard-shortcuts.ts +0 -152
  252. package/src/hooks/accessibility/use-screen-reader.ts +0 -212
  253. package/src/hooks/core/index.ts +0 -47
  254. package/src/hooks/legacy.ts +0 -21
  255. package/src/hooks/use-buffer-health.ts +0 -218
  256. package/src/hooks/use-enhanced-media-player.ts +0 -575
  257. package/src/hooks/use-focus-trap.tsx +0 -162
  258. package/src/hooks/use-intelligent-preloading.ts +0 -387
  259. package/src/hooks/use-keyboard-controls.ts +0 -115
  260. package/src/hooks/use-keyboard-shortcuts.ts +0 -255
  261. package/src/hooks/use-media-actions.ts +0 -184
  262. package/src/hooks/use-media-metadata.ts +0 -91
  263. package/src/hooks/use-media-optimistic.ts +0 -264
  264. package/src/hooks/use-media-player.ts +0 -343
  265. package/src/hooks/use-media-state.ts +0 -194
  266. package/src/hooks/use-memory-optimization.ts +0 -360
  267. package/src/hooks/use-network-status.ts +0 -124
  268. package/src/hooks/use-optimistic-controls.ts +0 -95
  269. package/src/hooks/use-optimized-media.ts +0 -283
  270. package/src/hooks/use-smart-preload.ts +0 -229
  271. package/src/hooks/use-touch-gestures.ts +0 -461
  272. package/src/hooks/useEnhancedSubtitles.ts +0 -258
  273. package/src/hooks/useKeyboardShortcuts.ts +0 -106
  274. package/src/hooks/useMediaControls.ts +0 -52
  275. package/src/hooks/useScreenshot.ts +0 -61
  276. package/src/hooks/useSubtitles.ts +0 -91
  277. package/src/hooks/useVideoPlayer.ts +0 -278
  278. package/src/icons/components/FullscreenIcon.tsx +0 -36
  279. package/src/icons/components/SettingsIcon.tsx +0 -37
  280. package/src/icons/components/animated/LoadingIcon.tsx +0 -27
  281. package/src/icons/components/animated/PlayPauseIcon.tsx +0 -42
  282. package/src/icons/components/media/PauseIcon.tsx +0 -38
  283. package/src/icons/components/media/PlayIcon.tsx +0 -37
  284. package/src/icons/components/volume/VolumeIcon.tsx +0 -38
  285. package/src/icons/components/volume/VolumeOffIcon.tsx +0 -38
  286. package/src/icons/index.ts +0 -56
  287. package/src/icons/provider.tsx +0 -58
  288. package/src/icons/types.ts +0 -60
  289. package/src/index-enhanced.ts +0 -35
  290. package/src/index-legacy.ts +0 -324
  291. package/src/index.css +0 -102
  292. package/src/lib/__tests__/async-utils.test.ts +0 -291
  293. package/src/lib/async-utils.ts +0 -194
  294. package/src/lib/deprecation.ts +0 -51
  295. package/src/lib/format-time.ts +0 -37
  296. package/src/lib/index.ts +0 -4
  297. package/src/lib/utils.ts +0 -6
  298. package/src/styles/globals.css +0 -462
  299. package/src/styles/minimal-player.css +0 -621
  300. package/src/styles/pixel-art.css +0 -41
  301. package/src/styles/videojs.css +0 -100
  302. package/src/types/events.ts +0 -47
  303. package/src/types/formats.ts +0 -79
  304. package/src/types/index.ts +0 -203
  305. package/src/types/videojs-plugins.d.ts +0 -14
@@ -1,544 +0,0 @@
1
- import React from "react"
2
-
3
- // Network monitoring and adaptive loading
4
- export interface NetworkInfo {
5
- effectiveType: "2g" | "3g" | "4g" | "5g" | "unknown"
6
- downlink: number // Mbps
7
- rtt: number // Round trip time in ms
8
- saveData: boolean
9
- isOnline: boolean
10
- }
11
-
12
- export interface MediaLoadingConfig {
13
- preloadStrategy: "none" | "metadata" | "auto"
14
- adaptiveBitrate: boolean
15
- maxPreloadSize: number // bytes
16
- networkThresholds: {
17
- "2g": { maxBitrate: number; preload: boolean }
18
- "3g": { maxBitrate: number; preload: boolean }
19
- "4g": { maxBitrate: number; preload: boolean }
20
- "5g": { maxBitrate: number; preload: boolean }
21
- }
22
- bufferSize: number // seconds
23
- enableServiceWorker: boolean
24
- }
25
-
26
- export const defaultMediaLoadingConfig: MediaLoadingConfig = {
27
- preloadStrategy: "metadata",
28
- adaptiveBitrate: true,
29
- maxPreloadSize: 2 * 1024 * 1024, // 2MB
30
- networkThresholds: {
31
- "2g": { maxBitrate: 128, preload: false }, // 128 kbps
32
- "3g": { maxBitrate: 500, preload: false }, // 500 kbps
33
- "4g": { maxBitrate: 2000, preload: true }, // 2 Mbps
34
- "5g": { maxBitrate: 10000, preload: true } // 10 Mbps
35
- },
36
- bufferSize: 10, // 10 seconds
37
- enableServiceWorker: true
38
- }
39
-
40
- // Media loading performance tracker
41
- export interface MediaLoadingMetrics {
42
- loadStartTime: number
43
- firstByteTime?: number
44
- loadCompleteTime?: number
45
- totalLoadTime?: number
46
- bytesLoaded: number
47
- loadSpeed: number // bytes per second
48
- networkType: string
49
- quality: string
50
- bufferHealth: number // 0-1 scale
51
- stallsCount: number
52
- stallsDuration: number
53
- }
54
-
55
- // Network monitoring utility
56
- export class NetworkMonitor {
57
- private connection: any
58
- private listeners: Set<(info: NetworkInfo) => void> = new Set()
59
- private currentInfo: NetworkInfo
60
-
61
- constructor() {
62
- if (typeof window === "undefined" || typeof navigator === "undefined") {
63
- // Server-side rendering fallback
64
- this.connection = null
65
- this.currentInfo = {
66
- effectiveType: "unknown",
67
- downlink: 0,
68
- rtt: 0,
69
- saveData: false,
70
- isOnline: true
71
- }
72
- return
73
- }
74
-
75
- this.connection =
76
- (navigator as any).connection ||
77
- (navigator as any).mozConnection ||
78
- (navigator as any).webkitConnection
79
-
80
- this.currentInfo = this.getNetworkInfo()
81
- this.initializeListeners()
82
- }
83
-
84
- private getNetworkInfo(): NetworkInfo {
85
- if (typeof navigator === "undefined") {
86
- // Server-side rendering fallback
87
- return {
88
- effectiveType: "unknown",
89
- downlink: 0,
90
- rtt: 0,
91
- saveData: false,
92
- isOnline: true
93
- }
94
- }
95
-
96
- const isOnline = navigator.onLine
97
-
98
- if (this.connection) {
99
- return {
100
- effectiveType: this.connection.effectiveType || "unknown",
101
- downlink: this.connection.downlink || 0,
102
- rtt: this.connection.rtt || 0,
103
- saveData: this.connection.saveData || false,
104
- isOnline
105
- }
106
- }
107
-
108
- // Fallback for browsers without Network Information API
109
- return {
110
- effectiveType: "unknown",
111
- downlink: 0,
112
- rtt: 0,
113
- saveData: false,
114
- isOnline
115
- }
116
- }
117
-
118
- private initializeListeners() {
119
- if (typeof window === "undefined") {
120
- // Server-side rendering - skip event listeners
121
- return
122
- }
123
-
124
- if (this.connection) {
125
- this.connection.addEventListener("change", this.handleNetworkChange.bind(this))
126
- }
127
-
128
- window.addEventListener("online", this.handleNetworkChange.bind(this))
129
- window.addEventListener("offline", this.handleNetworkChange.bind(this))
130
- }
131
-
132
- private handleNetworkChange() {
133
- const newInfo = this.getNetworkInfo()
134
- this.currentInfo = newInfo
135
- this.listeners.forEach((listener) => listener(newInfo))
136
- }
137
-
138
- getCurrentNetworkInfo(): NetworkInfo {
139
- return { ...this.currentInfo }
140
- }
141
-
142
- subscribe(listener: (info: NetworkInfo) => void): () => void {
143
- this.listeners.add(listener)
144
- return () => this.listeners.delete(listener)
145
- }
146
-
147
- // Estimate available bandwidth with fallback detection
148
- async estimateBandwidth(): Promise<number> {
149
- if (this.connection && this.connection.downlink) {
150
- return this.connection.downlink * 1000 // Convert to kbps
151
- }
152
-
153
- // Fallback: simple bandwidth test
154
- try {
155
- const startTime = performance.now()
156
- const testUrl = "/api/bandwidth-test?size=100kb" // Would need to be implemented
157
- const response = await fetch(testUrl)
158
- const blob = await response.blob()
159
- const endTime = performance.now()
160
-
161
- const timeInSeconds = (endTime - startTime) / 1000
162
- const bytesLoaded = blob.size
163
- const bitsPerSecond = (bytesLoaded * 8) / timeInSeconds
164
-
165
- return bitsPerSecond / 1000 // Return in kbps
166
- } catch (error) {
167
- console.warn("Bandwidth estimation failed:", error)
168
- return 1000 // Default to 1Mbps
169
- }
170
- }
171
- }
172
-
173
- // Media loading optimizer
174
- export class MediaLoadingOptimizer {
175
- private config: MediaLoadingConfig
176
- private networkMonitor: NetworkMonitor
177
- private loadingMetrics: Map<string, MediaLoadingMetrics> = new Map()
178
- private preloadCache: Map<string, Promise<Blob>> = new Map()
179
-
180
- constructor(config: Partial<MediaLoadingConfig> = {}) {
181
- this.config = { ...defaultMediaLoadingConfig, ...config }
182
- this.networkMonitor = new NetworkMonitor()
183
- this.initializeNetworkMonitoring()
184
- }
185
-
186
- private initializeNetworkMonitoring() {
187
- this.networkMonitor.subscribe((networkInfo) => {
188
- this.handleNetworkChange(networkInfo)
189
- })
190
- }
191
-
192
- private handleNetworkChange(networkInfo: NetworkInfo) {
193
- console.log("Network changed:", networkInfo)
194
-
195
- // Adjust quality based on network conditions
196
- if (this.config.adaptiveBitrate) {
197
- this.adjustQualityForNetwork(networkInfo)
198
- }
199
-
200
- // Clear preload cache if on slow network
201
- if (networkInfo.effectiveType === "2g" || networkInfo.saveData) {
202
- this.clearPreloadCache()
203
- }
204
- }
205
-
206
- // Optimize media loading based on network conditions
207
- async optimizeMediaLoading(
208
- mediaUrl: string,
209
- element: HTMLMediaElement,
210
- options: {
211
- quality?: string
212
- preload?: boolean
213
- priority?: "high" | "normal" | "low"
214
- } = {}
215
- ): Promise<MediaLoadingMetrics> {
216
- const startTime = performance.now()
217
- const networkInfo = this.networkMonitor.getCurrentNetworkInfo()
218
-
219
- const metrics: MediaLoadingMetrics = {
220
- loadStartTime: startTime,
221
- bytesLoaded: 0,
222
- loadSpeed: 0,
223
- networkType: networkInfo.effectiveType,
224
- quality: options.quality || "auto",
225
- bufferHealth: 0,
226
- stallsCount: 0,
227
- stallsDuration: 0
228
- }
229
-
230
- this.loadingMetrics.set(mediaUrl, metrics)
231
-
232
- try {
233
- // Choose optimal loading strategy
234
- const loadingStrategy = this.chooseLoadingStrategy(networkInfo, options)
235
-
236
- // Apply preload strategy
237
- if (loadingStrategy.shouldPreload) {
238
- await this.preloadMedia(mediaUrl, loadingStrategy.preloadAmount)
239
- }
240
-
241
- // Set appropriate preload attribute
242
- element.preload = loadingStrategy.preloadAttribute
243
-
244
- // Monitor loading progress
245
- this.monitorLoadingProgress(element, metrics)
246
-
247
- // Apply quality adjustments
248
- if (this.config.adaptiveBitrate && loadingStrategy.suggestedQuality) {
249
- this.applyQualitySettings(element, loadingStrategy.suggestedQuality)
250
- }
251
-
252
- return metrics
253
- } catch (error) {
254
- console.error("Media loading optimization failed:", error)
255
- return metrics
256
- }
257
- }
258
-
259
- private chooseLoadingStrategy(
260
- networkInfo: NetworkInfo,
261
- options: { preload?: boolean; priority?: string; quality?: string }
262
- ) {
263
- const effectiveType = networkInfo.effectiveType === "unknown" ? "4g" : networkInfo.effectiveType
264
- const threshold =
265
- this.config.networkThresholds[effectiveType] || this.config.networkThresholds["4g"]
266
-
267
- return {
268
- shouldPreload: options.preload !== false && threshold.preload && !networkInfo.saveData,
269
- preloadAmount: networkInfo.saveData ? 0 : this.config.maxPreloadSize,
270
- preloadAttribute: this.getPreloadAttribute(networkInfo),
271
- suggestedQuality: this.getSuggestedQuality(networkInfo, threshold.maxBitrate),
272
- bufferTarget: this.getBufferTarget(networkInfo)
273
- }
274
- }
275
-
276
- private getPreloadAttribute(networkInfo: NetworkInfo): "none" | "metadata" | "auto" {
277
- if (networkInfo.saveData || networkInfo.effectiveType === "2g") {
278
- return "none"
279
- }
280
-
281
- if (networkInfo.effectiveType === "3g") {
282
- return "metadata"
283
- }
284
-
285
- return this.config.preloadStrategy
286
- }
287
-
288
- private getSuggestedQuality(networkInfo: NetworkInfo, maxBitrate: number): string {
289
- const availableBandwidth = networkInfo.downlink * 1000 // Convert to kbps
290
-
291
- if (availableBandwidth >= maxBitrate * 2) return "high"
292
- if (availableBandwidth >= maxBitrate) return "medium"
293
- return "low"
294
- }
295
-
296
- private getBufferTarget(networkInfo: NetworkInfo): number {
297
- switch (networkInfo.effectiveType) {
298
- case "2g":
299
- return 2 // 2 seconds
300
- case "3g":
301
- return 5 // 5 seconds
302
- case "4g":
303
- return this.config.bufferSize
304
- case "5g":
305
- return this.config.bufferSize * 1.5
306
- default:
307
- return this.config.bufferSize
308
- }
309
- }
310
-
311
- // Preload media content
312
- async preloadMedia(url: string, maxSize: number): Promise<void> {
313
- if (this.preloadCache.has(url)) {
314
- return // Already preloading or preloaded
315
- }
316
-
317
- const preloadPromise = this.fetchWithProgress(url, maxSize)
318
- this.preloadCache.set(url, preloadPromise)
319
-
320
- try {
321
- await preloadPromise
322
- } catch (error) {
323
- console.warn(`Preload failed for ${url}:`, error)
324
- this.preloadCache.delete(url)
325
- }
326
- }
327
-
328
- private async fetchWithProgress(url: string, maxSize: number): Promise<Blob> {
329
- const response = await fetch(url, {
330
- headers: {
331
- Range: `bytes=0-${maxSize - 1}` // Limit preload size
332
- }
333
- })
334
-
335
- if (!response.ok) {
336
- throw new Error(`Failed to preload: ${response.status}`)
337
- }
338
-
339
- const reader = response.body?.getReader()
340
- if (!reader) {
341
- throw new Error("Response body not readable")
342
- }
343
-
344
- const chunks: Uint8Array[] = []
345
- let bytesRead = 0
346
-
347
- try {
348
- while (bytesRead < maxSize) {
349
- const { done, value } = await reader.read()
350
- if (done) break
351
-
352
- chunks.push(value)
353
- bytesRead += value.length
354
- }
355
- } finally {
356
- reader.releaseLock()
357
- }
358
-
359
- return new Blob(chunks)
360
- }
361
-
362
- // Monitor loading progress and update metrics
363
- private monitorLoadingProgress(element: HTMLMediaElement, metrics: MediaLoadingMetrics) {
364
- let stallStartTime: number | null = null
365
-
366
- const updateMetrics = () => {
367
- if (element.buffered.length > 0) {
368
- const bufferedEnd = element.buffered.end(element.buffered.length - 1)
369
- const currentTime = element.currentTime
370
- metrics.bufferHealth = Math.min((bufferedEnd - currentTime) / this.config.bufferSize, 1)
371
- }
372
- }
373
-
374
- // Track first byte
375
- const onLoadStart = () => {
376
- metrics.firstByteTime = performance.now()
377
- }
378
-
379
- // Track load completion
380
- const onCanPlay = () => {
381
- metrics.loadCompleteTime = performance.now()
382
- metrics.totalLoadTime = metrics.loadCompleteTime - metrics.loadStartTime
383
-
384
- // Calculate load speed
385
- if (metrics.totalLoadTime && metrics.bytesLoaded > 0) {
386
- metrics.loadSpeed = metrics.bytesLoaded / (metrics.totalLoadTime / 1000)
387
- }
388
- }
389
-
390
- // Track stalls
391
- const onWaiting = () => {
392
- if (stallStartTime === null) {
393
- stallStartTime = performance.now()
394
- metrics.stallsCount++
395
- }
396
- }
397
-
398
- const onPlaying = () => {
399
- if (stallStartTime !== null) {
400
- metrics.stallsDuration += performance.now() - stallStartTime
401
- stallStartTime = null
402
- }
403
- updateMetrics()
404
- }
405
-
406
- // Track progress
407
- const onProgress = () => {
408
- if (element.buffered.length > 0) {
409
- const bufferedBytes = element.buffered.end(0) * 1000 // Rough estimate
410
- metrics.bytesLoaded = bufferedBytes
411
- }
412
- updateMetrics()
413
- }
414
-
415
- // Add event listeners
416
- element.addEventListener("loadstart", onLoadStart)
417
- element.addEventListener("canplay", onCanPlay)
418
- element.addEventListener("waiting", onWaiting)
419
- element.addEventListener("playing", onPlaying)
420
- element.addEventListener("progress", onProgress)
421
-
422
- // Cleanup function
423
- const cleanup = () => {
424
- element.removeEventListener("loadstart", onLoadStart)
425
- element.removeEventListener("canplay", onCanPlay)
426
- element.removeEventListener("waiting", onWaiting)
427
- element.removeEventListener("playing", onPlaying)
428
- element.removeEventListener("progress", onProgress)
429
- }
430
-
431
- // Auto-cleanup after 5 minutes
432
- setTimeout(cleanup, 5 * 60 * 1000)
433
- }
434
-
435
- // Apply quality settings (would integrate with HLS.js or similar)
436
- private applyQualitySettings(element: HTMLMediaElement, quality: string) {
437
- // This would integrate with your video streaming library
438
- console.log(`Applying quality setting: ${quality} to`, element)
439
-
440
- // Example integration with HLS.js:
441
- // if (element.hls) {
442
- // element.hls.currentLevel = this.getQualityLevel(quality);
443
- // }
444
- }
445
-
446
- private adjustQualityForNetwork(networkInfo: NetworkInfo) {
447
- // Auto-adjust quality for all active media elements
448
- console.log("Adjusting quality for network conditions:", networkInfo.effectiveType)
449
- }
450
-
451
- // Clear preload cache to save memory
452
- clearPreloadCache() {
453
- this.preloadCache.clear()
454
- }
455
-
456
- // Get loading metrics for a specific media URL
457
- getLoadingMetrics(url: string): MediaLoadingMetrics | undefined {
458
- return this.loadingMetrics.get(url)
459
- }
460
-
461
- // Get all loading metrics
462
- getAllMetrics(): MediaLoadingMetrics[] {
463
- return Array.from(this.loadingMetrics.values())
464
- }
465
-
466
- // Calculate average loading performance
467
- getAverageLoadingTime(): number {
468
- const metrics = this.getAllMetrics()
469
- const completedLoads = metrics.filter((m) => m.totalLoadTime !== undefined)
470
-
471
- if (completedLoads.length === 0) return 0
472
-
473
- const total = completedLoads.reduce((sum, m) => sum + (m.totalLoadTime || 0), 0)
474
- return total / completedLoads.length
475
- }
476
-
477
- // Get network-specific performance stats
478
- getNetworkPerformanceStats(): {
479
- networkType: string
480
- avgLoadTime: number
481
- avgStalls: number
482
- avgBufferHealth: number
483
- }[] {
484
- const statsByNetwork = new Map<string, MediaLoadingMetrics[]>()
485
-
486
- this.getAllMetrics().forEach((metrics) => {
487
- const network = metrics.networkType
488
- if (!statsByNetwork.has(network)) {
489
- statsByNetwork.set(network, [])
490
- }
491
- statsByNetwork.get(network)!.push(metrics)
492
- })
493
-
494
- return Array.from(statsByNetwork.entries()).map(([networkType, metrics]) => ({
495
- networkType,
496
- avgLoadTime: metrics.reduce((sum, m) => sum + (m.totalLoadTime || 0), 0) / metrics.length,
497
- avgStalls: metrics.reduce((sum, m) => sum + m.stallsCount, 0) / metrics.length,
498
- avgBufferHealth: metrics.reduce((sum, m) => sum + m.bufferHealth, 0) / metrics.length
499
- }))
500
- }
501
- }
502
-
503
- // Global media loading optimizer instance
504
- export const mediaLoadingOptimizer = new MediaLoadingOptimizer()
505
-
506
- // React hook for media loading optimization
507
- export function useMediaLoadingOptimizer(config?: Partial<MediaLoadingConfig>) {
508
- const [optimizer] = React.useState(() =>
509
- config ? new MediaLoadingOptimizer(config) : mediaLoadingOptimizer
510
- )
511
-
512
- const [networkInfo, setNetworkInfo] = React.useState<NetworkInfo | null>(null)
513
- const [loadingMetrics, setLoadingMetrics] = React.useState<MediaLoadingMetrics[]>([])
514
-
515
- React.useEffect(() => {
516
- const unsubscribe = optimizer["networkMonitor"].subscribe(setNetworkInfo)
517
- setNetworkInfo(optimizer["networkMonitor"].getCurrentNetworkInfo())
518
-
519
- // Update metrics periodically
520
- const interval = setInterval(() => {
521
- setLoadingMetrics(optimizer.getAllMetrics())
522
- }, 1000)
523
-
524
- return () => {
525
- unsubscribe()
526
- clearInterval(interval)
527
- }
528
- }, [optimizer])
529
-
530
- const optimizeLoading = React.useCallback(
531
- (mediaUrl: string, element: HTMLMediaElement, options?: any) => {
532
- return optimizer.optimizeMediaLoading(mediaUrl, element, options)
533
- },
534
- [optimizer]
535
- )
536
-
537
- return {
538
- networkInfo,
539
- loadingMetrics,
540
- optimizeLoading,
541
- averageLoadTime: optimizer.getAverageLoadingTime(),
542
- networkStats: optimizer.getNetworkPerformanceStats()
543
- }
544
- }