react-helios 2.5.0 → 2.7.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.
- package/README.md +52 -14
- package/dist/index.d.mts +60 -16
- package/dist/index.d.ts +60 -16
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# react-helios
|
|
2
2
|
|
|
3
|
-
Production-grade React video player with HLS streaming, audio mode, adaptive quality selection, live stream support, subtitle tracks, VTT sprite sheet thumbnail preview, Picture-in-Picture, and full keyboard control.
|
|
3
|
+
Production-grade React video player with HLS streaming, zero-cost audio mode, adaptive quality selection, live stream support, subtitle tracks, VTT sprite sheet thumbnail preview, Picture-in-Picture, and full keyboard control.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -60,7 +60,7 @@ On Safari the browser's native HLS engine is used. A **LIVE** badge and **GO LIV
|
|
|
60
60
|
|
|
61
61
|
## Audio Mode
|
|
62
62
|
|
|
63
|
-
Audio mode
|
|
63
|
+
Audio mode pauses the video element completely (stopping all video decoding), shows the poster artwork, and hands playback off to a lightweight `<audio>` element — so the player uses roughly the same CPU/GPU as a music app instead of a playing video.
|
|
64
64
|
|
|
65
65
|
```tsx
|
|
66
66
|
<VideoPlayer
|
|
@@ -79,9 +79,13 @@ Audio mode hides the video, shows the poster artwork, and keeps the audio stream
|
|
|
79
79
|
|
|
80
80
|
The audio toggle button only appears in the control bar when `audioSrc` is provided. Custom icons can be passed via `audioModeIcon` / `videoModeIcon`.
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
When switching between modes, position, volume, and playback rate are synced automatically — the listener hears no gap.
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
### Automatic switching
|
|
85
|
+
|
|
86
|
+
The player uses two independent signals to detect poor conditions and switch to audio mode automatically. Either one firing is enough.
|
|
87
|
+
|
|
88
|
+
**Bandwidth-based** — measures the actual download speed of each HLS fragment and switches when the rolling average drops below a threshold:
|
|
85
89
|
|
|
86
90
|
```tsx
|
|
87
91
|
import { AUDIO_BANDWIDTH_THRESHOLDS } from "react-helios";
|
|
@@ -89,8 +93,8 @@ import { AUDIO_BANDWIDTH_THRESHOLDS } from "react-helios";
|
|
|
89
93
|
<VideoPlayer
|
|
90
94
|
src="https://example.com/stream.m3u8"
|
|
91
95
|
options={{
|
|
92
|
-
audioBandwidthThreshold: AUDIO_BANDWIDTH_THRESHOLDS.
|
|
93
|
-
// audioBandwidthThreshold: 0, // disable
|
|
96
|
+
audioBandwidthThreshold: AUDIO_BANDWIDTH_THRESHOLDS.FAIR, // recommended
|
|
97
|
+
// audioBandwidthThreshold: 0, // disable bandwidth-based switching
|
|
94
98
|
}}
|
|
95
99
|
/>
|
|
96
100
|
```
|
|
@@ -98,11 +102,43 @@ import { AUDIO_BANDWIDTH_THRESHOLDS } from "react-helios";
|
|
|
98
102
|
| Preset | Kbps | Typical connection |
|
|
99
103
|
|--------|------|--------------------|
|
|
100
104
|
| `EXTREME` | 100 | 2G / Edge |
|
|
101
|
-
| `POOR` | 300 | Slow 3G
|
|
102
|
-
| `FAIR` |
|
|
103
|
-
| `GOOD` | 1500 | 4G / Wi-Fi |
|
|
105
|
+
| `POOR` | 300 | Slow 3G |
|
|
106
|
+
| `FAIR` | 800 | Marginal 3G ← **recommended** |
|
|
107
|
+
| `GOOD` | 1500 | Weak 4G / congested Wi-Fi |
|
|
108
|
+
|
|
109
|
+
**Level-based** — switches when HLS.js drops to a specific quality level (its own ABR algorithm already does the hard work):
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
import { AUDIO_SWITCH_LEVELS } from "react-helios";
|
|
113
|
+
|
|
114
|
+
<VideoPlayer
|
|
115
|
+
src="https://example.com/stream.m3u8"
|
|
116
|
+
options={{
|
|
117
|
+
audioModeSwitchLevel: AUDIO_SWITCH_LEVELS.LOWEST, // switch at lowest quality level
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
```
|
|
104
121
|
|
|
105
|
-
|
|
122
|
+
| Preset | Value | Meaning |
|
|
123
|
+
|--------|-------|---------|
|
|
124
|
+
| `LOWEST` | 0 | Switch when HLS.js is at the lowest available quality |
|
|
125
|
+
| `SECOND_LOWEST` | 1 | Switch one level above the lowest |
|
|
126
|
+
| `DISABLED` | -1 | Disable level-based switching |
|
|
127
|
+
|
|
128
|
+
Using **both together** is the most reliable approach:
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
<VideoPlayer
|
|
132
|
+
src="https://example.com/stream.m3u8"
|
|
133
|
+
options={{
|
|
134
|
+
audioSrc: "https://example.com/audio-only.m3u8",
|
|
135
|
+
audioBandwidthThreshold: AUDIO_BANDWIDTH_THRESHOLDS.FAIR,
|
|
136
|
+
audioModeSwitchLevel: AUDIO_SWITCH_LEVELS.LOWEST,
|
|
137
|
+
}}
|
|
138
|
+
/>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
After the user manually toggles audio mode a 60-second cooldown suppresses automatic switching. The player also probes for bandwidth recovery every 30 seconds while in auto-switched audio mode (configurable via `audioModeRecoveryInterval`).
|
|
106
142
|
|
|
107
143
|
## Thumbnail Preview
|
|
108
144
|
|
|
@@ -199,7 +235,9 @@ To disable the preview entirely:
|
|
|
199
235
|
| `videoModeIcon` | `ReactNode` | built-in video icon | Icon shown when in audio mode (click → video) |
|
|
200
236
|
| `audioModeFallback` | `ReactNode` | — | Custom content shown in audio mode when no `poster` is provided |
|
|
201
237
|
| `logo` | `string \| ReactNode` | — | Logo shown in audio mode when no `poster` or `audioModeFallback` is provided |
|
|
202
|
-
| `audioBandwidthThreshold` | `number` | `300` | Kbps —
|
|
238
|
+
| `audioBandwidthThreshold` | `number` | `300` | Kbps — switch when per-fragment bandwidth average drops below this. `0` = disabled (HLS only) |
|
|
239
|
+
| `audioModeSwitchLevel` | `number` | — | HLS quality level index — switch when HLS.js drops to this level or below. `0` = lowest. `-1` = disabled |
|
|
240
|
+
| `audioModeRecoveryInterval` | `number` | `30000` | Ms between recovery probes while in auto-switched audio mode |
|
|
203
241
|
|
|
204
242
|
### `options` — Callbacks
|
|
205
243
|
|
|
@@ -407,7 +445,7 @@ import type {
|
|
|
407
445
|
ControlBarItem,
|
|
408
446
|
} from "react-helios";
|
|
409
447
|
|
|
410
|
-
import { AUDIO_BANDWIDTH_THRESHOLDS } from "react-helios";
|
|
448
|
+
import { AUDIO_BANDWIDTH_THRESHOLDS, AUDIO_SWITCH_LEVELS } from "react-helios";
|
|
411
449
|
|
|
412
450
|
// VTT utilities (useful for server-side pre-parsing or custom UIs)
|
|
413
451
|
import { parseThumbnailVtt, findThumbnailCue } from "react-helios";
|
|
@@ -525,11 +563,11 @@ if (cue) {
|
|
|
525
563
|
The player is architected to produce **zero React re-renders during playback**:
|
|
526
564
|
|
|
527
565
|
- `timeupdate` and `progress` events are handled by direct DOM mutation (refs), not React state.
|
|
528
|
-
- `ProgressBar` and `TimeDisplay` self-subscribe to the
|
|
566
|
+
- `ProgressBar` and `TimeDisplay` self-subscribe to the active media element — the parent tree never re-renders on seek or time change.
|
|
529
567
|
- `Controls` and `AudioModeOverlay` are wrapped in `React.memo` — they only re-render when their own props change, not when unrelated state (buffering, errors) updates.
|
|
530
568
|
- VTT sprite thumbnails are looked up via binary search (O(log n)) and rendered via CSS `background-position` — no hidden `<video>` element, no canvas, no network requests per hover.
|
|
531
569
|
- Buffered ranges are the only state that triggers a re-render (fires every few seconds during buffering, not 60× per second).
|
|
532
|
-
- In audio mode the `<video>` element
|
|
570
|
+
- In audio mode the `<video>` element is **paused** — the browser stops decoding frames entirely. A lightweight `<audio>` element takes over with `preload="none"` (no network cost at startup). The `<audio>` element only loads its source the first time the user switches to audio mode.
|
|
533
571
|
|
|
534
572
|
## Project Structure
|
|
535
573
|
|
package/dist/index.d.mts
CHANGED
|
@@ -5,30 +5,57 @@ import { HlsConfig } from 'hls.js';
|
|
|
5
5
|
/**
|
|
6
6
|
* Preset bandwidth thresholds (Kbps) for automatic audio mode switching.
|
|
7
7
|
*
|
|
8
|
-
* | Preset | Kbps | Typical connection
|
|
9
|
-
*
|
|
10
|
-
* | EXTREME | 100 | 2G / Edge
|
|
11
|
-
* | POOR | 300 | Slow 3G
|
|
12
|
-
* | FAIR |
|
|
13
|
-
* | GOOD | 1500 | 4G / Wi-Fi
|
|
8
|
+
* | Preset | Kbps | Typical connection |
|
|
9
|
+
* |-----------|------|--------------------------------|
|
|
10
|
+
* | EXTREME | 100 | 2G / Edge |
|
|
11
|
+
* | POOR | 300 | Slow 3G |
|
|
12
|
+
* | FAIR | 800 | Marginal 3G ← **recommended** |
|
|
13
|
+
* | GOOD | 1500 | Weak 4G / congested Wi-Fi |
|
|
14
14
|
*
|
|
15
15
|
* Pass any of these (or a custom number) as `audioBandwidthThreshold`.
|
|
16
|
-
* Set to `0` to disable
|
|
16
|
+
* Set to `0` to disable bandwidth-based switching entirely.
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* import { AUDIO_BANDWIDTH_THRESHOLDS } from "react-helios";
|
|
20
|
-
* <VideoPlayer
|
|
20
|
+
* <VideoPlayer options={{ audioBandwidthThreshold: AUDIO_BANDWIDTH_THRESHOLDS.FAIR }} />
|
|
21
21
|
*/
|
|
22
22
|
declare const AUDIO_BANDWIDTH_THRESHOLDS: {
|
|
23
23
|
/** < 100 Kbps — very poor, 2G / Edge */
|
|
24
24
|
readonly EXTREME: 100;
|
|
25
|
-
/** < 300 Kbps — poor, slow 3G
|
|
25
|
+
/** < 300 Kbps — poor, slow 3G */
|
|
26
26
|
readonly POOR: 300;
|
|
27
|
-
/** <
|
|
28
|
-
readonly FAIR:
|
|
29
|
-
/** < 1500 Kbps —
|
|
27
|
+
/** < 800 Kbps — marginal 3G ← **recommended default** */
|
|
28
|
+
readonly FAIR: 800;
|
|
29
|
+
/** < 1500 Kbps — weak 4G / congested Wi-Fi */
|
|
30
30
|
readonly GOOD: 1500;
|
|
31
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* Preset HLS quality level indices for automatic audio mode switching.
|
|
34
|
+
*
|
|
35
|
+
* When HLS.js drops to this level or below (due to poor bandwidth), the player
|
|
36
|
+
* automatically switches to audio mode. Level `0` is always the lowest quality
|
|
37
|
+
* available in the manifest.
|
|
38
|
+
*
|
|
39
|
+
* | Preset | Value | Meaning |
|
|
40
|
+
* |----------------|-------|-----------------------------------------------|
|
|
41
|
+
* | LOWEST | 0 | Switch when at the very lowest quality ← **recommended** |
|
|
42
|
+
* | SECOND_LOWEST | 1 | Switch one level above the lowest |
|
|
43
|
+
* | DISABLED | -1 | Disable level-based switching entirely |
|
|
44
|
+
*
|
|
45
|
+
* Works alongside `audioBandwidthThreshold` — whichever fires first wins.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* import { AUDIO_SWITCH_LEVELS } from "react-helios";
|
|
49
|
+
* <VideoPlayer options={{ audioModeSwitchLevel: AUDIO_SWITCH_LEVELS.LOWEST }} />
|
|
50
|
+
*/
|
|
51
|
+
declare const AUDIO_SWITCH_LEVELS: {
|
|
52
|
+
/** Switch when HLS.js is at the lowest available quality (recommended default). */
|
|
53
|
+
readonly LOWEST: 0;
|
|
54
|
+
/** Switch when HLS.js drops to the second-lowest quality. */
|
|
55
|
+
readonly SECOND_LOWEST: 1;
|
|
56
|
+
/** Disable level-based auto-switching. */
|
|
57
|
+
readonly DISABLED: -1;
|
|
58
|
+
};
|
|
32
59
|
interface BufferedRange {
|
|
33
60
|
start: number;
|
|
34
61
|
end: number;
|
|
@@ -130,7 +157,24 @@ interface VideoPlayerOptions {
|
|
|
130
157
|
/** Label shown next to the icon when in audio mode (click → switches to video). Default: "Video" */
|
|
131
158
|
videoModeLabel?: string;
|
|
132
159
|
defaultAudioMode?: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Kbps — switch to audio mode when rolling average bandwidth drops below this value.
|
|
162
|
+
* `0` disables bandwidth-based switching. Default: `300` (slow 3G).
|
|
163
|
+
* Works alongside `audioModeSwitchLevel` — whichever fires first wins.
|
|
164
|
+
*/
|
|
133
165
|
audioBandwidthThreshold?: number;
|
|
166
|
+
/**
|
|
167
|
+
* HLS quality level index — switch to audio mode when HLS.js drops to this level or below.
|
|
168
|
+
* `0` = lowest quality (recommended default). `-1` disables level-based switching.
|
|
169
|
+
* Works alongside `audioBandwidthThreshold` — whichever fires first wins.
|
|
170
|
+
*/
|
|
171
|
+
audioModeSwitchLevel?: number;
|
|
172
|
+
/**
|
|
173
|
+
* Milliseconds between automatic recovery probes while in auto-switched audio mode.
|
|
174
|
+
* The player briefly resumes video loading to sample bandwidth, then switches back
|
|
175
|
+
* to video if conditions have improved. Default: `30000` (30 seconds).
|
|
176
|
+
*/
|
|
177
|
+
audioModeRecoveryInterval?: number;
|
|
134
178
|
onPlay?: () => void;
|
|
135
179
|
onPause?: () => void;
|
|
136
180
|
onEnded?: () => void;
|
|
@@ -154,7 +198,7 @@ interface VideoPlayerProps {
|
|
|
154
198
|
declare const VideoPlayer: react__default.ForwardRefExoticComponent<VideoPlayerProps & react__default.RefAttributes<VideoPlayerRef>>;
|
|
155
199
|
|
|
156
200
|
interface ControlsProps {
|
|
157
|
-
videoRef: react__default.RefObject<
|
|
201
|
+
videoRef: react__default.RefObject<HTMLMediaElement | null>;
|
|
158
202
|
playerRef: VideoPlayerRef;
|
|
159
203
|
playerContainerRef: react__default.RefObject<HTMLElement | null>;
|
|
160
204
|
playbackRates: PlaybackRate[];
|
|
@@ -182,7 +226,7 @@ interface ControlsProps {
|
|
|
182
226
|
declare const Controls: react__default.NamedExoticComponent<ControlsProps>;
|
|
183
227
|
|
|
184
228
|
interface TimeDisplayProps {
|
|
185
|
-
videoRef: React.RefObject<
|
|
229
|
+
videoRef: React.RefObject<HTMLMediaElement | null>;
|
|
186
230
|
isLive?: boolean;
|
|
187
231
|
}
|
|
188
232
|
/**
|
|
@@ -203,7 +247,7 @@ interface SettingsMenuProps {
|
|
|
203
247
|
declare const SettingsMenu: react.NamedExoticComponent<SettingsMenuProps>;
|
|
204
248
|
|
|
205
249
|
interface ProgressBarProps {
|
|
206
|
-
videoRef: react__default.RefObject<
|
|
250
|
+
videoRef: react__default.RefObject<HTMLMediaElement | null>;
|
|
207
251
|
playerRef: VideoPlayerRef;
|
|
208
252
|
enablePreview?: boolean;
|
|
209
253
|
thumbnailVtt?: string;
|
|
@@ -321,4 +365,4 @@ declare function parseThumbnailVtt(text: string, baseUrl?: string): ThumbnailCue
|
|
|
321
365
|
*/
|
|
322
366
|
declare function findThumbnailCue(cues: ThumbnailCue[], time: number): ThumbnailCue | null;
|
|
323
367
|
|
|
324
|
-
export { AUDIO_BANDWIDTH_THRESHOLDS, type BufferedRange, type ContextMenuItem, type ControlBarItem, index as ControlElements, Controls, type HLSQualityLevel, type PlaybackRate, type PlayerState, type SubtitleTrack, type ThumbnailCue, type VideoError, type VideoErrorCode, VideoPlayer, type VideoPlayerOptions, type VideoPlayerProps, type VideoPlayerRef, findThumbnailCue, formatTime, getMimeType, isHLSUrl, parseThumbnailVtt };
|
|
368
|
+
export { AUDIO_BANDWIDTH_THRESHOLDS, AUDIO_SWITCH_LEVELS, type BufferedRange, type ContextMenuItem, type ControlBarItem, index as ControlElements, Controls, type HLSQualityLevel, type PlaybackRate, type PlayerState, type SubtitleTrack, type ThumbnailCue, type VideoError, type VideoErrorCode, VideoPlayer, type VideoPlayerOptions, type VideoPlayerProps, type VideoPlayerRef, findThumbnailCue, formatTime, getMimeType, isHLSUrl, parseThumbnailVtt };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,30 +5,57 @@ import { HlsConfig } from 'hls.js';
|
|
|
5
5
|
/**
|
|
6
6
|
* Preset bandwidth thresholds (Kbps) for automatic audio mode switching.
|
|
7
7
|
*
|
|
8
|
-
* | Preset | Kbps | Typical connection
|
|
9
|
-
*
|
|
10
|
-
* | EXTREME | 100 | 2G / Edge
|
|
11
|
-
* | POOR | 300 | Slow 3G
|
|
12
|
-
* | FAIR |
|
|
13
|
-
* | GOOD | 1500 | 4G / Wi-Fi
|
|
8
|
+
* | Preset | Kbps | Typical connection |
|
|
9
|
+
* |-----------|------|--------------------------------|
|
|
10
|
+
* | EXTREME | 100 | 2G / Edge |
|
|
11
|
+
* | POOR | 300 | Slow 3G |
|
|
12
|
+
* | FAIR | 800 | Marginal 3G ← **recommended** |
|
|
13
|
+
* | GOOD | 1500 | Weak 4G / congested Wi-Fi |
|
|
14
14
|
*
|
|
15
15
|
* Pass any of these (or a custom number) as `audioBandwidthThreshold`.
|
|
16
|
-
* Set to `0` to disable
|
|
16
|
+
* Set to `0` to disable bandwidth-based switching entirely.
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* import { AUDIO_BANDWIDTH_THRESHOLDS } from "react-helios";
|
|
20
|
-
* <VideoPlayer
|
|
20
|
+
* <VideoPlayer options={{ audioBandwidthThreshold: AUDIO_BANDWIDTH_THRESHOLDS.FAIR }} />
|
|
21
21
|
*/
|
|
22
22
|
declare const AUDIO_BANDWIDTH_THRESHOLDS: {
|
|
23
23
|
/** < 100 Kbps — very poor, 2G / Edge */
|
|
24
24
|
readonly EXTREME: 100;
|
|
25
|
-
/** < 300 Kbps — poor, slow 3G
|
|
25
|
+
/** < 300 Kbps — poor, slow 3G */
|
|
26
26
|
readonly POOR: 300;
|
|
27
|
-
/** <
|
|
28
|
-
readonly FAIR:
|
|
29
|
-
/** < 1500 Kbps —
|
|
27
|
+
/** < 800 Kbps — marginal 3G ← **recommended default** */
|
|
28
|
+
readonly FAIR: 800;
|
|
29
|
+
/** < 1500 Kbps — weak 4G / congested Wi-Fi */
|
|
30
30
|
readonly GOOD: 1500;
|
|
31
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* Preset HLS quality level indices for automatic audio mode switching.
|
|
34
|
+
*
|
|
35
|
+
* When HLS.js drops to this level or below (due to poor bandwidth), the player
|
|
36
|
+
* automatically switches to audio mode. Level `0` is always the lowest quality
|
|
37
|
+
* available in the manifest.
|
|
38
|
+
*
|
|
39
|
+
* | Preset | Value | Meaning |
|
|
40
|
+
* |----------------|-------|-----------------------------------------------|
|
|
41
|
+
* | LOWEST | 0 | Switch when at the very lowest quality ← **recommended** |
|
|
42
|
+
* | SECOND_LOWEST | 1 | Switch one level above the lowest |
|
|
43
|
+
* | DISABLED | -1 | Disable level-based switching entirely |
|
|
44
|
+
*
|
|
45
|
+
* Works alongside `audioBandwidthThreshold` — whichever fires first wins.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* import { AUDIO_SWITCH_LEVELS } from "react-helios";
|
|
49
|
+
* <VideoPlayer options={{ audioModeSwitchLevel: AUDIO_SWITCH_LEVELS.LOWEST }} />
|
|
50
|
+
*/
|
|
51
|
+
declare const AUDIO_SWITCH_LEVELS: {
|
|
52
|
+
/** Switch when HLS.js is at the lowest available quality (recommended default). */
|
|
53
|
+
readonly LOWEST: 0;
|
|
54
|
+
/** Switch when HLS.js drops to the second-lowest quality. */
|
|
55
|
+
readonly SECOND_LOWEST: 1;
|
|
56
|
+
/** Disable level-based auto-switching. */
|
|
57
|
+
readonly DISABLED: -1;
|
|
58
|
+
};
|
|
32
59
|
interface BufferedRange {
|
|
33
60
|
start: number;
|
|
34
61
|
end: number;
|
|
@@ -130,7 +157,24 @@ interface VideoPlayerOptions {
|
|
|
130
157
|
/** Label shown next to the icon when in audio mode (click → switches to video). Default: "Video" */
|
|
131
158
|
videoModeLabel?: string;
|
|
132
159
|
defaultAudioMode?: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Kbps — switch to audio mode when rolling average bandwidth drops below this value.
|
|
162
|
+
* `0` disables bandwidth-based switching. Default: `300` (slow 3G).
|
|
163
|
+
* Works alongside `audioModeSwitchLevel` — whichever fires first wins.
|
|
164
|
+
*/
|
|
133
165
|
audioBandwidthThreshold?: number;
|
|
166
|
+
/**
|
|
167
|
+
* HLS quality level index — switch to audio mode when HLS.js drops to this level or below.
|
|
168
|
+
* `0` = lowest quality (recommended default). `-1` disables level-based switching.
|
|
169
|
+
* Works alongside `audioBandwidthThreshold` — whichever fires first wins.
|
|
170
|
+
*/
|
|
171
|
+
audioModeSwitchLevel?: number;
|
|
172
|
+
/**
|
|
173
|
+
* Milliseconds between automatic recovery probes while in auto-switched audio mode.
|
|
174
|
+
* The player briefly resumes video loading to sample bandwidth, then switches back
|
|
175
|
+
* to video if conditions have improved. Default: `30000` (30 seconds).
|
|
176
|
+
*/
|
|
177
|
+
audioModeRecoveryInterval?: number;
|
|
134
178
|
onPlay?: () => void;
|
|
135
179
|
onPause?: () => void;
|
|
136
180
|
onEnded?: () => void;
|
|
@@ -154,7 +198,7 @@ interface VideoPlayerProps {
|
|
|
154
198
|
declare const VideoPlayer: react__default.ForwardRefExoticComponent<VideoPlayerProps & react__default.RefAttributes<VideoPlayerRef>>;
|
|
155
199
|
|
|
156
200
|
interface ControlsProps {
|
|
157
|
-
videoRef: react__default.RefObject<
|
|
201
|
+
videoRef: react__default.RefObject<HTMLMediaElement | null>;
|
|
158
202
|
playerRef: VideoPlayerRef;
|
|
159
203
|
playerContainerRef: react__default.RefObject<HTMLElement | null>;
|
|
160
204
|
playbackRates: PlaybackRate[];
|
|
@@ -182,7 +226,7 @@ interface ControlsProps {
|
|
|
182
226
|
declare const Controls: react__default.NamedExoticComponent<ControlsProps>;
|
|
183
227
|
|
|
184
228
|
interface TimeDisplayProps {
|
|
185
|
-
videoRef: React.RefObject<
|
|
229
|
+
videoRef: React.RefObject<HTMLMediaElement | null>;
|
|
186
230
|
isLive?: boolean;
|
|
187
231
|
}
|
|
188
232
|
/**
|
|
@@ -203,7 +247,7 @@ interface SettingsMenuProps {
|
|
|
203
247
|
declare const SettingsMenu: react.NamedExoticComponent<SettingsMenuProps>;
|
|
204
248
|
|
|
205
249
|
interface ProgressBarProps {
|
|
206
|
-
videoRef: react__default.RefObject<
|
|
250
|
+
videoRef: react__default.RefObject<HTMLMediaElement | null>;
|
|
207
251
|
playerRef: VideoPlayerRef;
|
|
208
252
|
enablePreview?: boolean;
|
|
209
253
|
thumbnailVtt?: string;
|
|
@@ -321,4 +365,4 @@ declare function parseThumbnailVtt(text: string, baseUrl?: string): ThumbnailCue
|
|
|
321
365
|
*/
|
|
322
366
|
declare function findThumbnailCue(cues: ThumbnailCue[], time: number): ThumbnailCue | null;
|
|
323
367
|
|
|
324
|
-
export { AUDIO_BANDWIDTH_THRESHOLDS, type BufferedRange, type ContextMenuItem, type ControlBarItem, index as ControlElements, Controls, type HLSQualityLevel, type PlaybackRate, type PlayerState, type SubtitleTrack, type ThumbnailCue, type VideoError, type VideoErrorCode, VideoPlayer, type VideoPlayerOptions, type VideoPlayerProps, type VideoPlayerRef, findThumbnailCue, formatTime, getMimeType, isHLSUrl, parseThumbnailVtt };
|
|
368
|
+
export { AUDIO_BANDWIDTH_THRESHOLDS, AUDIO_SWITCH_LEVELS, type BufferedRange, type ContextMenuItem, type ControlBarItem, index as ControlElements, Controls, type HLSQualityLevel, type PlaybackRate, type PlayerState, type SubtitleTrack, type ThumbnailCue, type VideoError, type VideoErrorCode, VideoPlayer, type VideoPlayerOptions, type VideoPlayerProps, type VideoPlayerRef, findThumbnailCue, formatTime, getMimeType, isHLSUrl, parseThumbnailVtt };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';var Dt=require('react'),Ee=require('hls.js'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Dt__default=/*#__PURE__*/_interopDefault(Dt);var Ee__default=/*#__PURE__*/_interopDefault(Ee);var ot=Object.defineProperty;var it=(n,t)=>{for(var r in t)ot(n,r,{get:t[r],enumerable:true});};function se(n){if(!Number.isFinite(n)||n<0)return "0:00";let t=Math.floor(n),r=Math.floor(t/3600),s=Math.floor(t%3600/60),a=t%60;return r>0?`${r}:${String(s).padStart(2,"0")}:${String(a).padStart(2,"0")}`:`${s}:${String(a).padStart(2,"0")}`}function ye(n){try{return new URL(n,"https://x").pathname.toLowerCase().endsWith(".m3u8")||/\/hls\//i.test(n)||/\/stream\.m3u8/i.test(n)}catch{return n.toLowerCase().includes(".m3u8")}}function at(n){if(ye(n))return "application/x-mpegURL";let t=n.toLowerCase().split("?")[0];return t.endsWith(".mp4")?"video/mp4":t.endsWith(".webm")?"video/webm":t.endsWith(".ogv")||t.endsWith(".ogg")?"video/ogg":t.endsWith(".mov")?"video/quicktime":"video/mp4"}function Oe(n){return n.map((t,r)=>({id:r,height:t.height??0,width:t.width??0,bitrate:t.bitrate??0,name:t.height?`${t.height}p`:`Level ${r+1}`}))}var ut={isPlaying:false,currentTime:0,duration:0,volume:1,isMuted:false,playbackRate:1,isFullscreen:false,isPictureInPicture:false,isTheaterMode:false,isAudioMode:false,isBuffering:false,bufferedRanges:[],error:null,isLive:false,qualityLevels:[],currentQualityLevel:-1};function _e(n,t,r={}){let s=Dt.useRef(null),a=Dt.useRef(null),p=Dt.useRef(1),u=Dt.useRef(0),l=Dt.useRef(r);l.current=r;let[L,c]=Dt.useState({...ut,isMuted:r.muted??false,volume:r.muted?0:1,isAudioMode:r.defaultAudioMode??false}),C=Dt.useRef(L);C.current=L;let k=Dt.useRef([]),R=Dt.useRef(false),T=Dt.useRef(false),m=Dt.useRef(null);Dt.useEffect(()=>{let e=n.current;if(!e||(s.current&&(s.current.destroy(),s.current=null),u.current=0,k.current=[],R.current=false,T.current=false,m.current&&(clearTimeout(m.current),m.current=null),c(v=>({...v,currentTime:0,duration:0,error:null,isBuffering:false,isLive:false,qualityLevels:[],currentQualityLevel:-1,isAudioMode:l.current.defaultAudioMode??false})),!t))return;let d=l.current;if(d.enableHLS!==false&&ye(t)){if(e.canPlayType("application/vnd.apple.mpegurl"))e.src=t,e.load(),d.autoplay&&e.play().catch(()=>{});else if(Ee__default.default.isSupported()){let v=new Ee__default.default({autoStartLoad:true,startLevel:-1,capLevelToPlayerSize:true,capLevelOnFPSDrop:true,enableWorker:true,maxBufferLength:30,maxMaxBufferLength:600,maxBufferSize:6e7,liveBackBufferLength:30,liveSyncDurationCount:3,...d.hlsConfig});v.attachMedia(e),v.loadSource(t),v.on(Ee.Events.MANIFEST_PARSED,(O,o)=>{let i=Oe(o.levels);c(f=>({...f,qualityLevels:i,currentQualityLevel:-1})),l.current.autoplay&&e.play().catch(()=>{});}),v.on(Ee.Events.LEVEL_SWITCHED,(O,o)=>{c(i=>({...i,currentQualityLevel:o.level}));}),v.on(Ee.Events.FRAG_LOADED,()=>{let O=l.current.audioBandwidthThreshold??300;if(!O||T.current)return;let o=v.bandwidthEstimate/1e3;if(o<=0)return;let i=k.current;if(i.push(o),i.length>5&&i.shift(),i.length<3)return;let f=i.reduce((y,S)=>y+S,0)/i.length;c(y=>!y.isAudioMode&&f<O?(R.current=true,l.current.onAudioModeChange?.(true),{...y,isAudioMode:true}):y.isAudioMode&&R.current&&f>O*1.5?(R.current=false,l.current.onAudioModeChange?.(false),{...y,isAudioMode:false}):y);});let V=3;v.on(Ee.Events.ERROR,(O,o)=>{if(!o.fatal){console.warn("[hls] non-fatal:",o.details);return}switch(o.type){case Ee__default.default.ErrorTypes.NETWORK_ERROR:if(u.current<V){u.current+=1;let i=1e3*u.current;console.warn(`[hls] network error \u2013 retry ${u.current}/${V} in ${i}ms`),setTimeout(()=>{s.current===v&&v.startLoad();},i);}else {let i={code:"HLS_NETWORK_ERROR",message:"Failed to load stream after multiple retries."};c(f=>({...f,error:i})),l.current.onError?.(i);}break;case Ee__default.default.ErrorTypes.MEDIA_ERROR:console.warn("[hls] media error \u2013 recovering"),v.recoverMediaError();break;default:{v.destroy(),s.current=null;let i={code:"HLS_FATAL_ERROR",message:"An unrecoverable HLS error occurred."};c(f=>({...f,error:i})),l.current.onError?.(i);break}}}),s.current=v;}}else e.src=t,e.load(),d.autoplay&&e.play().catch(()=>{});return ()=>{s.current&&(s.current.destroy(),s.current=null),m.current&&(clearTimeout(m.current),m.current=null);}},[t,n]),Dt.useEffect(()=>{let e=n.current;if(!e)return;l.current.muted&&(e.muted=true),l.current.loop&&(e.loop=true);let d=()=>{c(b=>({...b,isPlaying:true})),l.current.onPlay?.();},v=()=>{c(b=>({...b,isPlaying:false})),l.current.onPause?.();},V=()=>{c(b=>({...b,isPlaying:false})),l.current.onEnded?.();},O=()=>{l.current.onTimeUpdate?.(e.currentTime);},o=()=>{let b=e.duration,z=!Number.isFinite(b);c(j=>({...j,duration:z?0:b,isLive:z})),z||l.current.onDurationChange?.(b);},i=()=>{let b=e.volume;b>0&&!e.muted&&(p.current=b),c(z=>({...z,volume:b,isMuted:e.muted||b===0}));},f=()=>{c(b=>({...b,playbackRate:e.playbackRate}));},y=()=>{let b=e.error;if(!b)return;let j={code:{1:"MEDIA_ERR_ABORTED",2:"MEDIA_ERR_NETWORK",3:"MEDIA_ERR_DECODE",4:"MEDIA_ERR_SRC_NOT_SUPPORTED"}[b.code]??"UNKNOWN",message:b.message||"Unknown media error"};c(ae=>({...ae,error:j})),l.current.onError?.(j);},S=()=>{c(b=>({...b,isBuffering:true})),l.current.onBuffering?.(true);},h=()=>{c(b=>({...b,isBuffering:false})),l.current.onBuffering?.(false);},E=()=>c(b=>({...b,isBuffering:false})),g=()=>{let b=!!(document.fullscreenElement||document.webkitFullscreenElement);c(z=>({...z,isFullscreen:b}));},A=()=>{c(b=>({...b,isPictureInPicture:document.pictureInPictureElement===e}));};return e.addEventListener("play",d),e.addEventListener("pause",v),e.addEventListener("ended",V),e.addEventListener("timeupdate",O),e.addEventListener("durationchange",o),e.addEventListener("volumechange",i),e.addEventListener("ratechange",f),e.addEventListener("error",y),e.addEventListener("waiting",S),e.addEventListener("canplay",h),e.addEventListener("playing",E),document.addEventListener("fullscreenchange",g),document.addEventListener("webkitfullscreenchange",g),e.addEventListener("enterpictureinpicture",A),e.addEventListener("leavepictureinpicture",A),()=>{e.removeEventListener("play",d),e.removeEventListener("pause",v),e.removeEventListener("ended",V),e.removeEventListener("timeupdate",O),e.removeEventListener("durationchange",o),e.removeEventListener("volumechange",i),e.removeEventListener("ratechange",f),e.removeEventListener("error",y),e.removeEventListener("waiting",S),e.removeEventListener("canplay",h),e.removeEventListener("playing",E),document.removeEventListener("fullscreenchange",g),document.removeEventListener("webkitfullscreenchange",g),e.removeEventListener("enterpictureinpicture",A),e.removeEventListener("leavepictureinpicture",A);}},[n]);let B=Dt.useCallback(async()=>{let e=n.current;if(e)try{await e.play();}catch(d){d instanceof Error&&d.name!=="AbortError"&&console.error("[player] play() failed:",d);}},[n]),I=Dt.useCallback(()=>{n.current?.pause();},[n]),_=Dt.useCallback(e=>{let d=n.current;d&&(d.currentTime=Math.max(0,Math.min(e,d.duration||e)));},[n]),P=Dt.useCallback(e=>{let d=n.current;if(!d)return;let v=Math.max(0,Math.min(e,1));v>0&&(p.current=v),d.volume=v,d.muted=v===0;},[n]),x=Dt.useCallback(()=>{let e=n.current;if(e)if(e.muted||e.volume===0){let d=p.current>0?p.current:1;e.volume=d,e.muted=false;}else p.current=e.volume,e.muted=true;},[n]),D=Dt.useCallback(e=>{let d=n.current;d&&(d.playbackRate=e);},[n]),N=Dt.useCallback(e=>{let d=s.current;d&&(d.currentLevel=e,c(v=>({...v,currentQualityLevel:e})));},[]),ne=Dt.useCallback(()=>{let e=s.current,d=n.current;if(!e||!d)return;let v=e.liveSyncPosition;v!=null&&Number.isFinite(v)&&(d.currentTime=v);},[n]),Z=Dt.useCallback(async()=>{let e=n.current;if(!e)return;let d=a.current??e.parentElement;if(d)try{!document.fullscreenElement&&!document.webkitFullscreenElement?d.requestFullscreen?await d.requestFullscreen():d.webkitRequestFullscreen?.():document.exitFullscreen?await document.exitFullscreen():document.webkitExitFullscreen?.();}catch(v){console.error("[player] fullscreen toggle failed:",v);}},[n]),X=Dt.useCallback(async()=>{let e=n.current;if(e)try{document.pictureInPictureElement?await document.exitPictureInPicture():await e.requestPictureInPicture();}catch(d){console.error("[player] PiP toggle failed:",d);}},[n]),M=Dt.useCallback(()=>{let e=!C.current.isTheaterMode;c(d=>({...d,isTheaterMode:e})),l.current.onTheaterModeChange?.(e);},[]),G=Dt.useCallback(()=>{m.current&&clearTimeout(m.current),R.current=false,T.current=true,m.current=setTimeout(()=>{T.current=false,k.current=[];},6e4);let e=!C.current.isAudioMode;c(d=>({...d,isAudioMode:e})),l.current.onAudioModeChange?.(e);},[]),U=Dt.useCallback(()=>{let e=n.current,d=e?.currentTime??0,v=[];if(e)for(let V=0;V<e.buffered.length;V++)v.push({start:e.buffered.start(V),end:e.buffered.end(V)});return {...C.current,currentTime:d,bufferedRanges:v}},[n]),ee=Dt.useCallback(()=>n.current??null,[n]),ie=Dt.useMemo(()=>({play:B,pause:I,seek:_,setVolume:P,toggleMute:x,setPlaybackRate:D,setQualityLevel:N,seekToLive:ne,toggleFullscreen:Z,togglePictureInPicture:X,toggleTheaterMode:M,toggleAudioMode:G,getState:U,getVideoElement:ee}),[B,I,_,P,x,D,N,ne,Z,X,M,G,U,ee]);return {state:L,ref:ie,hlsRef:s,fullscreenContainerRef:a}}var Ge={};it(Ge,{ControlElements:()=>Q,FullscreenButton:()=>ve,PauseButton:()=>pe,PiPButton:()=>he,PlayButton:()=>fe,ProgressBar:()=>Pe,SettingsMenu:()=>Te,TheaterButton:()=>ge,TimeDisplay:()=>ke,VolumeControl:()=>Le});var fe=Dt.memo(({onClick:n})=>jsxRuntime.jsx("button",{onClick:n,className:"controlButton","aria-label":"Play",title:"Play (Space)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M8 5v14l11-7z"})})}));fe.displayName="PlayButton";var pe=Dt.memo(({onClick:n})=>jsxRuntime.jsx("button",{onClick:n,className:"controlButton","aria-label":"Pause",title:"Pause (Space)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M6 4h4v16H6V4zm8 0h4v16h-4V4z"})})}));pe.displayName="PauseButton";var ve=Dt.memo(({onClick:n,isFullscreen:t=false})=>jsxRuntime.jsx("button",{onClick:n,className:"controlButton","aria-label":t?"Exit Fullscreen":"Fullscreen",title:t?"Exit Fullscreen (F)":"Fullscreen (F)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:t?jsxRuntime.jsx("path",{d:"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"}):jsxRuntime.jsx("path",{d:"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"})})}));ve.displayName="FullscreenButton";var he=Dt.memo(({onClick:n,isPiP:t=false})=>jsxRuntime.jsx("button",{onClick:n,className:"controlButton","aria-label":t?"Exit Picture-in-Picture":"Picture-in-Picture",title:t?"Exit Picture-in-Picture (P)":"Picture-in-Picture (P)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M19 11h-8v6h8v-6zm4 8V4.98C23 3.88 22.1 3 21 3H3c-1.1 0-2 .88-2 1.98V19c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zm-2 .02H3V5h18v14.02z"})})}));he.displayName="PiPButton";var ge=Dt.memo(({onClick:n,isTheater:t=false})=>jsxRuntime.jsx("button",{onClick:n,className:"controlButton","aria-label":t?"Exit Theater Mode":"Theater Mode",title:t?"Exit Theater Mode (T)":"Theater Mode (T)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:t?jsxRuntime.jsx("path",{d:"M19 7H5c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 8H5V9h14v6z"}):jsxRuntime.jsx("path",{d:"M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h18v14z"})})}));ge.displayName="TheaterButton";var ze=Dt.memo(({volume:n,isMuted:t,onVolumeChange:r,onToggleMute:s})=>{let[a,p]=Dt.useState(false),u=t?0:n,l=u*100,L=Dt.useMemo(()=>`linear-gradient(to right, #60a5fa 0%, #60a5fa ${l}%, rgba(255,255,255,0.3) ${l}%, rgba(255,255,255,0.3) 100%)`,[l]);return jsxRuntime.jsxs("div",{className:"volumeContainer",onMouseEnter:()=>p(true),onMouseLeave:()=>p(false),children:[jsxRuntime.jsx("button",{onClick:s,className:"controlButton","aria-label":t?"Unmute":"Mute",title:t?"Unmute (M)":"Mute (M)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:u===0?jsxRuntime.jsx("path",{d:"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C23.16 14.42 24 13.3 24 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"}):u<.5?jsxRuntime.jsx("path",{d:"M7 9v6h4l5 5V4l-5 5H7z"}):jsxRuntime.jsx("path",{d:"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"})})}),a&&jsxRuntime.jsx("input",{type:"range",min:"0",max:"100",value:l,onChange:c=>r(Number(c.target.value)/100),className:"volumeSlider",style:{background:L},"aria-label":"Volume","aria-valuenow":Math.round(l)})]})});ze.displayName="VolumeControl";var Le=ze;function $e(n){let t=n.trim().split(":");return t.length===3?+t[0]*3600+ +t[1]*60+parseFloat(t[2]):+t[0]*60+parseFloat(t[1])}function pt(n,t){if(/^https?:\/\//i.test(t))return t;try{return new URL(t,n).href}catch{return t}}function Re(n,t=""){let r=[],s=n.replace(/\r\n/g,`
|
|
1
|
+
'use strict';var ot=require('react'),Ce=require('hls.js'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var ot__default=/*#__PURE__*/_interopDefault(ot);var Ce__default=/*#__PURE__*/_interopDefault(Ce);var lt=Object.defineProperty;var ct=(i,r)=>{for(var o in r)lt(i,o,{get:r[o],enumerable:true});};function ce(i){if(!Number.isFinite(i)||i<0)return "0:00";let r=Math.floor(i),o=Math.floor(r/3600),u=Math.floor(r%3600/60),s=r%60;return o>0?`${o}:${String(u).padStart(2,"0")}:${String(s).padStart(2,"0")}`:`${u}:${String(s).padStart(2,"0")}`}function Pe(i){try{return new URL(i,"https://x").pathname.toLowerCase().endsWith(".m3u8")||/\/hls\//i.test(i)||/\/stream\.m3u8/i.test(i)}catch{return i.toLowerCase().includes(".m3u8")}}function dt(i){if(Pe(i))return "application/x-mpegURL";let r=i.toLowerCase().split("?")[0];return r.endsWith(".mp4")?"video/mp4":r.endsWith(".webm")?"video/webm":r.endsWith(".ogv")||r.endsWith(".ogg")?"video/ogg":r.endsWith(".mov")?"video/quicktime":"video/mp4"}function Ue(i){return i.map((r,o)=>({id:o,height:r.height??0,width:r.width??0,bitrate:r.bitrate??0,name:r.height?`${r.height}p`:`Level ${o+1}`}))}var vt={isPlaying:false,currentTime:0,duration:0,volume:1,isMuted:false,playbackRate:1,isFullscreen:false,isPictureInPicture:false,isTheaterMode:false,isAudioMode:false,isBuffering:false,bufferedRanges:[],error:null,isLive:false,qualityLevels:[],currentQualityLevel:-1};function $e(i,r,o={}){let u=ot.useRef(null),s=ot.useRef(null),h=ot.useRef(1),d=ot.useRef(0),a=ot.useRef(o);a.current=o;let[L,l]=ot.useState({...vt,isMuted:o.muted??false,volume:o.muted?0:1,isAudioMode:o.defaultAudioMode??false}),T=ot.useRef(L);T.current=L;let S=ot.useRef([]),F=ot.useRef(0),C=ot.useRef(false),p=ot.useRef(false),x=ot.useRef(null),P=ot.useRef(null),A=ot.useRef(false),b=ot.useCallback(()=>{let e=a.current;return T.current.isAudioMode&&e.audioSrc&&e.audioRef?.current?e.audioRef.current:i.current},[i]);ot.useEffect(()=>{let e=i.current;if(!e||(u.current&&(u.current.destroy(),u.current=null),d.current=0,S.current=[],F.current=0,C.current=false,p.current=false,x.current&&(clearTimeout(x.current),x.current=null),P.current&&(clearTimeout(P.current),P.current=null),A.current=false,l(n=>({...n,currentTime:0,duration:0,error:null,isBuffering:false,isLive:false,qualityLevels:[],currentQualityLevel:-1,isAudioMode:a.current.defaultAudioMode??false})),!r))return;let t=a.current;if(t.enableHLS!==false&&Pe(r)){if(e.canPlayType("application/vnd.apple.mpegurl"))e.src=r,e.load(),t.autoplay&&e.play().catch(()=>{});else if(Ce__default.default.isSupported()){let n=new Ce__default.default({autoStartLoad:true,startLevel:-1,capLevelToPlayerSize:true,capLevelOnFPSDrop:true,enableWorker:true,maxBufferLength:30,maxMaxBufferLength:600,maxBufferSize:6e7,liveBackBufferLength:30,liveSyncDurationCount:3,...t.hlsConfig});n.attachMedia(e),n.loadSource(r),n.on(Ce.Events.MANIFEST_PARSED,(k,c)=>{let f=Ue(c.levels);l(M=>({...M,qualityLevels:f,currentQualityLevel:-1})),a.current.autoplay&&e.play().catch(()=>{});}),n.on(Ce.Events.LEVEL_SWITCHED,(k,c)=>{l(w=>({...w,currentQualityLevel:c.level}));let f=a.current,M=f.audioModeSwitchLevel;M===void 0||M<0||!f.audioSrc||p.current||F.current<3||l(w=>!w.isAudioMode&&c.level<=M?(C.current=true,a.current.onAudioModeChange?.(true),{...w,isAudioMode:true}):w);}),n.on(Ce.Events.FRAG_LOADED,(k,c)=>{let f=a.current;if(!f.audioSrc)return;F.current+=1;let M=c.stats.loading.end-c.stats.loading.start,w=M>0&&c.stats.total>0?c.stats.total*8/M:0,E=f.audioBandwidthThreshold??300;if(A.current){A.current=false,w>0&&E&&w>E*1.5?(C.current=false,n.startLoad(),a.current.onAudioModeChange?.(false),l(V=>({...V,isAudioMode:false}))):(n.stopLoad(),m());return}if(!E||p.current||w<=0)return;let v=S.current;if(v.push(w),v.length>5&&v.shift(),v.length<2)return;let N=v.reduce((V,g)=>V+g,0)/v.length;l(V=>!V.isAudioMode&&N<E?(C.current=true,a.current.onAudioModeChange?.(true),{...V,isAudioMode:true}):V);});let m=()=>{P.current&&clearTimeout(P.current);let k=a.current.audioModeRecoveryInterval??3e4;P.current=setTimeout(()=>{!C.current||!T.current.isAudioMode||(A.current=true,n.startLoad());},k);},y=3;n.on(Ce.Events.ERROR,(k,c)=>{if(!c.fatal){console.warn("[hls] non-fatal:",c.details);return}switch(c.type){case Ce__default.default.ErrorTypes.NETWORK_ERROR:if(d.current<y){d.current+=1;let f=1e3*d.current;console.warn(`[hls] network error \u2013 retry ${d.current}/${y} in ${f}ms`),setTimeout(()=>{u.current===n&&n.startLoad();},f);}else {let f={code:"HLS_NETWORK_ERROR",message:"Failed to load stream after multiple retries."};l(M=>({...M,error:f})),a.current.onError?.(f);}break;case Ce__default.default.ErrorTypes.MEDIA_ERROR:console.warn("[hls] media error \u2013 recovering"),n.recoverMediaError();break;default:{n.destroy(),u.current=null;let f={code:"HLS_FATAL_ERROR",message:"An unrecoverable HLS error occurred."};l(M=>({...M,error:f})),a.current.onError?.(f);break}}}),u.current=n;}}else e.src=r,e.load(),t.autoplay&&e.play().catch(()=>{});return ()=>{u.current&&(u.current.destroy(),u.current=null),x.current&&(clearTimeout(x.current),x.current=null),P.current&&(clearTimeout(P.current),P.current=null),A.current=false;let n=a.current.audioRef?.current;n&&(n.pause(),n.removeAttribute("src"),n.load());}},[r,i]),ot.useEffect(()=>{let e=i.current;if(!e)return;a.current.muted&&(e.muted=true),a.current.loop&&(e.loop=true);let t=()=>{l(g=>({...g,isPlaying:true})),a.current.onPlay?.();},n=()=>{l(g=>({...g,isPlaying:false})),a.current.onPause?.();},m=()=>{l(g=>({...g,isPlaying:false})),a.current.onEnded?.();},y=()=>{T.current.isAudioMode&&a.current.audioSrc||a.current.onTimeUpdate?.(e.currentTime);},k=()=>{let g=e.duration,Q=!Number.isFinite(g);l(le=>({...le,duration:Q?0:g,isLive:Q})),Q||a.current.onDurationChange?.(g);},c=()=>{let g=e.volume;g>0&&!e.muted&&(h.current=g),l(Q=>({...Q,volume:g,isMuted:e.muted||g===0}));},f=()=>{l(g=>({...g,playbackRate:e.playbackRate}));},M=()=>{let g=e.error;if(!g)return;let le={code:{1:"MEDIA_ERR_ABORTED",2:"MEDIA_ERR_NETWORK",3:"MEDIA_ERR_DECODE",4:"MEDIA_ERR_SRC_NOT_SUPPORTED"}[g.code]??"UNKNOWN",message:g.message||"Unknown media error"};l(Le=>({...Le,error:le})),a.current.onError?.(le);},w=()=>{l(g=>({...g,isBuffering:true})),a.current.onBuffering?.(true);},E=()=>{l(g=>({...g,isBuffering:false})),a.current.onBuffering?.(false);},v=()=>l(g=>({...g,isBuffering:false})),N=()=>{let g=!!(document.fullscreenElement||document.webkitFullscreenElement);l(Q=>({...Q,isFullscreen:g}));},V=()=>{l(g=>({...g,isPictureInPicture:document.pictureInPictureElement===e}));};return e.addEventListener("play",t),e.addEventListener("pause",n),e.addEventListener("ended",m),e.addEventListener("timeupdate",y),e.addEventListener("durationchange",k),e.addEventListener("volumechange",c),e.addEventListener("ratechange",f),e.addEventListener("error",M),e.addEventListener("waiting",w),e.addEventListener("canplay",E),e.addEventListener("playing",v),document.addEventListener("fullscreenchange",N),document.addEventListener("webkitfullscreenchange",N),e.addEventListener("enterpictureinpicture",V),e.addEventListener("leavepictureinpicture",V),()=>{e.removeEventListener("play",t),e.removeEventListener("pause",n),e.removeEventListener("ended",m),e.removeEventListener("timeupdate",y),e.removeEventListener("durationchange",k),e.removeEventListener("volumechange",c),e.removeEventListener("ratechange",f),e.removeEventListener("error",M),e.removeEventListener("waiting",w),e.removeEventListener("canplay",E),e.removeEventListener("playing",v),document.removeEventListener("fullscreenchange",N),document.removeEventListener("webkitfullscreenchange",N),e.removeEventListener("enterpictureinpicture",V),e.removeEventListener("leavepictureinpicture",V);}},[i]),ot.useEffect(()=>{let e=a.current.audioRef?.current;if(!e||!a.current.audioSrc)return;let t=()=>{l(E=>({...E,isPlaying:true})),a.current.onPlay?.();},n=()=>{l(E=>({...E,isPlaying:false})),a.current.onPause?.();},m=()=>{l(E=>({...E,isPlaying:false})),a.current.onEnded?.();},y=()=>{l(E=>({...E,isBuffering:true})),a.current.onBuffering?.(true);},k=()=>{l(E=>({...E,isBuffering:false})),a.current.onBuffering?.(false);},c=()=>l(E=>({...E,isBuffering:false})),f=()=>{T.current.isAudioMode&&a.current.onTimeUpdate?.(e.currentTime);},M=()=>{let E=e.duration;isFinite(E)&&(l(v=>({...v,duration:E})),a.current.onDurationChange?.(E));},w=()=>{let E={code:"MEDIA_ERR_NETWORK",message:"Audio source failed to load."};l(v=>({...v,error:E})),a.current.onError?.(E);};return e.addEventListener("play",t),e.addEventListener("pause",n),e.addEventListener("ended",m),e.addEventListener("waiting",y),e.addEventListener("canplay",k),e.addEventListener("playing",c),e.addEventListener("timeupdate",f),e.addEventListener("durationchange",M),e.addEventListener("error",w),()=>{e.removeEventListener("play",t),e.removeEventListener("pause",n),e.removeEventListener("ended",m),e.removeEventListener("waiting",y),e.removeEventListener("canplay",k),e.removeEventListener("playing",c),e.removeEventListener("timeupdate",f),e.removeEventListener("durationchange",M),e.removeEventListener("error",w);}},[r]),ot.useEffect(()=>{let e=a.current,t=i.current,n=e.audioRef?.current;if(!(!t||!n||!e.audioSrc))if(L.isAudioMode){let m=t.currentTime,y=!t.paused;if(t.pause(),u.current?.stopLoad(),n.getAttribute("src")||(n.src=e.audioSrc),n.currentTime=m,n.volume=t.volume,n.muted=t.muted,n.playbackRate=t.playbackRate,y&&n.play().catch(()=>{}),C.current){P.current&&clearTimeout(P.current);let k=e.audioModeRecoveryInterval??3e4;P.current=setTimeout(()=>{!C.current||!T.current.isAudioMode||(A.current=true,u.current?.startLoad());},k);}}else {let m=n.currentTime,y=!n.paused;n.pause(),P.current&&(clearTimeout(P.current),P.current=null),A.current=false,u.current?.startLoad(),t.currentTime=m,t.volume=n.volume,y&&t.play().catch(()=>{});}},[L.isAudioMode,i]);let B=ot.useCallback(async()=>{let e=b();if(e)try{await e.play();}catch(t){t instanceof Error&&t.name!=="AbortError"&&console.error("[player] play() failed:",t);}},[b]),I=ot.useCallback(()=>{b()?.pause();},[b]),D=ot.useCallback(e=>{let t=b();t&&(t.currentTime=Math.max(0,Math.min(e,t.duration||e)));},[b]),te=ot.useCallback(e=>{let t=b();if(!t)return;let n=Math.max(0,Math.min(e,1));n>0&&(h.current=n),t.volume=n,t.muted=n===0;},[b]),J=ot.useCallback(()=>{let e=b();if(e)if(e.muted||e.volume===0){let t=h.current>0?h.current:1;e.volume=t,e.muted=false;}else h.current=e.volume,e.muted=true;},[b]),j=ot.useCallback(e=>{let t=i.current;t&&(t.playbackRate=e);let n=a.current.audioRef?.current;n&&(n.playbackRate=e);},[i]),R=ot.useCallback(e=>{let t=u.current;t&&(t.currentLevel=e,l(n=>({...n,currentQualityLevel:e})));},[]),G=ot.useCallback(()=>{let e=u.current,t=i.current;if(!e||!t)return;let n=e.liveSyncPosition;n!=null&&Number.isFinite(n)&&(t.currentTime=n);},[i]),W=ot.useCallback(async()=>{let e=i.current;if(!e)return;let t=s.current??e.parentElement;if(t)try{!document.fullscreenElement&&!document.webkitFullscreenElement?t.requestFullscreen?await t.requestFullscreen():t.webkitRequestFullscreen?.():document.exitFullscreen?await document.exitFullscreen():document.webkitExitFullscreen?.();}catch(n){console.error("[player] fullscreen toggle failed:",n);}},[i]),Z=ot.useCallback(async()=>{let e=i.current;if(e)try{document.pictureInPictureElement?await document.exitPictureInPicture():await e.requestPictureInPicture();}catch(t){console.error("[player] PiP toggle failed:",t);}},[i]),ne=ot.useCallback(()=>{let e=!T.current.isTheaterMode;l(t=>({...t,isTheaterMode:e})),a.current.onTheaterModeChange?.(e);},[]),re=ot.useCallback(()=>{x.current&&clearTimeout(x.current),C.current=false,p.current=true,x.current=setTimeout(()=>{p.current=false,S.current=[];},6e4);let e=!T.current.isAudioMode;l(t=>({...t,isAudioMode:e})),a.current.onAudioModeChange?.(e);},[]),oe=ot.useCallback(()=>{let e=b(),t=e?.currentTime??0,n=[];if(e)for(let m=0;m<e.buffered.length;m++)n.push({start:e.buffered.start(m),end:e.buffered.end(m)});return {...T.current,currentTime:t,bufferedRanges:n}},[b]),ie=ot.useCallback(()=>i.current??null,[i]),ue=ot.useMemo(()=>({play:B,pause:I,seek:D,setVolume:te,toggleMute:J,setPlaybackRate:j,setQualityLevel:R,seekToLive:G,toggleFullscreen:W,togglePictureInPicture:Z,toggleTheaterMode:ne,toggleAudioMode:re,getState:oe,getVideoElement:ie}),[B,I,D,te,J,j,R,G,W,Z,ne,re,oe,ie]);return {state:L,ref:ue,hlsRef:u,fullscreenContainerRef:s}}var Ze={};ct(Ze,{ControlElements:()=>q,FullscreenButton:()=>be,PauseButton:()=>ge,PiPButton:()=>ye,PlayButton:()=>he,ProgressBar:()=>xe,SettingsMenu:()=>we,TheaterButton:()=>Ee,TimeDisplay:()=>Be,VolumeControl:()=>ke});var he=ot.memo(({onClick:i})=>jsxRuntime.jsx("button",{onClick:i,className:"controlButton","aria-label":"Play",title:"Play (Space)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M8 5v14l11-7z"})})}));he.displayName="PlayButton";var ge=ot.memo(({onClick:i})=>jsxRuntime.jsx("button",{onClick:i,className:"controlButton","aria-label":"Pause",title:"Pause (Space)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M6 4h4v16H6V4zm8 0h4v16h-4V4z"})})}));ge.displayName="PauseButton";var be=ot.memo(({onClick:i,isFullscreen:r=false})=>jsxRuntime.jsx("button",{onClick:i,className:"controlButton","aria-label":r?"Exit Fullscreen":"Fullscreen",title:r?"Exit Fullscreen (F)":"Fullscreen (F)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:r?jsxRuntime.jsx("path",{d:"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"}):jsxRuntime.jsx("path",{d:"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"})})}));be.displayName="FullscreenButton";var ye=ot.memo(({onClick:i,isPiP:r=false})=>jsxRuntime.jsx("button",{onClick:i,className:"controlButton","aria-label":r?"Exit Picture-in-Picture":"Picture-in-Picture",title:r?"Exit Picture-in-Picture (P)":"Picture-in-Picture (P)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M19 11h-8v6h8v-6zm4 8V4.98C23 3.88 22.1 3 21 3H3c-1.1 0-2 .88-2 1.98V19c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zm-2 .02H3V5h18v14.02z"})})}));ye.displayName="PiPButton";var Ee=ot.memo(({onClick:i,isTheater:r=false})=>jsxRuntime.jsx("button",{onClick:i,className:"controlButton","aria-label":r?"Exit Theater Mode":"Theater Mode",title:r?"Exit Theater Mode (T)":"Theater Mode (T)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:r?jsxRuntime.jsx("path",{d:"M19 7H5c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 8H5V9h14v6z"}):jsxRuntime.jsx("path",{d:"M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h18v14z"})})}));Ee.displayName="TheaterButton";var Ke=ot.memo(({volume:i,isMuted:r,onVolumeChange:o,onToggleMute:u})=>{let[s,h]=ot.useState(false),d=r?0:i,a=d*100,L=ot.useMemo(()=>`linear-gradient(to right, #60a5fa 0%, #60a5fa ${a}%, rgba(255,255,255,0.3) ${a}%, rgba(255,255,255,0.3) 100%)`,[a]);return jsxRuntime.jsxs("div",{className:"volumeContainer",onMouseEnter:()=>h(true),onMouseLeave:()=>h(false),children:[jsxRuntime.jsx("button",{onClick:u,className:"controlButton","aria-label":r?"Unmute":"Mute",title:r?"Unmute (M)":"Mute (M)",children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:d===0?jsxRuntime.jsx("path",{d:"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C23.16 14.42 24 13.3 24 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"}):d<.5?jsxRuntime.jsx("path",{d:"M7 9v6h4l5 5V4l-5 5H7z"}):jsxRuntime.jsx("path",{d:"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"})})}),s&&jsxRuntime.jsx("input",{type:"range",min:"0",max:"100",value:a,onChange:l=>o(Number(l.target.value)/100),className:"volumeSlider",style:{background:L},"aria-label":"Volume","aria-valuenow":Math.round(a)})]})});Ke.displayName="VolumeControl";var ke=Ke;function Qe(i){let r=i.trim().split(":");return r.length===3?+r[0]*3600+ +r[1]*60+parseFloat(r[2]):+r[0]*60+parseFloat(r[1])}function yt(i,r){if(/^https?:\/\//i.test(r))return r;try{return new URL(r,i).href}catch{return r}}function Ne(i,r=""){let o=[],u=i.replace(/\r\n/g,`
|
|
2
2
|
`).split(`
|
|
3
|
-
`),a=0;for(;a<s.length;){let p=s[a].trim();if(p.includes("-->")){let u=p.indexOf("-->"),l=$e(p.slice(0,u)),L=$e(p.slice(u+3));for(a++;a<s.length&&!s[a].trim();)a++;if(a<s.length){let c=s[a].trim(),C=c.lastIndexOf("#xywh="),k=c,R=0,T=0,m=160,B=90;if(C!==-1){k=c.slice(0,C);let I=c.slice(C+6).split(",").map(Number);R=I[0]??0,T=I[1]??0,m=I[2]??160,B=I[3]??90;}r.push({start:l,end:L,url:pt(t,k),x:R,y:T,w:m,h:B});}}a++;}return r}function Se(n,t){if(!n.length)return null;let r=0,s=n.length-1;for(;r<=s;){let a=r+s>>1;if(n[a].end<=t)r=a+1;else if(n[a].start>t)s=a-1;else return n[a]}return null}var Ue=Dt.memo(({videoRef:n,playerRef:t,enablePreview:r=true,thumbnailVtt:s})=>{let a=Dt.useRef(null),p=Dt.useRef(null),u=Dt.useRef(null),l=Dt.useRef(null),L=Dt.useRef(null),c=Dt.useRef(null),C=Dt.useRef(null),[k,R]=Dt.useState([]),T=Dt.useRef(false),m=Dt.useRef(0),B=Dt.useRef(0),I=Dt.useRef(null),_=Dt.useRef([]),P=Dt.useRef(null);Dt.useEffect(()=>{let o=()=>{P.current=null;};return window.addEventListener("resize",o,{passive:true}),()=>window.removeEventListener("resize",o)},[]);let x=Dt.useCallback(()=>(!P.current&&a.current&&(P.current=a.current.getBoundingClientRect()),P.current),[]);Dt.useEffect(()=>{if(!s){_.current=[];return}let o=false;return fetch(s).then(i=>i.text()).then(i=>{o||(_.current=Re(i,s));}).catch(()=>{o||(_.current=[]);}),()=>{o=true;}},[s]),Dt.useEffect(()=>{let o=n.current;if(!o)return;let i=()=>{let f=isFinite(o.duration)?o.duration:0,y=o.currentTime,S=f>0?y/f*100:0;p.current&&(p.current.style.width=`${S}%`),u.current&&(u.current.style.left=`${S}%`),a.current&&(a.current.setAttribute("aria-valuenow",String(Math.round(y))),a.current.setAttribute("aria-valuemax",String(Math.round(f))),a.current.setAttribute("aria-valuetext",se(y)));};return o.addEventListener("timeupdate",i),o.addEventListener("durationchange",i),o.addEventListener("seeked",i),i(),()=>{o.removeEventListener("timeupdate",i),o.removeEventListener("durationchange",i),o.removeEventListener("seeked",i);}},[n]),Dt.useEffect(()=>{let o=n.current;if(!o)return;let i=()=>{let f=[];for(let y=0;y<o.buffered.length;y++)f.push({start:o.buffered.start(y),end:o.buffered.end(y)});R(f);};return o.addEventListener("progress",i),()=>o.removeEventListener("progress",i)},[n]);let D=Dt.useCallback(()=>{T.current=true,u.current?.classList.add("dragging");},[]),N=Dt.useCallback(()=>{T.current=false,u.current?.classList.remove("dragging");},[]),ne=Dt.useCallback(()=>{r&&(P.current=null,l.current&&(l.current.style.display="block"),c.current&&(c.current.style.display="block"));},[r]),Z=Dt.useCallback(()=>{l.current&&(l.current.style.display="none"),c.current&&(c.current.style.display="none");},[]),X=Dt.useCallback(o=>{if(!C.current||!_.current.length)return;let i=Se(_.current,o);if(I.current=i,!i)return;let f=C.current;f.style.backgroundImage=`url(${i.url})`,f.style.backgroundPosition=`-${i.x}px -${i.y}px`,f.style.width=`${i.w}px`,f.style.height=`${i.h}px`;},[]),M=Dt.useCallback(o=>{let i=x(),f=n.current?.duration;return !i||i.width===0||!f||!isFinite(f)?0:Math.max(0,Math.min(o-i.left,i.width))/i.width*f},[x,n]),G=Dt.useCallback(o=>{let i=x();return i?Math.max(0,Math.min(o-i.left,i.width)):0},[x]),U=Dt.useCallback(o=>{let i=n.current;if(!i)return;let f=i.currentTime,y=isFinite(i.duration)?i.duration:0;switch(o.key){case "ArrowLeft":case "ArrowRight":{o.preventDefault(),o.nativeEvent.stopImmediatePropagation();let S=o.shiftKey?10:5;t.seek(o.key==="ArrowLeft"?Math.max(0,f-S):Math.min(y,f+S));break}case "Home":o.preventDefault(),o.nativeEvent.stopImmediatePropagation(),t.seek(0);break;case "End":y>0&&(o.preventDefault(),o.nativeEvent.stopImmediatePropagation(),t.seek(y));break}},[n,t]),ee=Dt.useCallback(o=>{let i=M(o.clientX),f=G(o.clientX);if(m.current=f,B.current=i,c.current&&(c.current.style.left=`${f}px`),L.current&&(L.current.textContent=se(i)),X(i),l.current){let y=l.current.offsetWidth,S=x()?.width??0,h=y/2,E=Math.max(h,Math.min(f,S-h));l.current.style.left=`${E}px`;}T.current&&t.seek(i);},[t,X,M,G,x]),ie=Dt.useCallback(()=>{Z(),N();},[Z,N]),e=Dt.useCallback(o=>{o.preventDefault(),D(),t.seek(M(o.clientX));},[D,M,t]),d=Dt.useCallback(o=>{T.current||t.seek(M(o.clientX));},[M,t]);Dt.useEffect(()=>{let o=a.current;if(!o)return;let i=f=>{T.current&&f.preventDefault();};return o.addEventListener("touchmove",i,{passive:false}),()=>o.removeEventListener("touchmove",i)},[]);let v=Dt.useCallback(o=>{P.current=null,D(),t.seek(M(o.touches[0].clientX));},[D,M,t]),V=Dt.useCallback(o=>{T.current&&t.seek(M(o.touches[0].clientX));},[M,t]);Dt.useEffect(()=>{let o=()=>N();return window.addEventListener("mouseup",o),()=>window.removeEventListener("mouseup",o)},[N]);let O=Dt.useMemo(()=>{let o=n.current,i=o&&isFinite(o.duration)?o.duration:0;return i<=0||!k.length?null:k.map((f,y)=>{let S=f.start/i*100,h=(f.end-f.start)/i*100;return jsxRuntime.jsx("div",{className:"bufferedSegment",style:{left:`${S}%`,width:`${h}%`}},y)})},[k,n]);return jsxRuntime.jsxs("div",{ref:a,className:"progressContainer",onMouseMove:ee,onMouseEnter:ne,onMouseLeave:ie,onMouseDown:e,onMouseUp:N,onClick:d,onTouchStart:v,onTouchMove:V,onTouchEnd:N,onKeyDown:U,role:"slider","aria-label":"Video progress","aria-valuemin":0,"aria-valuemax":0,"aria-valuenow":0,"aria-valuetext":"0:00",tabIndex:0,children:[r&&jsxRuntime.jsxs("div",{ref:l,className:"previewTooltip",style:{left:0,display:"none"},"aria-hidden":"true",children:[s&&jsxRuntime.jsx("div",{ref:C,className:"previewThumbnail"}),jsxRuntime.jsx("div",{ref:L,className:"previewTime"})]}),jsxRuntime.jsxs("div",{className:"progressBackground",children:[O,jsxRuntime.jsx("div",{ref:p,className:"progressFilled",style:{width:"0%"}}),r&&jsxRuntime.jsx("div",{ref:c,className:"hoverIndicator",style:{left:0,display:"none"},"aria-hidden":"true"})]}),jsxRuntime.jsx("div",{ref:u,className:"scrubHandle",style:{left:"0%"},"aria-hidden":"true"})]})});Ue.displayName="ProgressBar";var Pe=Ue;var Qe=Dt.memo(({currentRate:n,playbackRates:t,onRateChange:r,qualityLevels:s=[],currentQualityLevel:a=-1,onQualityChange:p})=>{let[u,l]=Dt.useState(false),[L,c]=Dt.useState("speed"),C=Dt.useRef(null),k=s.length>0&&!!p;Dt.useEffect(()=>{let m=B=>{C.current&&!C.current.contains(B.target)&&l(false);};return u&&document.addEventListener("mousedown",m),()=>document.removeEventListener("mousedown",m)},[u]);let R=Dt.useMemo(()=>[...s].sort((m,B)=>B.bitrate-m.bitrate),[s]),T=Dt.useMemo(()=>a===-1?"Auto":s.find(m=>m.id===a)?.name??"Auto",[s,a]);return jsxRuntime.jsxs("div",{ref:C,className:"settingsContainer",children:[jsxRuntime.jsx("button",{onClick:()=>l(m=>!m),className:"controlButton","aria-label":"Settings",title:"Settings","aria-expanded":u,children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M19.14 12.94c.04-.3.06-.61.06-.94s-.02-.64-.07-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.49.49 0 0 0-.59-.22l-2.39.96a7.02 7.02 0 0 0-1.62-.94l-.36-2.54a.484.484 0 0 0-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54a6.88 6.88 0 0 0-1.61.94l-2.39-.96a.488.488 0 0 0-.59.22L2.74 8.87a.48.48 0 0 0 .12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58a.49.49 0 0 0-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54a6.88 6.88 0 0 0 1.61-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32a.47.47 0 0 0-.12-.61l-2.01-1.58zM12 15.6A3.6 3.6 0 0 1 8.4 12 3.6 3.6 0 0 1 12 8.4a3.6 3.6 0 0 1 3.6 3.6 3.6 3.6 0 0 1-3.6 3.6z"})})}),u&&jsxRuntime.jsxs("div",{className:"settingsDropdown",role:"menu",children:[k&&jsxRuntime.jsxs("div",{className:"settingsTabs",children:[jsxRuntime.jsx("button",{className:`settingsTab${L==="speed"?" active":""}`,onClick:()=>c("speed"),children:"Speed"}),jsxRuntime.jsx("button",{className:`settingsTab${L==="quality"?" active":""}`,onClick:()=>c("quality"),children:"Quality"})]}),(!k||L==="speed")&&jsxRuntime.jsxs("div",{children:[!k&&jsxRuntime.jsx("div",{className:"settingsPanelLabel",children:"Playback Speed"}),t.map(m=>jsxRuntime.jsx("button",{onClick:()=>{r(m),l(false);},className:`settingsOption${n===m?" active":""}`,role:"menuitemradio","aria-checked":n===m,children:m===1?"Normal":`${m}\xD7`},m))]}),k&&L==="quality"&&jsxRuntime.jsxs("div",{children:[jsxRuntime.jsxs("button",{onClick:()=>{p(-1),l(false);},className:`settingsOption${a===-1?" active":""}`,role:"menuitemradio","aria-checked":a===-1,children:["Auto ",a===-1&&T!=="Auto"?`(${T})`:""]}),R.map(m=>jsxRuntime.jsxs("button",{onClick:()=>{p(m.id),l(false);},className:`settingsOption${a===m.id?" active":""}`,role:"menuitemradio","aria-checked":a===m.id,children:[m.name,m.bitrate>0&&jsxRuntime.jsxs("span",{className:"settingsOptionBadge",children:[Math.round(m.bitrate/1e3)," kbps"]})]},m.id))]})]})]})});Qe.displayName="SettingsMenu";var Te=Qe;var Xe=Dt.memo(({videoRef:n,isLive:t=false})=>{let r=Dt.useRef(null),s=Dt.useRef(null);return Dt.useEffect(()=>{let a=n.current;if(!a)return;let p=()=>{r.current&&(r.current.textContent=se(a.currentTime));},u=()=>{if(s.current){let l=isFinite(a.duration)?a.duration:0;s.current.textContent=` / ${se(l)}`;}};return a.addEventListener("timeupdate",p),a.addEventListener("durationchange",u),a.addEventListener("seeked",p),p(),u(),()=>{a.removeEventListener("timeupdate",p),a.removeEventListener("durationchange",u),a.removeEventListener("seeked",p);}},[n,t]),t?jsxRuntime.jsx("span",{className:"timeDisplay",style:{opacity:.7},children:jsxRuntime.jsx("span",{ref:r,children:"0:00"})}):jsxRuntime.jsxs("span",{className:"timeDisplay",children:[jsxRuntime.jsx("span",{ref:r,children:"0:00"}),jsxRuntime.jsx("span",{ref:s,style:{opacity:.6},children:" / 0:00"})]})});Xe.displayName="TimeDisplay";var ke=Xe;var Q={PlayButton:fe,PauseButton:pe,FullscreenButton:ve,PiPButton:he,TheaterButton:ge,VolumeControl:Le,ProgressBar:Pe,SettingsMenu:Te,TimeDisplay:ke};var xe=Dt.memo(function({videoRef:t,playerRef:r,playerContainerRef:s,playbackRates:a,enablePreview:p,thumbnailVtt:u,isPlaying:l,volume:L,isMuted:c,playbackRate:C,isFullscreen:k,isPictureInPicture:R,isTheaterMode:T,isAudioMode:m,showAudioButton:B,audioModeIcon:I,videoModeIcon:_,audioModeLabel:P,videoModeLabel:x,isLive:D,qualityLevels:N,currentQualityLevel:ne,controlBarItems:Z,autoHideControls:X}){let M=Dt.useRef(null),[G,U]=Dt.useState(true),ee=Dt.useRef({isPlaying:l,volume:L,isMuted:c,isLive:D});ee.current={isPlaying:l,volume:L,isMuted:c,isLive:D},Dt.useEffect(()=>{if(m||!X){U(true),M.current&&clearTimeout(M.current);return}if(!l){U(true),M.current&&clearTimeout(M.current);return}let h=s.current;if(!h)return;let E=()=>{U(true),M.current&&clearTimeout(M.current),M.current=setTimeout(()=>U(false),3e3);},g=()=>{M.current&&clearTimeout(M.current),U(false);};return h.addEventListener("mousemove",E),h.addEventListener("mouseenter",E),h.addEventListener("mouseleave",g),h.addEventListener("touchstart",E,{passive:true}),U(false),()=>{h.removeEventListener("mousemove",E),h.removeEventListener("mouseenter",E),h.removeEventListener("mouseleave",g),h.removeEventListener("touchstart",E),M.current&&clearTimeout(M.current);}},[l,m,X,s]),Dt.useEffect(()=>{let h=E=>{if(!s.current?.contains(document.activeElement))return;let g=E.target;if(g.tagName==="INPUT"||g.tagName==="TEXTAREA"||g.isContentEditable)return;let{isPlaying:A,volume:b,isLive:z}=ee.current,j=t.current?.currentTime??0,ae=t.current?.duration??0;switch(E.code){case "Space":case "KeyK":E.preventDefault(),A?r.pause():r.play();break;case "ArrowLeft":E.preventDefault(),r.seek(Math.max(0,j-5));break;case "ArrowRight":E.preventDefault(),r.seek(Math.min(ae||1/0,j+5));break;case "ArrowUp":E.preventDefault(),r.setVolume(Math.min(1,b+.1));break;case "ArrowDown":E.preventDefault(),r.setVolume(Math.max(0,b-.1));break;case "KeyM":E.preventDefault(),r.toggleMute();break;case "KeyF":E.preventDefault(),r.toggleFullscreen();break;case "KeyP":E.preventDefault(),r.togglePictureInPicture();break;case "KeyT":E.preventDefault(),r.toggleTheaterMode();break;case "KeyL":E.preventDefault(),z&&r.seekToLive();break;case "Digit0":case "Digit1":case "Digit2":case "Digit3":case "Digit4":case "Digit5":case "Digit6":case "Digit7":case "Digit8":case "Digit9":{E.preventDefault();let we=Number(E.code.replace("Digit",""))*10;r.seek(ae/100*we);break}}};return window.addEventListener("keydown",h),()=>window.removeEventListener("keydown",h)},[r,s,t]);let ie=Dt.useCallback(()=>r.play(),[r]),e=Dt.useCallback(()=>r.pause(),[r]),d=Dt.useCallback(h=>r.setVolume(h),[r]),v=Dt.useCallback(()=>r.toggleMute(),[r]),V=Dt.useCallback(h=>r.setPlaybackRate(h),[r]),O=Dt.useCallback(h=>r.setQualityLevel(h),[r]),o=Dt.useCallback(()=>r.togglePictureInPicture(),[r]),i=Dt.useCallback(()=>r.toggleTheaterMode(),[r]),f=Dt.useCallback(()=>r.toggleAudioMode(),[r]),y=Dt.useCallback(()=>r.toggleFullscreen(),[r]),S=Dt.useCallback(()=>r.seekToLive(),[r]);return jsxRuntime.jsx("div",{style:{position:"absolute",inset:0,display:"flex",flexDirection:"column",justifyContent:"flex-end",opacity:G?1:0,transition:"opacity 0.3s",pointerEvents:"none",zIndex:2},children:jsxRuntime.jsxs("div",{style:{background:"linear-gradient(to top, rgba(0,0,0,0.75) 0%, rgba(0,0,0,0.2) 60%, transparent 100%)",padding:"48px 12px 12px",pointerEvents:G?"auto":"none"},role:"region","aria-label":"Video player controls",children:[jsxRuntime.jsx(Q.ProgressBar,{videoRef:t,playerRef:r,enablePreview:p,thumbnailVtt:u}),jsxRuntime.jsxs("div",{style:{display:"flex",alignItems:"center",gap:4,marginTop:4},children:[l?jsxRuntime.jsx(Q.PauseButton,{onClick:e}):jsxRuntime.jsx(Q.PlayButton,{onClick:ie}),jsxRuntime.jsx(Q.VolumeControl,{volume:L,isMuted:c,onVolumeChange:d,onToggleMute:v}),jsxRuntime.jsx(Q.TimeDisplay,{videoRef:t,isLive:D}),jsxRuntime.jsx("div",{style:{flex:1}}),D&&jsxRuntime.jsx(Ze,{onClick:S}),B&&jsxRuntime.jsx(Je,{onClick:f,isAudioMode:m,audioModeIcon:I,videoModeIcon:_,audioModeLabel:P,videoModeLabel:x}),jsxRuntime.jsx(Q.SettingsMenu,{currentRate:C,playbackRates:a,onRateChange:V,qualityLevels:N,currentQualityLevel:ne,onQualityChange:O}),Z?.map(h=>jsxRuntime.jsx("button",{className:"controlButton","aria-label":h.label,title:h.title??h.label,onClick:h.onClick,children:h.icon},h.key)),jsxRuntime.jsx(Q.PiPButton,{onClick:o,isPiP:R}),jsxRuntime.jsx(Q.TheaterButton,{onClick:i,isTheater:T}),jsxRuntime.jsx(Q.FullscreenButton,{onClick:y,isFullscreen:k})]})]})})});xe.displayName="Controls";var Je=Dt.memo(({onClick:n,isAudioMode:t,audioModeIcon:r,videoModeIcon:s,audioModeLabel:a,videoModeLabel:p})=>{let u=t?p??"Video":a??"Audio";return jsxRuntime.jsxs("button",{onClick:n,className:"rvp-audio-toggle-btn","aria-label":u,title:u,"aria-pressed":t,children:[t?s??jsxRuntime.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"})}):r??jsxRuntime.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M12 3a9 9 0 0 0-9 9v7c0 1.1.9 2 2 2h1a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H4v-1a8 8 0 0 1 16 0v1h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h1a3 3 0 0 0 3-3v-4c0-4.97-4.03-9-9-9z"})}),u]})});Je.displayName="AudioModeButton";var Ze=Dt.memo(({onClick:n})=>jsxRuntime.jsx("button",{onClick:n,style:{background:"none",border:"1px solid rgba(255,255,255,0.6)",color:"#fff",borderRadius:3,padding:"2px 8px",fontSize:11,fontWeight:700,cursor:"pointer",letterSpacing:"0.06em"},title:"Go to live (L)",children:"GO LIVE"}));Ze.displayName="GoLiveButton";var Ve=Dt.memo(({x:n,y:t,isPlaying:r,src:s,videoRef:a,playerRef:p,onClose:u,contextMenuItems:l})=>{let L=Dt.useRef(null),[c,C]=Dt.useState(()=>a.current?.loop??false),k=Math.min(n,window.innerWidth-220),R=Math.min(t,window.innerHeight-290);Dt.useEffect(()=>{let P=N=>{L.current&&!L.current.contains(N.target)&&u();},x=N=>{N.key==="Escape"&&u();},D=()=>u();return document.addEventListener("mousedown",P),document.addEventListener("keydown",x),window.addEventListener("scroll",D,true),()=>{document.removeEventListener("mousedown",P),document.removeEventListener("keydown",x),window.removeEventListener("scroll",D,true);}},[u]);let T=Dt.useCallback(()=>{r?p.pause():p.play(),u();},[r,p,u]),m=Dt.useCallback(()=>{let P=a.current;if(!P)return;let x=!c;P.loop=x,C(x);},[a,c]),B=Dt.useCallback(async()=>{try{await navigator.clipboard.writeText(s);}catch{}u();},[s,u]),I=Dt.useCallback(async()=>{let P=Math.floor(a.current?.currentTime??0);try{await navigator.clipboard.writeText(`${s}?t=${P}`);}catch{}u();},[s,a,u]),_=Dt.useCallback(()=>{p.togglePictureInPicture(),u();},[p,u]);return jsxRuntime.jsxs("div",{ref:L,className:"contextMenu",style:{left:k,top:R},children:[jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:T,children:r?"Pause":"Play"}),jsxRuntime.jsxs("button",{className:"contextMenuItem",onClick:m,children:[jsxRuntime.jsx("span",{children:"Loop"}),c&&jsxRuntime.jsx("span",{className:"contextMenuCheck",children:"\u2713"})]}),jsxRuntime.jsx("div",{className:"contextMenuDivider"}),jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:B,children:"Copy video URL"}),jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:I,children:"Copy video URL at current time"}),jsxRuntime.jsx("div",{className:"contextMenuDivider"}),jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:_,children:"Picture-in-Picture"}),l&&l.length>0&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{className:"contextMenuDivider"}),l.map((P,x)=>jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:()=>{P.onClick(),u();},children:P.label},x))]})]})});Ve.displayName="ContextMenu";var Ae=Dt.memo(function({poster:t,logo:r,audioModeFallback:s,isBuffering:a=false,onOverlayClick:p}){return jsxRuntime.jsxs("div",{className:"rvp-audio-overlay",onClick:p,"data-test":"audio-mode-overlay",children:[t?jsxRuntime.jsx("div",{className:"rvp-audio-artwork-container",children:jsxRuntime.jsx("img",{src:t,alt:"Artwork",className:"rvp-audio-artwork",draggable:false})}):s?jsxRuntime.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center"},children:s}):r?typeof r=="string"?jsxRuntime.jsx("img",{src:r,alt:"Logo",className:"rvp-audio-logo",draggable:false}):jsxRuntime.jsx("div",{className:"rvp-audio-logo-node",children:r}):null,jsxRuntime.jsx("span",{className:"rvp-audio-label",children:"Audio Mode"}),a?jsxRuntime.jsx("div",{className:"rvp-audio-buffering-overlay","aria-label":"Buffering",children:jsxRuntime.jsx("div",{className:"rvp-audio-spinner"})}):null]})});Ae.displayName="AudioModeOverlay";var nt=Dt.forwardRef((n,t)=>{let{src:r,poster:s,className:a,controls:p=true,options:u={}}=n,{autoplay:l=false,muted:L=false,loop:c=false,preload:C="metadata",playbackRates:k=[.25,.5,.75,1,1.25,1.5,1.75,2],enableHLS:R=true,enablePreview:T=true,thumbnailVtt:m,hlsConfig:B,autoHideControls:I=true,subtitles:_,crossOrigin:P,logo:x,audioModeFallback:D,audioSrc:N,showAudioButton:ne,audioModeIcon:Z,videoModeIcon:X,audioModeLabel:M,videoModeLabel:G,defaultAudioMode:U,audioBandwidthThreshold:ee,onPlay:ie,onPause:e,onEnded:d,onError:v,onTimeUpdate:V,onDurationChange:O,onBuffering:o,onTheaterModeChange:i,onAudioModeChange:f,contextMenuItems:y,controlBarItems:S}=u,h=Dt.useRef(null),E=Dt.useRef(null),{state:g,ref:A,fullscreenContainerRef:b}=_e(h,r,{autoplay:l,muted:L,loop:c,playbackRates:k,enableHLS:R,hlsConfig:B,defaultAudioMode:U,audioBandwidthThreshold:ee,onPlay:ie,onPause:e,onEnded:d,onError:v,onTimeUpdate:V,onDurationChange:O,onBuffering:o,onTheaterModeChange:i,onAudioModeChange:f}),[z,j]=Dt.useState(null);Dt.useEffect(()=>{b.current=E.current;},[b]),Dt__default.default.useImperativeHandle(t,()=>A,[A]);let ae=Dt.useCallback(()=>{E.current?.focus(),g.isPlaying?A.pause():A.play();},[g.isPlaying,A]),we=Dt.useCallback(()=>{A.toggleFullscreen();},[A]),rt=Dt.useCallback(te=>{te.preventDefault(),j({x:te.clientX,y:te.clientY});},[]);return jsxRuntime.jsxs("div",{ref:E,tabIndex:0,style:{position:"relative",width:"100%",backgroundColor:"#000",aspectRatio:"16 / 9",userSelect:"none",outline:"none"},className:a,"data-test":"video-player-container","data-theater":g.isTheaterMode?"true":void 0,onContextMenu:rt,children:[jsxRuntime.jsx("video",{ref:h,poster:s,preload:C,crossOrigin:P,onClick:ae,onDoubleClick:we,playsInline:true,style:{width:"100%",height:"100%",display:"block",cursor:"pointer",visibility:g.isAudioMode?"hidden":"visible"},"data-test":"video-element",children:_?.map(te=>jsxRuntime.jsx("track",{kind:"subtitles",src:te.src,label:te.label,srcLang:te.srclang,default:te.default},te.id))}),g.isAudioMode&&jsxRuntime.jsx(Ae,{poster:s,logo:x,audioModeFallback:D,isBuffering:g.isBuffering,onOverlayClick:ae}),p&&jsxRuntime.jsx(xe,{videoRef:h,playerRef:A,playerContainerRef:E,playbackRates:k,enablePreview:T,thumbnailVtt:g.isAudioMode?void 0:m,isPlaying:g.isPlaying,volume:g.volume,isMuted:g.isMuted,playbackRate:g.playbackRate,isFullscreen:g.isFullscreen,isPictureInPicture:g.isPictureInPicture,isTheaterMode:g.isTheaterMode,isAudioMode:g.isAudioMode,showAudioButton:ne??!!N,audioModeIcon:Z,videoModeIcon:X,audioModeLabel:M,videoModeLabel:G,isLive:g.isLive,qualityLevels:g.qualityLevels,currentQualityLevel:g.currentQualityLevel,controlBarItems:S,autoHideControls:I}),z&&jsxRuntime.jsx(Ve,{x:z.x,y:z.y,isPlaying:g.isPlaying,src:r,videoRef:h,playerRef:A,onClose:()=>j(null),contextMenuItems:y}),g.isLive&&jsxRuntime.jsx("div",{style:{position:"absolute",top:12,left:12,backgroundColor:"#e53935",color:"#fff",fontSize:11,fontWeight:700,letterSpacing:"0.08em",padding:"2px 8px",borderRadius:3,pointerEvents:"none"},children:"LIVE"}),g.isBuffering&&!g.error&&jsxRuntime.jsx("div",{style:{position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:12,color:"#fff",pointerEvents:"none"},"data-test":"buffering-indicator",children:jsxRuntime.jsx("div",{style:{width:48,height:48,border:"4px solid rgba(255,255,255,0.25)",borderTop:"4px solid #fff",borderRadius:"50%",animation:"rvp-spin 0.8s linear infinite"}})}),g.error&&jsxRuntime.jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"rgba(0,0,0,0.85)",color:"#fff",padding:24},"data-test":"error-overlay",children:jsxRuntime.jsxs("div",{style:{textAlign:"center",maxWidth:400},children:[jsxRuntime.jsx("div",{style:{fontSize:36,marginBottom:12},children:"\u26A0"}),jsxRuntime.jsx("h3",{style:{margin:"0 0 8px",fontSize:18},children:g.error.code==="MEDIA_ERR_SRC_NOT_SUPPORTED"?"Unsupported Format":g.error.code.startsWith("HLS")?"Stream Error":"Playback Error"}),jsxRuntime.jsx("p",{style:{margin:0,fontSize:13,opacity:.75},children:g.error.message})]})})]})});nt.displayName="VideoPlayer";var At=nt;var It={EXTREME:100,POOR:300,FAIR:700,GOOD:1500};exports.AUDIO_BANDWIDTH_THRESHOLDS=It;exports.ControlElements=Ge;exports.Controls=xe;exports.VideoPlayer=At;exports.findThumbnailCue=Se;exports.formatTime=se;exports.getMimeType=at;exports.isHLSUrl=ye;exports.parseThumbnailVtt=Re;//# sourceMappingURL=index.js.map
|
|
3
|
+
`),s=0;for(;s<u.length;){let h=u[s].trim();if(h.includes("-->")){let d=h.indexOf("-->"),a=Qe(h.slice(0,d)),L=Qe(h.slice(d+3));for(s++;s<u.length&&!u[s].trim();)s++;if(s<u.length){let l=u[s].trim(),T=l.lastIndexOf("#xywh="),S=l,F=0,C=0,p=160,x=90;if(T!==-1){S=l.slice(0,T);let P=l.slice(T+6).split(",").map(Number);F=P[0]??0,C=P[1]??0,p=P[2]??160,x=P[3]??90;}o.push({start:a,end:L,url:yt(r,S),x:F,y:C,w:p,h:x});}}s++;}return o}function He(i,r){if(!i.length)return null;let o=0,u=i.length-1;for(;o<=u;){let s=o+u>>1;if(i[s].end<=r)o=s+1;else if(i[s].start>r)u=s-1;else return i[s]}return null}var qe=ot.memo(({videoRef:i,playerRef:r,enablePreview:o=true,thumbnailVtt:u})=>{let s=ot.useRef(null),h=ot.useRef(null),d=ot.useRef(null),a=ot.useRef(null),L=ot.useRef(null),l=ot.useRef(null),T=ot.useRef(null),[S,F]=ot.useState([]),C=ot.useRef(false),p=ot.useRef(0),x=ot.useRef(0),P=ot.useRef(null),A=ot.useRef([]),b=ot.useRef(null);ot.useEffect(()=>{let t=()=>{b.current=null;};return window.addEventListener("resize",t,{passive:true}),()=>window.removeEventListener("resize",t)},[]);let B=ot.useCallback(()=>(!b.current&&s.current&&(b.current=s.current.getBoundingClientRect()),b.current),[]);ot.useEffect(()=>{if(!u){A.current=[];return}let t=false;return fetch(u).then(n=>n.text()).then(n=>{t||(A.current=Ne(n,u));}).catch(()=>{t||(A.current=[]);}),()=>{t=true;}},[u]),ot.useEffect(()=>{let t=i.current;if(!t)return;let n=()=>{let m=isFinite(t.duration)?t.duration:0,y=t.currentTime,k=m>0?y/m*100:0;h.current&&(h.current.style.width=`${k}%`),d.current&&(d.current.style.left=`${k}%`),s.current&&(s.current.setAttribute("aria-valuenow",String(Math.round(y))),s.current.setAttribute("aria-valuemax",String(Math.round(m))),s.current.setAttribute("aria-valuetext",ce(y)));};return t.addEventListener("timeupdate",n),t.addEventListener("durationchange",n),t.addEventListener("seeked",n),n(),()=>{t.removeEventListener("timeupdate",n),t.removeEventListener("durationchange",n),t.removeEventListener("seeked",n);}},[i]),ot.useEffect(()=>{let t=i.current;if(!t)return;let n=()=>{let m=[];for(let y=0;y<t.buffered.length;y++)m.push({start:t.buffered.start(y),end:t.buffered.end(y)});F(m);};return t.addEventListener("progress",n),()=>t.removeEventListener("progress",n)},[i]);let I=ot.useCallback(()=>{C.current=true,d.current?.classList.add("dragging");},[]),D=ot.useCallback(()=>{C.current=false,d.current?.classList.remove("dragging");},[]),te=ot.useCallback(()=>{o&&(b.current=null,a.current&&(a.current.style.display="block"),l.current&&(l.current.style.display="block"));},[o]),J=ot.useCallback(()=>{a.current&&(a.current.style.display="none"),l.current&&(l.current.style.display="none");},[]),j=ot.useCallback(t=>{if(!T.current||!A.current.length)return;let n=He(A.current,t);if(P.current=n,!n)return;let m=T.current;m.style.backgroundImage=`url(${n.url})`,m.style.backgroundPosition=`-${n.x}px -${n.y}px`,m.style.width=`${n.w}px`,m.style.height=`${n.h}px`;},[]),R=ot.useCallback(t=>{let n=B(),m=i.current?.duration;return !n||n.width===0||!m||!isFinite(m)?0:Math.max(0,Math.min(t-n.left,n.width))/n.width*m},[B,i]),G=ot.useCallback(t=>{let n=B();return n?Math.max(0,Math.min(t-n.left,n.width)):0},[B]),W=ot.useCallback(t=>{let n=i.current;if(!n)return;let m=n.currentTime,y=isFinite(n.duration)?n.duration:0;switch(t.key){case "ArrowLeft":case "ArrowRight":{t.preventDefault(),t.nativeEvent.stopImmediatePropagation();let k=t.shiftKey?10:5;r.seek(t.key==="ArrowLeft"?Math.max(0,m-k):Math.min(y,m+k));break}case "Home":t.preventDefault(),t.nativeEvent.stopImmediatePropagation(),r.seek(0);break;case "End":y>0&&(t.preventDefault(),t.nativeEvent.stopImmediatePropagation(),r.seek(y));break}},[i,r]),Z=ot.useCallback(t=>{let n=R(t.clientX),m=G(t.clientX);if(p.current=m,x.current=n,l.current&&(l.current.style.left=`${m}px`),L.current&&(L.current.textContent=ce(n)),j(n),a.current){let y=a.current.offsetWidth,k=B()?.width??0,c=y/2,f=Math.max(c,Math.min(m,k-c));a.current.style.left=`${f}px`;}C.current&&r.seek(n);},[r,j,R,G,B]),ne=ot.useCallback(()=>{J(),D();},[J,D]),re=ot.useCallback(t=>{t.preventDefault(),I(),r.seek(R(t.clientX));},[I,R,r]),oe=ot.useCallback(t=>{C.current||r.seek(R(t.clientX));},[R,r]);ot.useEffect(()=>{let t=s.current;if(!t)return;let n=m=>{C.current&&m.preventDefault();};return t.addEventListener("touchmove",n,{passive:false}),()=>t.removeEventListener("touchmove",n)},[]);let ie=ot.useCallback(t=>{b.current=null,I(),r.seek(R(t.touches[0].clientX));},[I,R,r]),ue=ot.useCallback(t=>{C.current&&r.seek(R(t.touches[0].clientX));},[R,r]);ot.useEffect(()=>{let t=()=>D();return window.addEventListener("mouseup",t),()=>window.removeEventListener("mouseup",t)},[D]);let e=ot.useMemo(()=>{let t=i.current,n=t&&isFinite(t.duration)?t.duration:0;return n<=0||!S.length?null:S.map((m,y)=>{let k=m.start/n*100,c=(m.end-m.start)/n*100;return jsxRuntime.jsx("div",{className:"bufferedSegment",style:{left:`${k}%`,width:`${c}%`}},y)})},[S,i]);return jsxRuntime.jsxs("div",{ref:s,className:"progressContainer",onMouseMove:Z,onMouseEnter:te,onMouseLeave:ne,onMouseDown:re,onMouseUp:D,onClick:oe,onTouchStart:ie,onTouchMove:ue,onTouchEnd:D,onKeyDown:W,role:"slider","aria-label":"Video progress","aria-valuemin":0,"aria-valuemax":0,"aria-valuenow":0,"aria-valuetext":"0:00",tabIndex:0,children:[o&&jsxRuntime.jsxs("div",{ref:a,className:"previewTooltip",style:{left:0,display:"none"},"aria-hidden":"true",children:[u&&jsxRuntime.jsx("div",{ref:T,className:"previewThumbnail"}),jsxRuntime.jsx("div",{ref:L,className:"previewTime"})]}),jsxRuntime.jsxs("div",{className:"progressBackground",children:[e,jsxRuntime.jsx("div",{ref:h,className:"progressFilled",style:{width:"0%"}}),o&&jsxRuntime.jsx("div",{ref:l,className:"hoverIndicator",style:{left:0,display:"none"},"aria-hidden":"true"})]}),jsxRuntime.jsx("div",{ref:d,className:"scrubHandle",style:{left:"0%"},"aria-hidden":"true"})]})});qe.displayName="ProgressBar";var xe=qe;var Ge=ot.memo(({currentRate:i,playbackRates:r,onRateChange:o,qualityLevels:u=[],currentQualityLevel:s=-1,onQualityChange:h})=>{let[d,a]=ot.useState(false),[L,l]=ot.useState("speed"),T=ot.useRef(null),S=u.length>0&&!!h;ot.useEffect(()=>{let p=x=>{T.current&&!T.current.contains(x.target)&&a(false);};return d&&document.addEventListener("mousedown",p),()=>document.removeEventListener("mousedown",p)},[d]);let F=ot.useMemo(()=>[...u].sort((p,x)=>x.bitrate-p.bitrate),[u]),C=ot.useMemo(()=>s===-1?"Auto":u.find(p=>p.id===s)?.name??"Auto",[u,s]);return jsxRuntime.jsxs("div",{ref:T,className:"settingsContainer",children:[jsxRuntime.jsx("button",{onClick:()=>a(p=>!p),className:"controlButton","aria-label":"Settings",title:"Settings","aria-expanded":d,children:jsxRuntime.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M19.14 12.94c.04-.3.06-.61.06-.94s-.02-.64-.07-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.49.49 0 0 0-.59-.22l-2.39.96a7.02 7.02 0 0 0-1.62-.94l-.36-2.54a.484.484 0 0 0-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54a6.88 6.88 0 0 0-1.61.94l-2.39-.96a.488.488 0 0 0-.59.22L2.74 8.87a.48.48 0 0 0 .12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58a.49.49 0 0 0-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54a6.88 6.88 0 0 0 1.61-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32a.47.47 0 0 0-.12-.61l-2.01-1.58zM12 15.6A3.6 3.6 0 0 1 8.4 12 3.6 3.6 0 0 1 12 8.4a3.6 3.6 0 0 1 3.6 3.6 3.6 3.6 0 0 1-3.6 3.6z"})})}),d&&jsxRuntime.jsxs("div",{className:"settingsDropdown",role:"menu",children:[S&&jsxRuntime.jsxs("div",{className:"settingsTabs",children:[jsxRuntime.jsx("button",{className:`settingsTab${L==="speed"?" active":""}`,onClick:()=>l("speed"),children:"Speed"}),jsxRuntime.jsx("button",{className:`settingsTab${L==="quality"?" active":""}`,onClick:()=>l("quality"),children:"Quality"})]}),(!S||L==="speed")&&jsxRuntime.jsxs("div",{children:[!S&&jsxRuntime.jsx("div",{className:"settingsPanelLabel",children:"Playback Speed"}),r.map(p=>jsxRuntime.jsx("button",{onClick:()=>{o(p),a(false);},className:`settingsOption${i===p?" active":""}`,role:"menuitemradio","aria-checked":i===p,children:p===1?"Normal":`${p}\xD7`},p))]}),S&&L==="quality"&&jsxRuntime.jsxs("div",{children:[jsxRuntime.jsxs("button",{onClick:()=>{h(-1),a(false);},className:`settingsOption${s===-1?" active":""}`,role:"menuitemradio","aria-checked":s===-1,children:["Auto ",s===-1&&C!=="Auto"?`(${C})`:""]}),F.map(p=>jsxRuntime.jsxs("button",{onClick:()=>{h(p.id),a(false);},className:`settingsOption${s===p.id?" active":""}`,role:"menuitemradio","aria-checked":s===p.id,children:[p.name,p.bitrate>0&&jsxRuntime.jsxs("span",{className:"settingsOptionBadge",children:[Math.round(p.bitrate/1e3)," kbps"]})]},p.id))]})]})]})});Ge.displayName="SettingsMenu";var we=Ge;var Je=ot.memo(({videoRef:i,isLive:r=false})=>{let o=ot.useRef(null),u=ot.useRef(null);return ot.useEffect(()=>{let s=i.current;if(!s)return;let h=()=>{o.current&&(o.current.textContent=ce(s.currentTime));},d=()=>{if(u.current){let a=isFinite(s.duration)?s.duration:0;u.current.textContent=` / ${ce(a)}`;}};return s.addEventListener("timeupdate",h),s.addEventListener("durationchange",d),s.addEventListener("seeked",h),h(),d(),()=>{s.removeEventListener("timeupdate",h),s.removeEventListener("durationchange",d),s.removeEventListener("seeked",h);}},[i,r]),r?jsxRuntime.jsx("span",{className:"timeDisplay",style:{opacity:.7},children:jsxRuntime.jsx("span",{ref:o,children:"0:00"})}):jsxRuntime.jsxs("span",{className:"timeDisplay",children:[jsxRuntime.jsx("span",{ref:o,children:"0:00"}),jsxRuntime.jsx("span",{ref:u,style:{opacity:.6},children:" / 0:00"})]})});Je.displayName="TimeDisplay";var Be=Je;var q={PlayButton:he,PauseButton:ge,FullscreenButton:be,PiPButton:ye,TheaterButton:Ee,VolumeControl:ke,ProgressBar:xe,SettingsMenu:we,TimeDisplay:Be};var De=ot.memo(function({videoRef:r,playerRef:o,playerContainerRef:u,playbackRates:s,enablePreview:h,thumbnailVtt:d,isPlaying:a,volume:L,isMuted:l,playbackRate:T,isFullscreen:S,isPictureInPicture:F,isTheaterMode:C,isAudioMode:p,showAudioButton:x,audioModeIcon:P,videoModeIcon:A,audioModeLabel:b,videoModeLabel:B,isLive:I,qualityLevels:D,currentQualityLevel:te,controlBarItems:J,autoHideControls:j}){let R=ot.useRef(null),[G,W]=ot.useState(true),Z=ot.useRef({isPlaying:a,volume:L,isMuted:l,isLive:I});Z.current={isPlaying:a,volume:L,isMuted:l,isLive:I},ot.useEffect(()=>{if(p||!j){W(true),R.current&&clearTimeout(R.current);return}if(!a){W(true),R.current&&clearTimeout(R.current);return}let c=u.current;if(!c)return;let f=()=>{W(true),R.current&&clearTimeout(R.current),R.current=setTimeout(()=>W(false),3e3);},M=()=>{R.current&&clearTimeout(R.current),W(false);};return c.addEventListener("mousemove",f),c.addEventListener("mouseenter",f),c.addEventListener("mouseleave",M),c.addEventListener("touchstart",f,{passive:true}),W(false),()=>{c.removeEventListener("mousemove",f),c.removeEventListener("mouseenter",f),c.removeEventListener("mouseleave",M),c.removeEventListener("touchstart",f),R.current&&clearTimeout(R.current);}},[a,p,j,u]),ot.useEffect(()=>{let c=f=>{if(!u.current?.contains(document.activeElement))return;let M=f.target;if(M.tagName==="INPUT"||M.tagName==="TEXTAREA"||M.isContentEditable)return;let{isPlaying:w,volume:E,isLive:v}=Z.current,N=r.current?.currentTime??0,V=r.current?.duration??0;switch(f.code){case "Space":case "KeyK":f.preventDefault(),w?o.pause():o.play();break;case "ArrowLeft":f.preventDefault(),o.seek(Math.max(0,N-5));break;case "ArrowRight":f.preventDefault(),o.seek(Math.min(V||1/0,N+5));break;case "ArrowUp":f.preventDefault(),o.setVolume(Math.min(1,E+.1));break;case "ArrowDown":f.preventDefault(),o.setVolume(Math.max(0,E-.1));break;case "KeyM":f.preventDefault(),o.toggleMute();break;case "KeyF":f.preventDefault(),o.toggleFullscreen();break;case "KeyP":f.preventDefault(),o.togglePictureInPicture();break;case "KeyT":f.preventDefault(),o.toggleTheaterMode();break;case "KeyL":f.preventDefault(),v&&o.seekToLive();break;case "Digit0":case "Digit1":case "Digit2":case "Digit3":case "Digit4":case "Digit5":case "Digit6":case "Digit7":case "Digit8":case "Digit9":{f.preventDefault();let g=Number(f.code.replace("Digit",""))*10;o.seek(V/100*g);break}}};return window.addEventListener("keydown",c),()=>window.removeEventListener("keydown",c)},[o,u,r]);let ne=ot.useCallback(()=>o.play(),[o]),re=ot.useCallback(()=>o.pause(),[o]),oe=ot.useCallback(c=>o.setVolume(c),[o]),ie=ot.useCallback(()=>o.toggleMute(),[o]),ue=ot.useCallback(c=>o.setPlaybackRate(c),[o]),e=ot.useCallback(c=>o.setQualityLevel(c),[o]),t=ot.useCallback(()=>o.togglePictureInPicture(),[o]),n=ot.useCallback(()=>o.toggleTheaterMode(),[o]),m=ot.useCallback(()=>o.toggleAudioMode(),[o]),y=ot.useCallback(()=>o.toggleFullscreen(),[o]),k=ot.useCallback(()=>o.seekToLive(),[o]);return jsxRuntime.jsx("div",{style:{position:"absolute",inset:0,display:"flex",flexDirection:"column",justifyContent:"flex-end",opacity:G?1:0,transition:"opacity 0.3s",pointerEvents:"none",zIndex:2},children:jsxRuntime.jsxs("div",{style:{background:"linear-gradient(to top, rgba(0,0,0,0.75) 0%, rgba(0,0,0,0.2) 60%, transparent 100%)",padding:"48px 12px 12px",pointerEvents:G?"auto":"none"},role:"region","aria-label":"Video player controls",children:[jsxRuntime.jsx(q.ProgressBar,{videoRef:r,playerRef:o,enablePreview:h,thumbnailVtt:d}),jsxRuntime.jsxs("div",{style:{display:"flex",alignItems:"center",gap:4,marginTop:4},children:[a?jsxRuntime.jsx(q.PauseButton,{onClick:re}):jsxRuntime.jsx(q.PlayButton,{onClick:ne}),jsxRuntime.jsx(q.VolumeControl,{volume:L,isMuted:l,onVolumeChange:oe,onToggleMute:ie}),jsxRuntime.jsx(q.TimeDisplay,{videoRef:r,isLive:I}),jsxRuntime.jsx("div",{style:{flex:1}}),I&&jsxRuntime.jsx(rt,{onClick:k}),x&&jsxRuntime.jsx(nt,{onClick:m,isAudioMode:p,audioModeIcon:P,videoModeIcon:A,audioModeLabel:b,videoModeLabel:B}),jsxRuntime.jsx(q.SettingsMenu,{currentRate:T,playbackRates:s,onRateChange:ue,qualityLevels:D,currentQualityLevel:te,onQualityChange:e}),J?.map(c=>jsxRuntime.jsx("button",{className:"controlButton","aria-label":c.label,title:c.title??c.label,onClick:c.onClick,children:c.icon},c.key)),jsxRuntime.jsx(q.PiPButton,{onClick:t,isPiP:F}),jsxRuntime.jsx(q.TheaterButton,{onClick:n,isTheater:C}),jsxRuntime.jsx(q.FullscreenButton,{onClick:y,isFullscreen:S})]})]})})});De.displayName="Controls";var nt=ot.memo(({onClick:i,isAudioMode:r,audioModeIcon:o,videoModeIcon:u,audioModeLabel:s,videoModeLabel:h})=>{let d=r?h??"Video":s??"Audio";return jsxRuntime.jsxs("button",{onClick:i,className:"rvp-audio-toggle-btn","aria-label":d,title:d,"aria-pressed":r,children:[r?u??jsxRuntime.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"})}):o??jsxRuntime.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"currentColor",children:jsxRuntime.jsx("path",{d:"M12 3a9 9 0 0 0-9 9v7c0 1.1.9 2 2 2h1a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H4v-1a8 8 0 0 1 16 0v1h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h1a3 3 0 0 0 3-3v-4c0-4.97-4.03-9-9-9z"})}),d]})});nt.displayName="AudioModeButton";var rt=ot.memo(({onClick:i})=>jsxRuntime.jsx("button",{onClick:i,style:{background:"none",border:"1px solid rgba(255,255,255,0.6)",color:"#fff",borderRadius:3,padding:"2px 8px",fontSize:11,fontWeight:700,cursor:"pointer",letterSpacing:"0.06em"},title:"Go to live (L)",children:"GO LIVE"}));rt.displayName="GoLiveButton";var _e=ot.memo(({x:i,y:r,isPlaying:o,src:u,videoRef:s,playerRef:h,onClose:d,contextMenuItems:a})=>{let L=ot.useRef(null),[l,T]=ot.useState(()=>s.current?.loop??false),S=Math.min(i,window.innerWidth-220),F=Math.min(r,window.innerHeight-290);ot.useEffect(()=>{let b=D=>{L.current&&!L.current.contains(D.target)&&d();},B=D=>{D.key==="Escape"&&d();},I=()=>d();return document.addEventListener("mousedown",b),document.addEventListener("keydown",B),window.addEventListener("scroll",I,true),()=>{document.removeEventListener("mousedown",b),document.removeEventListener("keydown",B),window.removeEventListener("scroll",I,true);}},[d]);let C=ot.useCallback(()=>{o?h.pause():h.play(),d();},[o,h,d]),p=ot.useCallback(()=>{let b=s.current;if(!b)return;let B=!l;b.loop=B,T(B);},[s,l]),x=ot.useCallback(async()=>{try{await navigator.clipboard.writeText(u);}catch{}d();},[u,d]),P=ot.useCallback(async()=>{let b=Math.floor(s.current?.currentTime??0);try{await navigator.clipboard.writeText(`${u}?t=${b}`);}catch{}d();},[u,s,d]),A=ot.useCallback(()=>{h.togglePictureInPicture(),d();},[h,d]);return jsxRuntime.jsxs("div",{ref:L,className:"contextMenu",style:{left:S,top:F},children:[jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:C,children:o?"Pause":"Play"}),jsxRuntime.jsxs("button",{className:"contextMenuItem",onClick:p,children:[jsxRuntime.jsx("span",{children:"Loop"}),l&&jsxRuntime.jsx("span",{className:"contextMenuCheck",children:"\u2713"})]}),jsxRuntime.jsx("div",{className:"contextMenuDivider"}),jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:x,children:"Copy video URL"}),jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:P,children:"Copy video URL at current time"}),jsxRuntime.jsx("div",{className:"contextMenuDivider"}),jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:A,children:"Picture-in-Picture"}),a&&a.length>0&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{className:"contextMenuDivider"}),a.map((b,B)=>jsxRuntime.jsx("button",{className:"contextMenuItem",onClick:()=>{b.onClick(),d();},children:b.label},B))]})]})});_e.displayName="ContextMenu";var ze=ot.memo(function({poster:r,logo:o,audioModeFallback:u,isBuffering:s=false,onOverlayClick:h}){return jsxRuntime.jsxs("div",{className:"rvp-audio-overlay",onClick:h,"data-test":"audio-mode-overlay",children:[r?jsxRuntime.jsx("div",{className:"rvp-audio-artwork-container",children:jsxRuntime.jsx("img",{src:r,alt:"Artwork",className:"rvp-audio-artwork",draggable:false})}):u?jsxRuntime.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center"},children:u}):o?typeof o=="string"?jsxRuntime.jsx("img",{src:o,alt:"Logo",className:"rvp-audio-logo",draggable:false}):jsxRuntime.jsx("div",{className:"rvp-audio-logo-node",children:o}):null,jsxRuntime.jsx("span",{className:"rvp-audio-label",children:"Audio Mode"}),s?jsxRuntime.jsx("div",{className:"rvp-audio-buffering-overlay","aria-label":"Buffering",children:jsxRuntime.jsx("div",{className:"rvp-audio-spinner"})}):null]})});ze.displayName="AudioModeOverlay";var at=ot.forwardRef((i,r)=>{let{src:o,poster:u,className:s,controls:h=true,options:d={}}=i,{autoplay:a=false,muted:L=false,loop:l=false,preload:T="metadata",playbackRates:S=[.25,.5,.75,1,1.25,1.5,1.75,2],enableHLS:F=true,enablePreview:C=true,thumbnailVtt:p,hlsConfig:x,autoHideControls:P=true,subtitles:A,crossOrigin:b,logo:B,audioModeFallback:I,audioSrc:D,showAudioButton:te,audioModeIcon:J,videoModeIcon:j,audioModeLabel:R,videoModeLabel:G,defaultAudioMode:W,audioBandwidthThreshold:Z,audioModeSwitchLevel:ne,audioModeRecoveryInterval:re,onPlay:oe,onPause:ie,onEnded:ue,onError:e,onTimeUpdate:t,onDurationChange:n,onBuffering:m,onTheaterModeChange:y,onAudioModeChange:k,contextMenuItems:c,controlBarItems:f}=d,M=ot.useRef(null),w=ot.useRef(null),E=ot.useRef(null),{state:v,ref:N,fullscreenContainerRef:V}=$e(M,o,{autoplay:a,muted:L,loop:l,playbackRates:S,enableHLS:F,hlsConfig:x,defaultAudioMode:W,audioBandwidthThreshold:Z,audioModeSwitchLevel:ne,audioModeRecoveryInterval:re,onPlay:oe,onPause:ie,onEnded:ue,onError:e,onTimeUpdate:t,onDurationChange:n,onBuffering:m,onTheaterModeChange:y,onAudioModeChange:k,audioRef:w,audioSrc:D}),g=ot.useRef(null);ot__default.default.useLayoutEffect(()=>{g.current=v.isAudioMode&&D&&w.current?w.current:M.current;},[v.isAudioMode,D]),g.current===null&&(g.current=M.current);let[Q,le]=ot.useState(null);ot.useEffect(()=>{V.current=E.current;},[V]),ot__default.default.useImperativeHandle(r,()=>N,[N]);let Le=ot.useCallback(()=>{E.current?.focus(),v.isPlaying?N.pause():N.play();},[v.isPlaying,N]),st=ot.useCallback(()=>{N.toggleFullscreen();},[N]),ut=ot.useCallback(ee=>{ee.preventDefault(),le({x:ee.clientX,y:ee.clientY});},[]);return jsxRuntime.jsxs("div",{ref:E,tabIndex:0,style:{position:"relative",width:"100%",backgroundColor:"#000",aspectRatio:"16 / 9",userSelect:"none",outline:"none"},className:s,"data-test":"video-player-container","data-theater":v.isTheaterMode?"true":void 0,onContextMenu:ut,children:[jsxRuntime.jsx("video",{ref:M,poster:u,preload:T,crossOrigin:b,onClick:Le,onDoubleClick:st,playsInline:true,style:{width:"100%",height:"100%",display:"block",cursor:"pointer",visibility:v.isAudioMode?"hidden":"visible"},"data-test":"video-element",children:A?.map(ee=>jsxRuntime.jsx("track",{kind:"subtitles",src:ee.src,label:ee.label,srcLang:ee.srclang,default:ee.default},ee.id))}),D&&jsxRuntime.jsx("audio",{ref:w,preload:"none",style:{display:"none"},"aria-hidden":"true"}),v.isAudioMode&&jsxRuntime.jsx(ze,{poster:u,logo:B,audioModeFallback:I,isBuffering:v.isBuffering,onOverlayClick:Le}),h&&jsxRuntime.jsx(De,{videoRef:g,playerRef:N,playerContainerRef:E,playbackRates:S,enablePreview:C,thumbnailVtt:v.isAudioMode?void 0:p,isPlaying:v.isPlaying,volume:v.volume,isMuted:v.isMuted,playbackRate:v.playbackRate,isFullscreen:v.isFullscreen,isPictureInPicture:v.isPictureInPicture,isTheaterMode:v.isTheaterMode,isAudioMode:v.isAudioMode,showAudioButton:te??!!D,audioModeIcon:J,videoModeIcon:j,audioModeLabel:R,videoModeLabel:G,isLive:v.isLive,qualityLevels:v.qualityLevels,currentQualityLevel:v.currentQualityLevel,controlBarItems:f,autoHideControls:P}),Q&&jsxRuntime.jsx(_e,{x:Q.x,y:Q.y,isPlaying:v.isPlaying,src:o,videoRef:M,playerRef:N,onClose:()=>le(null),contextMenuItems:c}),v.isLive&&jsxRuntime.jsx("div",{style:{position:"absolute",top:12,left:12,backgroundColor:"#e53935",color:"#fff",fontSize:11,fontWeight:700,letterSpacing:"0.08em",padding:"2px 8px",borderRadius:3,pointerEvents:"none"},children:"LIVE"}),v.isBuffering&&!v.error&&!v.isAudioMode&&jsxRuntime.jsx("div",{style:{position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:12,color:"#fff",pointerEvents:"none"},"data-test":"buffering-indicator",children:jsxRuntime.jsx("div",{style:{width:48,height:48,border:"4px solid rgba(255,255,255,0.25)",borderTop:"4px solid #fff",borderRadius:"50%",animation:"rvp-spin 0.8s linear infinite"}})}),v.error&&jsxRuntime.jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"rgba(0,0,0,0.85)",color:"#fff",padding:24},"data-test":"error-overlay",children:jsxRuntime.jsxs("div",{style:{textAlign:"center",maxWidth:400},children:[jsxRuntime.jsx("div",{style:{fontSize:36,marginBottom:12},children:"\u26A0"}),jsxRuntime.jsx("h3",{style:{margin:"0 0 8px",fontSize:18},children:v.error.code==="MEDIA_ERR_SRC_NOT_SUPPORTED"?"Unsupported Format":v.error.code.startsWith("HLS")?"Stream Error":"Playback Error"}),jsxRuntime.jsx("p",{style:{margin:0,fontSize:13,opacity:.75},children:v.error.message})]})})]})});at.displayName="VideoPlayer";var _t=at;var zt={EXTREME:100,POOR:300,FAIR:800,GOOD:1500},Wt={LOWEST:0,SECOND_LOWEST:1,DISABLED:-1};exports.AUDIO_BANDWIDTH_THRESHOLDS=zt;exports.AUDIO_SWITCH_LEVELS=Wt;exports.ControlElements=Ze;exports.Controls=De;exports.VideoPlayer=_t;exports.findThumbnailCue=He;exports.formatTime=ce;exports.getMimeType=dt;exports.isHLSUrl=Pe;exports.parseThumbnailVtt=Ne;//# sourceMappingURL=index.js.map
|
|
4
4
|
//# sourceMappingURL=index.js.map
|