UNPKG

p2p-media-loader-hlsjs

Version:
203 lines (202 loc) 7.84 kB
import { CoreRequestError as E, debug as M, Core as C } from "p2p-media-loader-core"; function H(r, t) { return t ? `${r}|${t.start}-${t.end}` : r; } function L(r, t) { if (r !== void 0 && t !== void 0 && r <= t) return { start: r, end: t }; } class I { context; config; stats; #t; #a; #e; #i; #s; #n; constructor(t, e) { this.#i = e, this.#a = () => new t.loader(t), this.stats = { aborted: !1, chunkCount: 0, loading: { start: 0, first: 0, end: 0 }, buffering: { start: 0, first: 0, end: 0 }, parsing: { start: 0, end: 0 }, total: 1, loaded: 1, bwEstimate: 0, retry: 0 }; } load(t, e, s) { this.context = t, this.config = e, this.#t = s; const { stats: i } = this, { rangeStart: a, rangeEnd: n } = t, o = L(a, n !== void 0 ? n - 1 : void 0); this.#n = H(t.url, o); const u = this.#i.isSegmentLoadable(this.#n); if (!this.#i.hasSegment(this.#n) || !u) return this.#e = this.#a(), this.#e.stats = this.stats, void this.#e.load(t, e, s); this.#i.loadSegment(this.#n, { onSuccess: (d) => { this.#s = d; const h = this.#s.data.byteLength; i.loading = (function(g, f, c) { const p = 8e3 * f / g, l = c - p; return { start: l - 10, first: l, end: c }; })(this.#s.bandwidth, h, performance.now()), i.total = h, i.loaded = h, s.onProgress && s.onProgress(this.stats, t, this.#s.data, void 0), s.onSuccess({ data: this.#s.data, url: t.url }, this.stats, t, void 0); }, onError: (d) => { d instanceof E && d.type === "aborted" && this.stats.aborted || this.#o(d); } }); } #o(t) { const e = { code: 0, text: "" }; (t instanceof E && t.type === "failed" || t instanceof Error) && (e.text = t.message), this.#t?.onError(e, this.context, null, this.stats); } #r() { !this.#s && this.#n && (this.stats.aborted = !0, this.#i.abortSegmentLoading(this.#n)); } abort() { this.#e ? this.#e.abort() : (this.#r(), this.#t?.onAbort?.(this.stats, this.context, {})); } destroy() { this.#e ? this.#e.destroy() : (this.stats.aborted || this.#r(), this.#t = null, this.config = null); } } class S { #t; context; stats; constructor(t) { this.#t = new t.loader(t), this.stats = this.#t.stats, this.context = this.#t.context; } load(t, e, s) { this.#t.load(t, e, s); } abort() { this.#t.abort(); } destroy() { this.#t.destroy(); } } class x { core; constructor(t) { this.core = t; } processMainManifest(t) { const { levels: e, audioTracks: s } = t; for (const [i, a] of e.entries()) { const { url: n } = a; this.core.addStreamIfNoneExists({ runtimeId: Array.isArray(n) ? n[0] : n, type: "main", index: i }); } for (const [i, a] of s.entries()) { const { url: n } = a; this.core.addStreamIfNoneExists({ runtimeId: Array.isArray(n) ? n[0] : n, type: "secondary", index: i }); } } updatePlaylist(t) { const { details: { url: e, fragments: s, live: i } } = t, a = this.core.getStream(e); if (!a) return; const n = new Set(a.segments.keys()), o = []; s.forEach((u, d) => { const { url: h, byteRange: g, sn: f, start: c, end: p } = u, [l, v] = g, m = L(l, v !== void 0 ? v - 1 : void 0), y = H(h, m); n.delete(y), a.segments.has(y) || o.push({ runtimeId: y, url: h, externalId: i ? f : d, byteRange: m, startTime: c, endTime: p }); }), (o.length || n.size) && this.core.updateStream(e, o, n.values()); } } class b { core; segmentManager; hlsInstanceGetter; currentHlsInstance; debug = M("p2pml-hlsjs:engine"); static injectMixin(t) { return e = t, class extends e { #t; get p2pEngine() { return this.#t; } constructor(...s) { const i = s[0], { p2p: a, ...n } = i ?? {}, o = new b(a); super({ ...n, ...o.getConfigForHlsJs() }), o.bindHls(this), this.#t = o, a?.onHlsJsCreated?.(this); } }; var e; } constructor(t) { this.core = new C(t?.core), this.segmentManager = new x(this.core); } addEventListener(t, e) { this.core.addEventListener(t, e); } removeEventListener(t, e) { this.core.removeEventListener(t, e); } getConfigForHlsJs() { return { fLoader: this.createFragmentLoaderClass(), pLoader: this.createPlaylistLoaderClass() }; } getConfig() { return { core: this.core.getConfig() }; } applyDynamicConfig(t) { t.core && this.core.applyDynamicConfig(t.core); } bindHls(t) { this.hlsInstanceGetter = typeof t == "function" ? t : () => t; } initHlsEvents() { const t = this.hlsInstanceGetter?.(); this.currentHlsInstance !== t && (this.currentHlsInstance && this.destroy(), this.currentHlsInstance = t, this.updateHlsEventsHandlers("register"), this.updateMediaElementEventHandlers("register")); } updateHlsEventsHandlers(t) { const e = this.currentHlsInstance; if (!e) return; const s = t === "register" ? "on" : "off"; e[s]("hlsManifestLoaded", this.handleManifestLoaded), e[s]("hlsLevelSwitching", this.handleLevelSwitching), e[s]("hlsLevelUpdated", this.handleLevelUpdated), e[s]("hlsAudioTrackLoaded", this.handleLevelUpdated), e[s]("hlsDestroying", this.destroy), e[s]("hlsMediaAttaching", this.destroyCore), e[s]("hlsManifestLoading", this.destroyCore), e[s]("hlsMediaDetached", this.handleMediaDetached), e[s]("hlsMediaAttached", this.handleMediaAttached); } updateMediaElementEventHandlers = (t) => { const e = this.currentHlsInstance?.media; if (!e) return; const s = t === "register" ? "addEventListener" : "removeEventListener"; e[s]("timeupdate", this.handlePlaybackUpdate), e[s]("seeking", this.handlePlaybackUpdate), e[s]("ratechange", this.handlePlaybackUpdate); }; handleManifestLoaded = (t, e) => { const s = e.networkDetails; s instanceof XMLHttpRequest ? this.core.setManifestResponseUrl(s.responseURL) : s instanceof Response && this.core.setManifestResponseUrl(s.url), this.segmentManager.processMainManifest(e); }; handleLevelSwitching = (t, e) => { e.bitrate && this.core.setActiveLevelBitrate(e.bitrate); }; handleLevelUpdated = (t, e) => { this.currentHlsInstance && e.details.live && e.details.fragments[0].type === "main" && !this.currentHlsInstance.userConfig.liveSyncDuration && !this.currentHlsInstance.userConfig.liveSyncDurationCount && e.details.fragments.length > 4 && this.updateLiveSyncDurationCount(e), this.core.setIsLive(e.details.live), this.segmentManager.updatePlaylist(e); }; updateLiveSyncDurationCount(t) { const e = t.details.targetduration, s = Math.floor(120 / e), i = Math.min(t.details.fragments.length - 1, s); this.currentHlsInstance && this.currentHlsInstance.config.liveSyncDurationCount !== i && (this.debug(`Setting liveSyncDurationCount to ${i}`), this.currentHlsInstance.config.liveSyncDurationCount = i); } handleMediaAttached = () => { this.updateMediaElementEventHandlers("register"); }; handleMediaDetached = () => { this.updateMediaElementEventHandlers("unregister"); }; handlePlaybackUpdate = (t) => { const e = t.target; this.core.updatePlayback(e.currentTime, e.playbackRate); }; destroyCore = () => this.core.destroy(); destroy = () => { this.destroyCore(), this.updateHlsEventsHandlers("unregister"), this.updateMediaElementEventHandlers("unregister"), this.currentHlsInstance = void 0; }; createFragmentLoaderClass() { const { core: t } = this, e = this; return class extends I { constructor(s) { super(s, t); } static getEngine() { return e; } }; } createPlaylistLoaderClass() { const t = this; return class extends S { constructor(e) { super(e), t.initHlsEvents(); } }; } } export { b as HlsJsP2PEngine }; //# sourceMappingURL=p2p-media-loader-hlsjs.es.min.js.map