@codenkay/video-nsgplayer-core 3.0.0 → 3.0.2
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 +18 -0
- package/dist/index.cjs +309 -139
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -24
- package/dist/index.d.ts +27 -24
- package/dist/index.js +308 -139
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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 = "
|
|
149
|
+
var PACKAGE_VERSION = "3.0.2";
|
|
150
150
|
var DEFAULT_PLAYER_BEHAVIOR = {
|
|
151
151
|
autoplay: true,
|
|
152
152
|
startMuted: true,
|
|
@@ -325,7 +325,8 @@ function mergePlayerConfig(partial) {
|
|
|
325
325
|
...partial?.streaming?.hls
|
|
326
326
|
},
|
|
327
327
|
keyProxyUrlBuilder: partial?.streaming?.keyProxyUrlBuilder,
|
|
328
|
-
getKeyAccessToken: partial?.streaming?.getKeyAccessToken
|
|
328
|
+
getKeyAccessToken: partial?.streaming?.getKeyAccessToken,
|
|
329
|
+
keyProxyMaxFailures: partial?.streaming?.keyProxyMaxFailures
|
|
329
330
|
},
|
|
330
331
|
logging: { ...DEFAULT_PLAYER_CONFIG.logging, ...partial?.logging },
|
|
331
332
|
debug: { ...DEFAULT_PLAYER_CONFIG.debug, ...partial?.debug },
|
|
@@ -765,9 +766,13 @@ function seekToLiveEdge(media, options) {
|
|
|
765
766
|
}
|
|
766
767
|
|
|
767
768
|
// src/streaming/authParamsLoader.ts
|
|
768
|
-
import { XhrLoader as BuiltinXhrLoader } from "hls.js";
|
|
769
769
|
var ENC_KEY_PATH_RE = /enc\.key$/i;
|
|
770
770
|
var BUILTIN_LOADER_NAMES = /* @__PURE__ */ new Set(["XhrLoader", "FetchLoader"]);
|
|
771
|
+
var BUILTIN_LOADER_REF = /* @__PURE__ */ Symbol.for(
|
|
772
|
+
"@codenkay/video-nsgplayer-core/builtin-hls-loader"
|
|
773
|
+
);
|
|
774
|
+
var builtinLoaderByHls = /* @__PURE__ */ new WeakMap();
|
|
775
|
+
var KEY_PROXY_MAX_FAILURES = 2;
|
|
771
776
|
function isEncryptionKeyUrl(rawUrl, baseOrigin = typeof location !== "undefined" ? location.origin : "http://localhost") {
|
|
772
777
|
try {
|
|
773
778
|
return ENC_KEY_PATH_RE.test(new URL(rawUrl, baseOrigin).pathname);
|
|
@@ -775,18 +780,34 @@ function isEncryptionKeyUrl(rawUrl, baseOrigin = typeof location !== "undefined"
|
|
|
775
780
|
return /enc\.key/i.test(rawUrl);
|
|
776
781
|
}
|
|
777
782
|
}
|
|
778
|
-
function
|
|
779
|
-
|
|
780
|
-
|
|
783
|
+
function isBuiltinLoaderName(name) {
|
|
784
|
+
return BUILTIN_LOADER_NAMES.has(name);
|
|
785
|
+
}
|
|
786
|
+
function rememberBuiltin(HlsClass, loader) {
|
|
787
|
+
if (isBuiltinLoaderName(typeof loader.name === "string" ? loader.name : "")) {
|
|
788
|
+
builtinLoaderByHls.set(HlsClass, loader);
|
|
781
789
|
}
|
|
790
|
+
return loader;
|
|
791
|
+
}
|
|
792
|
+
function getStashedBuiltinLoader(loader) {
|
|
793
|
+
return loader[BUILTIN_LOADER_REF];
|
|
794
|
+
}
|
|
795
|
+
function resolveBuiltinHlsLoader(HlsClass) {
|
|
796
|
+
const cached = builtinLoaderByHls.get(HlsClass);
|
|
797
|
+
if (cached) return cached;
|
|
782
798
|
const start = HlsClass.DefaultConfig.loader;
|
|
783
799
|
let current = start;
|
|
784
800
|
const seen = /* @__PURE__ */ new Set();
|
|
785
801
|
while (current && !seen.has(current)) {
|
|
786
802
|
seen.add(current);
|
|
787
803
|
const name = typeof current.name === "string" ? current.name : "";
|
|
788
|
-
if (
|
|
789
|
-
return current;
|
|
804
|
+
if (isBuiltinLoaderName(name)) {
|
|
805
|
+
return rememberBuiltin(HlsClass, current);
|
|
806
|
+
}
|
|
807
|
+
const stashed = getStashedBuiltinLoader(current);
|
|
808
|
+
if (stashed) {
|
|
809
|
+
current = stashed;
|
|
810
|
+
continue;
|
|
790
811
|
}
|
|
791
812
|
const parentCtor = Object.getPrototypeOf(current.prototype)?.constructor;
|
|
792
813
|
if (!parentCtor || parentCtor === Object || parentCtor === Function) {
|
|
@@ -794,7 +815,8 @@ function resolveBuiltinHlsLoader(HlsClass) {
|
|
|
794
815
|
}
|
|
795
816
|
current = parentCtor;
|
|
796
817
|
}
|
|
797
|
-
|
|
818
|
+
const fallback = builtinLoaderByHls.get(HlsClass);
|
|
819
|
+
return fallback ?? start;
|
|
798
820
|
}
|
|
799
821
|
function rewriteHlsRequestUrl(rawUrl, store, options = {}, baseOrigin = typeof location !== "undefined" ? location.origin : "http://localhost") {
|
|
800
822
|
if (!rawUrl) return rawUrl;
|
|
@@ -828,68 +850,230 @@ function createLoaderStats() {
|
|
|
828
850
|
buffering: { start: 0, first: 0, end: 0 }
|
|
829
851
|
};
|
|
830
852
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
{
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
853
|
+
function isProxyUpstreamBlocked(status, contentType, bodyHead, errorText) {
|
|
854
|
+
if (status === 0 || status === 502 || status === 503 || status === 504) {
|
|
855
|
+
return true;
|
|
856
|
+
}
|
|
857
|
+
if (status === 403 || status === 401) return true;
|
|
858
|
+
if (contentType?.includes("text/html")) return true;
|
|
859
|
+
if (/<!DOCTYPE|<html|Just a moment|Cloudflare|blocked/i.test(bodyHead)) {
|
|
860
|
+
return true;
|
|
861
|
+
}
|
|
862
|
+
if (errorText && /Cloudflare|HTML|DOCTYPE|blocked|502/i.test(errorText)) {
|
|
863
|
+
return true;
|
|
864
|
+
}
|
|
865
|
+
return false;
|
|
866
|
+
}
|
|
867
|
+
async function fetchEncryptionKeyBytes(url, accessToken, signal) {
|
|
868
|
+
const headers = accessToken ? { Authorization: `Bearer ${accessToken}`, Accept: "*/*" } : void 0;
|
|
869
|
+
try {
|
|
870
|
+
const response = await fetch(url, {
|
|
871
|
+
method: "GET",
|
|
872
|
+
...headers ? { headers } : {},
|
|
873
|
+
credentials: "omit",
|
|
874
|
+
cache: "no-store",
|
|
875
|
+
signal
|
|
876
|
+
});
|
|
877
|
+
if (!response.ok) {
|
|
878
|
+
return {
|
|
879
|
+
ok: false,
|
|
880
|
+
status: response.status,
|
|
881
|
+
text: response.statusText || `enc.key HTTP ${response.status}`,
|
|
882
|
+
cors: false,
|
|
883
|
+
response
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
const data = await response.arrayBuffer();
|
|
887
|
+
const head = new TextDecoder().decode(data.slice(0, 32));
|
|
888
|
+
if (/<!DOCTYPE|<html/i.test(head)) {
|
|
889
|
+
return {
|
|
890
|
+
ok: false,
|
|
891
|
+
status: 403,
|
|
892
|
+
text: "enc.key returned HTML (CDN challenge/block), not an AES key",
|
|
893
|
+
cors: false,
|
|
894
|
+
response
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
return {
|
|
898
|
+
ok: true,
|
|
899
|
+
data,
|
|
855
900
|
response,
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
901
|
+
url: response.url || url
|
|
902
|
+
};
|
|
903
|
+
} catch (error) {
|
|
904
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
905
|
+
return {
|
|
906
|
+
ok: false,
|
|
907
|
+
status: 0,
|
|
908
|
+
text: "enc.key fetch aborted/timeout",
|
|
909
|
+
cors: false,
|
|
910
|
+
response: null
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
const cors = error instanceof TypeError || error instanceof Error && /Failed to fetch|NetworkError|CORS/i.test(error.message);
|
|
914
|
+
return {
|
|
915
|
+
ok: false,
|
|
916
|
+
status: 0,
|
|
917
|
+
text: error instanceof Error ? error.message : "enc.key fetch failed",
|
|
918
|
+
cors,
|
|
919
|
+
response: null
|
|
920
|
+
};
|
|
859
921
|
}
|
|
860
|
-
|
|
922
|
+
}
|
|
923
|
+
function reportKeySuccess(context, callbacks, result) {
|
|
924
|
+
const stats = createLoaderStats();
|
|
861
925
|
const end = performance.now();
|
|
926
|
+
stats.loading.first = stats.loading.start;
|
|
862
927
|
stats.loading.end = end;
|
|
863
|
-
stats.loaded = data.byteLength;
|
|
864
|
-
stats.total = data.byteLength;
|
|
865
|
-
|
|
866
|
-
|
|
928
|
+
stats.loaded = result.data.byteLength;
|
|
929
|
+
stats.total = result.data.byteLength;
|
|
930
|
+
callbacks.onSuccess(
|
|
931
|
+
{
|
|
932
|
+
url: result.url,
|
|
933
|
+
data: result.data,
|
|
934
|
+
code: result.response.status
|
|
935
|
+
},
|
|
936
|
+
stats,
|
|
937
|
+
context,
|
|
938
|
+
result.response
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
async function loadEncryptionKeyEnterprise(context, callbacks, plan, signal, state) {
|
|
942
|
+
const stats = createLoaderStats();
|
|
943
|
+
const canTryProxy = Boolean(plan.proxyUrl) && !state.circuitOpen && state.proxyFailures < plan.maxProxyFailures;
|
|
944
|
+
if (canTryProxy && plan.proxyUrl) {
|
|
945
|
+
while (!state.circuitOpen && state.proxyFailures < plan.maxProxyFailures && !signal.aborted) {
|
|
946
|
+
state.proxyFailures += 1;
|
|
947
|
+
try {
|
|
948
|
+
const response = await fetch(plan.proxyUrl, {
|
|
949
|
+
method: "GET",
|
|
950
|
+
headers: { Accept: "*/*" },
|
|
951
|
+
credentials: "same-origin",
|
|
952
|
+
cache: "no-store",
|
|
953
|
+
signal
|
|
954
|
+
});
|
|
955
|
+
const contentType = response.headers.get("content-type");
|
|
956
|
+
const data = await response.arrayBuffer();
|
|
957
|
+
const head = new TextDecoder().decode(data.slice(0, 64));
|
|
958
|
+
if (response.ok && !isProxyUpstreamBlocked(response.status, contentType, head)) {
|
|
959
|
+
const end = performance.now();
|
|
960
|
+
stats.loading.end = end;
|
|
961
|
+
stats.loaded = data.byteLength;
|
|
962
|
+
stats.total = data.byteLength;
|
|
963
|
+
callbacks.onSuccess(
|
|
964
|
+
{
|
|
965
|
+
url: response.url || plan.proxyUrl,
|
|
966
|
+
data,
|
|
967
|
+
code: response.status
|
|
968
|
+
},
|
|
969
|
+
stats,
|
|
970
|
+
{ ...context, url: plan.proxyUrl },
|
|
971
|
+
response
|
|
972
|
+
);
|
|
973
|
+
return "ok";
|
|
974
|
+
}
|
|
975
|
+
if (isProxyUpstreamBlocked(
|
|
976
|
+
response.status,
|
|
977
|
+
contentType,
|
|
978
|
+
head,
|
|
979
|
+
response.statusText
|
|
980
|
+
)) {
|
|
981
|
+
if (response.status === 502 || contentType?.includes("text/html") || /Cloudflare|DOCTYPE|blocked/i.test(head)) {
|
|
982
|
+
state.circuitOpen = true;
|
|
983
|
+
break;
|
|
984
|
+
}
|
|
985
|
+
continue;
|
|
986
|
+
}
|
|
987
|
+
callbacks.onError(
|
|
988
|
+
{
|
|
989
|
+
code: response.status,
|
|
990
|
+
text: `enc.key proxy HTTP ${response.status}`
|
|
991
|
+
},
|
|
992
|
+
{ ...context, url: plan.proxyUrl },
|
|
993
|
+
response,
|
|
994
|
+
stats
|
|
995
|
+
);
|
|
996
|
+
return "ok";
|
|
997
|
+
} catch (error) {
|
|
998
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
999
|
+
callbacks.onError(
|
|
1000
|
+
{ code: 0, text: "enc.key proxy aborted/timeout" },
|
|
1001
|
+
context,
|
|
1002
|
+
null,
|
|
1003
|
+
stats
|
|
1004
|
+
);
|
|
1005
|
+
return "ok";
|
|
1006
|
+
}
|
|
1007
|
+
state.circuitOpen = true;
|
|
1008
|
+
break;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
state.circuitOpen = true;
|
|
1012
|
+
}
|
|
1013
|
+
const queryResult = await fetchEncryptionKeyBytes(
|
|
1014
|
+
plan.signedKeyUrl,
|
|
1015
|
+
null,
|
|
1016
|
+
signal
|
|
1017
|
+
);
|
|
1018
|
+
if (queryResult.ok) {
|
|
1019
|
+
reportKeySuccess(
|
|
1020
|
+
{ ...context, url: plan.signedKeyUrl },
|
|
1021
|
+
callbacks,
|
|
1022
|
+
queryResult
|
|
1023
|
+
);
|
|
1024
|
+
return "ok";
|
|
1025
|
+
}
|
|
1026
|
+
const needsBearer = Boolean(plan.accessToken) && (queryResult.status === 401 || queryResult.status === 403);
|
|
1027
|
+
if (needsBearer && plan.accessToken) {
|
|
1028
|
+
const bearerResult = await fetchEncryptionKeyBytes(
|
|
1029
|
+
plan.signedKeyUrl,
|
|
1030
|
+
plan.accessToken,
|
|
1031
|
+
signal
|
|
1032
|
+
);
|
|
1033
|
+
if (bearerResult.ok) {
|
|
1034
|
+
reportKeySuccess(
|
|
1035
|
+
{ ...context, url: plan.signedKeyUrl },
|
|
1036
|
+
callbacks,
|
|
1037
|
+
bearerResult
|
|
1038
|
+
);
|
|
1039
|
+
return "ok";
|
|
1040
|
+
}
|
|
1041
|
+
if (bearerResult.cors) {
|
|
1042
|
+
return "try_xhr";
|
|
1043
|
+
}
|
|
867
1044
|
callbacks.onError(
|
|
868
1045
|
{
|
|
869
|
-
code:
|
|
870
|
-
text:
|
|
1046
|
+
code: bearerResult.status,
|
|
1047
|
+
text: bearerResult.text
|
|
871
1048
|
},
|
|
872
|
-
context,
|
|
873
|
-
response,
|
|
1049
|
+
{ ...context, url: plan.signedKeyUrl },
|
|
1050
|
+
bearerResult.response,
|
|
874
1051
|
stats
|
|
875
1052
|
);
|
|
876
|
-
return;
|
|
1053
|
+
return "ok";
|
|
877
1054
|
}
|
|
878
|
-
|
|
1055
|
+
if (queryResult.cors || queryResult.status === 0) {
|
|
1056
|
+
return "try_xhr";
|
|
1057
|
+
}
|
|
1058
|
+
callbacks.onError(
|
|
879
1059
|
{
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
code: response.status
|
|
1060
|
+
code: queryResult.status,
|
|
1061
|
+
text: queryResult.text
|
|
883
1062
|
},
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
1063
|
+
{ ...context, url: plan.signedKeyUrl },
|
|
1064
|
+
queryResult.response,
|
|
1065
|
+
stats
|
|
887
1066
|
);
|
|
1067
|
+
return "ok";
|
|
888
1068
|
}
|
|
889
1069
|
function createAuthParamsLoader(HlsClass, store, options = {}) {
|
|
890
1070
|
const BaseLoader = resolveBuiltinHlsLoader(HlsClass);
|
|
891
|
-
|
|
1071
|
+
rememberBuiltin(HlsClass, BaseLoader);
|
|
1072
|
+
const maxProxyFailures = typeof options.keyProxyMaxFailures === "number" && options.keyProxyMaxFailures >= 0 ? options.keyProxyMaxFailures : KEY_PROXY_MAX_FAILURES;
|
|
1073
|
+
const keyProxyState = { proxyFailures: 0, circuitOpen: false };
|
|
1074
|
+
class AuthParamsLoader {
|
|
892
1075
|
constructor(config) {
|
|
1076
|
+
this.context = null;
|
|
893
1077
|
this.keyAbort = null;
|
|
894
1078
|
this.inner = new BaseLoader(config);
|
|
895
1079
|
this.stats = this.inner.stats;
|
|
@@ -897,14 +1081,16 @@ function createAuthParamsLoader(HlsClass, store, options = {}) {
|
|
|
897
1081
|
abort() {
|
|
898
1082
|
this.keyAbort?.abort();
|
|
899
1083
|
this.keyAbort = null;
|
|
900
|
-
this.inner.abort
|
|
1084
|
+
this.inner.abort();
|
|
901
1085
|
}
|
|
902
1086
|
destroy() {
|
|
903
1087
|
this.keyAbort?.abort();
|
|
904
1088
|
this.keyAbort = null;
|
|
1089
|
+
this.context = null;
|
|
905
1090
|
this.inner.destroy();
|
|
906
1091
|
}
|
|
907
1092
|
load(context, config, callbacks) {
|
|
1093
|
+
this.context = context;
|
|
908
1094
|
if (!context.url) {
|
|
909
1095
|
this.inner.load(context, config, callbacks);
|
|
910
1096
|
return;
|
|
@@ -912,92 +1098,70 @@ function createAuthParamsLoader(HlsClass, store, options = {}) {
|
|
|
912
1098
|
try {
|
|
913
1099
|
const originalUrl = context.url;
|
|
914
1100
|
const isKey = isEncryptionKeyUrl(originalUrl);
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
}) : context.url;
|
|
922
|
-
context.url = rewriteHlsRequestUrl(originalUrl, store, options);
|
|
923
|
-
if (usingKeyProxy) {
|
|
924
|
-
const accessToken = options.getKeyAccessToken?.() ?? null;
|
|
925
|
-
if (!accessToken) {
|
|
926
|
-
this.inner.load(context, config, callbacks);
|
|
927
|
-
return;
|
|
1101
|
+
if (!isKey) {
|
|
1102
|
+
if (store.hasParams()) {
|
|
1103
|
+
context.url = rewriteHlsRequestUrl(originalUrl, store, {
|
|
1104
|
+
...options,
|
|
1105
|
+
keyProxyUrlBuilder: void 0
|
|
1106
|
+
});
|
|
928
1107
|
}
|
|
929
|
-
|
|
930
|
-
...callbacks,
|
|
931
|
-
onError: (error, errContext, networkDetails, stats) => {
|
|
932
|
-
const code = error?.code;
|
|
933
|
-
const retryable = code === 0 || code === 502 || code === 403 || code === 401 || /Cloudflare|HTML|DOCTYPE|blocked/i.test(error?.text ?? "");
|
|
934
|
-
if (!retryable) {
|
|
935
|
-
callbacks.onError(error, errContext, networkDetails, stats);
|
|
936
|
-
return;
|
|
937
|
-
}
|
|
938
|
-
this.keyAbort?.abort();
|
|
939
|
-
this.keyAbort = new AbortController();
|
|
940
|
-
const bearerContext = { ...context, url: signedKeyUrl };
|
|
941
|
-
void loadEncryptionKeyWithFetch(
|
|
942
|
-
bearerContext,
|
|
943
|
-
callbacks,
|
|
944
|
-
accessToken,
|
|
945
|
-
this.keyAbort.signal
|
|
946
|
-
).catch((fetchError) => {
|
|
947
|
-
callbacks.onError(
|
|
948
|
-
{
|
|
949
|
-
code: 0,
|
|
950
|
-
text: fetchError instanceof Error ? fetchError.message : error.text || "enc.key proxy and Bearer fetch failed"
|
|
951
|
-
},
|
|
952
|
-
bearerContext,
|
|
953
|
-
null,
|
|
954
|
-
stats
|
|
955
|
-
);
|
|
956
|
-
});
|
|
957
|
-
}
|
|
958
|
-
};
|
|
959
|
-
this.inner.load(context, config, proxyCallbacks);
|
|
1108
|
+
this.inner.load(context, config, callbacks);
|
|
960
1109
|
return;
|
|
961
1110
|
}
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
}).finally(() => {
|
|
991
|
-
clearTimeout(timer);
|
|
992
|
-
});
|
|
993
|
-
return;
|
|
1111
|
+
const signedKeyUrl = rewriteHlsRequestUrl(originalUrl, store, {
|
|
1112
|
+
...options,
|
|
1113
|
+
keyProxyUrlBuilder: void 0
|
|
1114
|
+
});
|
|
1115
|
+
const proxyConfigured = Boolean(
|
|
1116
|
+
options.keyProxyUrlBuilder && options.videoId
|
|
1117
|
+
);
|
|
1118
|
+
const proxyUrl = proxyConfigured && !keyProxyState.circuitOpen ? rewriteHlsRequestUrl(originalUrl, store, options) : null;
|
|
1119
|
+
const accessToken = options.getKeyAccessToken?.() ?? null;
|
|
1120
|
+
this.keyAbort?.abort();
|
|
1121
|
+
this.keyAbort = new AbortController();
|
|
1122
|
+
const timeoutMs = typeof config?.timeout === "number" && config.timeout > 0 ? config.timeout : 2e4;
|
|
1123
|
+
const timer = setTimeout(() => this.keyAbort?.abort(), timeoutMs);
|
|
1124
|
+
void loadEncryptionKeyEnterprise(
|
|
1125
|
+
context,
|
|
1126
|
+
callbacks,
|
|
1127
|
+
{
|
|
1128
|
+
proxyUrl,
|
|
1129
|
+
signedKeyUrl,
|
|
1130
|
+
accessToken,
|
|
1131
|
+
maxProxyFailures
|
|
1132
|
+
},
|
|
1133
|
+
this.keyAbort.signal,
|
|
1134
|
+
keyProxyState
|
|
1135
|
+
).then((result) => {
|
|
1136
|
+
if (result === "try_xhr") {
|
|
1137
|
+
context.url = signedKeyUrl;
|
|
1138
|
+
this.inner.load(context, config, callbacks);
|
|
994
1139
|
}
|
|
995
|
-
}
|
|
1140
|
+
}).catch((error) => {
|
|
1141
|
+
callbacks.onError(
|
|
1142
|
+
{
|
|
1143
|
+
code: 0,
|
|
1144
|
+
text: error instanceof Error ? error.message : "enc.key load failed"
|
|
1145
|
+
},
|
|
1146
|
+
context,
|
|
1147
|
+
null,
|
|
1148
|
+
createLoaderStats()
|
|
1149
|
+
);
|
|
1150
|
+
}).finally(() => {
|
|
1151
|
+
clearTimeout(timer);
|
|
1152
|
+
});
|
|
1153
|
+
return;
|
|
996
1154
|
} catch {
|
|
997
1155
|
}
|
|
998
1156
|
this.inner.load(context, config, callbacks);
|
|
999
1157
|
}
|
|
1000
|
-
}
|
|
1158
|
+
}
|
|
1159
|
+
Object.defineProperty(AuthParamsLoader, BUILTIN_LOADER_REF, {
|
|
1160
|
+
value: BaseLoader,
|
|
1161
|
+
enumerable: false,
|
|
1162
|
+
configurable: false
|
|
1163
|
+
});
|
|
1164
|
+
return AuthParamsLoader;
|
|
1001
1165
|
}
|
|
1002
1166
|
|
|
1003
1167
|
// src/streaming/HlsEngine.ts
|
|
@@ -1062,7 +1226,8 @@ var HlsEngine = class {
|
|
|
1062
1226
|
const loader = createAuthParamsLoader(Hls, authParams, {
|
|
1063
1227
|
videoId,
|
|
1064
1228
|
keyProxyUrlBuilder,
|
|
1065
|
-
getKeyAccessToken
|
|
1229
|
+
getKeyAccessToken,
|
|
1230
|
+
keyProxyMaxFailures: this.options.keyProxyMaxFailures
|
|
1066
1231
|
});
|
|
1067
1232
|
this.hls = new Hls({
|
|
1068
1233
|
enableWorker: hlsConfig.enableWorker,
|
|
@@ -1486,11 +1651,13 @@ function createVideoPlayer(options) {
|
|
|
1486
1651
|
volume: config.player.volume,
|
|
1487
1652
|
videoId: options.videoId,
|
|
1488
1653
|
keyProxyUrlBuilder: config.streaming.keyProxyUrlBuilder,
|
|
1489
|
-
// Enterprise AES key auth:
|
|
1490
|
-
// 1) keyProxyUrlBuilder
|
|
1491
|
-
// 2)
|
|
1492
|
-
// 3)
|
|
1654
|
+
// Enterprise AES key auth (see authParamsLoader):
|
|
1655
|
+
// 1) keyProxyUrlBuilder BFF — max 2 failures then circuit
|
|
1656
|
+
// 2) signed-query fetch (no Bearer / no CORS preflight)
|
|
1657
|
+
// 3) Bearer only on HTTP 401/403 when getKeyAccessToken is set
|
|
1658
|
+
// 4) signed-query XHR fallback if fetch is CORS-blocked
|
|
1493
1659
|
getKeyAccessToken: config.streaming.getKeyAccessToken ?? (() => authManager.getAccessToken()),
|
|
1660
|
+
keyProxyMaxFailures: config.streaming.keyProxyMaxFailures,
|
|
1494
1661
|
hlsConfig: config.streaming.hls,
|
|
1495
1662
|
logger,
|
|
1496
1663
|
callbacks: {
|
|
@@ -1808,7 +1975,8 @@ function createVideoPlayer(options) {
|
|
|
1808
1975
|
engine: "hls",
|
|
1809
1976
|
hls: { ...config.streaming.hls, ...partial?.streaming?.hls },
|
|
1810
1977
|
keyProxyUrlBuilder: partial?.streaming?.keyProxyUrlBuilder ?? config.streaming.keyProxyUrlBuilder,
|
|
1811
|
-
getKeyAccessToken: partial?.streaming?.getKeyAccessToken ?? config.streaming.getKeyAccessToken ?? (() => authManager.getAccessToken())
|
|
1978
|
+
getKeyAccessToken: partial?.streaming?.getKeyAccessToken ?? config.streaming.getKeyAccessToken ?? (() => authManager.getAccessToken()),
|
|
1979
|
+
keyProxyMaxFailures: partial?.streaming?.keyProxyMaxFailures ?? config.streaming.keyProxyMaxFailures
|
|
1812
1980
|
},
|
|
1813
1981
|
logging: { ...config.logging, ...partial?.logging },
|
|
1814
1982
|
debug: { ...config.debug, ...partial?.debug },
|
|
@@ -1839,6 +2007,7 @@ export {
|
|
|
1839
2007
|
DEFAULT_THEME,
|
|
1840
2008
|
DEFAULT_WATERMARK,
|
|
1841
2009
|
EventEmitter,
|
|
2010
|
+
KEY_PROXY_MAX_FAILURES,
|
|
1842
2011
|
PACKAGE_VERSION,
|
|
1843
2012
|
PLAYBACK_RATES,
|
|
1844
2013
|
PlaybackSourceManager,
|