@codenkay/video-nsgplayer-core 0.1.2 → 0.1.3

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/dist/index.d.cts CHANGED
@@ -1,3 +1,5 @@
1
+ import Hls, { LoaderContext, LoaderConfiguration, LoaderCallbacks } from 'hls.js';
2
+
1
3
  /** Player lifecycle states. */
2
4
  type PlayerState = "idle" | "loading" | "ready" | "playing" | "paused" | "buffering" | "renewing" | "ended" | "error" | "destroyed";
3
5
  type HlsSupportMode = "hls.js" | "native" | "unsupported";
@@ -166,6 +168,7 @@ type PlayerConfig = Required<{
166
168
  streaming: {
167
169
  engine: "hls";
168
170
  hls: Required<NonNullable<StreamingConfig["hls"]>>;
171
+ keyProxyUrlBuilder?: StreamingConfig["keyProxyUrlBuilder"];
169
172
  };
170
173
  logging: Required<LoggingConfig>;
171
174
  debug: Required<DebugConfig>;
@@ -239,7 +242,7 @@ type PlayerEventMap = {
239
242
  };
240
243
 
241
244
  declare const PLAYBACK_RATES: readonly [0.5, 0.75, 1, 1.25, 1.5, 2];
242
- declare const PACKAGE_VERSION = "0.1.2";
245
+ declare const PACKAGE_VERSION = "0.1.3";
243
246
  declare const DEFAULT_PLAYER_BEHAVIOR: Required<PlayerBehaviorConfig>;
244
247
  declare const DEFAULT_CONTROLS: Required<ControlsConfig>;
245
248
  declare const DEFAULT_THEME: Required<ThemeConfig>;
@@ -270,7 +273,7 @@ type PlayerConfigPartial = Partial<{
270
273
  streaming: {
271
274
  engine?: "hls";
272
275
  hls?: Partial<PlayerConfig["streaming"]["hls"]>;
273
- keyProxyUrlBuilder?: unknown;
276
+ keyProxyUrlBuilder?: PlayerConfig["streaming"]["keyProxyUrlBuilder"];
274
277
  };
275
278
  logging: Partial<PlayerConfig["logging"]>;
276
279
  debug: Partial<PlayerConfig["debug"]>;
@@ -343,7 +346,14 @@ declare class AuthParamsStore {
343
346
  constructor(initial?: URLSearchParams | Record<string, string>);
344
347
  getSnapshot(): URLSearchParams;
345
348
  toRecord(): Record<string, string>;
349
+ /** True when at least one auth query param is stored. */
350
+ hasParams(): boolean;
351
+ toString(): string;
346
352
  update(next: URLSearchParams | Record<string, string>): void;
353
+ /**
354
+ * Merges current auth params onto a target URL, preserving unrelated query keys.
355
+ * Critical for child HLS playlists/segments that omit signed query params.
356
+ */
347
357
  applyToUrl(rawUrl: string, baseOrigin?: string): string;
348
358
  }
349
359
 
@@ -376,6 +386,8 @@ type HlsEngineOptions = {
376
386
  startMuted: boolean;
377
387
  startPosition?: number;
378
388
  volume?: number;
389
+ videoId?: string;
390
+ keyProxyUrlBuilder?: StreamingConfig["keyProxyUrlBuilder"];
379
391
  hlsConfig: {
380
392
  enableWorker: boolean;
381
393
  lowLatencyMode: boolean;
@@ -387,6 +399,11 @@ type HlsEngineOptions = {
387
399
  };
388
400
  /**
389
401
  * Dual-path HLS engine: hls.js when supported, otherwise native Safari HLS.
402
+ *
403
+ * Signed CDN playback requires auth query params on *every* HLS request
404
+ * (master, media playlist, segments, keys). hls.js only receives the signed
405
+ * master URL via loadSource; child URIs are relative and unsigned unless a
406
+ * custom loader re-applies AuthParamsStore on each request.
390
407
  */
391
408
  declare class HlsEngine {
392
409
  private readonly options;
@@ -558,7 +575,27 @@ declare class RefreshManager {
558
575
  private renew;
559
576
  }
560
577
 
578
+ type HlsLoader = new (config: object) => {
579
+ load(context: LoaderContext, config: LoaderConfiguration, callbacks: LoaderCallbacks<LoaderContext>): void;
580
+ destroy(): void;
581
+ };
582
+ type AuthParamsLoaderOptions = {
583
+ videoId?: string;
584
+ keyProxyUrlBuilder?: StreamingConfig["keyProxyUrlBuilder"];
585
+ };
586
+ /**
587
+ * Rewrites an HLS request URL so signed auth query params are present.
588
+ * Master playlists are signed on loadSource; child playlists / segments / keys
589
+ * are relative and would otherwise be fetched unsigned → CDN 403.
590
+ */
591
+ declare function rewriteHlsRequestUrl(rawUrl: string, store: AuthParamsStore, options?: AuthParamsLoaderOptions, baseOrigin?: string): string;
592
+ /**
593
+ * hls.js loader that re-applies live AuthParamsStore credentials on every
594
+ * manifest / level / fragment / key request.
595
+ */
596
+ declare function createAuthParamsLoader(HlsClass: typeof Hls, store: AuthParamsStore, options?: AuthParamsLoaderOptions): HlsLoader;
597
+
561
598
  declare function redactValue(key: string, value: unknown, seen?: WeakSet<object>, depth?: number): unknown;
562
599
  declare function redactObject(obj: Record<string, unknown>, seen?: WeakSet<object>, depth?: number): Record<string, unknown>;
563
600
 
564
- 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, SECRET_SCAN_MAX_DEPTH, type SeekToLiveResult, type StreamingConfig, type ThemeConfig, type VideoPlayer, type WatermarkConfig, assertNoSecretsInConfig, createPlayerError, createVideoPlayer, getLiveEdgeTime, isAtLiveEdge, isPlainObject, mergePlayerConfig, redactObject, redactSensitive, redactValue, seekToLiveEdge, themeToCssVars };
601
+ 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, SECRET_SCAN_MAX_DEPTH, type SeekToLiveResult, type StreamingConfig, type ThemeConfig, type VideoPlayer, type WatermarkConfig, assertNoSecretsInConfig, createAuthParamsLoader, createPlayerError, createVideoPlayer, getLiveEdgeTime, isAtLiveEdge, isPlainObject, mergePlayerConfig, redactObject, redactSensitive, redactValue, rewriteHlsRequestUrl, seekToLiveEdge, themeToCssVars };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import Hls, { LoaderContext, LoaderConfiguration, LoaderCallbacks } from 'hls.js';
2
+
1
3
  /** Player lifecycle states. */
2
4
  type PlayerState = "idle" | "loading" | "ready" | "playing" | "paused" | "buffering" | "renewing" | "ended" | "error" | "destroyed";
3
5
  type HlsSupportMode = "hls.js" | "native" | "unsupported";
@@ -166,6 +168,7 @@ type PlayerConfig = Required<{
166
168
  streaming: {
167
169
  engine: "hls";
168
170
  hls: Required<NonNullable<StreamingConfig["hls"]>>;
171
+ keyProxyUrlBuilder?: StreamingConfig["keyProxyUrlBuilder"];
169
172
  };
170
173
  logging: Required<LoggingConfig>;
171
174
  debug: Required<DebugConfig>;
@@ -239,7 +242,7 @@ type PlayerEventMap = {
239
242
  };
240
243
 
241
244
  declare const PLAYBACK_RATES: readonly [0.5, 0.75, 1, 1.25, 1.5, 2];
242
- declare const PACKAGE_VERSION = "0.1.2";
245
+ declare const PACKAGE_VERSION = "0.1.3";
243
246
  declare const DEFAULT_PLAYER_BEHAVIOR: Required<PlayerBehaviorConfig>;
244
247
  declare const DEFAULT_CONTROLS: Required<ControlsConfig>;
245
248
  declare const DEFAULT_THEME: Required<ThemeConfig>;
@@ -270,7 +273,7 @@ type PlayerConfigPartial = Partial<{
270
273
  streaming: {
271
274
  engine?: "hls";
272
275
  hls?: Partial<PlayerConfig["streaming"]["hls"]>;
273
- keyProxyUrlBuilder?: unknown;
276
+ keyProxyUrlBuilder?: PlayerConfig["streaming"]["keyProxyUrlBuilder"];
274
277
  };
275
278
  logging: Partial<PlayerConfig["logging"]>;
276
279
  debug: Partial<PlayerConfig["debug"]>;
@@ -343,7 +346,14 @@ declare class AuthParamsStore {
343
346
  constructor(initial?: URLSearchParams | Record<string, string>);
344
347
  getSnapshot(): URLSearchParams;
345
348
  toRecord(): Record<string, string>;
349
+ /** True when at least one auth query param is stored. */
350
+ hasParams(): boolean;
351
+ toString(): string;
346
352
  update(next: URLSearchParams | Record<string, string>): void;
353
+ /**
354
+ * Merges current auth params onto a target URL, preserving unrelated query keys.
355
+ * Critical for child HLS playlists/segments that omit signed query params.
356
+ */
347
357
  applyToUrl(rawUrl: string, baseOrigin?: string): string;
348
358
  }
349
359
 
@@ -376,6 +386,8 @@ type HlsEngineOptions = {
376
386
  startMuted: boolean;
377
387
  startPosition?: number;
378
388
  volume?: number;
389
+ videoId?: string;
390
+ keyProxyUrlBuilder?: StreamingConfig["keyProxyUrlBuilder"];
379
391
  hlsConfig: {
380
392
  enableWorker: boolean;
381
393
  lowLatencyMode: boolean;
@@ -387,6 +399,11 @@ type HlsEngineOptions = {
387
399
  };
388
400
  /**
389
401
  * Dual-path HLS engine: hls.js when supported, otherwise native Safari HLS.
402
+ *
403
+ * Signed CDN playback requires auth query params on *every* HLS request
404
+ * (master, media playlist, segments, keys). hls.js only receives the signed
405
+ * master URL via loadSource; child URIs are relative and unsigned unless a
406
+ * custom loader re-applies AuthParamsStore on each request.
390
407
  */
391
408
  declare class HlsEngine {
392
409
  private readonly options;
@@ -558,7 +575,27 @@ declare class RefreshManager {
558
575
  private renew;
559
576
  }
560
577
 
578
+ type HlsLoader = new (config: object) => {
579
+ load(context: LoaderContext, config: LoaderConfiguration, callbacks: LoaderCallbacks<LoaderContext>): void;
580
+ destroy(): void;
581
+ };
582
+ type AuthParamsLoaderOptions = {
583
+ videoId?: string;
584
+ keyProxyUrlBuilder?: StreamingConfig["keyProxyUrlBuilder"];
585
+ };
586
+ /**
587
+ * Rewrites an HLS request URL so signed auth query params are present.
588
+ * Master playlists are signed on loadSource; child playlists / segments / keys
589
+ * are relative and would otherwise be fetched unsigned → CDN 403.
590
+ */
591
+ declare function rewriteHlsRequestUrl(rawUrl: string, store: AuthParamsStore, options?: AuthParamsLoaderOptions, baseOrigin?: string): string;
592
+ /**
593
+ * hls.js loader that re-applies live AuthParamsStore credentials on every
594
+ * manifest / level / fragment / key request.
595
+ */
596
+ declare function createAuthParamsLoader(HlsClass: typeof Hls, store: AuthParamsStore, options?: AuthParamsLoaderOptions): HlsLoader;
597
+
561
598
  declare function redactValue(key: string, value: unknown, seen?: WeakSet<object>, depth?: number): unknown;
562
599
  declare function redactObject(obj: Record<string, unknown>, seen?: WeakSet<object>, depth?: number): Record<string, unknown>;
563
600
 
564
- 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, SECRET_SCAN_MAX_DEPTH, type SeekToLiveResult, type StreamingConfig, type ThemeConfig, type VideoPlayer, type WatermarkConfig, assertNoSecretsInConfig, createPlayerError, createVideoPlayer, getLiveEdgeTime, isAtLiveEdge, isPlainObject, mergePlayerConfig, redactObject, redactSensitive, redactValue, seekToLiveEdge, themeToCssVars };
601
+ 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, SECRET_SCAN_MAX_DEPTH, type SeekToLiveResult, type StreamingConfig, type ThemeConfig, type VideoPlayer, type WatermarkConfig, assertNoSecretsInConfig, createAuthParamsLoader, createPlayerError, createVideoPlayer, getLiveEdgeTime, isAtLiveEdge, isPlainObject, mergePlayerConfig, redactObject, redactSensitive, redactValue, rewriteHlsRequestUrl, seekToLiveEdge, themeToCssVars };
package/dist/index.js CHANGED
@@ -146,7 +146,7 @@ var AuthManager = class {
146
146
 
147
147
  // src/config/defaults.ts
148
148
  var PLAYBACK_RATES = [0.5, 0.75, 1, 1.25, 1.5, 2];
149
- var PACKAGE_VERSION = "0.1.2";
149
+ var PACKAGE_VERSION = "0.1.3";
150
150
  var DEFAULT_PLAYER_BEHAVIOR = {
151
151
  autoplay: true,
152
152
  startMuted: true,
@@ -322,7 +322,8 @@ function mergePlayerConfig(partial) {
322
322
  hls: {
323
323
  ...DEFAULT_PLAYER_CONFIG.streaming.hls,
324
324
  ...partial?.streaming?.hls
325
- }
325
+ },
326
+ keyProxyUrlBuilder: partial?.streaming?.keyProxyUrlBuilder
326
327
  },
327
328
  logging: { ...DEFAULT_PLAYER_CONFIG.logging, ...partial?.logging },
328
329
  debug: { ...DEFAULT_PLAYER_CONFIG.debug, ...partial?.debug },
@@ -498,11 +499,25 @@ var AuthParamsStore = class {
498
499
  });
499
500
  return out;
500
501
  }
502
+ /** True when at least one auth query param is stored. */
503
+ hasParams() {
504
+ return [...this.params.keys()].length > 0;
505
+ }
506
+ toString() {
507
+ return this.params.toString();
508
+ }
501
509
  update(next) {
502
510
  this.params = next instanceof URLSearchParams ? new URLSearchParams(next) : new URLSearchParams(next);
503
511
  }
512
+ /**
513
+ * Merges current auth params onto a target URL, preserving unrelated query keys.
514
+ * Critical for child HLS playlists/segments that omit signed query params.
515
+ */
504
516
  applyToUrl(rawUrl, baseOrigin) {
505
- const target = new URL(rawUrl, baseOrigin ?? (typeof location !== "undefined" ? location.origin : "http://localhost"));
517
+ const target = new URL(
518
+ rawUrl,
519
+ baseOrigin ?? (typeof location !== "undefined" ? location.origin : "http://localhost")
520
+ );
506
521
  this.params.forEach((value, key) => {
507
522
  target.searchParams.set(key, value);
508
523
  });
@@ -737,6 +752,39 @@ function seekToLiveEdge(media, options) {
737
752
  return { moved: true, edge };
738
753
  }
739
754
 
755
+ // src/streaming/authParamsLoader.ts
756
+ var ENC_KEY_PATH_RE = /\/enc\.key$/i;
757
+ function rewriteHlsRequestUrl(rawUrl, store, options = {}, baseOrigin = typeof location !== "undefined" ? location.origin : "http://localhost") {
758
+ if (!rawUrl) return rawUrl;
759
+ const parsed = new URL(rawUrl, baseOrigin);
760
+ const isKey = ENC_KEY_PATH_RE.test(parsed.pathname);
761
+ if (isKey && options.keyProxyUrlBuilder && options.videoId) {
762
+ const snapshot = store.toRecord();
763
+ return options.keyProxyUrlBuilder({
764
+ videoId: options.videoId,
765
+ keyUrl: parsed.toString(),
766
+ token: snapshot.token,
767
+ expires: snapshot.expires
768
+ });
769
+ }
770
+ if (!store.hasParams()) return parsed.toString();
771
+ return store.applyToUrl(rawUrl, baseOrigin);
772
+ }
773
+ function createAuthParamsLoader(HlsClass, store, options = {}) {
774
+ const BaseLoader = HlsClass.DefaultConfig.loader;
775
+ return class AuthParamsLoader extends BaseLoader {
776
+ load(context, config, callbacks) {
777
+ if (context.url) {
778
+ try {
779
+ context.url = rewriteHlsRequestUrl(context.url, store, options);
780
+ } catch {
781
+ }
782
+ }
783
+ super.load(context, config, callbacks);
784
+ }
785
+ };
786
+ }
787
+
740
788
  // src/streaming/HlsEngine.ts
741
789
  var HlsEngine = class {
742
790
  constructor(options) {
@@ -789,15 +837,16 @@ var HlsEngine = class {
789
837
  }
790
838
  }
791
839
  async startWithHlsJs(Hls, playbackUrl) {
792
- const { videoEl, authParams, hlsConfig, callbacks } = this.options;
840
+ const { videoEl, authParams, hlsConfig, callbacks, videoId, keyProxyUrlBuilder } = this.options;
841
+ const loader = createAuthParamsLoader(Hls, authParams, {
842
+ videoId,
843
+ keyProxyUrlBuilder
844
+ });
793
845
  this.hls = new Hls({
794
846
  enableWorker: hlsConfig.enableWorker,
795
847
  lowLatencyMode: hlsConfig.lowLatencyMode,
796
848
  backBufferLength: hlsConfig.backBufferLength,
797
- xhrSetup: (xhr, url) => {
798
- void xhr;
799
- void url;
800
- }
849
+ loader
801
850
  });
802
851
  this.hls.attachMedia(videoEl);
803
852
  this.hls.loadSource(authParams.applyToUrl(playbackUrl));
@@ -1005,6 +1054,8 @@ function createVideoPlayer(options) {
1005
1054
  startMuted: config.player.startMuted,
1006
1055
  startPosition: config.player.startPosition,
1007
1056
  volume: config.player.volume,
1057
+ videoId: options.videoId,
1058
+ keyProxyUrlBuilder: options.streaming?.keyProxyUrlBuilder,
1008
1059
  hlsConfig: config.streaming.hls,
1009
1060
  logger,
1010
1061
  callbacks: {
@@ -1265,7 +1316,8 @@ function createVideoPlayer(options) {
1265
1316
  watermark: { ...config.watermark, ...partial?.watermark },
1266
1317
  streaming: {
1267
1318
  engine: "hls",
1268
- hls: { ...config.streaming.hls, ...partial?.streaming?.hls }
1319
+ hls: { ...config.streaming.hls, ...partial?.streaming?.hls },
1320
+ keyProxyUrlBuilder: partial?.streaming?.keyProxyUrlBuilder ?? config.streaming.keyProxyUrlBuilder
1269
1321
  },
1270
1322
  logging: { ...config.logging, ...partial?.logging },
1271
1323
  debug: { ...config.debug, ...partial?.debug },
@@ -1303,6 +1355,7 @@ export {
1303
1355
  RefreshManager,
1304
1356
  SECRET_SCAN_MAX_DEPTH,
1305
1357
  assertNoSecretsInConfig,
1358
+ createAuthParamsLoader,
1306
1359
  createPlayerError,
1307
1360
  createVideoPlayer,
1308
1361
  getLiveEdgeTime,
@@ -1312,6 +1365,7 @@ export {
1312
1365
  redactObject,
1313
1366
  redactSensitive,
1314
1367
  redactValue,
1368
+ rewriteHlsRequestUrl,
1315
1369
  seekToLiveEdge,
1316
1370
  themeToCssVars
1317
1371
  };