@scarlett-player/hls 1.11.0 → 1.13.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 +75 -1
- package/dist/{chunk-NVPSLRJY.js → chunk-3KFYKCR2.js} +361 -57
- package/dist/index.cjs +363 -57
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -1
- package/dist/light.cjs +363 -57
- package/dist/light.d.cts +2 -2
- package/dist/light.d.ts +2 -2
- package/dist/light.js +5 -1
- package/dist/live-metrics-CoYkWhl5.d.cts +388 -0
- package/dist/live-metrics-CoYkWhl5.d.ts +388 -0
- package/package.json +2 -2
- package/dist/types-DnvcTuSn.d.cts +0 -143
- package/dist/types-DnvcTuSn.d.ts +0 -143
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import { Plugin } from '@scarlett-player/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* HLS Plugin Types
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** HLS plugin configuration options */
|
|
8
|
+
interface HLSPluginConfig {
|
|
9
|
+
/** Enable debug logging */
|
|
10
|
+
debug?: boolean;
|
|
11
|
+
/** Auto start loading when source is set */
|
|
12
|
+
autoStartLoad?: boolean;
|
|
13
|
+
/** Start position in seconds (-1 for default) */
|
|
14
|
+
startPosition?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Enable low-latency HLS for live streams (default: false).
|
|
17
|
+
*
|
|
18
|
+
* Turning this on does more than set the hls.js flag: it also enables
|
|
19
|
+
* latency catch-up (`maxLiveSyncPlaybackRate`, which hls.js leaves at 1 and
|
|
20
|
+
* therefore disabled). Without it, LL-HLS parses and loads parts but latency
|
|
21
|
+
* settles wherever the buffer lands and is never pulled back. The retry
|
|
22
|
+
* budgets are deliberately left at their standard-live values; see
|
|
23
|
+
* `buildBaseHlsConfig()` for why widening them changes nothing a viewer
|
|
24
|
+
* could see.
|
|
25
|
+
*
|
|
26
|
+
* Opt-in, and it is a REQUEST: the manifest has to carry `EXT-X-PART` or
|
|
27
|
+
* advertise `CAN-BLOCK-RELOAD=YES` for low latency to actually happen. The
|
|
28
|
+
* `lowLatencyMode` state key and the `live:lowlatency` event report what the
|
|
29
|
+
* manifest supports, not what was requested here.
|
|
30
|
+
*/
|
|
31
|
+
lowLatencyMode?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Target latency for live streams in seconds, overriding the manifest's
|
|
34
|
+
* `PART-HOLD-BACK` / `HOLD-BACK`. Left unset, hls.js derives the target from
|
|
35
|
+
* the manifest, which is what a correctly packaged stream wants.
|
|
36
|
+
*/
|
|
37
|
+
liveSyncDuration?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Target latency expressed as a count of target durations (hls.js default:
|
|
40
|
+
* 3). Mutually exclusive with `liveSyncDuration`: hls.js THROWS on a config
|
|
41
|
+
* carrying both, so the plugin forwards one group only and logs which half
|
|
42
|
+
* it dropped.
|
|
43
|
+
*/
|
|
44
|
+
liveSyncDurationCount?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Maximum latency in seconds before the player seeks forward to catch up.
|
|
47
|
+
* Left unset, hls.js uses `liveMaxLatencyDurationCount`.
|
|
48
|
+
*/
|
|
49
|
+
liveMaxLatencyDuration?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Maximum latency as a count of target durations (hls.js default: Infinity,
|
|
52
|
+
* i.e. never force a catch-up seek).
|
|
53
|
+
*/
|
|
54
|
+
liveMaxLatencyDurationCount?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Playback rate ceiling used to catch up to the live edge (hls.js default:
|
|
57
|
+
* 1, which disables catch-up entirely).
|
|
58
|
+
*
|
|
59
|
+
* Defaults to 1.1 when `lowLatencyMode` is true and is left at hls.js's
|
|
60
|
+
* default otherwise, so standard live and VOD are unchanged. 1.1 recovers a
|
|
61
|
+
* second of drift in ten and the pitch shift is barely audible; 1.05 is
|
|
62
|
+
* safer and slower.
|
|
63
|
+
*/
|
|
64
|
+
maxLiveSyncPlaybackRate?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Report live streams with an Infinity duration rather than the length of
|
|
67
|
+
* the current sliding window (hls.js default: false).
|
|
68
|
+
*/
|
|
69
|
+
liveDurationInfinity?: boolean;
|
|
70
|
+
/** Max buffer length in seconds */
|
|
71
|
+
maxBufferLength?: number;
|
|
72
|
+
/** Max max buffer length in seconds */
|
|
73
|
+
maxMaxBufferLength?: number;
|
|
74
|
+
/** Back buffer length in seconds for DVR */
|
|
75
|
+
backBufferLength?: number;
|
|
76
|
+
/** Enable worker for hls.js (better performance) */
|
|
77
|
+
enableWorker?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Max network error retries before giving up (default: 3).
|
|
80
|
+
*
|
|
81
|
+
* Governs both playback branches: hls.js retries the load, and the native
|
|
82
|
+
* (Safari/iOS) path reloads the source and restores position.
|
|
83
|
+
*/
|
|
84
|
+
maxNetworkRetries?: number;
|
|
85
|
+
/**
|
|
86
|
+
* Max media error retries before giving up (default: 2).
|
|
87
|
+
*
|
|
88
|
+
* Governs both playback branches: hls.js calls recoverMediaError(), and the
|
|
89
|
+
* native (Safari/iOS) path reloads the source and restores position.
|
|
90
|
+
*/
|
|
91
|
+
maxMediaRetries?: number;
|
|
92
|
+
/** Cap quality to player element dimensions (default: true) */
|
|
93
|
+
capLevelToPlayerSize?: boolean;
|
|
94
|
+
/** Override initial bandwidth estimate in bits per second */
|
|
95
|
+
initialBandwidthEstimate?: number;
|
|
96
|
+
/** Base retry delay in milliseconds (default: 1000) */
|
|
97
|
+
retryDelayMs?: number;
|
|
98
|
+
/** Exponential backoff multiplier (default: 2) */
|
|
99
|
+
retryBackoffFactor?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Watchdog for source loading in milliseconds (default: 30000, 0 disables).
|
|
102
|
+
* If the manifest has not parsed within this window the load fails with an
|
|
103
|
+
* error instead of leaving the viewer on a spinner forever.
|
|
104
|
+
*/
|
|
105
|
+
loadTimeoutMs?: number;
|
|
106
|
+
/**
|
|
107
|
+
* Automatically attempt to reconnect after a fatal network/media error
|
|
108
|
+
* once the stream had been playing (default: true). Viewers should not
|
|
109
|
+
* have to press anything when a connection blip resolves itself.
|
|
110
|
+
*/
|
|
111
|
+
autoReconnect?: boolean;
|
|
112
|
+
/** First auto-reconnect delay in milliseconds (default: 2000) */
|
|
113
|
+
reconnectBaseDelayMs?: number;
|
|
114
|
+
/** Cap for the auto-reconnect backoff in milliseconds (default: 30000) */
|
|
115
|
+
reconnectMaxDelayMs?: number;
|
|
116
|
+
/** Total window to keep auto-reconnecting in milliseconds (default: 300000 = 5 min) */
|
|
117
|
+
reconnectWindowMs?: number;
|
|
118
|
+
/**
|
|
119
|
+
* Validate every playlist response before it reaches the M3U8 parser
|
|
120
|
+
* (default: true). A live refresh that returns an error page, a
|
|
121
|
+
* master-only response, or an empty document becomes a normal network
|
|
122
|
+
* error (bounded retries, then reconnect, then the retry UI) instead of
|
|
123
|
+
* being indexed blindly.
|
|
124
|
+
*/
|
|
125
|
+
validatePlaylists?: boolean;
|
|
126
|
+
/** Index signature for PluginConfig compatibility */
|
|
127
|
+
[key: string]: unknown;
|
|
128
|
+
}
|
|
129
|
+
/** Quality level information */
|
|
130
|
+
interface HLSQualityLevel {
|
|
131
|
+
/** Level index in hls.js */
|
|
132
|
+
index: number;
|
|
133
|
+
/** Video width */
|
|
134
|
+
width: number;
|
|
135
|
+
/** Video height */
|
|
136
|
+
height: number;
|
|
137
|
+
/** Bitrate in bits per second */
|
|
138
|
+
bitrate: number;
|
|
139
|
+
/** Human-readable label (e.g., "1080p") */
|
|
140
|
+
label: string;
|
|
141
|
+
/** Codec info */
|
|
142
|
+
codec?: string;
|
|
143
|
+
}
|
|
144
|
+
/** HLS error types */
|
|
145
|
+
type HLSErrorType = 'network' | 'media' | 'mux' | 'other';
|
|
146
|
+
/** HLS error details */
|
|
147
|
+
interface HLSError {
|
|
148
|
+
type: HLSErrorType;
|
|
149
|
+
details: string;
|
|
150
|
+
fatal: boolean;
|
|
151
|
+
url?: string;
|
|
152
|
+
reason?: string;
|
|
153
|
+
response?: {
|
|
154
|
+
code: number;
|
|
155
|
+
text: string;
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/** Live stream info */
|
|
159
|
+
interface HLSLiveInfo {
|
|
160
|
+
/** Whether stream is live */
|
|
161
|
+
isLive: boolean;
|
|
162
|
+
/** Edge latency in seconds */
|
|
163
|
+
latency: number;
|
|
164
|
+
/** Target latency for low latency mode */
|
|
165
|
+
targetLatency: number;
|
|
166
|
+
/** Drift from live edge */
|
|
167
|
+
drift: number;
|
|
168
|
+
/** Position to seek to for live sync (seconds from start), when known */
|
|
169
|
+
liveSyncPosition?: number;
|
|
170
|
+
/**
|
|
171
|
+
* Whether the stream is EFFECTIVELY low latency - the manifest carries
|
|
172
|
+
* `EXT-X-PART` or advertises `CAN-BLOCK-RELOAD=YES` - rather than whether
|
|
173
|
+
* `lowLatencyMode` was requested in the plugin config.
|
|
174
|
+
*/
|
|
175
|
+
lowLatency: boolean;
|
|
176
|
+
}
|
|
177
|
+
/** HLS Plugin interface extending base Plugin */
|
|
178
|
+
interface IHLSPlugin extends Plugin<HLSPluginConfig> {
|
|
179
|
+
readonly id: 'hls-provider';
|
|
180
|
+
/** Check if this provider can play a source */
|
|
181
|
+
canPlay(src: string): boolean;
|
|
182
|
+
/** Load and play a source */
|
|
183
|
+
loadSource(src: string): Promise<void>;
|
|
184
|
+
/** Get current quality level index (-1 = auto) */
|
|
185
|
+
getCurrentLevel(): number;
|
|
186
|
+
/** Set quality level (-1 for auto) */
|
|
187
|
+
setLevel(index: number): void;
|
|
188
|
+
/** Get all available quality levels */
|
|
189
|
+
getLevels(): HLSQualityLevel[];
|
|
190
|
+
/** Get the raw hls.js instance (for advanced use) */
|
|
191
|
+
getHlsInstance(): unknown | null;
|
|
192
|
+
/** Check if using native HLS (Safari) */
|
|
193
|
+
isNativeHLS(): boolean;
|
|
194
|
+
/** Get live stream info */
|
|
195
|
+
getLiveInfo(): HLSLiveInfo | null;
|
|
196
|
+
/** Switch from hls.js to native HLS (for AirPlay) */
|
|
197
|
+
switchToNative(): Promise<void>;
|
|
198
|
+
/** Switch from native HLS back to hls.js */
|
|
199
|
+
switchToHlsJs(): Promise<void>;
|
|
200
|
+
}
|
|
201
|
+
/** Type guard for hls.js level */
|
|
202
|
+
interface HlsLevel {
|
|
203
|
+
width: number;
|
|
204
|
+
height: number;
|
|
205
|
+
bitrate: number;
|
|
206
|
+
codecSet?: string;
|
|
207
|
+
name?: string;
|
|
208
|
+
}
|
|
209
|
+
/** Minimal hls.js interface for type safety */
|
|
210
|
+
interface HlsInstance {
|
|
211
|
+
loadSource(src: string): void;
|
|
212
|
+
attachMedia(media: HTMLMediaElement): void;
|
|
213
|
+
detachMedia(): void;
|
|
214
|
+
startLoad(startPosition?: number): void;
|
|
215
|
+
stopLoad(): void;
|
|
216
|
+
recoverMediaError(): void;
|
|
217
|
+
destroy(): void;
|
|
218
|
+
on(event: string, handler: (...args: any[]) => void): void;
|
|
219
|
+
off(event: string, handler: (...args: any[]) => void): void;
|
|
220
|
+
levels: HlsLevel[];
|
|
221
|
+
currentLevel: number;
|
|
222
|
+
autoLevelEnabled: boolean;
|
|
223
|
+
nextLevel: number;
|
|
224
|
+
loadLevel: number;
|
|
225
|
+
latency?: number;
|
|
226
|
+
targetLatency?: number;
|
|
227
|
+
drift?: number;
|
|
228
|
+
liveSyncPosition?: number;
|
|
229
|
+
bandwidthEstimate?: number;
|
|
230
|
+
media: HTMLMediaElement | null;
|
|
231
|
+
/** Alternate audio renditions declared by the manifest. */
|
|
232
|
+
audioTracks: HlsAudioTrack[];
|
|
233
|
+
/** Index into {@link audioTracks} of the rendition currently playing. */
|
|
234
|
+
audioTrack: number;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* One alternate audio rendition, as hls.js reports it.
|
|
238
|
+
*
|
|
239
|
+
* Only the fields this plugin reads; hls.js attaches several more.
|
|
240
|
+
*/
|
|
241
|
+
interface HlsAudioTrack {
|
|
242
|
+
/** hls.js's own numeric id for the track. */
|
|
243
|
+
id?: number;
|
|
244
|
+
/** Human-readable NAME from the manifest, e.g. "Director Commentary". */
|
|
245
|
+
name?: string;
|
|
246
|
+
/** BCP 47 language tag from the manifest, when it declares one. */
|
|
247
|
+
lang?: string;
|
|
248
|
+
/** Whether the manifest marked this the default rendition. */
|
|
249
|
+
default?: boolean;
|
|
250
|
+
/** Rendition group the track belongs to. */
|
|
251
|
+
groupId?: string;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Live metrics: the single writer for the player's live/DVR state.
|
|
256
|
+
*
|
|
257
|
+
* Before this module, `liveLatency`, `liveEdge` and `seekableRange` had two
|
|
258
|
+
* writers with different definitions of "latency": `hlsLevelLoaded` computed
|
|
259
|
+
* an edge flag from the level details, and the `timeupdate` handler then
|
|
260
|
+
* recomputed it unconditionally from `video.seekable` as `latency < 10`. Under
|
|
261
|
+
* MSE the second source is wrong (`video.seekable.start(0)` stays 0 instead of
|
|
262
|
+
* following the sliding window), and at a 2-4s low-latency target `< 10s` is
|
|
263
|
+
* always true, so "GO LIVE" could never appear no matter how far a viewer
|
|
264
|
+
* drifted. Every write of those keys now goes through {@link applyLiveMetrics},
|
|
265
|
+
* so there is exactly one definition and no clobber.
|
|
266
|
+
*
|
|
267
|
+
* Latency truth differs by playback path:
|
|
268
|
+
*
|
|
269
|
+
* - **hls.js (MSE):** `hls.latency` is real wall-clock latency, computed from
|
|
270
|
+
* `EXT-X-PROGRAM-DATE-TIME` drift where the manifest carries it, measured
|
|
271
|
+
* against `hls.targetLatency` (which hls.js derives from `PART-HOLD-BACK` /
|
|
272
|
+
* `HOLD-BACK`, or from `liveSyncDuration`* config when set).
|
|
273
|
+
* - **native (Safari/iOS):** there is no latency API. `video.seekable.end` is
|
|
274
|
+
* the best available stand-in for the edge, so latency is the distance to it
|
|
275
|
+
* — a buffer distance, not a measured latency. Treated as an approximation
|
|
276
|
+
* throughout, and the edge threshold is deliberately loose unless a target
|
|
277
|
+
* latency is known from a previous hls.js session on the same source.
|
|
278
|
+
*/
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* The level-details fields the live path reads, as hls.js reports them on
|
|
282
|
+
* `hlsLevelLoaded`.
|
|
283
|
+
*
|
|
284
|
+
* The LL-HLS members are the ones that decide whether a stream is *effectively*
|
|
285
|
+
* low latency: a host can set `lowLatencyMode: true` against a plain live
|
|
286
|
+
* manifest, and that must not produce an LL badge.
|
|
287
|
+
*/
|
|
288
|
+
interface HlsLevelDetails {
|
|
289
|
+
/** Whether the playlist is live (no EXT-X-ENDLIST) */
|
|
290
|
+
live?: boolean;
|
|
291
|
+
/** Total duration of the fragments in the playlist window, in seconds */
|
|
292
|
+
totalduration?: number;
|
|
293
|
+
/** EXT-X-TARGETDURATION, in seconds */
|
|
294
|
+
targetduration?: number;
|
|
295
|
+
/** Start of the sliding window, in seconds on the player timeline */
|
|
296
|
+
fragmentStart?: number;
|
|
297
|
+
/** End of the sliding window (live edge), in seconds on the player timeline */
|
|
298
|
+
edge?: number;
|
|
299
|
+
/** Fragments in the current playlist window */
|
|
300
|
+
fragments?: Array<{
|
|
301
|
+
start?: number;
|
|
302
|
+
}>;
|
|
303
|
+
/** LL-HLS: partial segments in the current window (EXT-X-PART) */
|
|
304
|
+
partList?: unknown[] | null;
|
|
305
|
+
/** LL-HLS: EXT-X-PART-INF PART-TARGET, in seconds */
|
|
306
|
+
partTarget?: number;
|
|
307
|
+
/** LL-HLS: EXT-X-SERVER-CONTROL CAN-BLOCK-RELOAD=YES */
|
|
308
|
+
canBlockReload?: boolean;
|
|
309
|
+
/** LL-HLS: EXT-X-SERVER-CONTROL PART-HOLD-BACK, in seconds */
|
|
310
|
+
partHoldBack?: number;
|
|
311
|
+
/** EXT-X-SERVER-CONTROL HOLD-BACK, in seconds */
|
|
312
|
+
holdBack?: number;
|
|
313
|
+
}
|
|
314
|
+
/** A snapshot of the live state of the stream, from one source of truth. */
|
|
315
|
+
interface LiveMetrics {
|
|
316
|
+
/** Latency behind the live edge, in seconds */
|
|
317
|
+
latency: number;
|
|
318
|
+
/** Latency the stream is aiming for, in seconds */
|
|
319
|
+
targetLatency: number;
|
|
320
|
+
/** Whether the viewer counts as being AT the live edge (see below) */
|
|
321
|
+
atEdge: boolean;
|
|
322
|
+
/** DVR window on the player timeline, when it is known */
|
|
323
|
+
seekableRange: {
|
|
324
|
+
start: number;
|
|
325
|
+
end: number;
|
|
326
|
+
} | null;
|
|
327
|
+
/**
|
|
328
|
+
* Whether low latency is EFFECTIVE: the manifest carries `EXT-X-PART` or
|
|
329
|
+
* advertises `CAN-BLOCK-RELOAD=YES`, AND low latency was requested in the
|
|
330
|
+
* plugin config. Both halves matter. A host that sets `lowLatencyMode`
|
|
331
|
+
* against a plain live manifest gets no LL badge because the stream cannot
|
|
332
|
+
* deliver it; a host that leaves the flag off gets none against an LL
|
|
333
|
+
* manifest either, because hls.js will not load the parts.
|
|
334
|
+
*/
|
|
335
|
+
lowLatency: boolean;
|
|
336
|
+
}
|
|
337
|
+
/** Where a {@link LiveMetrics} snapshot is measured from. */
|
|
338
|
+
type LiveMetricsSource = {
|
|
339
|
+
/** hls.js (MSE) path: latency comes from hls.js itself */
|
|
340
|
+
kind: 'hls';
|
|
341
|
+
/** The live hls.js instance */
|
|
342
|
+
hls: HlsInstance;
|
|
343
|
+
/** Most recent level details, when one has been seen */
|
|
344
|
+
details?: HlsLevelDetails | null;
|
|
345
|
+
/**
|
|
346
|
+
* Whether low latency was requested in the plugin config. Defaults to
|
|
347
|
+
* true when omitted, so a caller that only has a manifest still gets the
|
|
348
|
+
* manifest's answer.
|
|
349
|
+
*/
|
|
350
|
+
lowLatencyRequested?: boolean;
|
|
351
|
+
} | {
|
|
352
|
+
/** Native path (Safari/iOS): latency is approximated from `seekable` */
|
|
353
|
+
kind: 'media';
|
|
354
|
+
/** The media element playing the live stream */
|
|
355
|
+
media: HTMLMediaElement;
|
|
356
|
+
/**
|
|
357
|
+
* Target latency carried over from an hls.js session on the same source
|
|
358
|
+
* (an AirPlay handoff). Absent on a stream that has only ever played
|
|
359
|
+
* natively, where nothing reveals the manifest's hold-back.
|
|
360
|
+
*/
|
|
361
|
+
targetLatency?: number;
|
|
362
|
+
/**
|
|
363
|
+
* Whether to report the stream as effectively low latency. The HLS
|
|
364
|
+
* plugin never sets it on this path: native playback is a handoff, and
|
|
365
|
+
* nothing is loading parts any more.
|
|
366
|
+
*/
|
|
367
|
+
lowLatency?: boolean;
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* Target latency assumed when nothing better is known. Matches hls.js's own
|
|
371
|
+
* fallback and the value `getLiveInfo()` reported before LL-HLS.
|
|
372
|
+
*/
|
|
373
|
+
declare const DEFAULT_TARGET_LATENCY = 3;
|
|
374
|
+
/**
|
|
375
|
+
* Measure the live state of the stream from one source.
|
|
376
|
+
*
|
|
377
|
+
* Call it only for live content: for VOD the numbers are meaningless and the
|
|
378
|
+
* caller should not be writing live state at all.
|
|
379
|
+
*
|
|
380
|
+
* A viewer is AT the edge when `latency <= targetLatency + tolerance`, with the
|
|
381
|
+
* tolerance from {@link edgeTolerance}.
|
|
382
|
+
*
|
|
383
|
+
* @param source - hls.js instance (with its latest level details) or media element
|
|
384
|
+
* @returns The snapshot, or null when the source reveals nothing usable
|
|
385
|
+
*/
|
|
386
|
+
declare function computeLiveMetrics(source: LiveMetricsSource): LiveMetrics | null;
|
|
387
|
+
|
|
388
|
+
export { DEFAULT_TARGET_LATENCY as D, type HLSPluginConfig as H, type IHLSPlugin as I, type LiveMetrics as L, type HLSQualityLevel as a, type HLSError as b, type HLSLiveInfo as c, computeLiveMetrics as d, type LiveMetricsSource as e, type HlsLevelDetails as f };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scarlett-player/hls",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "HLS Provider Plugin for Scarlett Player",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"vitest": "^1.6.0",
|
|
38
38
|
"@vitest/coverage-v8": "^1.6.0",
|
|
39
39
|
"jsdom": "^24.0.0",
|
|
40
|
-
"@scarlett-player/core": "1.
|
|
40
|
+
"@scarlett-player/core": "1.13.0"
|
|
41
41
|
},
|
|
42
42
|
"keywords": [
|
|
43
43
|
"video",
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { Plugin } from '@scarlett-player/core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* HLS Plugin Types
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** HLS plugin configuration options */
|
|
8
|
-
interface HLSPluginConfig {
|
|
9
|
-
/** Enable debug logging */
|
|
10
|
-
debug?: boolean;
|
|
11
|
-
/** Auto start loading when source is set */
|
|
12
|
-
autoStartLoad?: boolean;
|
|
13
|
-
/** Start position in seconds (-1 for default) */
|
|
14
|
-
startPosition?: number;
|
|
15
|
-
/** Enable low latency mode for live streams */
|
|
16
|
-
lowLatencyMode?: boolean;
|
|
17
|
-
/** Max buffer length in seconds */
|
|
18
|
-
maxBufferLength?: number;
|
|
19
|
-
/** Max max buffer length in seconds */
|
|
20
|
-
maxMaxBufferLength?: number;
|
|
21
|
-
/** Back buffer length in seconds for DVR */
|
|
22
|
-
backBufferLength?: number;
|
|
23
|
-
/** Enable worker for hls.js (better performance) */
|
|
24
|
-
enableWorker?: boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Max network error retries before giving up (default: 3).
|
|
27
|
-
*
|
|
28
|
-
* Governs both playback branches: hls.js retries the load, and the native
|
|
29
|
-
* (Safari/iOS) path reloads the source and restores position.
|
|
30
|
-
*/
|
|
31
|
-
maxNetworkRetries?: number;
|
|
32
|
-
/**
|
|
33
|
-
* Max media error retries before giving up (default: 2).
|
|
34
|
-
*
|
|
35
|
-
* Governs both playback branches: hls.js calls recoverMediaError(), and the
|
|
36
|
-
* native (Safari/iOS) path reloads the source and restores position.
|
|
37
|
-
*/
|
|
38
|
-
maxMediaRetries?: number;
|
|
39
|
-
/** Cap quality to player element dimensions (default: true) */
|
|
40
|
-
capLevelToPlayerSize?: boolean;
|
|
41
|
-
/** Override initial bandwidth estimate in bits per second */
|
|
42
|
-
initialBandwidthEstimate?: number;
|
|
43
|
-
/** Base retry delay in milliseconds (default: 1000) */
|
|
44
|
-
retryDelayMs?: number;
|
|
45
|
-
/** Exponential backoff multiplier (default: 2) */
|
|
46
|
-
retryBackoffFactor?: number;
|
|
47
|
-
/**
|
|
48
|
-
* Watchdog for source loading in milliseconds (default: 30000, 0 disables).
|
|
49
|
-
* If the manifest has not parsed within this window the load fails with an
|
|
50
|
-
* error instead of leaving the viewer on a spinner forever.
|
|
51
|
-
*/
|
|
52
|
-
loadTimeoutMs?: number;
|
|
53
|
-
/**
|
|
54
|
-
* Automatically attempt to reconnect after a fatal network/media error
|
|
55
|
-
* once the stream had been playing (default: true). Viewers should not
|
|
56
|
-
* have to press anything when a connection blip resolves itself.
|
|
57
|
-
*/
|
|
58
|
-
autoReconnect?: boolean;
|
|
59
|
-
/** First auto-reconnect delay in milliseconds (default: 2000) */
|
|
60
|
-
reconnectBaseDelayMs?: number;
|
|
61
|
-
/** Cap for the auto-reconnect backoff in milliseconds (default: 30000) */
|
|
62
|
-
reconnectMaxDelayMs?: number;
|
|
63
|
-
/** Total window to keep auto-reconnecting in milliseconds (default: 300000 = 5 min) */
|
|
64
|
-
reconnectWindowMs?: number;
|
|
65
|
-
/**
|
|
66
|
-
* Validate every playlist response before it reaches the M3U8 parser
|
|
67
|
-
* (default: true). A live refresh that returns an error page, a
|
|
68
|
-
* master-only response, or an empty document becomes a normal network
|
|
69
|
-
* error (bounded retries, then reconnect, then the retry UI) instead of
|
|
70
|
-
* being indexed blindly.
|
|
71
|
-
*/
|
|
72
|
-
validatePlaylists?: boolean;
|
|
73
|
-
/** Index signature for PluginConfig compatibility */
|
|
74
|
-
[key: string]: unknown;
|
|
75
|
-
}
|
|
76
|
-
/** Quality level information */
|
|
77
|
-
interface HLSQualityLevel {
|
|
78
|
-
/** Level index in hls.js */
|
|
79
|
-
index: number;
|
|
80
|
-
/** Video width */
|
|
81
|
-
width: number;
|
|
82
|
-
/** Video height */
|
|
83
|
-
height: number;
|
|
84
|
-
/** Bitrate in bits per second */
|
|
85
|
-
bitrate: number;
|
|
86
|
-
/** Human-readable label (e.g., "1080p") */
|
|
87
|
-
label: string;
|
|
88
|
-
/** Codec info */
|
|
89
|
-
codec?: string;
|
|
90
|
-
}
|
|
91
|
-
/** HLS error types */
|
|
92
|
-
type HLSErrorType = 'network' | 'media' | 'mux' | 'other';
|
|
93
|
-
/** HLS error details */
|
|
94
|
-
interface HLSError {
|
|
95
|
-
type: HLSErrorType;
|
|
96
|
-
details: string;
|
|
97
|
-
fatal: boolean;
|
|
98
|
-
url?: string;
|
|
99
|
-
reason?: string;
|
|
100
|
-
response?: {
|
|
101
|
-
code: number;
|
|
102
|
-
text: string;
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/** Live stream info */
|
|
106
|
-
interface HLSLiveInfo {
|
|
107
|
-
/** Whether stream is live */
|
|
108
|
-
isLive: boolean;
|
|
109
|
-
/** Edge latency in seconds */
|
|
110
|
-
latency: number;
|
|
111
|
-
/** Target latency for low latency mode */
|
|
112
|
-
targetLatency: number;
|
|
113
|
-
/** Drift from live edge */
|
|
114
|
-
drift: number;
|
|
115
|
-
/** Position to seek to for live sync (seconds from start), when known */
|
|
116
|
-
liveSyncPosition?: number;
|
|
117
|
-
}
|
|
118
|
-
/** HLS Plugin interface extending base Plugin */
|
|
119
|
-
interface IHLSPlugin extends Plugin<HLSPluginConfig> {
|
|
120
|
-
readonly id: 'hls-provider';
|
|
121
|
-
/** Check if this provider can play a source */
|
|
122
|
-
canPlay(src: string): boolean;
|
|
123
|
-
/** Load and play a source */
|
|
124
|
-
loadSource(src: string): Promise<void>;
|
|
125
|
-
/** Get current quality level index (-1 = auto) */
|
|
126
|
-
getCurrentLevel(): number;
|
|
127
|
-
/** Set quality level (-1 for auto) */
|
|
128
|
-
setLevel(index: number): void;
|
|
129
|
-
/** Get all available quality levels */
|
|
130
|
-
getLevels(): HLSQualityLevel[];
|
|
131
|
-
/** Get the raw hls.js instance (for advanced use) */
|
|
132
|
-
getHlsInstance(): unknown | null;
|
|
133
|
-
/** Check if using native HLS (Safari) */
|
|
134
|
-
isNativeHLS(): boolean;
|
|
135
|
-
/** Get live stream info */
|
|
136
|
-
getLiveInfo(): HLSLiveInfo | null;
|
|
137
|
-
/** Switch from hls.js to native HLS (for AirPlay) */
|
|
138
|
-
switchToNative(): Promise<void>;
|
|
139
|
-
/** Switch from native HLS back to hls.js */
|
|
140
|
-
switchToHlsJs(): Promise<void>;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export type { HLSPluginConfig as H, IHLSPlugin as I, HLSQualityLevel as a, HLSError as b, HLSLiveInfo as c };
|
package/dist/types-DnvcTuSn.d.ts
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { Plugin } from '@scarlett-player/core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* HLS Plugin Types
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** HLS plugin configuration options */
|
|
8
|
-
interface HLSPluginConfig {
|
|
9
|
-
/** Enable debug logging */
|
|
10
|
-
debug?: boolean;
|
|
11
|
-
/** Auto start loading when source is set */
|
|
12
|
-
autoStartLoad?: boolean;
|
|
13
|
-
/** Start position in seconds (-1 for default) */
|
|
14
|
-
startPosition?: number;
|
|
15
|
-
/** Enable low latency mode for live streams */
|
|
16
|
-
lowLatencyMode?: boolean;
|
|
17
|
-
/** Max buffer length in seconds */
|
|
18
|
-
maxBufferLength?: number;
|
|
19
|
-
/** Max max buffer length in seconds */
|
|
20
|
-
maxMaxBufferLength?: number;
|
|
21
|
-
/** Back buffer length in seconds for DVR */
|
|
22
|
-
backBufferLength?: number;
|
|
23
|
-
/** Enable worker for hls.js (better performance) */
|
|
24
|
-
enableWorker?: boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Max network error retries before giving up (default: 3).
|
|
27
|
-
*
|
|
28
|
-
* Governs both playback branches: hls.js retries the load, and the native
|
|
29
|
-
* (Safari/iOS) path reloads the source and restores position.
|
|
30
|
-
*/
|
|
31
|
-
maxNetworkRetries?: number;
|
|
32
|
-
/**
|
|
33
|
-
* Max media error retries before giving up (default: 2).
|
|
34
|
-
*
|
|
35
|
-
* Governs both playback branches: hls.js calls recoverMediaError(), and the
|
|
36
|
-
* native (Safari/iOS) path reloads the source and restores position.
|
|
37
|
-
*/
|
|
38
|
-
maxMediaRetries?: number;
|
|
39
|
-
/** Cap quality to player element dimensions (default: true) */
|
|
40
|
-
capLevelToPlayerSize?: boolean;
|
|
41
|
-
/** Override initial bandwidth estimate in bits per second */
|
|
42
|
-
initialBandwidthEstimate?: number;
|
|
43
|
-
/** Base retry delay in milliseconds (default: 1000) */
|
|
44
|
-
retryDelayMs?: number;
|
|
45
|
-
/** Exponential backoff multiplier (default: 2) */
|
|
46
|
-
retryBackoffFactor?: number;
|
|
47
|
-
/**
|
|
48
|
-
* Watchdog for source loading in milliseconds (default: 30000, 0 disables).
|
|
49
|
-
* If the manifest has not parsed within this window the load fails with an
|
|
50
|
-
* error instead of leaving the viewer on a spinner forever.
|
|
51
|
-
*/
|
|
52
|
-
loadTimeoutMs?: number;
|
|
53
|
-
/**
|
|
54
|
-
* Automatically attempt to reconnect after a fatal network/media error
|
|
55
|
-
* once the stream had been playing (default: true). Viewers should not
|
|
56
|
-
* have to press anything when a connection blip resolves itself.
|
|
57
|
-
*/
|
|
58
|
-
autoReconnect?: boolean;
|
|
59
|
-
/** First auto-reconnect delay in milliseconds (default: 2000) */
|
|
60
|
-
reconnectBaseDelayMs?: number;
|
|
61
|
-
/** Cap for the auto-reconnect backoff in milliseconds (default: 30000) */
|
|
62
|
-
reconnectMaxDelayMs?: number;
|
|
63
|
-
/** Total window to keep auto-reconnecting in milliseconds (default: 300000 = 5 min) */
|
|
64
|
-
reconnectWindowMs?: number;
|
|
65
|
-
/**
|
|
66
|
-
* Validate every playlist response before it reaches the M3U8 parser
|
|
67
|
-
* (default: true). A live refresh that returns an error page, a
|
|
68
|
-
* master-only response, or an empty document becomes a normal network
|
|
69
|
-
* error (bounded retries, then reconnect, then the retry UI) instead of
|
|
70
|
-
* being indexed blindly.
|
|
71
|
-
*/
|
|
72
|
-
validatePlaylists?: boolean;
|
|
73
|
-
/** Index signature for PluginConfig compatibility */
|
|
74
|
-
[key: string]: unknown;
|
|
75
|
-
}
|
|
76
|
-
/** Quality level information */
|
|
77
|
-
interface HLSQualityLevel {
|
|
78
|
-
/** Level index in hls.js */
|
|
79
|
-
index: number;
|
|
80
|
-
/** Video width */
|
|
81
|
-
width: number;
|
|
82
|
-
/** Video height */
|
|
83
|
-
height: number;
|
|
84
|
-
/** Bitrate in bits per second */
|
|
85
|
-
bitrate: number;
|
|
86
|
-
/** Human-readable label (e.g., "1080p") */
|
|
87
|
-
label: string;
|
|
88
|
-
/** Codec info */
|
|
89
|
-
codec?: string;
|
|
90
|
-
}
|
|
91
|
-
/** HLS error types */
|
|
92
|
-
type HLSErrorType = 'network' | 'media' | 'mux' | 'other';
|
|
93
|
-
/** HLS error details */
|
|
94
|
-
interface HLSError {
|
|
95
|
-
type: HLSErrorType;
|
|
96
|
-
details: string;
|
|
97
|
-
fatal: boolean;
|
|
98
|
-
url?: string;
|
|
99
|
-
reason?: string;
|
|
100
|
-
response?: {
|
|
101
|
-
code: number;
|
|
102
|
-
text: string;
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/** Live stream info */
|
|
106
|
-
interface HLSLiveInfo {
|
|
107
|
-
/** Whether stream is live */
|
|
108
|
-
isLive: boolean;
|
|
109
|
-
/** Edge latency in seconds */
|
|
110
|
-
latency: number;
|
|
111
|
-
/** Target latency for low latency mode */
|
|
112
|
-
targetLatency: number;
|
|
113
|
-
/** Drift from live edge */
|
|
114
|
-
drift: number;
|
|
115
|
-
/** Position to seek to for live sync (seconds from start), when known */
|
|
116
|
-
liveSyncPosition?: number;
|
|
117
|
-
}
|
|
118
|
-
/** HLS Plugin interface extending base Plugin */
|
|
119
|
-
interface IHLSPlugin extends Plugin<HLSPluginConfig> {
|
|
120
|
-
readonly id: 'hls-provider';
|
|
121
|
-
/** Check if this provider can play a source */
|
|
122
|
-
canPlay(src: string): boolean;
|
|
123
|
-
/** Load and play a source */
|
|
124
|
-
loadSource(src: string): Promise<void>;
|
|
125
|
-
/** Get current quality level index (-1 = auto) */
|
|
126
|
-
getCurrentLevel(): number;
|
|
127
|
-
/** Set quality level (-1 for auto) */
|
|
128
|
-
setLevel(index: number): void;
|
|
129
|
-
/** Get all available quality levels */
|
|
130
|
-
getLevels(): HLSQualityLevel[];
|
|
131
|
-
/** Get the raw hls.js instance (for advanced use) */
|
|
132
|
-
getHlsInstance(): unknown | null;
|
|
133
|
-
/** Check if using native HLS (Safari) */
|
|
134
|
-
isNativeHLS(): boolean;
|
|
135
|
-
/** Get live stream info */
|
|
136
|
-
getLiveInfo(): HLSLiveInfo | null;
|
|
137
|
-
/** Switch from hls.js to native HLS (for AirPlay) */
|
|
138
|
-
switchToNative(): Promise<void>;
|
|
139
|
-
/** Switch from native HLS back to hls.js */
|
|
140
|
-
switchToHlsJs(): Promise<void>;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export type { HLSPluginConfig as H, IHLSPlugin as I, HLSQualityLevel as a, HLSError as b, HLSLiveInfo as c };
|