@oddin-gg/havik-player 1.0.2 → 1.0.4
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 +1 -1
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +66 -54
- package/dist/index.js.map +1 -1
- package/docs/API.md +16 -0
- package/embed/index.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -510,17 +510,17 @@ function I(e, t) {
|
|
|
510
510
|
function L() {
|
|
511
511
|
return e.isSupported();
|
|
512
512
|
}
|
|
513
|
-
var R = 3, z = 5, B = 3, V = 3e4, H = 12e3, U = 3e3, de =
|
|
514
|
-
function
|
|
513
|
+
var R = 3, z = 5, B = 3, V = 3e4, H = 12e3, U = 3e3, de = 6e3, fe = 3, pe = 9;
|
|
514
|
+
function me(e) {
|
|
515
515
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
516
516
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
517
517
|
return;
|
|
518
518
|
}
|
|
519
|
-
e.liveSyncDuration ??=
|
|
520
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
519
|
+
e.liveSyncDuration ??= fe;
|
|
520
|
+
let t = Math.max(12, e.liveSyncDuration + pe);
|
|
521
521
|
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t);
|
|
522
522
|
}
|
|
523
|
-
var
|
|
523
|
+
var he = class {
|
|
524
524
|
name = "hls";
|
|
525
525
|
hls = null;
|
|
526
526
|
deps;
|
|
@@ -538,6 +538,9 @@ var me = class {
|
|
|
538
538
|
lastAdvanceMs = 0;
|
|
539
539
|
endWatchdog = null;
|
|
540
540
|
endedEmitted = !1;
|
|
541
|
+
chaseSuspended = !1;
|
|
542
|
+
savedLiveMaxLatency;
|
|
543
|
+
savedMaxSyncRate;
|
|
541
544
|
constructor(e) {
|
|
542
545
|
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl;
|
|
543
546
|
}
|
|
@@ -584,7 +587,7 @@ var me = class {
|
|
|
584
587
|
} : {},
|
|
585
588
|
...s
|
|
586
589
|
};
|
|
587
|
-
|
|
590
|
+
me(u);
|
|
588
591
|
let d = new e(u);
|
|
589
592
|
this.hls = d, d.on(e.Events.MANIFEST_PARSED, () => {
|
|
590
593
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, c({ type: "ready" });
|
|
@@ -684,20 +687,29 @@ var me = class {
|
|
|
684
687
|
if (t.live === !0) {
|
|
685
688
|
this.sawLive = !0;
|
|
686
689
|
let e = t.endSN ?? -1;
|
|
687
|
-
e !== this.lastEndSN && (this.lastEndSN = e, this.lastAdvanceMs = Date.now());
|
|
690
|
+
e !== this.lastEndSN && (this.lastEndSN = e, this.lastAdvanceMs = Date.now(), this.chaseSuspended && this.resumeChasing());
|
|
688
691
|
return;
|
|
689
692
|
}
|
|
690
693
|
this.sawLive && this.emitEnded("endlist");
|
|
691
694
|
}
|
|
692
695
|
}
|
|
693
696
|
checkEndStale() {
|
|
694
|
-
if (
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
}
|
|
699
|
-
Date.now() - this.lastAdvanceMs > H && this.emitEnded("stalled");
|
|
697
|
+
if (this.endedEmitted || !this.sawLive || this.lastAdvanceMs === 0) return;
|
|
698
|
+
if (typeof document < "u" && document.hidden) {
|
|
699
|
+
this.lastAdvanceMs = Date.now();
|
|
700
|
+
return;
|
|
700
701
|
}
|
|
702
|
+
let e = Date.now() - this.lastAdvanceMs;
|
|
703
|
+
!this.chaseSuspended && e > de && this.suspendChasing(), e > H && this.emitEnded("stalled");
|
|
704
|
+
}
|
|
705
|
+
suspendChasing() {
|
|
706
|
+
let e = this.hls;
|
|
707
|
+
e && (this.chaseSuspended = !0, this.savedLiveMaxLatency = e.config.liveMaxLatencyDuration, this.savedMaxSyncRate = e.config.maxLiveSyncPlaybackRate, e.config.liveMaxLatencyDuration = 2 ** 53 - 1, e.config.maxLiveSyncPlaybackRate = 1);
|
|
708
|
+
}
|
|
709
|
+
resumeChasing() {
|
|
710
|
+
this.chaseSuspended = !1;
|
|
711
|
+
let e = this.hls;
|
|
712
|
+
e && (e.config.liveMaxLatencyDuration = this.savedLiveMaxLatency, e.config.maxLiveSyncPlaybackRate = this.savedMaxSyncRate);
|
|
701
713
|
}
|
|
702
714
|
emitEnded(e) {
|
|
703
715
|
this.endedEmitted || (this.endedEmitted = !0, this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.deps.emit({
|
|
@@ -799,7 +811,7 @@ var me = class {
|
|
|
799
811
|
};
|
|
800
812
|
//#endregion
|
|
801
813
|
//#region src/core/engine/native.ts
|
|
802
|
-
function
|
|
814
|
+
function ge(e) {
|
|
803
815
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
804
816
|
}
|
|
805
817
|
var W = class {
|
|
@@ -930,15 +942,15 @@ function q(e, t) {
|
|
|
930
942
|
}
|
|
931
943
|
//#endregion
|
|
932
944
|
//#region src/ui/styles.ts
|
|
933
|
-
var J = "havik-player-styles",
|
|
934
|
-
function
|
|
945
|
+
var J = "havik-player-styles", _e = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:rgba(255,255,255,.3);border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:70px;opacity:1}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:50%;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
|
|
946
|
+
function ve(e = document) {
|
|
935
947
|
if (e.getElementById(J)) return;
|
|
936
948
|
let t = e.createElement("style");
|
|
937
|
-
t.id = J, t.textContent =
|
|
949
|
+
t.id = J, t.textContent = _e, e.head.appendChild(t);
|
|
938
950
|
}
|
|
939
951
|
//#endregion
|
|
940
952
|
//#region src/ui/icons.ts
|
|
941
|
-
var
|
|
953
|
+
var ye = {
|
|
942
954
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
943
955
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
944
956
|
volumeHigh: "<path d=\"M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4zm-2.5-9v2.06A7 7 0 0 1 14 19v2a9 9 0 0 0 0-18z\"/>",
|
|
@@ -952,20 +964,20 @@ var ve = {
|
|
|
952
964
|
retry: "<path d=\"M17.65 6.35A8 8 0 1 0 19.73 13h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>"
|
|
953
965
|
};
|
|
954
966
|
function Y(e) {
|
|
955
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
967
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${ye[e]}</svg>`;
|
|
956
968
|
}
|
|
957
969
|
//#endregion
|
|
958
970
|
//#region src/ui/controls.ts
|
|
959
|
-
var
|
|
971
|
+
var be = 3e3, xe = /* @__PURE__ */ new Set([
|
|
960
972
|
"GONE",
|
|
961
973
|
"NOT_FOUND",
|
|
962
974
|
"INVALID_URN",
|
|
963
975
|
"UNAUTHORIZED"
|
|
964
976
|
]);
|
|
965
|
-
function
|
|
966
|
-
return new
|
|
977
|
+
function Se(e) {
|
|
978
|
+
return new Ce(e);
|
|
967
979
|
}
|
|
968
|
-
var
|
|
980
|
+
var Ce = class {
|
|
969
981
|
root;
|
|
970
982
|
video;
|
|
971
983
|
player;
|
|
@@ -1005,7 +1017,7 @@ var Se = class {
|
|
|
1005
1017
|
scrubbing = !1;
|
|
1006
1018
|
offFns = [];
|
|
1007
1019
|
constructor(e) {
|
|
1008
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
1020
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? be, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.errorMessage = e.errorMessage, ve(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
1009
1021
|
let t = (e, t, n) => {
|
|
1010
1022
|
let r = this.doc.createElement(e);
|
|
1011
1023
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1092,7 +1104,7 @@ var Se = class {
|
|
|
1092
1104
|
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Y("play"), e.addEventListener("click", () => void this.player.play()), t.append(e);
|
|
1093
1105
|
} else {
|
|
1094
1106
|
let n = this.doc.createElement("div");
|
|
1095
|
-
if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !
|
|
1107
|
+
if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !xe.has(this.lastError.code)) {
|
|
1096
1108
|
let e = this.doc.createElement("button");
|
|
1097
1109
|
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Y("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), t.append(e);
|
|
1098
1110
|
}
|
|
@@ -1181,17 +1193,17 @@ var Se = class {
|
|
|
1181
1193
|
renderQualityMenu() {
|
|
1182
1194
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
1183
1195
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
1184
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
1196
|
+
for (let n of e) this.menu.append(this.menuItem(we(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
1185
1197
|
}
|
|
1186
1198
|
renderAudioMenu() {
|
|
1187
1199
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
1188
1200
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
1189
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1201
|
+
for (let t of e) this.menu.append(this.menuItem(Te(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
1190
1202
|
}
|
|
1191
1203
|
renderCcMenu() {
|
|
1192
1204
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
1193
1205
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
1194
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1206
|
+
for (let t of e) this.menu.append(this.menuItem(Ee(t), !1, () => this.player.setTextTrack(t.id)));
|
|
1195
1207
|
}
|
|
1196
1208
|
onTracksChanged() {
|
|
1197
1209
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -1297,27 +1309,27 @@ function X(e) {
|
|
|
1297
1309
|
let t = Math.floor(e % 60), n = Math.floor(e / 60 % 60), r = Math.floor(e / 3600), i = r > 0 ? String(n).padStart(2, "0") : String(n), a = String(t).padStart(2, "0");
|
|
1298
1310
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
1299
1311
|
}
|
|
1300
|
-
function
|
|
1312
|
+
function we(e) {
|
|
1301
1313
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
1302
1314
|
}
|
|
1303
|
-
function
|
|
1315
|
+
function Te(e) {
|
|
1304
1316
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1305
1317
|
}
|
|
1306
|
-
function
|
|
1318
|
+
function Ee(e) {
|
|
1307
1319
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1308
1320
|
}
|
|
1309
1321
|
//#endregion
|
|
1310
1322
|
//#region src/managed/index.ts
|
|
1311
|
-
var
|
|
1323
|
+
var De = 6e3, Oe = 45e3, ke = 2e3, Z = 3, Ae = 2e3, je = 480 * 1e3;
|
|
1312
1324
|
async function Q(e) {
|
|
1313
1325
|
if (!e.video || typeof e.video.play != "function") throw new t("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
1314
1326
|
if (!e.baseUrl) throw new t("INTERNAL", 0, "createPlayer: baseUrl is required");
|
|
1315
1327
|
if (!e.matchUrn) throw new t("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
1316
1328
|
if (!e.credential) throw new t("INTERNAL", 0, "createPlayer: credential is required");
|
|
1317
|
-
let n = new
|
|
1329
|
+
let n = new Me(e);
|
|
1318
1330
|
return await n.start(), n;
|
|
1319
1331
|
}
|
|
1320
|
-
var
|
|
1332
|
+
var Me = class {
|
|
1321
1333
|
opts;
|
|
1322
1334
|
abort = new AbortController();
|
|
1323
1335
|
listeners = {};
|
|
@@ -1396,13 +1408,13 @@ var je = class {
|
|
|
1396
1408
|
!r && !s() && l();
|
|
1397
1409
|
}, e);
|
|
1398
1410
|
};
|
|
1399
|
-
d(
|
|
1411
|
+
d(De), this.armingSub = w({
|
|
1400
1412
|
eventsBaseUrl: n,
|
|
1401
1413
|
matchUrn: this.opts.matchUrn,
|
|
1402
1414
|
credential: this.opts.credential,
|
|
1403
|
-
onAlive: () => d(
|
|
1415
|
+
onAlive: () => d(Oe),
|
|
1404
1416
|
onState: (e) => {
|
|
1405
|
-
r || s() || (e.state === "live" || e.state === "gone") && setTimeout(u, Math.random() *
|
|
1417
|
+
r || s() || (e.state === "live" || e.state === "gone") && setTimeout(u, Math.random() * ke);
|
|
1406
1418
|
},
|
|
1407
1419
|
onError: () => l()
|
|
1408
1420
|
});
|
|
@@ -1447,8 +1459,8 @@ var je = class {
|
|
|
1447
1459
|
emit: (e) => this.onEngineEvent(e)
|
|
1448
1460
|
}, a = this.opts.engine ?? "auto";
|
|
1449
1461
|
if (a === "native") return new W(i);
|
|
1450
|
-
if (a === "hls" || L()) return new
|
|
1451
|
-
if (
|
|
1462
|
+
if (a === "hls" || L()) return new he(i);
|
|
1463
|
+
if (ge(this.opts.video)) return new W(i);
|
|
1452
1464
|
throw new t("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
1453
1465
|
}
|
|
1454
1466
|
onEngineEvent(e) {
|
|
@@ -1493,7 +1505,7 @@ var je = class {
|
|
|
1493
1505
|
r = 0, i = !1;
|
|
1494
1506
|
},
|
|
1495
1507
|
onError: () => {
|
|
1496
|
-
this.destroyed || e !== this.loadGen || i || (r += 1, r >=
|
|
1508
|
+
this.destroyed || e !== this.loadGen || i || (r += 1, r >= Z && (i = !0, this.emit("warning", new t("NETWORK", 0, `live-state events unreachable at ${n} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
|
|
1497
1509
|
}
|
|
1498
1510
|
});
|
|
1499
1511
|
}
|
|
@@ -1515,7 +1527,7 @@ var je = class {
|
|
|
1515
1527
|
}
|
|
1516
1528
|
t.controls = !1;
|
|
1517
1529
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
1518
|
-
r && r.insertBefore(n, t), n.appendChild(t), q(n, this.opts.theme), this.container = n, this.controlBar =
|
|
1530
|
+
r && r.insertBefore(n, t), n.appendChild(t), q(n, this.opts.theme), this.container = n, this.controlBar = Se({
|
|
1519
1531
|
root: n,
|
|
1520
1532
|
video: t,
|
|
1521
1533
|
player: this,
|
|
@@ -1538,7 +1550,7 @@ var je = class {
|
|
|
1538
1550
|
}
|
|
1539
1551
|
startStats() {
|
|
1540
1552
|
this.stopStats();
|
|
1541
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
1553
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Ae);
|
|
1542
1554
|
this.statsTimer = setInterval(() => {
|
|
1543
1555
|
this.engine && this.emit("stats", this.engine.getStats());
|
|
1544
1556
|
}, e);
|
|
@@ -1548,7 +1560,7 @@ var je = class {
|
|
|
1548
1560
|
}
|
|
1549
1561
|
scheduleLicenseRefresh() {
|
|
1550
1562
|
this.stopRefresh();
|
|
1551
|
-
let e = this.opts.licenseRefreshMs ??
|
|
1563
|
+
let e = this.opts.licenseRefreshMs ?? je;
|
|
1552
1564
|
!e || !this._descriptor?.drmEnabled || (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
1553
1565
|
}
|
|
1554
1566
|
stopRefresh() {
|
|
@@ -1683,7 +1695,7 @@ function $(e) {
|
|
|
1683
1695
|
}
|
|
1684
1696
|
//#endregion
|
|
1685
1697
|
//#region src/embed/host.ts
|
|
1686
|
-
function
|
|
1698
|
+
function Ne(e) {
|
|
1687
1699
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
1688
1700
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
1689
1701
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -1742,8 +1754,8 @@ function Me(e) {
|
|
|
1742
1754
|
}
|
|
1743
1755
|
//#endregion
|
|
1744
1756
|
//#region src/embed/page.ts
|
|
1745
|
-
var
|
|
1746
|
-
function
|
|
1757
|
+
var Pe = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
1758
|
+
function Fe() {
|
|
1747
1759
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
1748
1760
|
if (e) return {
|
|
1749
1761
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -1765,9 +1777,9 @@ function Pe() {
|
|
|
1765
1777
|
waitForLive: !0
|
|
1766
1778
|
};
|
|
1767
1779
|
}
|
|
1768
|
-
async function
|
|
1769
|
-
let e =
|
|
1770
|
-
|
|
1780
|
+
async function Ie() {
|
|
1781
|
+
let e = Fe();
|
|
1782
|
+
Re();
|
|
1771
1783
|
let n = document.createElement("video");
|
|
1772
1784
|
n.setAttribute("playsinline", ""), n.muted = e.muted ?? !0, n.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(n);
|
|
1773
1785
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -1822,7 +1834,7 @@ async function Fe() {
|
|
|
1822
1834
|
code: e.code,
|
|
1823
1835
|
message: e.message
|
|
1824
1836
|
})), e.on("autoplayblocked", () => {
|
|
1825
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
1837
|
+
i({ type: "oddin:autoplayblocked" }), Le(n, e);
|
|
1826
1838
|
});
|
|
1827
1839
|
}, s = async (r) => {
|
|
1828
1840
|
a?.destroy(), a = null;
|
|
@@ -1888,7 +1900,7 @@ async function Fe() {
|
|
|
1888
1900
|
a?.retry();
|
|
1889
1901
|
break;
|
|
1890
1902
|
case "oddin:load":
|
|
1891
|
-
typeof e.matchUrn == "string" &&
|
|
1903
|
+
typeof e.matchUrn == "string" && Pe.test(e.matchUrn) && s(e.matchUrn);
|
|
1892
1904
|
break;
|
|
1893
1905
|
case "oddin:destroy":
|
|
1894
1906
|
c();
|
|
@@ -1902,18 +1914,18 @@ async function Fe() {
|
|
|
1902
1914
|
protocol: 1
|
|
1903
1915
|
});
|
|
1904
1916
|
}
|
|
1905
|
-
function
|
|
1917
|
+
function Le(e, t) {
|
|
1906
1918
|
if (document.getElementById("havik-tap")) return;
|
|
1907
1919
|
let n = document.createElement("button");
|
|
1908
1920
|
n.id = "havik-tap", n.textContent = "▶ Tap to play", n.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:0;background:rgba(0,0,0,.55);color:#fff;font:600 18px system-ui,sans-serif;cursor:pointer;z-index:9", n.addEventListener("click", () => {
|
|
1909
1921
|
n.remove(), t.play();
|
|
1910
1922
|
}), document.body.appendChild(n);
|
|
1911
1923
|
}
|
|
1912
|
-
function
|
|
1924
|
+
function Re() {
|
|
1913
1925
|
let e = document.createElement("style");
|
|
1914
1926
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
1915
1927
|
}
|
|
1916
1928
|
//#endregion
|
|
1917
|
-
export { G as ODDIN_THEME, t as PlaybackError, q as applyTheme,
|
|
1929
|
+
export { G as ODDIN_THEME, t as PlaybackError, q as applyTheme, Ie as bootEmbed, k as clearDeviceId, Q as createPlayer, T as deriveEventsBaseUrl, oe as fetchCatalog, ce as fetchTournament, ue as flattenMatches, O as getDeviceId, N as isLowLatencyManifest, $ as isOddinMessage, j as licenseRequestHeaders, Ne as mountEmbed, y as pollToLive, x as resolveStream, w as subscribeLiveState, C as watchStatus };
|
|
1918
1930
|
|
|
1919
1931
|
//# sourceMappingURL=index.js.map
|