@oddin-gg/havik-player 2.16.11 → 2.16.13
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.js +46 -30
- package/dist/index.js.map +1 -1
- package/docs/API.md +5 -0
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1540,14 +1540,14 @@ var Qt = class {
|
|
|
1540
1540
|
startHls() {
|
|
1541
1541
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
1542
1542
|
this.clearKick(), this.resetStarvationWindow(), this.resetChaseWindow(), this.resetFrameDropWindow(), this.lastFragLoadingMs = 0, this.lastEndSN = -1, this.lastAdvanceMs = 0;
|
|
1543
|
-
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = {
|
|
1543
|
+
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = H(this.deps.video) && U(), f = {
|
|
1544
1544
|
debug: s === !0,
|
|
1545
1545
|
enableWorker: !o,
|
|
1546
1546
|
lowLatencyMode: o,
|
|
1547
1547
|
backBufferLength: 90,
|
|
1548
1548
|
liveDurationInfinity: !0,
|
|
1549
1549
|
maxBufferHole: .5,
|
|
1550
|
-
maxLiveSyncPlaybackRate: 1.1,
|
|
1550
|
+
maxLiveSyncPlaybackRate: d ? 1 : 1.1,
|
|
1551
1551
|
abrEwmaDefaultEstimate: 1e6,
|
|
1552
1552
|
capLevelToPlayerSize: !1,
|
|
1553
1553
|
...this.loadStarted ? {} : { autoStartLoad: !1 },
|
|
@@ -1587,24 +1587,24 @@ var Qt = class {
|
|
|
1587
1587
|
} } : {},
|
|
1588
1588
|
...c
|
|
1589
1589
|
};
|
|
1590
|
-
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !
|
|
1590
|
+
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
|
|
1591
1591
|
let e = new pt({
|
|
1592
1592
|
sessionId: n.analytics?.sid,
|
|
1593
1593
|
contentId: n.matchUrn
|
|
1594
1594
|
}), t = mt(e);
|
|
1595
|
-
t && (this.prefetch = e,
|
|
1595
|
+
t && (this.prefetch = e, f.fLoader = t);
|
|
1596
1596
|
}
|
|
1597
|
-
Xt(
|
|
1598
|
-
let
|
|
1599
|
-
if (this.hls =
|
|
1600
|
-
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(
|
|
1601
|
-
}),
|
|
1597
|
+
Xt(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
|
|
1598
|
+
let p = new e(f);
|
|
1599
|
+
if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
|
|
1600
|
+
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1601
|
+
}), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1602
1602
|
t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1603
1603
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1604
1604
|
}, Ct)));
|
|
1605
|
-
}),
|
|
1605
|
+
}), p.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1606
1606
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1607
|
-
}),
|
|
1607
|
+
}), p.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1608
1608
|
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1);
|
|
1609
1609
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1610
1610
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
@@ -1615,7 +1615,7 @@ var Qt = class {
|
|
|
1615
1615
|
let e = Je(a);
|
|
1616
1616
|
e && (this.cdnHost = e);
|
|
1617
1617
|
}
|
|
1618
|
-
}),
|
|
1618
|
+
}), p.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
1619
1619
|
let n = t?.stats?.loaded;
|
|
1620
1620
|
if (typeof n == "number" && (this.playlistBytesLoaded += n), this.reportedFirstPlaylist || (this.reportedFirstPlaylist = !0, l({ type: "firstPlaylist" })), this.detectedLowLatency) return;
|
|
1621
1621
|
let r = t.details;
|
|
@@ -1623,31 +1623,31 @@ var Qt = class {
|
|
|
1623
1623
|
type: "lowLatencyDetected",
|
|
1624
1624
|
value: !0
|
|
1625
1625
|
}));
|
|
1626
|
-
}),
|
|
1626
|
+
}), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1627
1627
|
let t = this.prefetch;
|
|
1628
|
-
|
|
1628
|
+
p.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1629
1629
|
let r = n?.frag, i = gt(r?.type);
|
|
1630
|
-
if (r && t.isActive(i)) for (let e of _t(
|
|
1631
|
-
}),
|
|
1630
|
+
if (r && t.isActive(i)) for (let e of _t(p, r)) t.prefetch(e.url, i, e.kind);
|
|
1631
|
+
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(gt(n?.frag?.type)));
|
|
1632
1632
|
}
|
|
1633
|
-
|
|
1633
|
+
p.on(e.Events.KEY_LOADED, () => {
|
|
1634
1634
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1635
1635
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1636
1636
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1637
|
-
}, Tt),
|
|
1637
|
+
}, Tt), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1638
1638
|
this.renditionSwitches += 1;
|
|
1639
|
-
let n = this.lastLevelIndex >= 0 ?
|
|
1639
|
+
let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
|
|
1640
1640
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
1641
1641
|
type: "qualitychange",
|
|
1642
1642
|
index: t.level
|
|
1643
1643
|
});
|
|
1644
|
-
}),
|
|
1644
|
+
}), p.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
|
|
1645
1645
|
type: "audiotrackchange",
|
|
1646
1646
|
id: t.id
|
|
1647
|
-
})),
|
|
1647
|
+
})), p.on(e.Events.SUBTITLE_TRACK_SWITCH, (e, t) => l({
|
|
1648
1648
|
type: "texttrackchange",
|
|
1649
1649
|
id: t.id
|
|
1650
|
-
})),
|
|
1650
|
+
})), p.on(e.Events.ERROR, (e, t) => this.onError(t)), p.loadSource(n.manifestUrl), p.attachMedia(t);
|
|
1651
1651
|
}
|
|
1652
1652
|
getQualityLevels() {
|
|
1653
1653
|
return this.hls ? this.hls.levels.map((e, t) => ({
|
|
@@ -2519,7 +2519,7 @@ async function Sn() {
|
|
|
2519
2519
|
}
|
|
2520
2520
|
//#endregion
|
|
2521
2521
|
//#region src/core/version.ts
|
|
2522
|
-
var Cn = "2.16.
|
|
2522
|
+
var Cn = "2.16.13", wn = {
|
|
2523
2523
|
accent: "#E1B600",
|
|
2524
2524
|
accentText: "#1B1C23",
|
|
2525
2525
|
background: "#0e0f13",
|
|
@@ -2622,6 +2622,7 @@ var In = class {
|
|
|
2622
2622
|
lastError = null;
|
|
2623
2623
|
logoUrl;
|
|
2624
2624
|
statusOverlays;
|
|
2625
|
+
streamEnded;
|
|
2625
2626
|
endedMessage;
|
|
2626
2627
|
interruptedMessage;
|
|
2627
2628
|
errorMessage;
|
|
@@ -2634,7 +2635,7 @@ var In = class {
|
|
|
2634
2635
|
scrubbing = !1;
|
|
2635
2636
|
offFns = [];
|
|
2636
2637
|
constructor(e) {
|
|
2637
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Mn, 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, An(this.doc, e.cspNonce), 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");
|
|
2638
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Mn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, An(this.doc, e.cspNonce), 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");
|
|
2638
2639
|
let t = (e, t, n) => {
|
|
2639
2640
|
let r = this.doc.createElement(e);
|
|
2640
2641
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2799,8 +2800,8 @@ var In = class {
|
|
|
2799
2800
|
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Ln(this.video.currentTime)} / ${Ln(this.video.duration)}`);
|
|
2800
2801
|
}
|
|
2801
2802
|
syncLive() {
|
|
2802
|
-
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
2803
|
-
this.live.style.display = t ? "" : "none", this.time.style.display =
|
|
2803
|
+
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
2804
|
+
this.live.style.display = t && !n ? "" : "none", this.time.style.display = r ? "" : "none", this.seek.style.display = r ? "" : "none", this.live.classList.toggle("is-live", e.atLiveEdge !== !1 && t);
|
|
2804
2805
|
}
|
|
2805
2806
|
onSeekDown(e) {
|
|
2806
2807
|
let t = this.seekableRange();
|
|
@@ -3000,6 +3001,7 @@ var Xn = class {
|
|
|
3000
3001
|
container = null;
|
|
3001
3002
|
detachMedia;
|
|
3002
3003
|
detachPip;
|
|
3004
|
+
detachEndedPlayGuard;
|
|
3003
3005
|
statsTimer;
|
|
3004
3006
|
refreshTimer;
|
|
3005
3007
|
refreshInFlight;
|
|
@@ -3035,7 +3037,7 @@ var Xn = class {
|
|
|
3035
3037
|
return this._endedReason;
|
|
3036
3038
|
}
|
|
3037
3039
|
async start() {
|
|
3038
|
-
this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.setState("loading");
|
|
3040
|
+
this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.attachEndedPlayGuard(), this.setState("loading");
|
|
3039
3041
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
3040
3042
|
try {
|
|
3041
3043
|
let n = await v(t);
|
|
@@ -3307,12 +3309,18 @@ var Xn = class {
|
|
|
3307
3309
|
onStreamEnded(e = !1, t) {
|
|
3308
3310
|
if (!this.destroyed) {
|
|
3309
3311
|
if ((e || !this.rejoinEnabled()) && (this.cancelRejoin(), this.closeLiveState()), this.endedHandled) {
|
|
3310
|
-
t === "match_ended" && this._endedReason !== "match_ended" && (this._endedReason = t, this.emit("ended", t));
|
|
3312
|
+
t === "match_ended" && this._endedReason !== "match_ended" && (this._endedReason = t, this.emit("ended", t), this.leavePipOnEnd());
|
|
3311
3313
|
return;
|
|
3312
3314
|
}
|
|
3313
|
-
this.endedHandled = !0, this._endedReason = t ?? null, this.stopRefresh(), this.pendingStartLoad = !1, this.engine?.stop(), this.setState("ended");
|
|
3315
|
+
this.endedHandled = !0, this._endedReason = t ?? null, this.stopRefresh(), this.pendingStartLoad = !1, this.engine?.stop(), this.setState("ended"), this.leavePipOnEnd();
|
|
3314
3316
|
}
|
|
3315
3317
|
}
|
|
3318
|
+
leavePipOnEnd() {
|
|
3319
|
+
this._endedReason === "interrupted" && this.rejoinEnabled() || this.exitPictureInPicture().catch(() => {});
|
|
3320
|
+
}
|
|
3321
|
+
get streamEnded() {
|
|
3322
|
+
return this._state === "ended" && this.endedHandled;
|
|
3323
|
+
}
|
|
3316
3324
|
rejoinEnabled() {
|
|
3317
3325
|
return this.opts.rejoinOnLive !== !1 && this.opts.liveStateEvents !== !1;
|
|
3318
3326
|
}
|
|
@@ -3350,6 +3358,7 @@ var Xn = class {
|
|
|
3350
3358
|
logoUrl: this.opts.theme?.logoUrl,
|
|
3351
3359
|
statusOverlays: this.opts.statusOverlays,
|
|
3352
3360
|
endedMessage: this.opts.endedMessage,
|
|
3361
|
+
streamEnded: () => this.streamEnded,
|
|
3353
3362
|
interruptedMessage: this.opts.interruptedMessage,
|
|
3354
3363
|
errorMessage: this.opts.errorMessage,
|
|
3355
3364
|
cspNonce: this.opts.cspNonce
|
|
@@ -3372,6 +3381,12 @@ var Xn = class {
|
|
|
3372
3381
|
e.removeEventListener("enterpictureinpicture", n), e.removeEventListener("leavepictureinpicture", r), i?.removeEventListener("fullscreenchange", t), i?.removeEventListener("webkitfullscreenchange", t);
|
|
3373
3382
|
};
|
|
3374
3383
|
}
|
|
3384
|
+
attachEndedPlayGuard() {
|
|
3385
|
+
let e = this.opts.video, t = () => {
|
|
3386
|
+
this.streamEnded && e.pause();
|
|
3387
|
+
};
|
|
3388
|
+
e.addEventListener("play", t), this.detachEndedPlayGuard = () => e.removeEventListener("play", t);
|
|
3389
|
+
}
|
|
3375
3390
|
startStats() {
|
|
3376
3391
|
this.stopStats();
|
|
3377
3392
|
let e = Math.max(500, this.opts.statsIntervalMs ?? Gn);
|
|
@@ -3430,6 +3445,7 @@ var Xn = class {
|
|
|
3430
3445
|
this.idleClosed = !1, await this.reload();
|
|
3431
3446
|
return;
|
|
3432
3447
|
}
|
|
3448
|
+
if (this.streamEnded) return;
|
|
3433
3449
|
let t = this.pendingStartLoad && this._state !== "ended" && this._state !== "error";
|
|
3434
3450
|
this.opts.autoplay === !1 && this.analyticsSession?.notePlayIntent(), t && (this.pendingStartLoad = !1, this.setState("loading"), this.engine?.startLoad());
|
|
3435
3451
|
try {
|
|
@@ -3515,7 +3531,7 @@ var Xn = class {
|
|
|
3515
3531
|
return n.add(t), () => n.delete(t);
|
|
3516
3532
|
}
|
|
3517
3533
|
destroy() {
|
|
3518
|
-
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());
|
|
3534
|
+
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.detachEndedPlayGuard?.(), this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.engine?.destroy(), this.engine = null, this.setState("idle"), this.clearListeners());
|
|
3519
3535
|
}
|
|
3520
3536
|
clearListeners() {
|
|
3521
3537
|
for (let e of Object.keys(this.listeners)) this.listeners[e]?.clear();
|