@codenkay/video-nsgplayer-core 0.1.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/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +42 -0
- package/dist/index.cjs +1288 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +547 -0
- package/dist/index.d.ts +547 -0
- package/dist/index.js +1227 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
/** Player lifecycle states. */
|
|
2
|
+
type PlayerState = "idle" | "loading" | "ready" | "playing" | "paused" | "buffering" | "renewing" | "ended" | "error" | "destroyed";
|
|
3
|
+
type HlsSupportMode = "hls.js" | "native" | "unsupported";
|
|
4
|
+
type QualitySelection = "auto" | number;
|
|
5
|
+
type PlaybackRate = 0.5 | 0.75 | 1 | 1.25 | 1.5 | 2;
|
|
6
|
+
type HlsQualityLevel = {
|
|
7
|
+
index: number;
|
|
8
|
+
height: number;
|
|
9
|
+
width: number;
|
|
10
|
+
bitrate: number;
|
|
11
|
+
label: string;
|
|
12
|
+
uri?: string;
|
|
13
|
+
};
|
|
14
|
+
type PlayIconPreset = "triangle" | "circle" | "roundedSquare";
|
|
15
|
+
type PlayerZoomLevel = 1 | 1.25 | 1.5 | 2;
|
|
16
|
+
type PlayerSkipSeconds = 5 | 10 | 15 | 30;
|
|
17
|
+
type AuthToken = {
|
|
18
|
+
accessToken: string;
|
|
19
|
+
expiresAt: number;
|
|
20
|
+
};
|
|
21
|
+
type AuthTokenProviderContext = {
|
|
22
|
+
reason: "initial" | "expired" | "expiring" | "unauthorized" | "manual";
|
|
23
|
+
videoId?: string;
|
|
24
|
+
};
|
|
25
|
+
type PlaybackSource = {
|
|
26
|
+
url: string;
|
|
27
|
+
expiresAt: number;
|
|
28
|
+
authParams?: Record<string, string>;
|
|
29
|
+
token?: string;
|
|
30
|
+
/** When true, UI may show the LIVE badge and seek-to-live affordance. */
|
|
31
|
+
live?: boolean;
|
|
32
|
+
};
|
|
33
|
+
type PlaybackSourceContext = {
|
|
34
|
+
videoId: string;
|
|
35
|
+
reason: "initial" | "expired" | "expiring" | "auth_error" | "manual";
|
|
36
|
+
};
|
|
37
|
+
type AuthConfig = {
|
|
38
|
+
getToken: (context: AuthTokenProviderContext) => Promise<AuthToken>;
|
|
39
|
+
refreshBeforeExpiryMs?: number;
|
|
40
|
+
};
|
|
41
|
+
type PlaybackCredentialConfig = {
|
|
42
|
+
getSource: (context: PlaybackSourceContext) => Promise<PlaybackSource>;
|
|
43
|
+
refreshSource?: (context: PlaybackSourceContext) => Promise<PlaybackSource>;
|
|
44
|
+
refreshBeforeExpiryMs?: number;
|
|
45
|
+
renewMaxRetries?: number;
|
|
46
|
+
renewBackoffMs?: number;
|
|
47
|
+
authRecoveryCoalesceMs?: number;
|
|
48
|
+
};
|
|
49
|
+
type PlayerBehaviorConfig = {
|
|
50
|
+
autoplay?: boolean;
|
|
51
|
+
startMuted?: boolean;
|
|
52
|
+
volume?: number;
|
|
53
|
+
startPosition?: number;
|
|
54
|
+
skipSeconds?: PlayerSkipSeconds;
|
|
55
|
+
speedOptionCount?: number;
|
|
56
|
+
zoomEnabled?: boolean;
|
|
57
|
+
defaultZoom?: PlayerZoomLevel;
|
|
58
|
+
playbackRates?: readonly PlaybackRate[];
|
|
59
|
+
};
|
|
60
|
+
type ControlsConfig = {
|
|
61
|
+
enabled?: boolean;
|
|
62
|
+
showQuality?: boolean;
|
|
63
|
+
showSpeed?: boolean;
|
|
64
|
+
showCaptions?: boolean;
|
|
65
|
+
showAudio?: boolean;
|
|
66
|
+
showVolume?: boolean;
|
|
67
|
+
showFullscreen?: boolean;
|
|
68
|
+
showZoom?: boolean;
|
|
69
|
+
showSkip?: boolean;
|
|
70
|
+
/** Show LIVE badge after time text for live streams. */
|
|
71
|
+
showLive?: boolean;
|
|
72
|
+
seekCueDurationMs?: number;
|
|
73
|
+
keyboardShortcuts?: boolean;
|
|
74
|
+
};
|
|
75
|
+
type ThemeConfig = {
|
|
76
|
+
playIconPreset?: PlayIconPreset;
|
|
77
|
+
playButtonBackground?: string;
|
|
78
|
+
playButtonIconColor?: string;
|
|
79
|
+
seekTrackColor?: string;
|
|
80
|
+
seekProgressColor?: string;
|
|
81
|
+
seekBufferedColor?: string;
|
|
82
|
+
timeColor?: string;
|
|
83
|
+
controlIconColor?: string;
|
|
84
|
+
focusRingColor?: string;
|
|
85
|
+
spinnerColor?: string;
|
|
86
|
+
volumeIconColor?: string;
|
|
87
|
+
volumeTrackColor?: string;
|
|
88
|
+
volumeProgressColor?: string;
|
|
89
|
+
qualityOptionTextColor?: string;
|
|
90
|
+
qualityOptionBackground?: string;
|
|
91
|
+
qualityOptionActiveBackground?: string;
|
|
92
|
+
qualityOptionActiveTextColor?: string;
|
|
93
|
+
speedOptionTextColor?: string;
|
|
94
|
+
speedOptionBackground?: string;
|
|
95
|
+
speedOptionActiveBackground?: string;
|
|
96
|
+
speedOptionActiveTextColor?: string;
|
|
97
|
+
zoomIconColor?: string;
|
|
98
|
+
skipIconColor?: string;
|
|
99
|
+
skipCueBackground?: string;
|
|
100
|
+
skipCueTextColor?: string;
|
|
101
|
+
/** Filled LIVE indicator color (hollow ring when behind live). */
|
|
102
|
+
liveDotColor?: string;
|
|
103
|
+
};
|
|
104
|
+
type WatermarkConfig = {
|
|
105
|
+
enabled?: boolean;
|
|
106
|
+
text?: string;
|
|
107
|
+
durationMs?: number;
|
|
108
|
+
intervalMaxMs?: number;
|
|
109
|
+
};
|
|
110
|
+
type StreamingConfig = {
|
|
111
|
+
engine?: "hls";
|
|
112
|
+
hls?: {
|
|
113
|
+
enableWorker?: boolean;
|
|
114
|
+
lowLatencyMode?: boolean;
|
|
115
|
+
backBufferLength?: number;
|
|
116
|
+
fatalRecoveryLimit?: number;
|
|
117
|
+
};
|
|
118
|
+
keyProxyUrlBuilder?: (ctx: {
|
|
119
|
+
videoId: string;
|
|
120
|
+
keyUrl: string;
|
|
121
|
+
token?: string;
|
|
122
|
+
expires?: string;
|
|
123
|
+
}) => string;
|
|
124
|
+
};
|
|
125
|
+
type LoggingConfig = {
|
|
126
|
+
enabled?: boolean;
|
|
127
|
+
level?: "silent" | "error" | "warn" | "info" | "debug" | "trace";
|
|
128
|
+
};
|
|
129
|
+
type DebugConfig = {
|
|
130
|
+
enabled?: boolean;
|
|
131
|
+
network?: boolean;
|
|
132
|
+
events?: boolean;
|
|
133
|
+
state?: boolean;
|
|
134
|
+
};
|
|
135
|
+
type AnalyticsConfig = {
|
|
136
|
+
onEvent?: (event: {
|
|
137
|
+
type: string;
|
|
138
|
+
payload?: Record<string, unknown>;
|
|
139
|
+
}) => void;
|
|
140
|
+
};
|
|
141
|
+
type AccessibilityConfig = {
|
|
142
|
+
reducedMotion?: boolean;
|
|
143
|
+
};
|
|
144
|
+
type CreateVideoPlayerOptions = {
|
|
145
|
+
videoId?: string;
|
|
146
|
+
mount?: HTMLVideoElement;
|
|
147
|
+
auth?: AuthConfig;
|
|
148
|
+
playback?: PlaybackCredentialConfig;
|
|
149
|
+
/** Direct HLS URL without credential callbacks (no renewal). */
|
|
150
|
+
sourceUrl?: string;
|
|
151
|
+
player?: PlayerBehaviorConfig;
|
|
152
|
+
controls?: ControlsConfig;
|
|
153
|
+
theme?: ThemeConfig;
|
|
154
|
+
watermark?: WatermarkConfig;
|
|
155
|
+
streaming?: StreamingConfig;
|
|
156
|
+
logging?: LoggingConfig;
|
|
157
|
+
debug?: DebugConfig;
|
|
158
|
+
analytics?: AnalyticsConfig;
|
|
159
|
+
accessibility?: AccessibilityConfig;
|
|
160
|
+
};
|
|
161
|
+
type PlayerConfig = Required<{
|
|
162
|
+
player: Required<PlayerBehaviorConfig>;
|
|
163
|
+
controls: Required<ControlsConfig>;
|
|
164
|
+
theme: Required<ThemeConfig>;
|
|
165
|
+
watermark: Required<WatermarkConfig>;
|
|
166
|
+
streaming: {
|
|
167
|
+
engine: "hls";
|
|
168
|
+
hls: Required<NonNullable<StreamingConfig["hls"]>>;
|
|
169
|
+
};
|
|
170
|
+
logging: Required<LoggingConfig>;
|
|
171
|
+
debug: Required<DebugConfig>;
|
|
172
|
+
accessibility: Required<AccessibilityConfig>;
|
|
173
|
+
}>;
|
|
174
|
+
type PlayerDiagnostics = {
|
|
175
|
+
playerVersion: string;
|
|
176
|
+
currentState: PlayerState;
|
|
177
|
+
hlsSupport: HlsSupportMode;
|
|
178
|
+
videoId: string | null;
|
|
179
|
+
currentTime: number;
|
|
180
|
+
duration: number;
|
|
181
|
+
bufferedEnd: number;
|
|
182
|
+
currentQuality: string | null;
|
|
183
|
+
playbackSessionId: string | null;
|
|
184
|
+
authExpiryStatus: "unknown" | "valid" | "expiring_soon" | "expired";
|
|
185
|
+
sourceExpiryStatus: "unknown" | "valid" | "expiring_soon" | "expired";
|
|
186
|
+
lastError: string | null;
|
|
187
|
+
};
|
|
188
|
+
type BufferedRange = {
|
|
189
|
+
start: number;
|
|
190
|
+
end: number;
|
|
191
|
+
};
|
|
192
|
+
type PlayerEventMap = {
|
|
193
|
+
ready: void;
|
|
194
|
+
play: void;
|
|
195
|
+
pause: void;
|
|
196
|
+
playing: void;
|
|
197
|
+
timeupdate: {
|
|
198
|
+
currentTime: number;
|
|
199
|
+
duration: number;
|
|
200
|
+
};
|
|
201
|
+
buffering: void;
|
|
202
|
+
progress: {
|
|
203
|
+
bufferedEnd: number;
|
|
204
|
+
};
|
|
205
|
+
qualitychange: {
|
|
206
|
+
selection: QualitySelection;
|
|
207
|
+
label?: string;
|
|
208
|
+
};
|
|
209
|
+
volumechange: {
|
|
210
|
+
volume: number;
|
|
211
|
+
muted: boolean;
|
|
212
|
+
};
|
|
213
|
+
fullscreenchange: {
|
|
214
|
+
isFullscreen: boolean;
|
|
215
|
+
};
|
|
216
|
+
authrefresh: {
|
|
217
|
+
expiresAt: number;
|
|
218
|
+
};
|
|
219
|
+
tokenrefresh: {
|
|
220
|
+
expiresAt: number;
|
|
221
|
+
};
|
|
222
|
+
sourcechange: {
|
|
223
|
+
expiresAt: number;
|
|
224
|
+
};
|
|
225
|
+
autherror: {
|
|
226
|
+
message: string;
|
|
227
|
+
retryable: boolean;
|
|
228
|
+
};
|
|
229
|
+
ended: void;
|
|
230
|
+
error: {
|
|
231
|
+
code: string;
|
|
232
|
+
message: string;
|
|
233
|
+
fatal: boolean;
|
|
234
|
+
};
|
|
235
|
+
destroy: void;
|
|
236
|
+
statechange: {
|
|
237
|
+
state: PlayerState;
|
|
238
|
+
};
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
declare const PLAYBACK_RATES: readonly [0.5, 0.75, 1, 1.25, 1.5, 2];
|
|
242
|
+
declare const PACKAGE_VERSION = "0.1.0";
|
|
243
|
+
declare const DEFAULT_PLAYER_BEHAVIOR: Required<PlayerBehaviorConfig>;
|
|
244
|
+
declare const DEFAULT_CONTROLS: Required<ControlsConfig>;
|
|
245
|
+
declare const DEFAULT_THEME: Required<ThemeConfig>;
|
|
246
|
+
declare const DEFAULT_WATERMARK: Required<WatermarkConfig>;
|
|
247
|
+
declare const DEFAULT_PLAYER_CONFIG: PlayerConfig;
|
|
248
|
+
declare function assertNoSecretsInConfig(raw: unknown): void;
|
|
249
|
+
declare function mergePlayerConfig(partial?: Partial<{
|
|
250
|
+
player: Partial<PlayerBehaviorConfig>;
|
|
251
|
+
controls: Partial<ControlsConfig>;
|
|
252
|
+
theme: Partial<ThemeConfig>;
|
|
253
|
+
watermark: Partial<WatermarkConfig>;
|
|
254
|
+
streaming: {
|
|
255
|
+
engine?: "hls";
|
|
256
|
+
hls?: Partial<PlayerConfig["streaming"]["hls"]>;
|
|
257
|
+
keyProxyUrlBuilder?: unknown;
|
|
258
|
+
};
|
|
259
|
+
logging: Partial<PlayerConfig["logging"]>;
|
|
260
|
+
debug: Partial<PlayerConfig["debug"]>;
|
|
261
|
+
accessibility: Partial<PlayerConfig["accessibility"]>;
|
|
262
|
+
}>): PlayerConfig;
|
|
263
|
+
/** Maps theme colors to CSS custom properties for UI adapters. */
|
|
264
|
+
declare function themeToCssVars(theme: Required<ThemeConfig>): Record<string, string>;
|
|
265
|
+
|
|
266
|
+
type Handler<T> = T extends void ? () => void : (payload: T) => void;
|
|
267
|
+
declare class EventEmitter {
|
|
268
|
+
private listeners;
|
|
269
|
+
on<K extends keyof PlayerEventMap>(event: K, handler: Handler<PlayerEventMap[K]>): () => void;
|
|
270
|
+
off<K extends keyof PlayerEventMap>(event: K, handler: Handler<PlayerEventMap[K]>): void;
|
|
271
|
+
emit<K extends keyof PlayerEventMap>(event: K, ...args: PlayerEventMap[K] extends void ? [] : [PlayerEventMap[K]]): void;
|
|
272
|
+
removeAll(): void;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Live-edge helpers for HLS DVR / live streams.
|
|
277
|
+
* Uses HTMLMediaElement.seekable when available; falls back to duration.
|
|
278
|
+
*/
|
|
279
|
+
declare const DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS = 3;
|
|
280
|
+
type SeekableLike = {
|
|
281
|
+
length: number;
|
|
282
|
+
start: (index: number) => number;
|
|
283
|
+
end: (index: number) => number;
|
|
284
|
+
};
|
|
285
|
+
type LiveMediaSnapshot = {
|
|
286
|
+
currentTime: number;
|
|
287
|
+
duration: number;
|
|
288
|
+
seekable: SeekableLike;
|
|
289
|
+
};
|
|
290
|
+
/**
|
|
291
|
+
* Returns the latest seekable end (live edge), or null when unknown.
|
|
292
|
+
*/
|
|
293
|
+
declare function getLiveEdgeTime(media: Pick<LiveMediaSnapshot, "duration" | "seekable">): number | null;
|
|
294
|
+
/**
|
|
295
|
+
* True when playback is within `toleranceSeconds` of the live edge.
|
|
296
|
+
*/
|
|
297
|
+
declare function isAtLiveEdge(media: LiveMediaSnapshot, toleranceSeconds?: number): boolean;
|
|
298
|
+
type SeekToLiveResult = {
|
|
299
|
+
moved: true;
|
|
300
|
+
edge: number;
|
|
301
|
+
} | {
|
|
302
|
+
moved: false;
|
|
303
|
+
reason: "already_at_live" | "edge_unavailable";
|
|
304
|
+
edge: number | null;
|
|
305
|
+
};
|
|
306
|
+
type SeekableMediaElement = {
|
|
307
|
+
currentTime: number;
|
|
308
|
+
duration: number;
|
|
309
|
+
seekable: SeekableLike;
|
|
310
|
+
};
|
|
311
|
+
/**
|
|
312
|
+
* Seeks to the live edge. Returns whether the playhead moved.
|
|
313
|
+
*/
|
|
314
|
+
declare function seekToLiveEdge(media: SeekableMediaElement, options?: {
|
|
315
|
+
toleranceSeconds?: number;
|
|
316
|
+
/** Leave a tiny buffer behind the absolute end for decoder stability. */
|
|
317
|
+
edgeOffsetSeconds?: number;
|
|
318
|
+
}): SeekToLiveResult;
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Mutable store of the latest playback authorization query parameters.
|
|
322
|
+
* Updated on renewal without recreating the HLS player.
|
|
323
|
+
*/
|
|
324
|
+
declare class AuthParamsStore {
|
|
325
|
+
private params;
|
|
326
|
+
constructor(initial?: URLSearchParams | Record<string, string>);
|
|
327
|
+
getSnapshot(): URLSearchParams;
|
|
328
|
+
toRecord(): Record<string, string>;
|
|
329
|
+
update(next: URLSearchParams | Record<string, string>): void;
|
|
330
|
+
applyToUrl(rawUrl: string, baseOrigin?: string): string;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
declare class Logger {
|
|
334
|
+
private config;
|
|
335
|
+
constructor(config: Required<LoggingConfig>);
|
|
336
|
+
update(config: Partial<LoggingConfig>): void;
|
|
337
|
+
private shouldLog;
|
|
338
|
+
private write;
|
|
339
|
+
error(message: string, details?: Record<string, unknown>): void;
|
|
340
|
+
warn(message: string, details?: Record<string, unknown>): void;
|
|
341
|
+
info(message: string, details?: Record<string, unknown>): void;
|
|
342
|
+
debug(message: string, details?: Record<string, unknown>): void;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
type HlsEngineCallbacks = {
|
|
346
|
+
onStateChange?: (state: PlayerState) => void;
|
|
347
|
+
onSupportMode?: (mode: HlsSupportMode) => void;
|
|
348
|
+
onFatalError?: (message: string) => void;
|
|
349
|
+
onAuthRecoveryNeeded?: (reason: string) => void;
|
|
350
|
+
onQualitiesChange?: (levels: HlsQualityLevel[]) => void;
|
|
351
|
+
onQualitySelectionChange?: (selection: QualitySelection) => void;
|
|
352
|
+
onEnded?: () => void;
|
|
353
|
+
};
|
|
354
|
+
type HlsEngineOptions = {
|
|
355
|
+
videoEl: HTMLVideoElement;
|
|
356
|
+
playbackUrl: string;
|
|
357
|
+
authParams: AuthParamsStore;
|
|
358
|
+
autoplay: boolean;
|
|
359
|
+
startMuted: boolean;
|
|
360
|
+
startPosition?: number;
|
|
361
|
+
volume?: number;
|
|
362
|
+
hlsConfig: {
|
|
363
|
+
enableWorker: boolean;
|
|
364
|
+
lowLatencyMode: boolean;
|
|
365
|
+
backBufferLength: number;
|
|
366
|
+
fatalRecoveryLimit: number;
|
|
367
|
+
};
|
|
368
|
+
logger: Logger;
|
|
369
|
+
callbacks: HlsEngineCallbacks;
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* Dual-path HLS engine: hls.js when supported, otherwise native Safari HLS.
|
|
373
|
+
*/
|
|
374
|
+
declare class HlsEngine {
|
|
375
|
+
private readonly options;
|
|
376
|
+
private hls;
|
|
377
|
+
private destroyed;
|
|
378
|
+
private supportMode;
|
|
379
|
+
private networkRecoveryCount;
|
|
380
|
+
private mediaRecoveryCount;
|
|
381
|
+
private qualities;
|
|
382
|
+
private qualitySelection;
|
|
383
|
+
constructor(options: HlsEngineOptions);
|
|
384
|
+
start(): Promise<void>;
|
|
385
|
+
private startWithHlsJs;
|
|
386
|
+
private bindMediaEvents;
|
|
387
|
+
updateAuthParams(): void;
|
|
388
|
+
resumeAfterAuthRenew(): void;
|
|
389
|
+
setQuality(selection: QualitySelection): void;
|
|
390
|
+
getQuality(): QualitySelection;
|
|
391
|
+
getQualities(): HlsQualityLevel[];
|
|
392
|
+
getSupportMode(): HlsSupportMode;
|
|
393
|
+
destroy(): void;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
type VideoPlayer = {
|
|
397
|
+
play: () => Promise<void>;
|
|
398
|
+
pause: () => void;
|
|
399
|
+
seek: (time: number) => void;
|
|
400
|
+
/** Jump to the latest live edge. No-op when already at live. */
|
|
401
|
+
goToLive: () => SeekToLiveResult;
|
|
402
|
+
isLive: () => boolean;
|
|
403
|
+
isAtLiveEdge: () => boolean;
|
|
404
|
+
getCurrentTime: () => number;
|
|
405
|
+
getDuration: () => number;
|
|
406
|
+
setVolume: (volume: number) => void;
|
|
407
|
+
getVolume: () => number;
|
|
408
|
+
mute: () => void;
|
|
409
|
+
unmute: () => void;
|
|
410
|
+
isMuted: () => boolean;
|
|
411
|
+
setPlaybackRate: (rate: number) => void;
|
|
412
|
+
getPlaybackRate: () => number;
|
|
413
|
+
getState: () => PlayerState;
|
|
414
|
+
getBufferedRanges: () => BufferedRange[];
|
|
415
|
+
getQuality: () => QualitySelection;
|
|
416
|
+
setQuality: (selection: QualitySelection | string) => void;
|
|
417
|
+
getAvailableQualities: () => ReturnType<HlsEngine["getQualities"]>;
|
|
418
|
+
enterFullscreen: () => Promise<void>;
|
|
419
|
+
exitFullscreen: () => Promise<void>;
|
|
420
|
+
isFullscreen: () => boolean;
|
|
421
|
+
reload: () => Promise<void>;
|
|
422
|
+
destroy: () => void;
|
|
423
|
+
getDiagnostics: () => PlayerDiagnostics;
|
|
424
|
+
getConfig: () => PlayerConfig;
|
|
425
|
+
updateConfig: (partial: Parameters<typeof mergePlayerConfig>[0]) => void;
|
|
426
|
+
on: EventEmitter["on"];
|
|
427
|
+
off: EventEmitter["off"];
|
|
428
|
+
};
|
|
429
|
+
/**
|
|
430
|
+
* Creates a framework-agnostic video player.
|
|
431
|
+
* Never pass clientSecret — use auth.getToken / playback.getSource callbacks.
|
|
432
|
+
*/
|
|
433
|
+
declare function createVideoPlayer(options: CreateVideoPlayerOptions): VideoPlayer;
|
|
434
|
+
|
|
435
|
+
declare enum PlayerErrorCode {
|
|
436
|
+
INVALID_CONFIGURATION = "INVALID_CONFIGURATION",
|
|
437
|
+
AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED",
|
|
438
|
+
AUTH_TOKEN_REFRESH_FAILED = "AUTH_TOKEN_REFRESH_FAILED",
|
|
439
|
+
TOKEN_EXPIRED = "TOKEN_EXPIRED",
|
|
440
|
+
TOKEN_REFRESH_FAILED = "TOKEN_REFRESH_FAILED",
|
|
441
|
+
SOURCE_RESOLUTION_FAILED = "SOURCE_RESOLUTION_FAILED",
|
|
442
|
+
MANIFEST_LOAD_FAILED = "MANIFEST_LOAD_FAILED",
|
|
443
|
+
SEGMENT_LOAD_FAILED = "SEGMENT_LOAD_FAILED",
|
|
444
|
+
NETWORK_ERROR = "NETWORK_ERROR",
|
|
445
|
+
PLAYBACK_ERROR = "PLAYBACK_ERROR",
|
|
446
|
+
UNSUPPORTED_BROWSER = "UNSUPPORTED_BROWSER",
|
|
447
|
+
AUTOPLAY_BLOCKED = "AUTOPLAY_BLOCKED",
|
|
448
|
+
UNKNOWN = "UNKNOWN"
|
|
449
|
+
}
|
|
450
|
+
type PlayerError = {
|
|
451
|
+
code: PlayerErrorCode;
|
|
452
|
+
message: string;
|
|
453
|
+
category: "config" | "auth" | "network" | "playback" | "unknown";
|
|
454
|
+
fatal: boolean;
|
|
455
|
+
retryable: boolean;
|
|
456
|
+
timestamp: number;
|
|
457
|
+
cause?: unknown;
|
|
458
|
+
};
|
|
459
|
+
declare function createPlayerError(code: PlayerErrorCode, message: string, options?: Partial<Omit<PlayerError, "code" | "message" | "timestamp">>): PlayerError;
|
|
460
|
+
declare function redactSensitive(input: string): string;
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Manages provider auth-token lifecycle (independent from signed playback URL).
|
|
464
|
+
* Single-flight refresh; never stores clientSecret.
|
|
465
|
+
* Unauthorized recoveries are bounded to prevent infinite 401 → refresh loops.
|
|
466
|
+
*/
|
|
467
|
+
declare class AuthManager {
|
|
468
|
+
private readonly auth;
|
|
469
|
+
private readonly refreshBeforeExpiryMs;
|
|
470
|
+
private readonly logger;
|
|
471
|
+
private readonly onRefreshed?;
|
|
472
|
+
private readonly onError?;
|
|
473
|
+
private token;
|
|
474
|
+
private inFlight;
|
|
475
|
+
private timer;
|
|
476
|
+
private destroyed;
|
|
477
|
+
/** Consecutive unauthorized refresh attempts (reset on success). */
|
|
478
|
+
private unauthorizedAttempts;
|
|
479
|
+
private readonly maxUnauthorizedRetries;
|
|
480
|
+
constructor(auth: AuthConfig | undefined, refreshBeforeExpiryMs: number, logger: Logger, onRefreshed?: ((token: AuthToken) => void) | undefined, onError?: ((message: string, retryable: boolean) => void) | undefined, maxUnauthorizedRetries?: number);
|
|
481
|
+
getAccessToken(): string | null;
|
|
482
|
+
getExpiresAt(): number | null;
|
|
483
|
+
ensureToken(context: AuthTokenProviderContext): Promise<AuthToken | null>;
|
|
484
|
+
refresh(context: AuthTokenProviderContext): Promise<AuthToken>;
|
|
485
|
+
private scheduleProactiveRefresh;
|
|
486
|
+
destroy(): void;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Resolves and refreshes signed playback sources via consumer callbacks.
|
|
491
|
+
*/
|
|
492
|
+
declare class PlaybackSourceManager {
|
|
493
|
+
private readonly playback;
|
|
494
|
+
private readonly logger;
|
|
495
|
+
private source;
|
|
496
|
+
private inFlight;
|
|
497
|
+
readonly authParams: AuthParamsStore;
|
|
498
|
+
constructor(playback: PlaybackCredentialConfig | undefined, logger: Logger);
|
|
499
|
+
getSource(): PlaybackSource | null;
|
|
500
|
+
getExpiresAt(): number | null;
|
|
501
|
+
load(context: PlaybackSourceContext): Promise<PlaybackSource>;
|
|
502
|
+
refresh(context: PlaybackSourceContext): Promise<PlaybackSource>;
|
|
503
|
+
applyDirectSource(source: PlaybackSource): void;
|
|
504
|
+
private run;
|
|
505
|
+
private applyAuthParams;
|
|
506
|
+
destroy(): void;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
type RefreshReason = "proactive" | "frag_error" | "level_error" | "key_error" | "fatal_network" | "manual";
|
|
510
|
+
type RefreshManagerOptions = {
|
|
511
|
+
videoId: string;
|
|
512
|
+
authManager: AuthManager;
|
|
513
|
+
sourceManager: PlaybackSourceManager;
|
|
514
|
+
refreshBeforeExpiryMs: number;
|
|
515
|
+
renewMaxRetries: number;
|
|
516
|
+
renewBackoffMs: number;
|
|
517
|
+
coalesceMs: number;
|
|
518
|
+
logger: Logger;
|
|
519
|
+
isDestroyed: () => boolean;
|
|
520
|
+
onRenewing?: () => void;
|
|
521
|
+
onRenewed?: (expiresAt: number) => void;
|
|
522
|
+
onFatal?: (message: string) => void;
|
|
523
|
+
};
|
|
524
|
+
/**
|
|
525
|
+
* Schedules signed-URL renewal (playback clock) with single-flight + coalesce.
|
|
526
|
+
* Ensures auth token is fresh before calling refreshSource.
|
|
527
|
+
*/
|
|
528
|
+
declare class RefreshManager {
|
|
529
|
+
private readonly options;
|
|
530
|
+
private timer;
|
|
531
|
+
private coalesceTimer;
|
|
532
|
+
private inFlight;
|
|
533
|
+
private consecutiveFailures;
|
|
534
|
+
private stopped;
|
|
535
|
+
private pendingReason;
|
|
536
|
+
constructor(options: RefreshManagerOptions);
|
|
537
|
+
start(initialExpiresAt: number): void;
|
|
538
|
+
requestRenew(reason?: RefreshReason): void;
|
|
539
|
+
stop(): void;
|
|
540
|
+
private schedule;
|
|
541
|
+
private renew;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
declare function redactValue(key: string, value: unknown): unknown;
|
|
545
|
+
declare function redactObject(obj: Record<string, unknown>): Record<string, unknown>;
|
|
546
|
+
|
|
547
|
+
export { type AccessibilityConfig, type AnalyticsConfig, type AuthConfig, AuthManager, AuthParamsStore, type AuthToken, type AuthTokenProviderContext, type BufferedRange, type ControlsConfig, type CreateVideoPlayerOptions, DEFAULT_CONTROLS, DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS, DEFAULT_PLAYER_BEHAVIOR, DEFAULT_PLAYER_CONFIG, DEFAULT_THEME, DEFAULT_WATERMARK, type DebugConfig, EventEmitter, type HlsQualityLevel, type HlsSupportMode, type LiveMediaSnapshot, type LoggingConfig, PACKAGE_VERSION, PLAYBACK_RATES, type PlayIconPreset, type PlaybackCredentialConfig, type PlaybackRate, type PlaybackSource, type PlaybackSourceContext, PlaybackSourceManager, type PlayerBehaviorConfig, type PlayerConfig, type PlayerDiagnostics, type PlayerError, PlayerErrorCode, type PlayerEventMap, type PlayerSkipSeconds, type PlayerState, type PlayerZoomLevel, type QualitySelection, RefreshManager, type SeekToLiveResult, type StreamingConfig, type ThemeConfig, type VideoPlayer, type WatermarkConfig, assertNoSecretsInConfig, createPlayerError, createVideoPlayer, getLiveEdgeTime, isAtLiveEdge, mergePlayerConfig, redactObject, redactSensitive, redactValue, seekToLiveEdge, themeToCssVars };
|