@therealtinhtute/baroiplayer 1.0.0

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 (244) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +384 -0
  3. package/dist/context/media.js +2 -0
  4. package/dist/context/media.js.map +1 -0
  5. package/dist/context/media.mjs +15 -0
  6. package/dist/context/media.mjs.map +1 -0
  7. package/dist/context/store.js +2 -0
  8. package/dist/context/store.js.map +1 -0
  9. package/dist/context/store.mjs +5 -0
  10. package/dist/context/store.mjs.map +1 -0
  11. package/dist/context-BMteAJDN.js +1140 -0
  12. package/dist/context-BMteAJDN.js.map +1 -0
  13. package/dist/context-DCJ_scmO.cjs +23 -0
  14. package/dist/context-DCJ_scmO.cjs.map +1 -0
  15. package/dist/core-events-B5W_j8yU.js +480 -0
  16. package/dist/core-events-B5W_j8yU.js.map +1 -0
  17. package/dist/core-events-CN0-Vhhq.cjs +2 -0
  18. package/dist/core-events-CN0-Vhhq.cjs.map +1 -0
  19. package/dist/core-plugins-Bq9KLany.js +696 -0
  20. package/dist/core-plugins-Bq9KLany.js.map +1 -0
  21. package/dist/core-plugins-CPDSHMiQ.cjs +2 -0
  22. package/dist/core-plugins-CPDSHMiQ.cjs.map +1 -0
  23. package/dist/core.js +37 -0
  24. package/dist/core.js.map +1 -0
  25. package/dist/core.mjs +1217 -0
  26. package/dist/core.mjs.map +1 -0
  27. package/dist/enhanced-components-DHv0MFvG.js +1073 -0
  28. package/dist/enhanced-components-DHv0MFvG.js.map +1 -0
  29. package/dist/enhanced-components-DTIObgB7.cjs +2 -0
  30. package/dist/enhanced-components-DTIObgB7.cjs.map +1 -0
  31. package/dist/hooks-C_r8wexn.cjs +4 -0
  32. package/dist/hooks-C_r8wexn.cjs.map +1 -0
  33. package/dist/hooks-Da2wVXlF.js +1630 -0
  34. package/dist/hooks-Da2wVXlF.js.map +1 -0
  35. package/dist/index.css +1 -0
  36. package/dist/index.js +112 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/index.mjs +6126 -0
  39. package/dist/index.mjs.map +1 -0
  40. package/dist/minimal-components-DSq5sQpy.js +2002 -0
  41. package/dist/minimal-components-DSq5sQpy.js.map +1 -0
  42. package/dist/minimal-components-DflWiihN.cjs +2 -0
  43. package/dist/minimal-components-DflWiihN.cjs.map +1 -0
  44. package/dist/minimal-components.css +1 -0
  45. package/dist/mona-loading.gif +0 -0
  46. package/dist/performance-monitor-CUW6f5ll.cjs +2 -0
  47. package/dist/performance-monitor-CUW6f5ll.cjs.map +1 -0
  48. package/dist/performance-monitor-rMW1RgV3.js +302 -0
  49. package/dist/performance-monitor-rMW1RgV3.js.map +1 -0
  50. package/dist/utils-BnscpYYd.js +2798 -0
  51. package/dist/utils-BnscpYYd.js.map +1 -0
  52. package/dist/utils-D_czS_0K.cjs +9 -0
  53. package/dist/utils-D_czS_0K.cjs.map +1 -0
  54. package/dist/utils.js +2 -0
  55. package/dist/utils.js.map +1 -0
  56. package/dist/utils.mjs +7 -0
  57. package/dist/utils.mjs.map +1 -0
  58. package/package.json +114 -0
  59. package/src/adapters/videojs-adapter.tsx +470 -0
  60. package/src/assets/mona-loading.gif +0 -0
  61. package/src/components/AnimateLoading.tsx +115 -0
  62. package/src/components/LoadingState.tsx +248 -0
  63. package/src/components/accessibility/keyboard-help-overlay.tsx +213 -0
  64. package/src/components/audio-player.tsx +85 -0
  65. package/src/components/basic/index.ts +37 -0
  66. package/src/components/enhanced/advanced-features.tsx +316 -0
  67. package/src/components/enhanced/debug-panel.tsx +422 -0
  68. package/src/components/enhanced/enhanced-controls.tsx +600 -0
  69. package/src/components/enhanced/enhanced-media-player.tsx +509 -0
  70. package/src/components/enhanced/error-handling.tsx +345 -0
  71. package/src/components/enhanced/index.ts +39 -0
  72. package/src/components/enhanced/media-player-enhanced.tsx +349 -0
  73. package/src/components/examples/basic-video-player.tsx +55 -0
  74. package/src/components/examples/custom-controls-example.tsx +63 -0
  75. package/src/components/examples/enhanced-controls-example.tsx +114 -0
  76. package/src/components/examples/enhanced-media-player-example.tsx +293 -0
  77. package/src/components/examples/loading-states-demo.tsx +142 -0
  78. package/src/components/examples/react-19-demo.tsx +381 -0
  79. package/src/components/examples/volume-orientation-demo.tsx +114 -0
  80. package/src/components/icon-demo.tsx +209 -0
  81. package/src/components/icons/index.tsx +166 -0
  82. package/src/components/icons/svg-icons/ArrowLeftIcon.tsx +18 -0
  83. package/src/components/icons/svg-icons/ArrowRightIcon.tsx +18 -0
  84. package/src/components/icons/svg-icons/AudioIcon.tsx +22 -0
  85. package/src/components/icons/svg-icons/BackwardIcon.tsx +12 -0
  86. package/src/components/icons/svg-icons/CameraIcon.tsx +19 -0
  87. package/src/components/icons/svg-icons/CheckIcon.tsx +19 -0
  88. package/src/components/icons/svg-icons/EnablePiPIcon.tsx +17 -0
  89. package/src/components/icons/svg-icons/ForwardIcon.tsx +12 -0
  90. package/src/components/icons/svg-icons/FullscreenEnterIcon.tsx +23 -0
  91. package/src/components/icons/svg-icons/FullscreenExitIcon.tsx +23 -0
  92. package/src/components/icons/svg-icons/LoadingIcon.tsx +32 -0
  93. package/src/components/icons/svg-icons/PauseIcon.tsx +23 -0
  94. package/src/components/icons/svg-icons/PlayIcon.tsx +21 -0
  95. package/src/components/icons/svg-icons/PlaybackSpeedIcon.tsx +23 -0
  96. package/src/components/icons/svg-icons/QualityIcon.tsx +21 -0
  97. package/src/components/icons/svg-icons/SettingsIcon.tsx +12 -0
  98. package/src/components/icons/svg-icons/SliderIcon.tsx +21 -0
  99. package/src/components/icons/svg-icons/SubtitleIcon.tsx +21 -0
  100. package/src/components/icons/svg-icons/SubtitleOffIcon.tsx +25 -0
  101. package/src/components/icons/svg-icons/UnPiPIcon.tsx +17 -0
  102. package/src/components/icons/svg-icons/VolumeMutedIcon.tsx +16 -0
  103. package/src/components/icons/svg-icons/VolumeOneIcon.tsx +22 -0
  104. package/src/components/icons/svg-icons/VolumeThreeIcon.tsx +16 -0
  105. package/src/components/icons/svg-icons/VolumeTwoIcon.tsx +16 -0
  106. package/src/components/legacy.tsx +93 -0
  107. package/src/components/media-metadata-display.tsx +100 -0
  108. package/src/components/media-player-audio.tsx +39 -0
  109. package/src/components/media-player-controls.tsx +226 -0
  110. package/src/components/media-player-error.tsx +163 -0
  111. package/src/components/media-player-fullscreen.tsx +109 -0
  112. package/src/components/media-player-hls.tsx +111 -0
  113. package/src/components/media-player-loading.tsx +76 -0
  114. package/src/components/media-player-play.tsx +75 -0
  115. package/src/components/media-player-root.tsx +340 -0
  116. package/src/components/media-player-seek.tsx +168 -0
  117. package/src/components/media-player-time.tsx +99 -0
  118. package/src/components/media-player-tooltip.tsx +58 -0
  119. package/src/components/media-player-video.tsx +39 -0
  120. package/src/components/media-player-volume.tsx +155 -0
  121. package/src/components/media-player.tsx +257 -0
  122. package/src/components/media-suspense.tsx +362 -0
  123. package/src/components/player-settings-form.tsx +163 -0
  124. package/src/components/react-player-wrapper.tsx +651 -0
  125. package/src/components/simple-video-player.tsx +60 -0
  126. package/src/components/ui/enhanced-seek-bar.tsx +235 -0
  127. package/src/components/ui/fullscreen-button.tsx +60 -0
  128. package/src/components/ui/media-resource-preloader.tsx +395 -0
  129. package/src/components/ui/play-button.tsx +107 -0
  130. package/src/components/ui/seek-bar.tsx +161 -0
  131. package/src/components/ui/time-display.tsx +40 -0
  132. package/src/components/ui/volume-control.tsx +143 -0
  133. package/src/components/unified/base-media-player.tsx +246 -0
  134. package/src/components/unified/media-player.tsx +75 -0
  135. package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +561 -0
  136. package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +552 -0
  137. package/src/components/variants/minimal/MinimalControls.tsx +142 -0
  138. package/src/components/variants/minimal/MinimalLoading.tsx +32 -0
  139. package/src/components/variants/minimal/MinimalMediaPlayer.tsx +315 -0
  140. package/src/components/variants/minimal/MinimalOverlay.tsx +64 -0
  141. package/src/components/variants/minimal/MinimalPlayButton.tsx +65 -0
  142. package/src/components/variants/minimal/MinimalSeekBar.tsx +150 -0
  143. package/src/components/variants/minimal/MinimalVolumeControl.tsx +80 -0
  144. package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +210 -0
  145. package/src/components/variants/minimal/components/CenterPlayButton.tsx +22 -0
  146. package/src/components/variants/minimal/components/ControlBar.tsx +146 -0
  147. package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +361 -0
  148. package/src/components/variants/minimal/components/PlaybackControls.tsx +51 -0
  149. package/src/components/variants/minimal/components/RightControls.tsx +173 -0
  150. package/src/components/variants/minimal/components/SeekBar.tsx +131 -0
  151. package/src/components/variants/minimal/components/SettingsDropdown.tsx +70 -0
  152. package/src/components/variants/minimal/components/SubtitleDisplay.tsx +21 -0
  153. package/src/components/variants/minimal/components/TimeDisplay.tsx +18 -0
  154. package/src/components/variants/minimal/components/VideoElement.tsx +40 -0
  155. package/src/components/variants/minimal/components/VolumeControl.tsx +217 -0
  156. package/src/components/variants/minimal/index.ts +23 -0
  157. package/src/components/video-player.tsx +100 -0
  158. package/src/context/error-handling.ts +394 -0
  159. package/src/context/media-context.tsx +208 -0
  160. package/src/context/media-provider.tsx +265 -0
  161. package/src/context/media-store.ts +379 -0
  162. package/src/context/persistence.ts +453 -0
  163. package/src/core/events/event-system.ts +442 -0
  164. package/src/core/events/hooks.ts +302 -0
  165. package/src/core/events/index.ts +22 -0
  166. package/src/core/events/middleware.ts +269 -0
  167. package/src/core/index.ts +22 -0
  168. package/src/core/optimization/bundle-optimizer.tsx +308 -0
  169. package/src/core/performance/cicd.ts +96 -0
  170. package/src/core/performance/index.ts +38 -0
  171. package/src/core/performance/media-loading-optimizer.ts +538 -0
  172. package/src/core/performance/performance-budgets.ts +432 -0
  173. package/src/core/performance/performance-monitor.tsx +476 -0
  174. package/src/core/performance/performance-testing.ts +459 -0
  175. package/src/core/plugins/base-plugin.ts +224 -0
  176. package/src/core/plugins/enhanced-plugin-system.ts +411 -0
  177. package/src/core/plugins/examples/analytics-plugin.ts +242 -0
  178. package/src/core/plugins/index.ts +39 -0
  179. package/src/core/plugins/registry.ts +327 -0
  180. package/src/core/plugins/types.ts +159 -0
  181. package/src/core/plugins/utils.ts +316 -0
  182. package/src/core/progressive-loading.tsx +322 -0
  183. package/src/core/providers/enhanced-hls-provider.ts +339 -0
  184. package/src/core/providers/service-provider.tsx +168 -0
  185. package/src/core/utils.tsx +38 -0
  186. package/src/features/media-session/media-session-manager.ts +429 -0
  187. package/src/features/picture-in-picture/pip-manager.ts +429 -0
  188. package/src/features/playlist/playlist-manager.ts +606 -0
  189. package/src/features/subtitles/subtitle-manager.ts +441 -0
  190. package/src/features/subtitles/subtitle-parser.ts +280 -0
  191. package/src/features/thumbnails/thumbnail-generator.ts +519 -0
  192. package/src/hooks/accessibility/index.ts +27 -0
  193. package/src/hooks/accessibility/use-accessibility-preferences.ts +188 -0
  194. package/src/hooks/accessibility/use-focus-management.ts +176 -0
  195. package/src/hooks/accessibility/use-keyboard-shortcuts.ts +144 -0
  196. package/src/hooks/accessibility/use-screen-reader.ts +182 -0
  197. package/src/hooks/core/index.ts +47 -0
  198. package/src/hooks/legacy.ts +27 -0
  199. package/src/hooks/use-enhanced-media-player.ts +468 -0
  200. package/src/hooks/use-intelligent-preloading.ts +358 -0
  201. package/src/hooks/use-keyboard-controls.ts +115 -0
  202. package/src/hooks/use-media-actions.ts +175 -0
  203. package/src/hooks/use-media-metadata.ts +89 -0
  204. package/src/hooks/use-media-optimistic.ts +270 -0
  205. package/src/hooks/use-media-player.ts +312 -0
  206. package/src/hooks/use-media-state.ts +190 -0
  207. package/src/hooks/use-memory-optimization.ts +358 -0
  208. package/src/hooks/use-optimistic-controls.ts +92 -0
  209. package/src/hooks/use-optimized-media.ts +263 -0
  210. package/src/hooks/use-touch-gestures.ts +417 -0
  211. package/src/hooks/useEnhancedSubtitles.ts +258 -0
  212. package/src/hooks/useKeyboardShortcuts.ts +74 -0
  213. package/src/hooks/useMediaControls.ts +52 -0
  214. package/src/hooks/useScreenshot.ts +57 -0
  215. package/src/hooks/useSubtitles.ts +91 -0
  216. package/src/hooks/useVideoPlayer.ts +232 -0
  217. package/src/icons/components/FullscreenIcon.tsx +37 -0
  218. package/src/icons/components/SettingsIcon.tsx +38 -0
  219. package/src/icons/components/animated/LoadingIcon.tsx +43 -0
  220. package/src/icons/components/animated/PlayPauseIcon.tsx +50 -0
  221. package/src/icons/components/media/PauseIcon.tsx +39 -0
  222. package/src/icons/components/media/PlayIcon.tsx +38 -0
  223. package/src/icons/components/volume/VolumeIcon.tsx +39 -0
  224. package/src/icons/components/volume/VolumeOffIcon.tsx +39 -0
  225. package/src/icons/index.ts +56 -0
  226. package/src/icons/provider.tsx +64 -0
  227. package/src/icons/types.ts +40 -0
  228. package/src/index-enhanced.ts +35 -0
  229. package/src/index-legacy.ts +326 -0
  230. package/src/index.css +102 -0
  231. package/src/index.ts +216 -0
  232. package/src/lib/deprecation.ts +51 -0
  233. package/src/lib/format-time.ts +37 -0
  234. package/src/lib/index.ts +3 -0
  235. package/src/lib/utils.ts +6 -0
  236. package/src/styles/globals.css +462 -0
  237. package/src/styles/minimal-player.css +589 -0
  238. package/src/styles/pixel-art.css +46 -0
  239. package/src/styles/videojs.css +100 -0
  240. package/src/test/setup.ts +79 -0
  241. package/src/types/events.ts +47 -0
  242. package/src/types/formats.ts +95 -0
  243. package/src/types/index.ts +190 -0
  244. package/src/types/videojs-plugins.d.ts +14 -0
@@ -0,0 +1,509 @@
1
+ /**
2
+ * Enhanced Media Player with all optimizations applied
3
+ * Integrates React 19 features, HLS optimization, and intelligent preloading
4
+ */
5
+
6
+ import React, {
7
+ useRef,
8
+ useState,
9
+ useEffect,
10
+ useCallback,
11
+ useMemo,
12
+ useTransition,
13
+ useOptimistic,
14
+ useDeferredValue,
15
+ Suspense,
16
+ } from 'react';
17
+ import { MediaPlayerProps, MediaSource } from '../../types';
18
+ import { MediaResourcePreloader } from '../ui/media-resource-preloader';
19
+ import { useIntelligentPreloading } from '../../hooks/use-intelligent-preloading';
20
+ import { EnhancedHLSProvider, ENHANCED_HLS_DEFAULTS } from '../../core/providers/enhanced-hls-provider';
21
+ import { EnhancedPluginManager } from '../../core/plugins/enhanced-plugin-system';
22
+ import { cn } from '../../lib/utils';
23
+
24
+ interface EnhancedMediaPlayerProps extends MediaPlayerProps {
25
+ /** Enable enhanced HLS optimization */
26
+ enableEnhancedHLS?: boolean;
27
+ /** Enable intelligent preloading */
28
+ enableIntelligentPreloading?: boolean;
29
+ /** Enable performance monitoring */
30
+ enablePerformanceMonitoring?: boolean;
31
+ /** Custom HLS configuration */
32
+ hlsConfig?: any;
33
+ /** Preloading strategy */
34
+ preloadingStrategy?: 'conservative' | 'balanced' | 'aggressive';
35
+ /** Show performance debug panel (development only) */
36
+ showDebugPanel?: boolean;
37
+ }
38
+
39
+ interface MediaState {
40
+ isPlaying: boolean;
41
+ currentTime: number;
42
+ duration: number;
43
+ volume: number;
44
+ isMuted: boolean;
45
+ isFullscreen: boolean;
46
+ isBuffering: boolean;
47
+ quality: number;
48
+ error: MediaError | null;
49
+ }
50
+
51
+ interface PerformanceMetrics {
52
+ fps: number;
53
+ memoryUsage: number;
54
+ bufferHealth: number;
55
+ networkBandwidth: number;
56
+ droppedFrames: number;
57
+ }
58
+
59
+ /**
60
+ * Enhanced Media Player Component
61
+ */
62
+ export const EnhancedMediaPlayer: React.FC<EnhancedMediaPlayerProps> = ({
63
+ src,
64
+ sources,
65
+ poster,
66
+ autoPlay = false,
67
+ muted = false,
68
+ loop = false,
69
+ controls = true,
70
+ className,
71
+ enableEnhancedHLS = true,
72
+ enableIntelligentPreloading = true,
73
+ enablePerformanceMonitoring = process.env.NODE_ENV === 'development',
74
+ hlsConfig = {},
75
+ preloadingStrategy = 'balanced',
76
+ showDebugPanel = false,
77
+ onPlay,
78
+ onPause,
79
+ onEnded,
80
+ onError,
81
+ onTimeUpdate,
82
+ onLoadStart,
83
+ onCanPlay,
84
+ ...props
85
+ }) => {
86
+ const videoRef = useRef<HTMLVideoElement>(null);
87
+ const containerRef = useRef<HTMLDivElement>(null);
88
+ const hlsProviderRef = useRef<EnhancedHLSProvider | null>(null);
89
+ const pluginManagerRef = useRef<EnhancedPluginManager | null>(null);
90
+
91
+ // React 19 concurrent features
92
+ const [isPending, startTransition] = useTransition();
93
+ const optimisticState = useOptimistic(
94
+ { isPlaying: false, volume: 1 },
95
+ (state, update: Partial<MediaState>) => ({ ...state, ...update })
96
+ );
97
+
98
+ // Media state
99
+ const [mediaState, setMediaState] = useState<MediaState>({
100
+ isPlaying: false,
101
+ currentTime: 0,
102
+ duration: 0,
103
+ volume: 1,
104
+ isMuted: muted,
105
+ isFullscreen: false,
106
+ isBuffering: false,
107
+ quality: 0,
108
+ error: null,
109
+ });
110
+
111
+ // Performance metrics
112
+ const [performanceMetrics, setPerformanceMetrics] = useState<PerformanceMetrics>({
113
+ fps: 0,
114
+ memoryUsage: 0,
115
+ bufferHealth: 0,
116
+ networkBandwidth: 0,
117
+ droppedFrames: 0,
118
+ });
119
+
120
+ // Deferred values for non-critical updates
121
+ const deferredCurrentTime = useDeferredValue(mediaState.currentTime);
122
+ const deferredVolume = useDeferredValue(mediaState.volume);
123
+
124
+ // Prepare media sources
125
+ const mediaSources = useMemo((): MediaSource[] => {
126
+ if (sources) {
127
+ return sources;
128
+ }
129
+ if (src) {
130
+ const extension = src.split('.').pop()?.toLowerCase();
131
+ const type = getMediaTypeFromExtension(extension);
132
+ return [{ src, type }];
133
+ }
134
+ return [];
135
+ }, [src, sources]);
136
+
137
+ // Intelligent preloading
138
+ const preloadingControls = useIntelligentPreloading(mediaSources, {
139
+ trackUserBehavior: enableIntelligentPreloading,
140
+ adaptToNetwork: true,
141
+ strategy: preloadingStrategy,
142
+ maxPreloadItems: 3,
143
+ });
144
+
145
+ // Initialize HLS provider
146
+ const initializeHLS = useCallback(async () => {
147
+ if (!videoRef.current || !enableEnhancedHLS) return;
148
+
149
+ const hlsConfig = { ...ENHANCED_HLS_DEFAULTS, ...hlsConfig };
150
+ const provider = new EnhancedHLSProvider(hlsConfig);
151
+ hlsProviderRef.current = provider;
152
+
153
+ try {
154
+ const hls = provider.initialize(videoRef.current, mediaSources[0].src, {
155
+ hlsConfig: hlsConfig,
156
+ onError: handleMediaError,
157
+ });
158
+
159
+ // Setup HLS event listeners
160
+ hls.on(Hls.Events.LEVEL_SWITCHED, handleQualityChange);
161
+ hls.on(Hls.Events.FRAG_BUFFERED, handleFragmentBuffered);
162
+ hls.on(Hls.Events.ERROR, handleHLSError);
163
+
164
+ } catch (error) {
165
+ console.error('HLS initialization failed:', error);
166
+ fallbackToNativePlayback();
167
+ }
168
+ }, [enableEnhancedHLS, hlsConfig, mediaSources]);
169
+
170
+ // Fallback to native playback
171
+ const fallbackToNativePlayback = useCallback(() => {
172
+ if (!videoRef.current || !mediaSources[0]) return;
173
+
174
+ const source = document.createElement('source');
175
+ source.src = mediaSources[0].src;
176
+ source.type = getMediaTypeFromUrl(mediaSources[0].src);
177
+
178
+ videoRef.current.appendChild(source);
179
+ videoRef.current.load();
180
+ }, [mediaSources]);
181
+
182
+ // Media event handlers
183
+ const handlePlay = useCallback(() => {
184
+ startTransition(() => {
185
+ setMediaState(prev => ({ ...prev, isPlaying: true }));
186
+ });
187
+ onPlay?.();
188
+ }, [onPlay]);
189
+
190
+ const handlePause = useCallback(() => {
191
+ startTransition(() => {
192
+ setMediaState(prev => ({ ...prev, isPlaying: false }));
193
+ });
194
+ onPause?.();
195
+ }, [onPause]);
196
+
197
+ const handleEnded = useCallback(() => {
198
+ startTransition(() => {
199
+ setMediaState(prev => ({ ...prev, isPlaying: false }));
200
+ });
201
+ onEnded?.();
202
+ }, [onEnded]);
203
+
204
+ const handleTimeUpdate = useCallback(() => {
205
+ if (!videoRef.current) return;
206
+
207
+ startTransition(() => {
208
+ setMediaState(prev => ({
209
+ ...prev,
210
+ currentTime: videoRef.current!.currentTime,
211
+ }));
212
+ });
213
+ onTimeUpdate?.();
214
+ }, [onTimeUpdate]);
215
+
216
+ const handleLoadedMetadata = useCallback(() => {
217
+ if (!videoRef.current) return;
218
+
219
+ startTransition(() => {
220
+ setMediaState(prev => ({
221
+ ...prev,
222
+ duration: videoRef.current!.duration,
223
+ }));
224
+ });
225
+ }, []);
226
+
227
+ const handleVolumeChange = useCallback(() => {
228
+ if (!videoRef.current) return;
229
+
230
+ startTransition(() => {
231
+ setMediaState(prev => ({
232
+ ...prev,
233
+ volume: videoRef.current!.volume,
234
+ isMuted: videoRef.current!.muted,
235
+ }));
236
+ });
237
+ }, []);
238
+
239
+ const handleQualityChange = useCallback((event: any, data: any) => {
240
+ startTransition(() => {
241
+ setMediaState(prev => ({ ...prev, quality: data.level }));
242
+ });
243
+ }, []);
244
+
245
+ const handleFragmentBuffered = useCallback(() => {
246
+ // Update buffer health
247
+ if (videoRef.current) {
248
+ const buffered = videoRef.current.buffered;
249
+ const currentTime = videoRef.current.currentTime;
250
+ let bufferHealth = 0;
251
+
252
+ for (let i = 0; i < buffered.length; i++) {
253
+ const start = buffered.start(i);
254
+ const end = buffered.end(i);
255
+ if (start <= currentTime && end > currentTime) {
256
+ bufferHealth = end - currentTime;
257
+ break;
258
+ }
259
+ }
260
+
261
+ setPerformanceMetrics(prev => ({ ...prev, bufferHealth }));
262
+ }
263
+ }, []);
264
+
265
+ const handleMediaError = useCallback((error: MediaError) => {
266
+ startTransition(() => {
267
+ setMediaState(prev => ({ ...prev, error }));
268
+ });
269
+ onError?.(error);
270
+ }, [onError]);
271
+
272
+ const handleHLSError = useCallback((event: any, data: any) => {
273
+ if (data.fatal) {
274
+ console.error('Fatal HLS error:', data);
275
+ handleMediaError(new Error(`HLS Error: ${data.details}`));
276
+ }
277
+ }, [handleMediaError]);
278
+
279
+ // Performance monitoring
280
+ useEffect(() => {
281
+ if (!enablePerformanceMonitoring) return;
282
+
283
+ let frameCount = 0;
284
+ let lastTime = performance.now();
285
+
286
+ const measureFPS = () => {
287
+ frameCount++;
288
+ const currentTime = performance.now();
289
+
290
+ if (currentTime - lastTime >= 1000) {
291
+ const fps = Math.round((frameCount * 1000) / (currentTime - lastTime));
292
+
293
+ setPerformanceMetrics(prev => ({ ...prev, fps }));
294
+
295
+ frameCount = 0;
296
+ lastTime = currentTime;
297
+ }
298
+
299
+ if (videoRef.current && !videoRef.current.paused) {
300
+ requestAnimationFrame(measureFPS);
301
+ }
302
+ };
303
+
304
+ if (videoRef.current) {
305
+ videoRef.current.addEventListener('play', measureFPS);
306
+ }
307
+
308
+ return () => {
309
+ if (videoRef.current) {
310
+ videoRef.current.removeEventListener('play', measureFPS);
311
+ }
312
+ };
313
+ }, [enablePerformanceMonitoring]);
314
+
315
+ // Memory monitoring
316
+ useEffect(() => {
317
+ if (!enablePerformanceMonitoring || !('memory' in performance)) return;
318
+
319
+ const interval = setInterval(() => {
320
+ const memory = (performance as any).memory;
321
+ setPerformanceMetrics(prev => ({
322
+ ...prev,
323
+ memoryUsage: memory.usedJSHeapSize / 1024 / 1024, // MB
324
+ }));
325
+ }, 2000);
326
+
327
+ return () => clearInterval(interval);
328
+ }, [enablePerformanceMonitoring]);
329
+
330
+ // Initialize player
331
+ useEffect(() => {
332
+ if (!videoRef.current || mediaSources.length === 0) return;
333
+
334
+ // Setup native event listeners
335
+ const video = videoRef.current;
336
+
337
+ video.addEventListener('play', handlePlay);
338
+ video.addEventListener('pause', handlePause);
339
+ video.addEventListener('ended', handleEnded);
340
+ video.addEventListener('timeupdate', handleTimeUpdate);
341
+ video.addEventListener('loadedmetadata', handleLoadedMetadata);
342
+ video.addEventListener('volumechange', handleVolumeChange);
343
+ video.addEventListener('loadstart', onLoadStart);
344
+ video.addEventListener('canplay', onCanPlay);
345
+
346
+ // Initialize HLS if needed
347
+ if (mediaSources[0].type === 'hls' && enableEnhancedHLS) {
348
+ initializeHLS();
349
+ } else {
350
+ fallbackToNativePlayback();
351
+ }
352
+
353
+ // Initialize plugin manager
354
+ if (video) {
355
+ pluginManagerRef.current = new EnhancedPluginManager(video as any);
356
+ }
357
+
358
+ return () => {
359
+ // Cleanup
360
+ video.removeEventListener('play', handlePlay);
361
+ video.removeEventListener('pause', handlePause);
362
+ video.removeEventListener('ended', handleEnded);
363
+ video.removeEventListener('timeupdate', handleTimeUpdate);
364
+ video.removeEventListener('loadedmetadata', handleLoadedMetadata);
365
+ video.removeEventListener('volumechange', handleVolumeChange);
366
+ video.removeEventListener('loadstart', onLoadStart);
367
+ video.removeEventListener('canplay', onCanPlay);
368
+
369
+ hlsProviderRef.current?.destroy();
370
+ pluginManagerRef.current?.dispose();
371
+ };
372
+ }, [
373
+ mediaSources,
374
+ enableEnhancedHLS,
375
+ handlePlay,
376
+ handlePause,
377
+ handleEnded,
378
+ handleTimeUpdate,
379
+ handleLoadedMetadata,
380
+ handleVolumeChange,
381
+ onLoadStart,
382
+ onCanPlay,
383
+ initializeHLS,
384
+ fallbackToNativePlayback,
385
+ ]);
386
+
387
+ // Auto-play handling
388
+ useEffect(() => {
389
+ if (autoPlay && videoRef.current) {
390
+ videoRef.current.play().catch(error => {
391
+ console.warn('Auto-play failed:', error);
392
+ });
393
+ }
394
+ }, [autoPlay]);
395
+
396
+ // Render debug panel
397
+ const DebugPanel = useMemo(() => {
398
+ if (!showDebugPanel || process.env.NODE_ENV !== 'development') return null;
399
+
400
+ return (
401
+ <div className="fixed top-4 right-4 z-50 rounded-lg bg-black/80 p-4 font-mono text-white text-xs">
402
+ <h3 className="mb-2 font-bold">Performance Metrics</h3>
403
+ <div>FPS: {performanceMetrics.fps}</div>
404
+ <div>Memory: {performanceMetrics.memoryUsage.toFixed(2)} MB</div>
405
+ <div>Buffer: {performanceMetrics.bufferHealth.toFixed(2)}s</div>
406
+ <div>Time: {deferredCurrentTime.toFixed(2)}s / {mediaState.duration.toFixed(2)}s</div>
407
+ <div>Volume: {Math.round(deferredVolume * 100)}%</div>
408
+ <div>Quality: {mediaState.quality}</div>
409
+ <div>Playing: {mediaState.isPlaying ? 'Yes' : 'No'}</div>
410
+ <div>Buffering: {isPending ? 'Yes' : 'No'}</div>
411
+
412
+ <h3 className="mt-3 mb-2 font-bold">Preloading Stats</h3>
413
+ <div>Preloaded: {preloadingControls.getStats().preloadedItems}</div>
414
+ <div>Engagement: {preloadingControls.getStats().engagementScore.toFixed(1)}%</div>
415
+ <div>Queue: {preloadingControls.getStats().queueLength}</div>
416
+ </div>
417
+ );
418
+ }, [showDebugPanel, performanceMetrics, deferredCurrentTime, deferredVolume, mediaState, isPending, preloadingControls]);
419
+
420
+ return (
421
+ <div
422
+ ref={containerRef}
423
+ className={cn(
424
+ "relative aspect-video overflow-hidden rounded-lg bg-black",
425
+ className
426
+ )}
427
+ {...props}
428
+ >
429
+ {/* Media Resource Preloader */}
430
+ {enableIntelligentPreloading && (
431
+ <MediaResourcePreloader
432
+ sources={mediaSources}
433
+ enableIntelligentPreloading={true}
434
+ adaptToNetworkConditions={true}
435
+ priority="auto"
436
+ strategy={preloadingStrategy}
437
+ />
438
+ )}
439
+
440
+ {/* Video Element */}
441
+ <video
442
+ ref={videoRef}
443
+ className="h-full w-full"
444
+ poster={poster}
445
+ muted={muted}
446
+ loop={loop}
447
+ playsInline
448
+ preload="metadata"
449
+ crossOrigin="anonymous"
450
+ />
451
+
452
+ {/* Loading State */}
453
+ {isPending && (
454
+ <div className="absolute inset-0 flex items-center justify-center bg-black/50">
455
+ <div className="h-8 w-8 animate-spin rounded-full border-2 border-white border-t-transparent" />
456
+ </div>
457
+ )}
458
+
459
+ {/* Error State */}
460
+ {mediaState.error && (
461
+ <div className="absolute inset-0 flex items-center justify-center bg-black/75">
462
+ <div className="p-4 text-center text-white">
463
+ <h3 className="mb-2 font-semibold text-lg">Playback Error</h3>
464
+ <p className="text-sm opacity-75">{mediaState.error.message}</p>
465
+ </div>
466
+ </div>
467
+ )}
468
+
469
+ {/* Controls Slot */}
470
+ {controls && (
471
+ <div className="absolute right-0 bottom-0 left-0">
472
+ {/* Controls will be rendered here */}
473
+ </div>
474
+ )}
475
+
476
+ {/* Debug Panel */}
477
+ {DebugPanel}
478
+ </div>
479
+ );
480
+ };
481
+
482
+ // Helper functions
483
+ function getMediaTypeFromExtension(extension?: string): string {
484
+ switch (extension) {
485
+ case 'mp4':
486
+ return 'video/mp4';
487
+ case 'webm':
488
+ return 'video/webm';
489
+ case 'ogg':
490
+ return 'video/ogg';
491
+ case 'mp3':
492
+ return 'audio/mp3';
493
+ case 'wav':
494
+ return 'audio/wav';
495
+ case 'm3u8':
496
+ return 'hls';
497
+ case 'hls':
498
+ return 'hls';
499
+ default:
500
+ return 'video/mp4';
501
+ }
502
+ }
503
+
504
+ function getMediaTypeFromUrl(url: string): string {
505
+ const extension = url.split('.').pop()?.toLowerCase();
506
+ return getMediaTypeFromExtension(extension);
507
+ }
508
+
509
+ export default EnhancedMediaPlayer;