@oddin-gg/havik-player 2.0.4 → 2.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/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.d.cts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +426 -165
- package/dist/index.js.map +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -616,11 +616,15 @@ function Ce(e) {
|
|
|
616
616
|
}
|
|
617
617
|
//#endregion
|
|
618
618
|
//#region src/core/stats.ts
|
|
619
|
-
var
|
|
620
|
-
function
|
|
621
|
-
|
|
619
|
+
var we = { droppedFrames: 0 };
|
|
620
|
+
function F(e) {
|
|
621
|
+
let t = e.getVideoPlaybackQuality?.();
|
|
622
|
+
return {
|
|
623
|
+
dropped: t?.droppedVideoFrames ?? 0,
|
|
624
|
+
decoded: t?.totalVideoFrames ?? 0
|
|
625
|
+
};
|
|
622
626
|
}
|
|
623
|
-
function
|
|
627
|
+
function Te(e, t) {
|
|
624
628
|
let n = [
|
|
625
629
|
["playing", () => t("playing")],
|
|
626
630
|
["waiting", () => t("buffering")],
|
|
@@ -637,7 +641,7 @@ function we(e, t) {
|
|
|
637
641
|
}
|
|
638
642
|
//#endregion
|
|
639
643
|
//#region src/core/engine/native.ts
|
|
640
|
-
function
|
|
644
|
+
function Ee(e) {
|
|
641
645
|
try {
|
|
642
646
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
643
647
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -645,15 +649,15 @@ function Te(e) {
|
|
|
645
649
|
return;
|
|
646
650
|
}
|
|
647
651
|
}
|
|
648
|
-
function
|
|
652
|
+
function I(e) {
|
|
649
653
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
650
654
|
}
|
|
651
|
-
function
|
|
655
|
+
function L() {
|
|
652
656
|
if (typeof window > "u") return !1;
|
|
653
657
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
654
658
|
return e || t;
|
|
655
659
|
}
|
|
656
|
-
var
|
|
660
|
+
var R = class {
|
|
657
661
|
name = "native";
|
|
658
662
|
deps;
|
|
659
663
|
onLoaded;
|
|
@@ -687,7 +691,7 @@ var z = class {
|
|
|
687
691
|
type: "error",
|
|
688
692
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
689
693
|
fatal: !0
|
|
690
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
694
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = De(t.manifestUrl, t.analytics?.sid), e.load();
|
|
691
695
|
}
|
|
692
696
|
startLoad() {
|
|
693
697
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -709,7 +713,7 @@ var z = class {
|
|
|
709
713
|
});
|
|
710
714
|
this.onEncrypted = (n) => {
|
|
711
715
|
let i = n;
|
|
712
|
-
!i.initData || this.fairplayArmed || (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
716
|
+
!i.initData || this.fairplayArmed || (this.fairplayArmed = !0, this.fairplayKeyIV = Ee(i.initData), (async () => {
|
|
713
717
|
try {
|
|
714
718
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
715
719
|
initDataTypes: [i.initDataType],
|
|
@@ -804,8 +808,11 @@ var z = class {
|
|
|
804
808
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
805
809
|
}
|
|
806
810
|
getStats() {
|
|
807
|
-
let e = this.deps.video, t =
|
|
808
|
-
|
|
811
|
+
let e = this.deps.video, t = F(e), n = {
|
|
812
|
+
droppedFrames: t.dropped,
|
|
813
|
+
decodedFrames: t.decoded
|
|
814
|
+
};
|
|
815
|
+
return this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity && (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), n;
|
|
809
816
|
}
|
|
810
817
|
stop() {
|
|
811
818
|
try {
|
|
@@ -824,29 +831,36 @@ var z = class {
|
|
|
824
831
|
} catch {}
|
|
825
832
|
}
|
|
826
833
|
};
|
|
827
|
-
function
|
|
834
|
+
function De(e, t) {
|
|
828
835
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
829
836
|
}
|
|
830
837
|
//#endregion
|
|
831
838
|
//#region src/core/engine/hls.ts
|
|
832
|
-
function
|
|
839
|
+
function Oe() {
|
|
833
840
|
return e.isSupported();
|
|
834
841
|
}
|
|
835
|
-
var
|
|
836
|
-
function
|
|
842
|
+
var ke = 3, Ae = 5, je = 3, Me = 3e4, Ne = 12e3, Pe = 3e3, z = 6e3, Fe = 4e3, Ie = 2, Le = 5, Re = 2, ze = 2, Be = 2e3, Ve = 3e4, He = 2, Ue = 9, We = .5, Ge = 64;
|
|
843
|
+
function Ke(e) {
|
|
844
|
+
try {
|
|
845
|
+
return new URL(e).host;
|
|
846
|
+
} catch {
|
|
847
|
+
return "";
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
function qe(e) {
|
|
837
851
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
838
852
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
839
853
|
return;
|
|
840
854
|
}
|
|
841
|
-
e.liveSyncDuration ??=
|
|
842
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
843
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
855
|
+
e.liveSyncDuration ??= He;
|
|
856
|
+
let t = Math.max(12, e.liveSyncDuration + Ue);
|
|
857
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Je(e, e.liveSyncDuration);
|
|
844
858
|
}
|
|
845
|
-
function
|
|
859
|
+
function Je(e, t) {
|
|
846
860
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
847
861
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
848
862
|
}
|
|
849
|
-
var
|
|
863
|
+
var B = class {
|
|
850
864
|
name = "hls";
|
|
851
865
|
hls = null;
|
|
852
866
|
deps;
|
|
@@ -856,6 +870,16 @@ var V = class {
|
|
|
856
870
|
playlistBytesLoaded = 0;
|
|
857
871
|
renditionSwitches = 0;
|
|
858
872
|
licenseTimeMs = 0;
|
|
873
|
+
licenseRequested = !1;
|
|
874
|
+
upshifts = 0;
|
|
875
|
+
downshifts = 0;
|
|
876
|
+
lastLevelIndex = -1;
|
|
877
|
+
requestCount = 0;
|
|
878
|
+
requestErrors = 0;
|
|
879
|
+
requestTimesMs = [];
|
|
880
|
+
cdnHost = "";
|
|
881
|
+
ladderHeights;
|
|
882
|
+
ladderTopBitrateKbps = 0;
|
|
859
883
|
mediaRecoveries = 0;
|
|
860
884
|
networkRecoveries = 0;
|
|
861
885
|
licenseRecoveries = 0;
|
|
@@ -890,7 +914,7 @@ var V = class {
|
|
|
890
914
|
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
891
915
|
}
|
|
892
916
|
async load() {
|
|
893
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
917
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = I(r) && L(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
894
918
|
if (e.drmEnabled && !o) {
|
|
895
919
|
i({
|
|
896
920
|
type: "error",
|
|
@@ -930,7 +954,7 @@ var V = class {
|
|
|
930
954
|
let t = e.liveSyncPosition;
|
|
931
955
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
932
956
|
let { video: n } = this.deps;
|
|
933
|
-
n.currentTime <= t +
|
|
957
|
+
n.currentTime <= t + We || (n.currentTime = t);
|
|
934
958
|
}
|
|
935
959
|
startHls() {
|
|
936
960
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -955,7 +979,7 @@ var V = class {
|
|
|
955
979
|
audioEncryptionScheme: "cbcs"
|
|
956
980
|
},
|
|
957
981
|
licenseXhrSetup: (e, t) => {
|
|
958
|
-
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a);
|
|
982
|
+
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0;
|
|
959
983
|
let o = performance.now();
|
|
960
984
|
e.addEventListener("loadend", () => {
|
|
961
985
|
this.licenseTimeMs = Math.max(1, Math.round(performance.now() - o));
|
|
@@ -969,19 +993,28 @@ var V = class {
|
|
|
969
993
|
} } : {},
|
|
970
994
|
...c
|
|
971
995
|
};
|
|
972
|
-
|
|
996
|
+
qe(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
973
997
|
let f = new e(d);
|
|
974
998
|
this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
975
|
-
this.mediaRecoveries = 0, this.networkRecoveries = 0
|
|
999
|
+
this.mediaRecoveries = 0, this.networkRecoveries = 0;
|
|
1000
|
+
let e = f.levels.map((e) => e.height).filter((e) => !!e);
|
|
1001
|
+
this.ladderHeights = e.length ? [...new Set(e)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = f.levels.length ? Math.round(Math.max(...f.levels.map((e) => e.bitrate)) / 1e3) : 0, this.applySizeCap(), l({ type: "ready" });
|
|
976
1002
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
977
1003
|
t?.frag?.type === "main" && (this.kickPending = !1, this.kickTicks = 0, (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
978
1004
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
979
|
-
},
|
|
1005
|
+
}, Me)));
|
|
980
1006
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
981
1007
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
982
1008
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
983
|
-
let n = t?.frag?.stats?.loaded;
|
|
984
|
-
typeof
|
|
1009
|
+
let n = t?.frag?.stats, r = n?.loaded;
|
|
1010
|
+
typeof r == "number" && (this.bytesLoaded += r);
|
|
1011
|
+
let i = n?.loading;
|
|
1012
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Ge && this.requestTimesMs.shift());
|
|
1013
|
+
let a = t?.frag?.url;
|
|
1014
|
+
if (a) {
|
|
1015
|
+
let e = Ke(a);
|
|
1016
|
+
e && (this.cdnHost = e);
|
|
1017
|
+
}
|
|
985
1018
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
986
1019
|
let n = t?.stats?.loaded;
|
|
987
1020
|
if (typeof n == "number" && (this.playlistBytesLoaded += n), this.detectedLowLatency) return;
|
|
@@ -992,8 +1025,10 @@ var V = class {
|
|
|
992
1025
|
}));
|
|
993
1026
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
994
1027
|
this.checkEndStale(), this.checkStarvation();
|
|
995
|
-
},
|
|
996
|
-
this.renditionSwitches += 1
|
|
1028
|
+
}, Pe), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1029
|
+
this.renditionSwitches += 1;
|
|
1030
|
+
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1031
|
+
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
997
1032
|
type: "qualitychange",
|
|
998
1033
|
index: t.level
|
|
999
1034
|
});
|
|
@@ -1054,7 +1089,7 @@ var V = class {
|
|
|
1054
1089
|
return;
|
|
1055
1090
|
}
|
|
1056
1091
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1057
|
-
let t = e > this.sizeCapLevel ?
|
|
1092
|
+
let t = e > this.sizeCapLevel ? Be : Ve;
|
|
1058
1093
|
this.capTimer = setTimeout(() => {
|
|
1059
1094
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1060
1095
|
}, t);
|
|
@@ -1101,20 +1136,28 @@ var V = class {
|
|
|
1101
1136
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1102
1137
|
}
|
|
1103
1138
|
getStats() {
|
|
1104
|
-
let e = this.hls, t = {
|
|
1105
|
-
droppedFrames:
|
|
1139
|
+
let e = this.hls, t = F(this.deps.video), n = {
|
|
1140
|
+
droppedFrames: t.dropped,
|
|
1141
|
+
decodedFrames: t.decoded,
|
|
1106
1142
|
lowLatency: this.detectedLowLatency,
|
|
1107
1143
|
bytesLoaded: this.bytesLoaded,
|
|
1108
1144
|
playlistBytesLoaded: this.playlistBytesLoaded,
|
|
1109
1145
|
renditionSwitches: this.renditionSwitches,
|
|
1110
|
-
licenseTimeMs: this.licenseTimeMs
|
|
1146
|
+
licenseTimeMs: this.licenseTimeMs,
|
|
1147
|
+
upshifts: this.upshifts,
|
|
1148
|
+
downshifts: this.downshifts,
|
|
1149
|
+
requestCount: this.requestCount,
|
|
1150
|
+
requestErrors: this.requestErrors,
|
|
1151
|
+
requestTimesMs: [...this.requestTimesMs],
|
|
1152
|
+
ladderHeights: this.ladderHeights,
|
|
1153
|
+
ladderTopBitrateKbps: this.ladderTopBitrateKbps || void 0
|
|
1111
1154
|
};
|
|
1112
|
-
if (e) {
|
|
1113
|
-
typeof e.latency == "number" && (
|
|
1114
|
-
let
|
|
1115
|
-
|
|
1155
|
+
if (this.cdnHost && (n.cdnHost = this.cdnHost), this.licenseRequested && (n.keySystem = "widevine", n.drmSecurityLevel = "L3"), e) {
|
|
1156
|
+
n.qualityPinned = !e.autoLevelEnabled, typeof e.latency == "number" && (n.latencySeconds = e.latency), typeof e.targetLatency == "number" && e.targetLatency > 0 && (n.targetLatencySeconds = e.targetLatency), typeof e.bandwidthEstimate == "number" && (n.bandwidthKbps = Math.round(e.bandwidthEstimate / 1e3));
|
|
1157
|
+
let t = e.currentLevel >= 0 ? e.levels[e.currentLevel] : void 0;
|
|
1158
|
+
t && (n.levelHeight = t.height), t?.videoCodec && (n.videoCodec = t.videoCodec), t?.audioCodec && (n.audioCodec = t.audioCodec), t && typeof t.bitrate == "number" && (n.renditionBitrateKbps = Math.round(t.bitrate / 1e3)), typeof t?.details?.live == "boolean" && (n.isLive = t.details.live, typeof e.liveSyncPosition == "number" && (n.atLiveEdge = this.deps.video.currentTime >= e.liveSyncPosition - 1.5));
|
|
1116
1159
|
}
|
|
1117
|
-
return
|
|
1160
|
+
return n;
|
|
1118
1161
|
}
|
|
1119
1162
|
trackEnd(e) {
|
|
1120
1163
|
let t = e.details;
|
|
@@ -1135,7 +1178,7 @@ var V = class {
|
|
|
1135
1178
|
return;
|
|
1136
1179
|
}
|
|
1137
1180
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1138
|
-
!this.chaseSuspended && e >
|
|
1181
|
+
!this.chaseSuspended && e > z && this.suspendChasing(), e > Ne && this.emitEnded("stalled");
|
|
1139
1182
|
}
|
|
1140
1183
|
checkStarvation() {
|
|
1141
1184
|
let e = this.hls, { video: t } = this.deps;
|
|
@@ -1144,17 +1187,17 @@ var V = class {
|
|
|
1144
1187
|
this.starvedTicks = 0;
|
|
1145
1188
|
return;
|
|
1146
1189
|
}
|
|
1147
|
-
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs <
|
|
1190
|
+
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < z, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > Fe;
|
|
1148
1191
|
if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
|
|
1149
1192
|
this.starvedTicks = 0;
|
|
1150
1193
|
return;
|
|
1151
1194
|
}
|
|
1152
|
-
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks <
|
|
1153
|
-
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >=
|
|
1195
|
+
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < Ie)) {
|
|
1196
|
+
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Re && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < ze)) {
|
|
1154
1197
|
this.starvationRebuilds += 1, console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
|
|
1155
1198
|
return;
|
|
1156
1199
|
}
|
|
1157
|
-
if (!(this.starvationKicks >=
|
|
1200
|
+
if (!(this.starvationKicks >= Le)) {
|
|
1158
1201
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
1159
1202
|
try {
|
|
1160
1203
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1204,7 +1247,7 @@ var V = class {
|
|
|
1204
1247
|
scheduleLicenseRetry(t) {
|
|
1205
1248
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1206
1249
|
let n = t.response?.code ?? 0;
|
|
1207
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1250
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= je) return !1;
|
|
1208
1251
|
this.licenseRecoveries += 1;
|
|
1209
1252
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1210
1253
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1222,7 +1265,7 @@ var V = class {
|
|
|
1222
1265
|
}
|
|
1223
1266
|
}
|
|
1224
1267
|
onError(t) {
|
|
1225
|
-
if (!t.fatal) return;
|
|
1268
|
+
if (t.type === e.ErrorTypes.NETWORK_ERROR && String(t.details ?? "").startsWith("frag") && (this.requestErrors += 1), !t.fatal) return;
|
|
1226
1269
|
let n = this.hls;
|
|
1227
1270
|
if (n) {
|
|
1228
1271
|
if (this.clearRecoveryReset(), t.type === e.ErrorTypes.KEY_SYSTEM_ERROR) {
|
|
@@ -1230,12 +1273,13 @@ var V = class {
|
|
|
1230
1273
|
this.deps.emit({
|
|
1231
1274
|
type: "error",
|
|
1232
1275
|
error: this.toError(t, "DRM"),
|
|
1233
|
-
fatal: !0
|
|
1276
|
+
fatal: !0,
|
|
1277
|
+
detail: t.details
|
|
1234
1278
|
});
|
|
1235
1279
|
return;
|
|
1236
1280
|
}
|
|
1237
1281
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1238
|
-
if (this.networkRecoveries <
|
|
1282
|
+
if (this.networkRecoveries < Ae) {
|
|
1239
1283
|
this.networkRecoveries += 1;
|
|
1240
1284
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1241
1285
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1246,26 +1290,29 @@ var V = class {
|
|
|
1246
1290
|
this.deps.emit({
|
|
1247
1291
|
type: "error",
|
|
1248
1292
|
error: this.toError(t, "NETWORK"),
|
|
1249
|
-
fatal: !0
|
|
1293
|
+
fatal: !0,
|
|
1294
|
+
detail: t.details
|
|
1250
1295
|
});
|
|
1251
1296
|
return;
|
|
1252
1297
|
}
|
|
1253
1298
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1254
|
-
if (this.mediaRecoveries <
|
|
1299
|
+
if (this.mediaRecoveries < ke) {
|
|
1255
1300
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1256
1301
|
return;
|
|
1257
1302
|
}
|
|
1258
1303
|
this.deps.emit({
|
|
1259
1304
|
type: "error",
|
|
1260
1305
|
error: this.toError(t),
|
|
1261
|
-
fatal: !0
|
|
1306
|
+
fatal: !0,
|
|
1307
|
+
detail: t.details
|
|
1262
1308
|
});
|
|
1263
1309
|
return;
|
|
1264
1310
|
}
|
|
1265
1311
|
this.deps.emit({
|
|
1266
1312
|
type: "error",
|
|
1267
1313
|
error: this.toError(t),
|
|
1268
|
-
fatal: !0
|
|
1314
|
+
fatal: !0,
|
|
1315
|
+
detail: t.details
|
|
1269
1316
|
});
|
|
1270
1317
|
}
|
|
1271
1318
|
}
|
|
@@ -1273,7 +1320,29 @@ var V = class {
|
|
|
1273
1320
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1274
1321
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1275
1322
|
}
|
|
1276
|
-
},
|
|
1323
|
+
}, Ye = 15e3, Xe = 100, V = 1, Ze = 1e3, H = 3e4, Qe = {
|
|
1324
|
+
inline: "PRESENTATION_INLINE",
|
|
1325
|
+
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1326
|
+
pip: "PRESENTATION_PIP"
|
|
1327
|
+
}, $e = {
|
|
1328
|
+
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1329
|
+
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1330
|
+
none: "KEY_SYSTEM_NONE"
|
|
1331
|
+
};
|
|
1332
|
+
function U(e, t) {
|
|
1333
|
+
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1334
|
+
}
|
|
1335
|
+
var et = /* @__PURE__ */ new Set([
|
|
1336
|
+
"INVALID_URN",
|
|
1337
|
+
"NOT_FOUND",
|
|
1338
|
+
"GONE",
|
|
1339
|
+
"TOO_EARLY",
|
|
1340
|
+
"UNAVAILABLE",
|
|
1341
|
+
"UNAUTHORIZED",
|
|
1342
|
+
"FORBIDDEN",
|
|
1343
|
+
"RATE_LIMITED",
|
|
1344
|
+
"TIMEOUT"
|
|
1345
|
+
]), W = {
|
|
1277
1346
|
idle: "PLAYER_STATE_IDLE",
|
|
1278
1347
|
waiting: "PLAYER_STATE_WAITING",
|
|
1279
1348
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -1283,7 +1352,7 @@ var V = class {
|
|
|
1283
1352
|
ended: "PLAYER_STATE_ENDED",
|
|
1284
1353
|
error: "PLAYER_STATE_ERROR"
|
|
1285
1354
|
};
|
|
1286
|
-
function
|
|
1355
|
+
function tt(e) {
|
|
1287
1356
|
try {
|
|
1288
1357
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1289
1358
|
return !n || r.length === 0 || n !== "feed" && !n.startsWith("feed-") ? void 0 : (t.hostname = [n.replace(/^feed/, "beacons"), ...r].join("."), t.pathname = "", t.search = "", t.origin);
|
|
@@ -1291,7 +1360,7 @@ function Je(e) {
|
|
|
1291
1360
|
return;
|
|
1292
1361
|
}
|
|
1293
1362
|
}
|
|
1294
|
-
var
|
|
1363
|
+
var nt = class {
|
|
1295
1364
|
opts;
|
|
1296
1365
|
url;
|
|
1297
1366
|
now;
|
|
@@ -1315,50 +1384,133 @@ var Ye = class {
|
|
|
1315
1384
|
errorCount = 0;
|
|
1316
1385
|
seekCount = 0;
|
|
1317
1386
|
pauseCount = 0;
|
|
1387
|
+
isPlaying = !1;
|
|
1388
|
+
isHidden = !1;
|
|
1389
|
+
isMuted = !1;
|
|
1390
|
+
activeSinceMs = null;
|
|
1391
|
+
activeTotalMs = 0;
|
|
1392
|
+
mutedSinceMs = null;
|
|
1393
|
+
mutedTotalMs = 0;
|
|
1394
|
+
lastHbMutedMs = 0;
|
|
1395
|
+
volumeChanges = 0;
|
|
1396
|
+
muteChanges = 0;
|
|
1397
|
+
presentation = "inline";
|
|
1398
|
+
presentationSinceMs;
|
|
1399
|
+
fullscreenTotalMs = 0;
|
|
1400
|
+
pipTotalMs = 0;
|
|
1401
|
+
waitingSinceMs = null;
|
|
1402
|
+
waitingTotalMs = 0;
|
|
1403
|
+
firstAudioMs = 0;
|
|
1404
|
+
timeToFirstStallMs = 0;
|
|
1405
|
+
lastStallMs = 0;
|
|
1406
|
+
lastErrorMs = 0;
|
|
1407
|
+
lastSeekMs = 0;
|
|
1408
|
+
lastErrorStage = null;
|
|
1409
|
+
sawFirstBytes = !1;
|
|
1410
|
+
mediaInfoSignature = "";
|
|
1411
|
+
lastUpshifts = 0;
|
|
1412
|
+
lastDownshifts = 0;
|
|
1413
|
+
lastDecoded = 0;
|
|
1414
|
+
lastRequestCount = 0;
|
|
1415
|
+
lastRequestErrors = 0;
|
|
1416
|
+
pendingStart = null;
|
|
1417
|
+
firstFlushTimer = null;
|
|
1318
1418
|
bornMs;
|
|
1319
1419
|
startupTimeMs = 0;
|
|
1320
1420
|
manifestLoadMs = 0;
|
|
1321
1421
|
firstFragLoadMs = 0;
|
|
1322
1422
|
onPagehide = () => this.end("END_REASON_PAGEHIDE");
|
|
1323
1423
|
onVisibility = () => {
|
|
1324
|
-
typeof document > "u" || (document.visibilityState === "hidden" ? this.hiddenSinceMs === null && (this.hiddenSinceMs = this.now()) : this.hiddenSinceMs !== null && (this.hiddenTotalMs += this.now() - this.hiddenSinceMs, this.hiddenSinceMs = null));
|
|
1424
|
+
typeof document > "u" || (document.visibilityState === "hidden" ? (this.hiddenSinceMs === null && (this.hiddenSinceMs = this.now()), this.isHidden = !0) : (this.hiddenSinceMs !== null && (this.hiddenTotalMs += this.now() - this.hiddenSinceMs, this.hiddenSinceMs = null), this.isHidden = !1), this.syncActive());
|
|
1325
1425
|
};
|
|
1326
1426
|
constructor(e) {
|
|
1327
1427
|
this.opts = {
|
|
1328
1428
|
...e,
|
|
1329
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1330
|
-
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now();
|
|
1429
|
+
heartbeatMs: e.heartbeatMs ?? Ye
|
|
1430
|
+
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs;
|
|
1331
1431
|
}
|
|
1332
1432
|
start() {
|
|
1333
|
-
|
|
1433
|
+
if (this.endedFlag) return;
|
|
1434
|
+
let e = {
|
|
1334
1435
|
player: this.opts.player,
|
|
1335
|
-
sdkVersion: this.opts.sdkVersion
|
|
1336
|
-
|
|
1436
|
+
sdkVersion: this.opts.sdkVersion,
|
|
1437
|
+
...this.opts.environment
|
|
1438
|
+
};
|
|
1439
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Ze), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), this.onVisibility());
|
|
1337
1440
|
}
|
|
1338
1441
|
noteStateChange(e, t, n, r) {
|
|
1339
1442
|
if (this.endedFlag || e === t) return;
|
|
1340
1443
|
let i = this.now();
|
|
1341
|
-
t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
1444
|
+
t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(V, i - this.bornMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(V, i - this.bornMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing" ? (this.rebufferCount += 1, this.bufferingSinceMs = i, this.lastStallMs = i, this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(V, Math.round(this.playingTotalMs)))) : e === "buffering" && this.bufferingSinceMs !== null && (this.rebufferTotalMs += i - this.bufferingSinceMs, this.bufferingSinceMs = null), t === "paused" && (this.pauseCount += 1);
|
|
1342
1445
|
let a = {
|
|
1343
|
-
fromState:
|
|
1344
|
-
toState:
|
|
1345
|
-
|
|
1346
|
-
|
|
1446
|
+
fromState: W[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1447
|
+
toState: W[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1448
|
+
presentation: Qe[this.presentation]
|
|
1449
|
+
}, o = this.causeOf(e, t, i);
|
|
1450
|
+
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1451
|
+
}
|
|
1452
|
+
causeOf(e, t, n) {
|
|
1453
|
+
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
1454
|
+
if (t === "buffering") return n - this.lastSeekMs < 1e3 ? "TRANSITION_CAUSE_SEEK" : "TRANSITION_CAUSE_NETWORK_STALL";
|
|
1455
|
+
if (t === "paused" || t === "playing" && e === "paused") return "TRANSITION_CAUSE_USER";
|
|
1456
|
+
}
|
|
1457
|
+
syncActive() {
|
|
1458
|
+
let e = this.isPlaying && !this.isHidden && !this.isMuted;
|
|
1459
|
+
e && this.activeSinceMs === null ? this.activeSinceMs = this.now() : !e && this.activeSinceMs !== null && (this.activeTotalMs += this.now() - this.activeSinceMs, this.activeSinceMs = null);
|
|
1460
|
+
}
|
|
1461
|
+
closePresentation() {
|
|
1462
|
+
let e = this.now(), t = e - this.presentationSinceMs;
|
|
1463
|
+
this.presentation === "fullscreen" ? this.fullscreenTotalMs += t : this.presentation === "pip" && (this.pipTotalMs += t), this.presentationSinceMs = e;
|
|
1464
|
+
}
|
|
1465
|
+
noteAutoplay(e) {
|
|
1466
|
+
this.pendingStart && (this.pendingStart.autoplay = e);
|
|
1467
|
+
}
|
|
1468
|
+
noteEnvironment(e) {
|
|
1469
|
+
this.pendingStart && Object.assign(this.pendingStart, e);
|
|
1470
|
+
}
|
|
1471
|
+
seedVolume(e, t) {
|
|
1472
|
+
this.endedFlag || (this.isMuted = e || t === 0, this.isMuted && this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = this.now()), this.syncActive());
|
|
1473
|
+
}
|
|
1474
|
+
noteVolume(e, t) {
|
|
1475
|
+
if (this.endedFlag) return;
|
|
1476
|
+
let n = e || t === 0;
|
|
1477
|
+
if (n === this.isMuted) {
|
|
1478
|
+
this.volumeChanges += 1;
|
|
1479
|
+
return;
|
|
1480
|
+
}
|
|
1481
|
+
this.muteChanges += 1;
|
|
1482
|
+
let r = this.now();
|
|
1483
|
+
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(V, r - this.bornMs))), this.isMuted = n, this.syncActive();
|
|
1484
|
+
}
|
|
1485
|
+
notePresentation(e) {
|
|
1486
|
+
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
1347
1487
|
}
|
|
1348
1488
|
noteReady() {
|
|
1349
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
1489
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(V, this.now() - this.bornMs));
|
|
1350
1490
|
}
|
|
1351
1491
|
noteFirstBytes() {
|
|
1352
|
-
this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
1492
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(V, this.now() - this.bornMs));
|
|
1353
1493
|
}
|
|
1354
1494
|
noteSeek() {
|
|
1355
|
-
this.endedFlag || (this.seekCount += 1);
|
|
1495
|
+
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
1356
1496
|
}
|
|
1357
|
-
noteError(e, t, n, r, i) {
|
|
1497
|
+
noteError(e, t, n, r, i, a) {
|
|
1358
1498
|
if (this.endedFlag) return;
|
|
1359
|
-
this.errorCount += 1;
|
|
1360
|
-
let
|
|
1361
|
-
t && (
|
|
1499
|
+
this.errorCount += 1, this.lastErrorMs = this.now();
|
|
1500
|
+
let o = { code: e };
|
|
1501
|
+
t && (o.detail = t), n && (o.fatal = !0), r > 0 && (o.httpStatus = r), i > 0 && (o.positionMs = Math.round(i));
|
|
1502
|
+
let s = this.stageOf(e, t, a);
|
|
1503
|
+
o.stage = s, this.lastErrorStage = s;
|
|
1504
|
+
let c = this.safeSample()?.cdnHost;
|
|
1505
|
+
c && (o.cdnHost = c), this.enqueue({ error: o }), this.flush();
|
|
1506
|
+
}
|
|
1507
|
+
stageOf(e, t, n) {
|
|
1508
|
+
let r = n ?? "";
|
|
1509
|
+
if (r !== "") return /^fragLoad/i.test(r) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /^(manifest|level|audioTrack|subtitleTrack)/i.test(r) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(r) ? "ERROR_STAGE_DRM" : /parsing|append|buffer|remux|decrypt|media/i.test(r) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
1510
|
+
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
1511
|
+
if (et.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
1512
|
+
let i = t ?? "";
|
|
1513
|
+
return /frag|segment/i.test(i) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /manifest|level|playlist/i.test(i) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(i) ? "ERROR_STAGE_DRM" : /buffer|decode|media|append/i.test(i) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
1362
1514
|
}
|
|
1363
1515
|
noteEnded() {
|
|
1364
1516
|
this.end("END_REASON_ENDED");
|
|
@@ -1382,25 +1534,51 @@ var Ye = class {
|
|
|
1382
1534
|
let s = e.droppedFrames ?? 0;
|
|
1383
1535
|
s > this.lastDropped && (i.droppedFramesDelta = s - this.lastDropped), this.lastDropped = s;
|
|
1384
1536
|
let c = e.renditionSwitches ?? 0;
|
|
1385
|
-
c > this.lastSwitches && (i.renditionSwitchesDelta = c - this.lastSwitches), this.lastSwitches = c, n > this.lastHbPlayingMs && (i.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (i.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, typeof e.latencySeconds == "number" && (i.latencyMs = Math.round(e.latencySeconds * 1e3)), typeof e.targetLatencySeconds == "number" && (i.targetLatencyMs = Math.round(e.targetLatencySeconds * 1e3)), typeof e.bandwidthKbps == "number" && (i.bandwidthEstKbps = e.bandwidthKbps), typeof e.levelHeight == "number" && (i.renditionHeight = e.levelHeight), typeof e.renditionBitrateKbps == "number" && (i.renditionBitrateKbps = e.renditionBitrateKbps), e.atLiveEdge === !0 && (i.atLiveEdge = !0);
|
|
1386
|
-
let l = this.
|
|
1387
|
-
|
|
1537
|
+
c > this.lastSwitches && (i.renditionSwitchesDelta = c - this.lastSwitches), this.lastSwitches = c, n > this.lastHbPlayingMs && (i.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (i.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, typeof e.latencySeconds == "number" && (i.latencyMs = Math.round(e.latencySeconds * 1e3)), typeof e.targetLatencySeconds == "number" && (i.targetLatencyMs = Math.round(e.targetLatencySeconds * 1e3)), typeof e.bandwidthKbps == "number" && (i.bandwidthEstKbps = e.bandwidthKbps), typeof e.levelHeight == "number" && (i.renditionHeight = e.levelHeight), typeof e.renditionBitrateKbps == "number" && (i.renditionBitrateKbps = e.renditionBitrateKbps), e.atLiveEdge === !0 && (i.atLiveEdge = !0), typeof e.bufferedMs == "number" && e.bufferedMs > 0 && (i.bufferedMs = Math.round(e.bufferedMs)), i.playerState = W[e.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
1538
|
+
let l = this.mutedTotalMs;
|
|
1539
|
+
this.mutedSinceMs !== null && (l += t - this.mutedSinceMs), l > this.lastHbMutedMs && (i.mutedMsDelta = Math.round(l - this.lastHbMutedMs)), this.lastHbMutedMs = l;
|
|
1540
|
+
let u = e.upshifts ?? 0;
|
|
1541
|
+
u > this.lastUpshifts && (i.upshiftsDelta = u - this.lastUpshifts), this.lastUpshifts = u;
|
|
1542
|
+
let d = e.downshifts ?? 0;
|
|
1543
|
+
d > this.lastDownshifts && (i.downshiftsDelta = d - this.lastDownshifts), this.lastDownshifts = d;
|
|
1544
|
+
let f = e.decodedFrames ?? 0;
|
|
1545
|
+
f > this.lastDecoded && (i.decodedFramesDelta = f - this.lastDecoded), this.lastDecoded = f;
|
|
1546
|
+
let p = e.requestErrors ?? 0;
|
|
1547
|
+
p > this.lastRequestErrors && (i.requestErrorsDelta = p - this.lastRequestErrors), this.lastRequestErrors = p;
|
|
1548
|
+
let m = e.requestCount ?? 0, h = m - this.lastRequestCount;
|
|
1549
|
+
if (this.lastRequestCount = m, h > 0) {
|
|
1550
|
+
i.requestCountDelta = h;
|
|
1551
|
+
let t = e.requestTimesMs ?? [], n = t.slice(Math.max(0, t.length - h)).sort((e, t) => e - t);
|
|
1552
|
+
n.length > 0 && (i.requestTimeP50Ms = U(n, 50), i.requestTimeP95Ms = U(n, 95));
|
|
1553
|
+
}
|
|
1554
|
+
typeof e.latencySeconds == "number" && typeof e.targetLatencySeconds == "number" && (i.driftMs = Math.round((e.latencySeconds - e.targetLatencySeconds) * 1e3)), typeof e.playbackRate == "number" && e.playbackRate > 0 && (i.playbackRate = e.playbackRate), e.qualityPinned === !0 && (i.qualityPinned = !0), e.cdnHost && (i.cdnHost = e.cdnHost), this.maybeEmitMediaInfo(e), this.enqueue({ heartbeat: i }), this.flush(), a > 0 && this.noteFirstBytes();
|
|
1388
1555
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1556
|
+
maybeEmitMediaInfo(e) {
|
|
1557
|
+
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
1558
|
+
let t = {};
|
|
1559
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = $e[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
|
|
1560
|
+
let n = JSON.stringify(t);
|
|
1561
|
+
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
1392
1562
|
}
|
|
1393
1563
|
end(e) {
|
|
1394
1564
|
if (this.endedFlag) return;
|
|
1395
1565
|
this.endedFlag = !0;
|
|
1396
1566
|
let t = this.now();
|
|
1397
|
-
this.playingSinceMs !== null && (this.playingTotalMs += t - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += t - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += t - this.bufferingSinceMs, this.bufferingSinceMs = null), this.timer &&= (clearInterval(this.timer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && document.removeEventListener("visibilitychange", this.onVisibility);
|
|
1398
|
-
let n = this.safeSample()
|
|
1567
|
+
this.playingSinceMs !== null && (this.playingTotalMs += t - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += t - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += t - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += t - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += t - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(), this.closePresentation(), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && document.removeEventListener("visibilitychange", this.onVisibility);
|
|
1568
|
+
let n = this.safeSample();
|
|
1569
|
+
n && this.maybeEmitMediaInfo(n);
|
|
1570
|
+
let r = { reason: e }, i = n?.bytesLoaded ?? this.lastBytes;
|
|
1399
1571
|
i > 0 && (r.bytesDownloadedTotal = i), this.playingTotalMs > 0 && (r.watchTimeMs = Math.round(this.playingTotalMs)), this.rebufferCount > 0 && (r.rebufferCount = this.rebufferCount), this.rebufferTotalMs > 0 && (r.rebufferTimeMs = Math.round(this.rebufferTotalMs)), this.startupTimeMs > 0 && (r.startupTimeMs = Math.round(this.startupTimeMs)), this.manifestLoadMs > 0 && (r.manifestLoadMs = Math.round(this.manifestLoadMs)), this.firstFragLoadMs > 0 && (r.firstFragLoadMs = Math.round(this.firstFragLoadMs));
|
|
1400
1572
|
let a = n?.licenseTimeMs ?? 0;
|
|
1401
1573
|
a > 0 && (r.licenseTimeMs = Math.round(a));
|
|
1402
1574
|
let o = n?.droppedFrames ?? this.lastDropped;
|
|
1403
|
-
o > 0 && (r.droppedFramesTotal = o), this.errorCount > 0 && (r.errorCount = this.errorCount), this.hiddenTotalMs > 0 && (r.hiddenTimeMs = Math.round(this.hiddenTotalMs)), this.seekCount > 0 && (r.seekCount = this.seekCount), this.pauseCount > 0 && (r.pauseCount = this.pauseCount), this.
|
|
1575
|
+
o > 0 && (r.droppedFramesTotal = o), this.errorCount > 0 && (r.errorCount = this.errorCount), this.hiddenTotalMs > 0 && (r.hiddenTimeMs = Math.round(this.hiddenTotalMs)), this.seekCount > 0 && (r.seekCount = this.seekCount), this.pauseCount > 0 && (r.pauseCount = this.pauseCount), this.firstAudioMs > 0 && (r.firstAudioMs = Math.round(this.firstAudioMs)), this.waitingTotalMs > 0 && (r.waitingForLiveMs = Math.round(this.waitingTotalMs)), this.timeToFirstStallMs > 0 && (r.timeToFirstStallMs = Math.round(this.timeToFirstStallMs));
|
|
1576
|
+
let s = n?.positionMs ?? 0;
|
|
1577
|
+
s > 0 && (r.exitPositionMs = Math.round(s)), this.activeTotalMs > 0 && (r.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (r.mutedTimeMs = Math.round(this.mutedTotalMs));
|
|
1578
|
+
let c = e !== "END_REASON_ENDED";
|
|
1579
|
+
c && this.lastStallMs > 0 && t - this.lastStallMs <= H && (r.abandonAfterStallMs = Math.max(V, Math.round(t - this.lastStallMs))), c && this.lastErrorMs > 0 && t - this.lastErrorMs <= H && (r.abandonAfterErrorMs = Math.max(V, Math.round(t - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (r.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (r.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (r.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (r.muteChanges = this.muteChanges);
|
|
1580
|
+
let l = n?.decodedFrames ?? this.lastDecoded;
|
|
1581
|
+
l > 0 && (r.decodedFramesTotal = l), this.startupTimeMs === 0 && (r.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: r })), this.flush(e === "END_REASON_PAGEHIDE");
|
|
1404
1582
|
}
|
|
1405
1583
|
safeSample() {
|
|
1406
1584
|
try {
|
|
@@ -1418,13 +1596,13 @@ var Ye = class {
|
|
|
1418
1596
|
};
|
|
1419
1597
|
}
|
|
1420
1598
|
enqueue(e) {
|
|
1421
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
1599
|
+
for (this.pending.push(this.wrap(e)); this.pending.length > Xe;) {
|
|
1422
1600
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
1423
1601
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
1424
1602
|
}
|
|
1425
1603
|
}
|
|
1426
1604
|
flush(e = !1) {
|
|
1427
|
-
if (this.pending.length === 0) return;
|
|
1605
|
+
if (this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.pendingStart = null, this.pending.length === 0) return;
|
|
1428
1606
|
let t = JSON.stringify({ beacons: this.pending });
|
|
1429
1607
|
if (this.pending = [], e) {
|
|
1430
1608
|
let e = this.opts.sendBeacon ?? (typeof navigator < "u" && navigator.sendBeacon ? navigator.sendBeacon.bind(navigator) : void 0);
|
|
@@ -1440,7 +1618,74 @@ var Ye = class {
|
|
|
1440
1618
|
keepalive: !0
|
|
1441
1619
|
}).catch(() => {});
|
|
1442
1620
|
}
|
|
1443
|
-
}
|
|
1621
|
+
};
|
|
1622
|
+
//#endregion
|
|
1623
|
+
//#region src/core/environment.ts
|
|
1624
|
+
function rt() {
|
|
1625
|
+
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
1626
|
+
let e;
|
|
1627
|
+
try {
|
|
1628
|
+
e = window.top !== window.self;
|
|
1629
|
+
} catch {
|
|
1630
|
+
e = !0;
|
|
1631
|
+
}
|
|
1632
|
+
let t = window.location?.origin;
|
|
1633
|
+
if (!e) return {
|
|
1634
|
+
host: t && t !== "null" ? t : void 0,
|
|
1635
|
+
integration: "INTEGRATION_KIND_SDK"
|
|
1636
|
+
};
|
|
1637
|
+
let n;
|
|
1638
|
+
try {
|
|
1639
|
+
let e = window.location.ancestorOrigins;
|
|
1640
|
+
e && e.length > 0 && (n = e[e.length - 1] ?? void 0), !n && typeof document < "u" && document.referrer && (n = new URL(document.referrer).origin);
|
|
1641
|
+
} catch {
|
|
1642
|
+
n = void 0;
|
|
1643
|
+
}
|
|
1644
|
+
return n === "null" && (n = void 0), {
|
|
1645
|
+
host: n,
|
|
1646
|
+
integration: "INTEGRATION_KIND_IFRAME"
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
function it() {
|
|
1650
|
+
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
1651
|
+
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
1652
|
+
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
1653
|
+
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
1654
|
+
return e?.mobile ?? (typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1 && n > 0 && n < 900) ? n >= 600 ? "DEVICE_CLASS_TABLET" : "DEVICE_CLASS_PHONE" : e || n >= 900 || /mac|win|linux|chrome os/i.test(t) ? "DEVICE_CLASS_DESKTOP" : "DEVICE_CLASS_OTHER";
|
|
1655
|
+
}
|
|
1656
|
+
function at() {
|
|
1657
|
+
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
1658
|
+
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
1659
|
+
let t = { connectionType: e.type ? {
|
|
1660
|
+
wifi: "CONNECTION_TYPE_WIFI",
|
|
1661
|
+
cellular: "CONNECTION_TYPE_CELLULAR",
|
|
1662
|
+
ethernet: "CONNECTION_TYPE_ETHERNET"
|
|
1663
|
+
}[e.type] ?? "CONNECTION_TYPE_OTHER" : "CONNECTION_TYPE_UNKNOWN" };
|
|
1664
|
+
return typeof e.downlink == "number" && e.downlink > 0 && (t.downlinkKbps = Math.round(e.downlink * 1e3)), e.saveData && (t.saveData = !0), t;
|
|
1665
|
+
}
|
|
1666
|
+
function ot(e) {
|
|
1667
|
+
let t = rt(), n = {
|
|
1668
|
+
deviceClass: it(),
|
|
1669
|
+
integration: t.integration,
|
|
1670
|
+
...at()
|
|
1671
|
+
};
|
|
1672
|
+
t.host && (n.host = t.host), typeof screen < "u" && screen.width > 0 && (n.screenWidth = screen.width, n.screenHeight = screen.height), typeof window < "u" && window.devicePixelRatio > 0 && (n.devicePixelRatio = Math.round(window.devicePixelRatio * 100) / 100);
|
|
1673
|
+
let r = e.getBoundingClientRect?.();
|
|
1674
|
+
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
1675
|
+
}
|
|
1676
|
+
async function st() {
|
|
1677
|
+
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
1678
|
+
if (!e?.getHighEntropyValues) return {};
|
|
1679
|
+
try {
|
|
1680
|
+
let t = await e.getHighEntropyValues(["model", "platformVersion"]), n = {};
|
|
1681
|
+
return t.model && (n.deviceModel = t.model), t.platformVersion && (n.osVersion = t.platformVersion), n;
|
|
1682
|
+
} catch {
|
|
1683
|
+
return {};
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
//#endregion
|
|
1687
|
+
//#region src/core/version.ts
|
|
1688
|
+
var ct = "2.1.0", G = {
|
|
1444
1689
|
accent: "#E1B600",
|
|
1445
1690
|
accentText: "#1B1C23",
|
|
1446
1691
|
background: "#0e0f13",
|
|
@@ -1451,7 +1696,7 @@ var Ye = class {
|
|
|
1451
1696
|
border: "rgba(255, 255, 255, 0.1)",
|
|
1452
1697
|
radius: "8px",
|
|
1453
1698
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
1454
|
-
},
|
|
1699
|
+
}, K = {
|
|
1455
1700
|
accent: "--havik-accent",
|
|
1456
1701
|
accentText: "--havik-accent-text",
|
|
1457
1702
|
background: "--havik-bg",
|
|
@@ -1463,25 +1708,25 @@ var Ye = class {
|
|
|
1463
1708
|
radius: "--havik-radius",
|
|
1464
1709
|
fontFamily: "--havik-font"
|
|
1465
1710
|
};
|
|
1466
|
-
function
|
|
1711
|
+
function q(e, t) {
|
|
1467
1712
|
let n = {
|
|
1468
|
-
...
|
|
1713
|
+
...G,
|
|
1469
1714
|
...t
|
|
1470
1715
|
};
|
|
1471
|
-
for (let t of Object.keys(
|
|
1716
|
+
for (let t of Object.keys(K)) e.style.setProperty(K[t], n[t]);
|
|
1472
1717
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
1473
1718
|
}
|
|
1474
1719
|
//#endregion
|
|
1475
1720
|
//#region src/ui/styles.ts
|
|
1476
|
-
var
|
|
1477
|
-
function
|
|
1478
|
-
if (e.getElementById(
|
|
1721
|
+
var J = "havik-player-styles", lt = "\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/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\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/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n 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";
|
|
1722
|
+
function ut(e = document) {
|
|
1723
|
+
if (e.getElementById(J)) return;
|
|
1479
1724
|
let t = e.createElement("style");
|
|
1480
|
-
t.id =
|
|
1725
|
+
t.id = J, t.textContent = lt, e.head.appendChild(t);
|
|
1481
1726
|
}
|
|
1482
1727
|
//#endregion
|
|
1483
1728
|
//#region src/ui/icons.ts
|
|
1484
|
-
var
|
|
1729
|
+
var dt = {
|
|
1485
1730
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1486
1731
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1487
1732
|
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\"/>",
|
|
@@ -1494,21 +1739,21 @@ var $e = {
|
|
|
1494
1739
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
1495
1740
|
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\"/>"
|
|
1496
1741
|
};
|
|
1497
|
-
function
|
|
1498
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1742
|
+
function Y(e) {
|
|
1743
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${dt[e]}</svg>`;
|
|
1499
1744
|
}
|
|
1500
1745
|
//#endregion
|
|
1501
1746
|
//#region src/ui/controls.ts
|
|
1502
|
-
var
|
|
1747
|
+
var ft = 3e3, pt = /* @__PURE__ */ new Set([
|
|
1503
1748
|
"GONE",
|
|
1504
1749
|
"NOT_FOUND",
|
|
1505
1750
|
"INVALID_URN",
|
|
1506
1751
|
"UNAUTHORIZED"
|
|
1507
1752
|
]);
|
|
1508
|
-
function
|
|
1509
|
-
return new
|
|
1753
|
+
function mt(e) {
|
|
1754
|
+
return new ht(e);
|
|
1510
1755
|
}
|
|
1511
|
-
var
|
|
1756
|
+
var ht = class {
|
|
1512
1757
|
root;
|
|
1513
1758
|
video;
|
|
1514
1759
|
player;
|
|
@@ -1550,7 +1795,7 @@ var rt = class {
|
|
|
1550
1795
|
scrubbing = !1;
|
|
1551
1796
|
offFns = [];
|
|
1552
1797
|
constructor(e) {
|
|
1553
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
1798
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? ft, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, ut(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");
|
|
1554
1799
|
let t = (e, t, n) => {
|
|
1555
1800
|
let r = this.doc.createElement(e);
|
|
1556
1801
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1561,12 +1806,12 @@ var rt = class {
|
|
|
1561
1806
|
"aria-label": r,
|
|
1562
1807
|
title: r
|
|
1563
1808
|
});
|
|
1564
|
-
return i.innerHTML =
|
|
1809
|
+
return i.innerHTML = Y(n), i;
|
|
1565
1810
|
};
|
|
1566
1811
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
1567
1812
|
type: "button",
|
|
1568
1813
|
"aria-label": "Play"
|
|
1569
|
-
}), this.center.innerHTML =
|
|
1814
|
+
}), this.center.innerHTML = Y("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
1570
1815
|
role: "slider",
|
|
1571
1816
|
"aria-label": "Seek",
|
|
1572
1817
|
"aria-valuemin": "0",
|
|
@@ -1584,7 +1829,7 @@ var rt = class {
|
|
|
1584
1829
|
"aria-label": "Volume"
|
|
1585
1830
|
});
|
|
1586
1831
|
let a = t("div", "havik-vol");
|
|
1587
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
1832
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Y("liveDot");
|
|
1588
1833
|
let o = this.doc.createElement("span");
|
|
1589
1834
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
1590
1835
|
let s = t("div", "havik-spacer");
|
|
@@ -1638,12 +1883,12 @@ var rt = class {
|
|
|
1638
1883
|
}
|
|
1639
1884
|
if (e === "preplay") {
|
|
1640
1885
|
let e = this.doc.createElement("button");
|
|
1641
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
1886
|
+
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()), n.append(e);
|
|
1642
1887
|
} else {
|
|
1643
1888
|
let r = this.doc.createElement("div");
|
|
1644
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
1889
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !pt.has(this.lastError.code)) {
|
|
1645
1890
|
let e = this.doc.createElement("button");
|
|
1646
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
1891
|
+
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Y("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
1647
1892
|
}
|
|
1648
1893
|
}
|
|
1649
1894
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -1682,7 +1927,7 @@ var rt = class {
|
|
|
1682
1927
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
1683
1928
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
1684
1929
|
}
|
|
1685
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
1930
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${X(this.video.currentTime)} / ${X(this.video.duration)}`);
|
|
1686
1931
|
}
|
|
1687
1932
|
syncLive() {
|
|
1688
1933
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -1732,17 +1977,17 @@ var rt = class {
|
|
|
1732
1977
|
renderQualityMenu() {
|
|
1733
1978
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
1734
1979
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
1735
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
1980
|
+
for (let n of e) this.menu.append(this.menuItem(gt(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
1736
1981
|
}
|
|
1737
1982
|
renderAudioMenu() {
|
|
1738
1983
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
1739
1984
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
1740
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1985
|
+
for (let t of e) this.menu.append(this.menuItem(_t(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
1741
1986
|
}
|
|
1742
1987
|
renderCcMenu() {
|
|
1743
1988
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
1744
1989
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
1745
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1990
|
+
for (let t of e) this.menu.append(this.menuItem(vt(t), !1, () => this.player.setTextTrack(t.id)));
|
|
1746
1991
|
}
|
|
1747
1992
|
onTracksChanged() {
|
|
1748
1993
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -1825,7 +2070,7 @@ var rt = class {
|
|
|
1825
2070
|
}
|
|
1826
2071
|
}
|
|
1827
2072
|
setIcon(e, t) {
|
|
1828
|
-
e.innerHTML =
|
|
2073
|
+
e.innerHTML = Y(t);
|
|
1829
2074
|
}
|
|
1830
2075
|
destroy() {
|
|
1831
2076
|
this.hideTimer && clearTimeout(this.hideTimer);
|
|
@@ -1842,32 +2087,32 @@ var rt = class {
|
|
|
1842
2087
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
1843
2088
|
}
|
|
1844
2089
|
};
|
|
1845
|
-
function
|
|
2090
|
+
function X(e) {
|
|
1846
2091
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
1847
2092
|
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");
|
|
1848
2093
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
1849
2094
|
}
|
|
1850
|
-
function
|
|
2095
|
+
function gt(e) {
|
|
1851
2096
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
1852
2097
|
}
|
|
1853
|
-
function
|
|
2098
|
+
function _t(e) {
|
|
1854
2099
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1855
2100
|
}
|
|
1856
|
-
function
|
|
2101
|
+
function vt(e) {
|
|
1857
2102
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1858
2103
|
}
|
|
1859
2104
|
//#endregion
|
|
1860
2105
|
//#region src/managed/index.ts
|
|
1861
|
-
var
|
|
1862
|
-
async function
|
|
2106
|
+
var yt = 6e3, Z = 45e3, Q = 2e3, bt = 3, xt = 2e3, St = 48e4;
|
|
2107
|
+
async function Ct(e) {
|
|
1863
2108
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
1864
2109
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: baseUrl is required");
|
|
1865
2110
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
1866
2111
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
1867
|
-
let t = new
|
|
2112
|
+
let t = new wt(e);
|
|
1868
2113
|
return await t.start(), t;
|
|
1869
2114
|
}
|
|
1870
|
-
var
|
|
2115
|
+
var wt = class {
|
|
1871
2116
|
opts;
|
|
1872
2117
|
abort = new AbortController();
|
|
1873
2118
|
listeners = {};
|
|
@@ -1891,7 +2136,7 @@ var dt = class {
|
|
|
1891
2136
|
armFallbackCtrl = null;
|
|
1892
2137
|
_lastError = null;
|
|
1893
2138
|
analyticsSession = null;
|
|
1894
|
-
|
|
2139
|
+
detachMediaListeners;
|
|
1895
2140
|
playRequested = !1;
|
|
1896
2141
|
pendingStartLoad = !1;
|
|
1897
2142
|
constructor(e) {
|
|
@@ -1954,7 +2199,7 @@ var dt = class {
|
|
|
1954
2199
|
setTimeout(() => {
|
|
1955
2200
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
1956
2201
|
phase: i ? "unavailable" : "tooEarly",
|
|
1957
|
-
retryInMs:
|
|
2202
|
+
retryInMs: Z,
|
|
1958
2203
|
attempt: 1,
|
|
1959
2204
|
elapsedMs: 0,
|
|
1960
2205
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -1993,13 +2238,13 @@ var dt = class {
|
|
|
1993
2238
|
!a && !p() && h();
|
|
1994
2239
|
}, e);
|
|
1995
2240
|
};
|
|
1996
|
-
_(
|
|
2241
|
+
_(yt), this.armingSub = D({
|
|
1997
2242
|
eventsBaseUrl: t,
|
|
1998
2243
|
matchUrn: this.opts.matchUrn,
|
|
1999
2244
|
credential: this.opts.credential,
|
|
2000
|
-
onAlive: () => _(
|
|
2245
|
+
onAlive: () => _(Z),
|
|
2001
2246
|
onState: (e) => {
|
|
2002
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2247
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Q);
|
|
2003
2248
|
},
|
|
2004
2249
|
onError: () => h()
|
|
2005
2250
|
});
|
|
@@ -2022,7 +2267,7 @@ var dt = class {
|
|
|
2022
2267
|
let n = await s(this.opts.credential);
|
|
2023
2268
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2024
2269
|
this.setState("loading");
|
|
2025
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2270
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Te(this.opts.video, (e) => {
|
|
2026
2271
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2027
2272
|
});
|
|
2028
2273
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2038,30 +2283,40 @@ var dt = class {
|
|
|
2038
2283
|
}, 0));
|
|
2039
2284
|
}
|
|
2040
2285
|
startAnalytics(e, t, n) {
|
|
2041
|
-
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.
|
|
2286
|
+
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2042
2287
|
let r = e.analytics?.sid;
|
|
2043
2288
|
if (!r) return;
|
|
2044
|
-
let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ??
|
|
2289
|
+
let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? tt(this.opts.baseUrl);
|
|
2045
2290
|
if (!i) return;
|
|
2046
|
-
let a = this.opts.video, o = new
|
|
2291
|
+
let a = this.opts.video, o = new nt({
|
|
2047
2292
|
endpoint: i,
|
|
2048
2293
|
sid: r,
|
|
2049
2294
|
apiKey: n,
|
|
2050
2295
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2051
|
-
sdkVersion:
|
|
2296
|
+
sdkVersion: ct,
|
|
2297
|
+
environment: ot(a),
|
|
2052
2298
|
sample: () => {
|
|
2053
|
-
let e = this.engine?.getStats() ??
|
|
2299
|
+
let e = this.engine?.getStats() ?? we, t = a.buffered.length ? Math.max(0, a.buffered.end(a.buffered.length - 1) - a.currentTime) : 0;
|
|
2054
2300
|
return {
|
|
2055
2301
|
...e,
|
|
2056
2302
|
bufferedMs: Math.round(t * 1e3),
|
|
2057
2303
|
state: this._state,
|
|
2058
|
-
positionMs: Math.round(a.currentTime * 1e3)
|
|
2304
|
+
positionMs: Math.round(a.currentTime * 1e3),
|
|
2305
|
+
playbackRate: a.playbackRate
|
|
2059
2306
|
};
|
|
2060
2307
|
}
|
|
2061
2308
|
});
|
|
2062
2309
|
this.analyticsSession = o;
|
|
2063
|
-
let s = () => o.noteSeek();
|
|
2064
|
-
a.addEventListener("seeking", s),
|
|
2310
|
+
let s = () => o.noteSeek(), c = () => o.noteVolume(a.muted, a.volume);
|
|
2311
|
+
a.addEventListener("seeking", s), a.addEventListener("volumechange", c), this.detachMediaListeners = () => {
|
|
2312
|
+
a.removeEventListener("seeking", s), a.removeEventListener("volumechange", c);
|
|
2313
|
+
}, o.start(), o.seedVolume(a.muted, a.volume), o.notePresentation(this.currentPresentation()), st().then((e) => o.noteEnvironment(e)), this.opts.autoplay === !1 && o.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2314
|
+
}
|
|
2315
|
+
currentPresentation() {
|
|
2316
|
+
let e = this.opts.video;
|
|
2317
|
+
if (typeof document < "u" && document.pictureInPictureElement === e) return "pip";
|
|
2318
|
+
let t = typeof document < "u" ? document.fullscreenElement : null;
|
|
2319
|
+
return e.webkitDisplayingFullscreen === !0 || t && (t === e || t.contains(e)) ? "fullscreen" : "inline";
|
|
2065
2320
|
}
|
|
2066
2321
|
createEngine(e, t, r = !1) {
|
|
2067
2322
|
let i = { ...this.opts.hlsConfig };
|
|
@@ -2079,11 +2334,11 @@ var dt = class {
|
|
|
2079
2334
|
hlsConfig: i,
|
|
2080
2335
|
emit: (e) => this.onEngineEvent(e)
|
|
2081
2336
|
}, o = this.opts.engine ?? "auto";
|
|
2082
|
-
if (o === "native") return new
|
|
2083
|
-
if (o === "hls") return new
|
|
2084
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
2085
|
-
if (
|
|
2086
|
-
if (
|
|
2337
|
+
if (o === "native") return new R(a);
|
|
2338
|
+
if (o === "hls") return new B(a);
|
|
2339
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && I(this.opts.video) && L()) return new R(a);
|
|
2340
|
+
if (Oe()) return new B(a);
|
|
2341
|
+
if (I(this.opts.video)) return new R(a);
|
|
2087
2342
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2088
2343
|
}
|
|
2089
2344
|
onEngineEvent(e) {
|
|
@@ -2106,7 +2361,7 @@ var dt = class {
|
|
|
2106
2361
|
case "ended":
|
|
2107
2362
|
this.onStreamEnded();
|
|
2108
2363
|
break;
|
|
2109
|
-
case "error": this.analyticsSession?.noteError(e.error.code, e.error.message, e.fatal, e.error.httpStatus ?? 0, Math.round(this.opts.video.currentTime * 1e3)), e.fatal ? this.fail(e.error) : this.emit("warning", e.error);
|
|
2364
|
+
case "error": this.analyticsSession?.noteError(e.error.code, e.error.message, e.fatal, e.error.httpStatus ?? 0, Math.round(this.opts.video.currentTime * 1e3), e.detail), e.fatal ? this.fail(e.error) : this.emit("warning", e.error);
|
|
2110
2365
|
}
|
|
2111
2366
|
}
|
|
2112
2367
|
startLiveState(e) {
|
|
@@ -2126,7 +2381,7 @@ var dt = class {
|
|
|
2126
2381
|
r = 0, i = !1;
|
|
2127
2382
|
},
|
|
2128
2383
|
onError: () => {
|
|
2129
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2384
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= bt && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} 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.`))));
|
|
2130
2385
|
}
|
|
2131
2386
|
});
|
|
2132
2387
|
}
|
|
@@ -2148,7 +2403,7 @@ var dt = class {
|
|
|
2148
2403
|
scheduleRejoin(e) {
|
|
2149
2404
|
!this.rejoinEnabled() || this.rejoinTimer || (this.rejoinTimer = setTimeout(() => {
|
|
2150
2405
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2151
|
-
}, Math.random() *
|
|
2406
|
+
}, Math.random() * Q));
|
|
2152
2407
|
}
|
|
2153
2408
|
cancelRejoin() {
|
|
2154
2409
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2172,7 +2427,7 @@ var dt = class {
|
|
|
2172
2427
|
}
|
|
2173
2428
|
t.controls = !1;
|
|
2174
2429
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2175
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
2430
|
+
r && r.insertBefore(n, t), n.appendChild(t), q(n, this.opts.theme), this.container = n, this.controlBar = mt({
|
|
2176
2431
|
root: n,
|
|
2177
2432
|
video: t,
|
|
2178
2433
|
player: this,
|
|
@@ -2189,14 +2444,20 @@ var dt = class {
|
|
|
2189
2444
|
e && (e.parentNode ? (e.parentNode.insertBefore(this.opts.video, e), e.remove()) : this.opts.video.parentNode === e && e.removeChild(this.opts.video)), this.container = null;
|
|
2190
2445
|
}
|
|
2191
2446
|
attachPipListeners() {
|
|
2192
|
-
let e = this.opts.video, t = () => this.
|
|
2193
|
-
|
|
2194
|
-
|
|
2447
|
+
let e = this.opts.video, t = () => this.analyticsSession?.notePresentation(this.currentPresentation()), n = () => {
|
|
2448
|
+
t(), this.emit("pipchange", !0);
|
|
2449
|
+
}, r = () => {
|
|
2450
|
+
t(), this.emit("pipchange", !1);
|
|
2451
|
+
};
|
|
2452
|
+
e.addEventListener("enterpictureinpicture", n), e.addEventListener("leavepictureinpicture", r);
|
|
2453
|
+
let i = typeof document < "u" ? document : void 0;
|
|
2454
|
+
i?.addEventListener("fullscreenchange", t), i?.addEventListener("webkitfullscreenchange", t), this.detachPip = () => {
|
|
2455
|
+
e.removeEventListener("enterpictureinpicture", n), e.removeEventListener("leavepictureinpicture", r), i?.removeEventListener("fullscreenchange", t), i?.removeEventListener("webkitfullscreenchange", t);
|
|
2195
2456
|
};
|
|
2196
2457
|
}
|
|
2197
2458
|
startStats() {
|
|
2198
2459
|
this.stopStats();
|
|
2199
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
2460
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? xt);
|
|
2200
2461
|
this.statsTimer = setInterval(() => {
|
|
2201
2462
|
if (!this.engine) return;
|
|
2202
2463
|
let e = this.engine.getStats();
|
|
@@ -2208,7 +2469,7 @@ var dt = class {
|
|
|
2208
2469
|
}
|
|
2209
2470
|
scheduleLicenseRefresh() {
|
|
2210
2471
|
this.stopRefresh();
|
|
2211
|
-
let e = this.opts.licenseRefreshMs ??
|
|
2472
|
+
let e = this.opts.licenseRefreshMs ?? St;
|
|
2212
2473
|
!e || !this._descriptor?.drmEnabled || (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
2213
2474
|
}
|
|
2214
2475
|
stopRefresh() {
|
|
@@ -2235,9 +2496,9 @@ var dt = class {
|
|
|
2235
2496
|
let t = this.pendingStartLoad && this._state !== "ended" && this._state !== "error";
|
|
2236
2497
|
t && (this.pendingStartLoad = !1, this.setState("loading"), this.engine?.startLoad());
|
|
2237
2498
|
try {
|
|
2238
|
-
await this.opts.video.play();
|
|
2499
|
+
await this.opts.video.play(), e && this.analyticsSession?.noteAutoplay(this.opts.video.muted ? "AUTOPLAY_RESULT_ALLOWED_MUTED" : "AUTOPLAY_RESULT_ALLOWED");
|
|
2239
2500
|
} catch (n) {
|
|
2240
|
-
n instanceof DOMException && n.name === "NotAllowedError" && (e && (this.playRequested = !1), t && !this.destroyed && this._state === "loading" && this.setState("paused"), this.emit("autoplayblocked"));
|
|
2501
|
+
n instanceof DOMException && n.name === "NotAllowedError" && (this.analyticsSession?.noteAutoplay("AUTOPLAY_RESULT_BLOCKED"), e && (this.playRequested = !1), t && !this.destroyed && this._state === "loading" && this.setState("paused"), this.emit("autoplayblocked"));
|
|
2241
2502
|
}
|
|
2242
2503
|
}
|
|
2243
2504
|
pause() {
|
|
@@ -2250,7 +2511,7 @@ var dt = class {
|
|
|
2250
2511
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
2251
2512
|
}
|
|
2252
2513
|
getStats() {
|
|
2253
|
-
return this.engine?.getStats() ??
|
|
2514
|
+
return this.engine?.getStats() ?? we;
|
|
2254
2515
|
}
|
|
2255
2516
|
getQualityLevels() {
|
|
2256
2517
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -2317,7 +2578,7 @@ var dt = class {
|
|
|
2317
2578
|
return n.add(t), () => n.delete(t);
|
|
2318
2579
|
}
|
|
2319
2580
|
destroy() {
|
|
2320
|
-
this.destroyed || (this.destroyed = !0, this.loadGen += 1, this.abort.abort(), this.stopStats(), this.stopRefresh(), this.unmountControls(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.detachPip?.(), this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.
|
|
2581
|
+
this.destroyed || (this.destroyed = !0, this.loadGen += 1, this.abort.abort(), this.stopStats(), this.stopRefresh(), this.unmountControls(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.detachPip?.(), this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.engine?.destroy(), this.engine = null, this.setState("idle"), this.clearListeners());
|
|
2321
2582
|
}
|
|
2322
2583
|
clearListeners() {
|
|
2323
2584
|
for (let e of Object.keys(this.listeners)) this.listeners[e]?.clear();
|
|
@@ -2360,7 +2621,7 @@ function $(e) {
|
|
|
2360
2621
|
}
|
|
2361
2622
|
//#endregion
|
|
2362
2623
|
//#region src/embed/host.ts
|
|
2363
|
-
function
|
|
2624
|
+
function Tt(e) {
|
|
2364
2625
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
2365
2626
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
2366
2627
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -2419,8 +2680,8 @@ function ft(e) {
|
|
|
2419
2680
|
}
|
|
2420
2681
|
//#endregion
|
|
2421
2682
|
//#region src/embed/page.ts
|
|
2422
|
-
var
|
|
2423
|
-
function
|
|
2683
|
+
var Et = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
2684
|
+
function Dt() {
|
|
2424
2685
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
2425
2686
|
if (e) return {
|
|
2426
2687
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -2442,9 +2703,9 @@ function mt() {
|
|
|
2442
2703
|
waitForLive: !0
|
|
2443
2704
|
};
|
|
2444
2705
|
}
|
|
2445
|
-
async function
|
|
2446
|
-
let e =
|
|
2447
|
-
|
|
2706
|
+
async function Ot() {
|
|
2707
|
+
let e = Dt();
|
|
2708
|
+
At();
|
|
2448
2709
|
let t = document.createElement("video");
|
|
2449
2710
|
t.setAttribute("playsinline", ""), t.muted = e.muted ?? !0, t.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(t);
|
|
2450
2711
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -2499,12 +2760,12 @@ async function ht() {
|
|
|
2499
2760
|
code: e.code,
|
|
2500
2761
|
message: e.message
|
|
2501
2762
|
})), e.on("autoplayblocked", () => {
|
|
2502
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
2763
|
+
i({ type: "oddin:autoplayblocked" }), kt(t, e);
|
|
2503
2764
|
});
|
|
2504
2765
|
}, s = async (r) => {
|
|
2505
2766
|
a?.destroy(), a = null;
|
|
2506
2767
|
try {
|
|
2507
|
-
let n = await
|
|
2768
|
+
let n = await Ct({
|
|
2508
2769
|
video: t,
|
|
2509
2770
|
baseUrl: e.baseUrl,
|
|
2510
2771
|
matchUrn: r,
|
|
@@ -2565,7 +2826,7 @@ async function ht() {
|
|
|
2565
2826
|
a?.retry();
|
|
2566
2827
|
break;
|
|
2567
2828
|
case "oddin:load":
|
|
2568
|
-
typeof e.matchUrn == "string" &&
|
|
2829
|
+
typeof e.matchUrn == "string" && Et.test(e.matchUrn) && s(e.matchUrn);
|
|
2569
2830
|
break;
|
|
2570
2831
|
case "oddin:destroy": c();
|
|
2571
2832
|
}
|
|
@@ -2577,18 +2838,18 @@ async function ht() {
|
|
|
2577
2838
|
protocol: 1
|
|
2578
2839
|
});
|
|
2579
2840
|
}
|
|
2580
|
-
function
|
|
2841
|
+
function kt(e, t) {
|
|
2581
2842
|
if (document.getElementById("havik-tap")) return;
|
|
2582
2843
|
let n = document.createElement("button");
|
|
2583
2844
|
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", () => {
|
|
2584
2845
|
n.remove(), t.play();
|
|
2585
2846
|
}), document.body.appendChild(n);
|
|
2586
2847
|
}
|
|
2587
|
-
function
|
|
2848
|
+
function At() {
|
|
2588
2849
|
let e = document.createElement("style");
|
|
2589
2850
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
2590
2851
|
}
|
|
2591
2852
|
//#endregion
|
|
2592
|
-
export {
|
|
2853
|
+
export { G as ODDIN_THEME, n as PlaybackError, q as applyTheme, Ot as bootEmbed, he as clearDeviceId, Ct as createPlayer, O as deriveEventsBaseUrl, xe as detectDrmSupport, T as enterVideoFullscreen, E as exitVideoFullscreen, le as fetchCatalog, de as fetchTournament, pe as flattenMatches, j as getDeviceId, Ce as isLowLatencyManifest, $ as isOddinMessage, _e as licenseRequestHeaders, Tt as mountEmbed, v as pollToLive, b as resolveStream, D as subscribeLiveState, w as videoFullscreenActive, me as watchStatus };
|
|
2593
2854
|
|
|
2594
2855
|
//# sourceMappingURL=index.js.map
|