@videojs/spf 0.1.0-alpha.2 → 10.0.0-beta.1

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.
@@ -0,0 +1,243 @@
1
+ import { a as PresentationAction, c as SourceBufferActor, d as WritableState, f as BandwidthState, l as TrackSelectionState, o as EventStream, s as loadTextTrackCues, t as SpfMedia, u as Presentation } from "../adapter-l8iJN_GI.js";
2
+
3
+ //#region src/dom/features/setup-sourcebuffer.d.ts
4
+
5
+ /**
6
+ * Media track type for SourceBuffer setup.
7
+ * Text tracks are excluded as they don't use MSE SourceBuffers.
8
+ */
9
+ type MediaTrackType = 'video' | 'audio';
10
+ //#endregion
11
+ //#region src/dom/features/load-segments.d.ts
12
+
13
+ /**
14
+ * State shape for segment loading.
15
+ */
16
+ interface SegmentLoadingState extends TrackSelectionState {
17
+ presentation?: Presentation;
18
+ preload?: string;
19
+ bandwidthState?: BandwidthState;
20
+ /** Current playback position in seconds. Defaults to 0 when undefined. */
21
+ currentTime?: number;
22
+ /** True once the user has initiated playback. Allows segment loading regardless of preload setting. */
23
+ playbackInitiated?: boolean;
24
+ }
25
+ /**
26
+ * Owners shape for segment loading.
27
+ */
28
+ interface SegmentLoadingOwners {
29
+ videoBuffer?: SourceBuffer;
30
+ audioBuffer?: SourceBuffer;
31
+ videoBufferActor?: SourceBufferActor;
32
+ audioBufferActor?: SourceBufferActor;
33
+ }
34
+ /**
35
+ * Load segments orchestration — Reactor layer.
36
+ *
37
+ * Sends typed load messages to a SegmentLoaderActor when relevant conditions
38
+ * change. Uses targeted subscriptions rather than broad combineLatest so only
39
+ * meaningful state changes trigger evaluation.
40
+ *
41
+ * Condition hierarchy (see SegmentLoadingKey for detail):
42
+ *
43
+ * !playbackInitiated
44
+ * preload==='none' (or unset) → dormant; no trigger
45
+ * preload==='metadata' → trigger on transition to 'metadata'
46
+ * preload==='auto' → trigger on transition to 'auto'
47
+ *
48
+ * !playbackInitiated → playbackInitiated
49
+ * preload !== 'auto' → trigger (message shape changes)
50
+ * preload === 'auto' → suppressed (was already full-range mode;
51
+ * let segmentStart take over post-play)
52
+ * KNOWN LIMITATION: seek-before-play with
53
+ * preload='auto' is not supported — if the
54
+ * user seeks before pressing play, the
55
+ * first re-send is delayed until the next
56
+ * segment boundary crossing post-play.
57
+ *
58
+ * playbackInitiated
59
+ * resolvedTrackId changes → trigger
60
+ * segmentStart(currentTime) changes → trigger (segment boundary only)
61
+ *
62
+ * @example
63
+ * const cleanup = loadSegments({ state, owners }, { type: 'video' });
64
+ */
65
+ declare function loadSegments({
66
+ state,
67
+ owners
68
+ }: {
69
+ state: WritableState<SegmentLoadingState>;
70
+ owners: WritableState<SegmentLoadingOwners>;
71
+ }, config: {
72
+ type: MediaTrackType;
73
+ }): () => void;
74
+ //#endregion
75
+ //#region src/dom/features/track-current-time.d.ts
76
+ /**
77
+ * State shape for current time tracking.
78
+ */
79
+ interface CurrentTimeState {
80
+ currentTime?: number;
81
+ }
82
+ /**
83
+ * Owners shape for current time tracking.
84
+ */
85
+ interface CurrentTimeOwners {
86
+ mediaElement?: HTMLMediaElement | undefined;
87
+ }
88
+ /**
89
+ * Track current playback position from the media element.
90
+ *
91
+ * Mirrors `mediaElement.currentTime` into reactive state on:
92
+ * - `timeupdate` — fires during playback (~4 Hz)
93
+ * - `seeking` — fires when a seek begins; per spec, `currentTime` is
94
+ * already at the new position when this event dispatches, so buffer
95
+ * management can react immediately rather than waiting for `timeupdate`,
96
+ * which does not fire while paused.
97
+ *
98
+ * Also syncs immediately when a media element becomes available.
99
+ *
100
+ * @example
101
+ * const cleanup = trackCurrentTime({ state, owners });
102
+ */
103
+ declare function trackCurrentTime({
104
+ state,
105
+ owners
106
+ }: {
107
+ state: WritableState<CurrentTimeState>;
108
+ owners: WritableState<CurrentTimeOwners>;
109
+ }): () => void;
110
+ //#endregion
111
+ //#region src/dom/features/track-playback-initiated.d.ts
112
+ /**
113
+ * State shape for playback initiation tracking.
114
+ */
115
+ interface PlaybackInitiatedState {
116
+ /** True once the user has initiated playback (play event fired). */
117
+ playbackInitiated?: boolean;
118
+ /** Current presentation — watched for URL changes to reset playbackInitiated. */
119
+ presentation?: {
120
+ url?: string;
121
+ };
122
+ }
123
+ /**
124
+ * Owners shape for playback initiation tracking.
125
+ */
126
+ interface PlaybackInitiatedOwners {
127
+ mediaElement?: HTMLMediaElement | undefined;
128
+ }
129
+ /**
130
+ * Track whether playback has been initiated by the user.
131
+ *
132
+ * Sets `state.playbackInitiated = true` when the media element fires a `play`
133
+ * event (via `element.play()`, native controls, or autoplay) and simultaneously
134
+ * dispatches `{ type: 'play' }` to the event stream so `resolvePresentation`
135
+ * can react.
136
+ *
137
+ * Resets `state.playbackInitiated = false` when `presentation.url` changes,
138
+ * so a new source with `preload="none"` won't load segments until play is
139
+ * triggered again.
140
+ *
141
+ * This flag is used by `shouldLoadSegments` to allow segment loading after
142
+ * play is initiated regardless of the initial `preload` setting — `preload`
143
+ * is a startup hint, not a runtime gate.
144
+ *
145
+ * @example
146
+ * const cleanup = trackPlaybackInitiated({ state, owners, events });
147
+ */
148
+ declare function trackPlaybackInitiated({
149
+ state,
150
+ owners,
151
+ events
152
+ }: {
153
+ state: WritableState<PlaybackInitiatedState>;
154
+ owners: WritableState<PlaybackInitiatedOwners>;
155
+ events: EventStream<PresentationAction>;
156
+ }): () => void;
157
+ //#endregion
158
+ //#region src/dom/features/track-playback-rate.d.ts
159
+ /**
160
+ * State shape for playback rate tracking.
161
+ */
162
+ interface PlaybackRateState {
163
+ playbackRate?: number;
164
+ }
165
+ /**
166
+ * Owners shape for playback rate tracking.
167
+ */
168
+ interface PlaybackRateOwners {
169
+ mediaElement?: HTMLMediaElement | undefined;
170
+ }
171
+ /**
172
+ * Track playback rate from the media element.
173
+ *
174
+ * Mirrors `mediaElement.playbackRate` into reactive state on each `ratechange`
175
+ * event. Also syncs immediately when a media element becomes available.
176
+ *
177
+ * @example
178
+ * const cleanup = trackPlaybackRate({ state, owners });
179
+ */
180
+ declare function trackPlaybackRate({
181
+ state,
182
+ owners
183
+ }: {
184
+ state: WritableState<PlaybackRateState>;
185
+ owners: WritableState<PlaybackRateOwners>;
186
+ }): () => void;
187
+ //#endregion
188
+ //#region src/dom/media/append-segment.d.ts
189
+ /**
190
+ * Segment appender helper (P11)
191
+ *
192
+ * Appends media segments (ArrayBuffer) to SourceBuffer.
193
+ */
194
+ /**
195
+ * Append a media segment to a SourceBuffer.
196
+ *
197
+ * Waits for the SourceBuffer to be ready (not updating), then appends
198
+ * the segment data. Returns a promise that resolves when append completes.
199
+ *
200
+ * @param sourceBuffer - The SourceBuffer to append to
201
+ * @param segmentData - The segment data as ArrayBuffer
202
+ * @returns Promise that resolves when append completes
203
+ *
204
+ * @example
205
+ * const data = await fetch(segmentUrl).then(r => r.arrayBuffer());
206
+ * await appendSegment(videoSourceBuffer, data);
207
+ */
208
+ declare function appendSegment(sourceBuffer: SourceBuffer, segmentData: ArrayBuffer): Promise<void>;
209
+ //#endregion
210
+ //#region src/dom/media/buffer-flusher.d.ts
211
+ /**
212
+ * Buffer flusher helper (P12)
213
+ *
214
+ * Removes a time range from a SourceBuffer to manage memory.
215
+ */
216
+ /**
217
+ * Remove a time range from a SourceBuffer.
218
+ *
219
+ * Waits for the SourceBuffer to be ready (not updating), then removes
220
+ * the specified range. Returns a promise that resolves when removal completes.
221
+ *
222
+ * @param sourceBuffer - The SourceBuffer to remove data from
223
+ * @param start - Start of the time range to remove (seconds)
224
+ * @param end - End of the time range to remove (seconds)
225
+ * @returns Promise that resolves when removal completes
226
+ *
227
+ * @example
228
+ * await flushBuffer(videoSourceBuffer, 0, 30);
229
+ */
230
+ declare function flushBuffer(sourceBuffer: SourceBuffer, start: number, end: number): Promise<void>;
231
+ //#endregion
232
+ //#region src/dom/text/parse-vtt-segment.d.ts
233
+ /**
234
+ * Parse a VTT segment using browser's native parser.
235
+ *
236
+ * Creates a dummy video element with a track element to leverage
237
+ * the browser's optimized VTT parsing. Returns parsed VTTCue objects.
238
+ */
239
+ declare function parseVttSegment(url: string): Promise<VTTCue[]>;
240
+ declare function destroyVttParser(): void;
241
+ //#endregion
242
+ export { type CurrentTimeOwners, type CurrentTimeState, type PlaybackInitiatedOwners, type PlaybackInitiatedState, type PlaybackRateOwners, type PlaybackRateState, SpfMedia, appendSegment, destroyVttParser, flushBuffer, loadSegments, loadTextTrackCues, parseVttSegment, trackCurrentTime, trackPlaybackInitiated, trackPlaybackRate };
243
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/dom/features/setup-sourcebuffer.ts","../../src/dom/features/load-segments.ts","../../src/dom/features/track-current-time.ts","../../src/dom/features/track-playback-initiated.ts","../../src/dom/features/track-playback-rate.ts","../../src/dom/media/append-segment.ts","../../src/dom/media/buffer-flusher.ts","../../src/dom/text/parse-vtt-segment.ts"],"sourcesContent":[],"mappings":";;;;;;;AC+DA;AACiB,KD7CL,cAAA,GC6CK,OAAA,GAAA,OAAA;;;;;;;AAD+C,UAA/C,mBAAA,SAA4B,mBAAmB,CAAA;EAa/C,YAAA,CAAA,EAZA,YAYoB;EACrB,OAAA,CAAA,EAAA,MAAA;EACA,cAAA,CAAA,EAZG,cAYH;EACK;EACA,WAAA,CAAA,EAAA,MAAA;EAAiB;EAgItB,iBAAY,CAAA,EAAA,OAAA;;;;;AAMF,UA1IT,oBAAA,CA0IS;EAAd,WAAA,CAAA,EAzII,YAyIJ;EAEM,WAAA,CAAA,EA1IF,YA0IE;EAAc,gBAAA,CAAA,EAzIX,iBAyIW;qBAxIX;;;AC1ErB;AAOA;AA6BA;;;;;;;;;;;AClCA;AAUA;AAuBA;;;;;;;;;;;;;;ACnCA;AAOiB,iBHmMD,YAAA,CGlMC;EAAA,KAAA;EAAA;CAAgB,EAAA;EAsBjB,KAAA,EHiLL,aGjLsB,CHiLR,mBGjLQ,CAAA;EAC/B,MAAA,EHiLU,aGjLV,CHiLwB,oBGjLxB,CAAA;CACA,EAAA,MAAA,EAAA;EAEqB,IAAA,EHgLL,cGhLK;CAAd,CAAA,EAAA,GAAA,GAAA,IAAA;;;;;AJrBT;UEbiB,gBAAA;;;ADyDjB;;;AAA6C,UClD5B,iBAAA,CDkD4B;EAAmB,YAAA,CAAA,ECjD/C,gBDiD+C,GAAA,SAAA;AAahE;;;;;;;;;;;ACtEA;AAOA;AA6BA;;;AAIuB,iBAJP,gBAAA,CAIO;EAAA,KAAA;EAAA;CAAA,EAAA;EAAd,KAAA,EAAA,aAAA,CAAc,gBAAd,CAAA;EACe,MAAA,EAAd,aAAc,CAAA,iBAAA,CAAA;CAAd,CAAA,EAAA,GAAA,GAAA,IAAA;;;AF5BV;;;UGXiB,sBAAA;EFuDA;EACA,iBAAA,CAAA,EAAA,OAAA;EAEE;EAH0B,YAAA,CAAA,EAAA;IAAmB,GAAA,CAAA,EAAA,MAAA;EAa/C,CAAA;;;;;AAIqB,UE9DrB,uBAAA,CF8DqB;EAgItB,YAAA,CAAA,EE7LC,gBF6LW,GAAA,SAAA;;;;;;;;;;;;AC1M5B;AAOA;AA6BA;;;;;;;AAKuB,iBCNP,sBAAA,CDMO;EAAA,KAAA;EAAA,MAAA;EAAA;ACvCvB,CDuCuB,EAAA;SCDd,cAAc;UACb,cAAc;UACd,YAAY;AAxCtB,CAAA,CAAA,EAAiB,GAAA,GAAA,IAAA;;;;;AHWjB;UIbiB,iBAAA;;;AHyDjB;;;AAA6C,UGlD5B,kBAAA,CHkD4B;EAAmB,YAAA,CAAA,EGjD/C,gBHiD+C,GAAA,SAAA;AAahE;;;;;;;;;;iBGxCgB,iBAAA;;;AFMhB;EApCiB,KAAA,EEkCR,aFlCwB,CEkCV,iBFlCU,CAAA;EAOhB,MAAA,EE4BP,aF5BwB,CE4BV,kBF3BP,CAAA;AA4BjB,CAAA,CAAA,EAAgB,GAAA,GAAA,IAAA;;;;;;AFvBhB;;;;AC4CA;;;;;AAaA;;;;;;AAoIA;AAEI,iBI9LkB,aAAA,CJ8LlB,YAAA,EI9L8C,YJ8L9C,EAAA,WAAA,EI9LyE,WJ8LzE,CAAA,EI9LuF,OJ8LvF,CAAA,IAAA,CAAA;;;;;;AD/LJ;;;;AC4CA;;;;;AAaA;;;;;;AAoIA;AAEI,iBK9LkB,WAAA,CL8LlB,YAAA,EK9L4C,YL8L5C,EAAA,KAAA,EAAA,MAAA,EAAA,GAAA,EAAA,MAAA,CAAA,EK9LuF,OL8LvF,CAAA,IAAA,CAAA;;;;;;AD/LJ;;;iBOEgB,eAAA,eAA8B,QAAQ;AN0CrC,iBMAD,gBAAA,CAAA,CNAqB,EAAA,IAAA"}
@@ -0,0 +1,38 @@
1
+ import "../src-DRsS_H80.js";
2
+ import { a as trackPlaybackInitiated, c as destroyVttParser, i as appendSegment, l as parseVttSegment, o as trackCurrentTime, r as flushBuffer, s as loadTextTrackCues, t as SpfMedia, u as loadSegments } from "../adapter-CMw-rvbk.js";
3
+ import { listen } from "@videojs/utils/dom";
4
+
5
+ //#region src/dom/features/track-playback-rate.ts
6
+ /**
7
+ * Track playback rate from the media element.
8
+ *
9
+ * Mirrors `mediaElement.playbackRate` into reactive state on each `ratechange`
10
+ * event. Also syncs immediately when a media element becomes available.
11
+ *
12
+ * @example
13
+ * const cleanup = trackPlaybackRate({ state, owners });
14
+ */
15
+ function trackPlaybackRate({ state, owners }) {
16
+ let lastMediaElement;
17
+ let removeListener = null;
18
+ const unsubscribe = owners.subscribe((currentOwners) => {
19
+ const { mediaElement } = currentOwners;
20
+ if (mediaElement === lastMediaElement) return;
21
+ removeListener?.();
22
+ removeListener = null;
23
+ lastMediaElement = mediaElement;
24
+ if (!mediaElement) return;
25
+ state.patch({ playbackRate: mediaElement.playbackRate });
26
+ removeListener = listen(mediaElement, "ratechange", () => {
27
+ state.patch({ playbackRate: mediaElement.playbackRate });
28
+ });
29
+ });
30
+ return () => {
31
+ removeListener?.();
32
+ unsubscribe();
33
+ };
34
+ }
35
+
36
+ //#endregion
37
+ export { SpfMedia, appendSegment, destroyVttParser, flushBuffer, loadSegments, loadTextTrackCues, parseVttSegment, trackCurrentTime, trackPlaybackInitiated, trackPlaybackRate };
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["lastMediaElement: HTMLMediaElement | undefined","removeListener: (() => void) | null"],"sources":["../../src/dom/features/track-playback-rate.ts"],"sourcesContent":["import { listen } from '@videojs/utils/dom';\nimport type { WritableState } from '../../core/state/create-state';\n\n/**\n * State shape for playback rate tracking.\n */\nexport interface PlaybackRateState {\n playbackRate?: number;\n}\n\n/**\n * Owners shape for playback rate tracking.\n */\nexport interface PlaybackRateOwners {\n mediaElement?: HTMLMediaElement | undefined;\n}\n\n/**\n * Check if we can track playback rate.\n *\n * Requires:\n * - mediaElement exists in owners\n */\nexport function canTrackPlaybackRate(owners: PlaybackRateOwners): boolean {\n return !!owners.mediaElement;\n}\n\n/**\n * Track playback rate from the media element.\n *\n * Mirrors `mediaElement.playbackRate` into reactive state on each `ratechange`\n * event. Also syncs immediately when a media element becomes available.\n *\n * @example\n * const cleanup = trackPlaybackRate({ state, owners });\n */\nexport function trackPlaybackRate({\n state,\n owners,\n}: {\n state: WritableState<PlaybackRateState>;\n owners: WritableState<PlaybackRateOwners>;\n}): () => void {\n let lastMediaElement: HTMLMediaElement | undefined;\n let removeListener: (() => void) | null = null;\n\n const unsubscribe = owners.subscribe((currentOwners) => {\n const { mediaElement } = currentOwners;\n\n if (mediaElement === lastMediaElement) return;\n\n removeListener?.();\n removeListener = null;\n lastMediaElement = mediaElement;\n\n if (!mediaElement) return;\n\n state.patch({ playbackRate: mediaElement.playbackRate });\n\n removeListener = listen(mediaElement, 'ratechange', () => {\n state.patch({ playbackRate: mediaElement.playbackRate });\n });\n });\n\n return () => {\n removeListener?.();\n unsubscribe();\n };\n}\n"],"mappings":";;;;;;;;;;;;;;AAoCA,SAAgB,kBAAkB,EAChC,OACA,UAIa;CACb,IAAIA;CACJ,IAAIC,iBAAsC;CAE1C,MAAM,cAAc,OAAO,WAAW,kBAAkB;EACtD,MAAM,EAAE,iBAAiB;AAEzB,MAAI,iBAAiB,iBAAkB;AAEvC,oBAAkB;AAClB,mBAAiB;AACjB,qBAAmB;AAEnB,MAAI,CAAC,aAAc;AAEnB,QAAM,MAAM,EAAE,cAAc,aAAa,cAAc,CAAC;AAExD,mBAAiB,OAAO,cAAc,oBAAoB;AACxD,SAAM,MAAM,EAAE,cAAc,aAAa,cAAc,CAAC;IACxD;GACF;AAEF,cAAa;AACX,oBAAkB;AAClB,eAAa"}
@@ -0,0 +1,2 @@
1
+ import { i as createPlaybackEngine, n as PlaybackEngine, r as PlaybackEngineConfig, t as SpfMedia } from "../../adapter-l8iJN_GI.js";
2
+ export { type PlaybackEngine, type PlaybackEngineConfig, SpfMedia, createPlaybackEngine };
@@ -0,0 +1,4 @@
1
+ import "../../src-DRsS_H80.js";
2
+ import { n as createPlaybackEngine, t as SpfMedia } from "../../adapter-CMw-rvbk.js";
3
+
4
+ export { SpfMedia, createPlaybackEngine };
@@ -0,0 +1,13 @@
1
+ //#region src/index.d.ts
2
+ /**
3
+ * Stream Processing Framework (SPF) for Video.js 10
4
+ *
5
+ * Bundle size target: < 20KB (minified + gzipped)
6
+ * Primary use case: CMAF HLS playback with Video.js v10
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ declare const VERSION = "0.1.0";
11
+ //#endregion
12
+ export { VERSION };
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;AAWA;;;;;;;cAAa,OAAA"}
package/dist/index.js CHANGED
@@ -1 +1,3 @@
1
- import{isNil as e,isUndefined as t}from"@videojs/utils/predicate";import{listen as n}from"@videojs/utils/dom";const r=Symbol(`@videojs/event-stream`);function i(){let e=new Set;return{[r]:!0,dispatch(t){let n=Array.from(e);for(let e of n)e(t)},subscribe(t){return e.add(t),()=>e.delete(t)}}}function a(e){let t=t=>{let n=Array(e.length),r=Array(e.length).fill(!1),i=[];for(let a=0;a<e.length;a++){let o=e[a].subscribe(e=>{n[a]=e,r[a]=!0,r.every(e=>e)&&t([...n])});i.push(o)}return()=>{for(let e of i)e()}};return{subscribe(e,n,r){if(n===void 0)return t(e);let i=e,a=n,o=r?.equalityFn??Object.is,s,c=!1;return t(e=>{let t=i(e);(!c||!o(s,t))&&(s=t,c=!0,a(t))})}}}function o(e){return`segments`in e}function s(e){return e.duration!==void 0}const c={video:`selectedVideoTrackId`,audio:`selectedAudioTrackId`,text:`selectedTextTrackId`},l={video:`videoBuffer`,audio:`audioBuffer`};function u(e,t){let{presentation:n}=e;if(!n||!(`id`in n))return;let r=e[c[t]];return n.selectionSets.find(({type:e})=>e===t)?.switchingSets[0]?.tracks.find(({id:e})=>e===r)}function d(e){return e.presentation?!!(e.selectedVideoTrackId||e.selectedAudioTrackId):!1}function f(e){if(!d(e))return!1;let{presentation:t}=e;if(t.duration!==void 0)return!1;let n=e.selectedVideoTrackId?u(e,`video`):void 0,r=e.selectedAudioTrackId?u(e,`audio`):void 0;return!!(n&&o(n)||r&&o(r))}function p(e){let t=e.selectedVideoTrackId?u(e,`video`):void 0;if(t&&o(t))return t.duration;let n=e.selectedAudioTrackId?u(e,`audio`):void 0;if(n&&o(n))return n.duration}function m({state:e}){return a([e]).subscribe(([t])=>{if(!f(t))return;let n=p(t);if(n===void 0||!Number.isFinite(n))return;let{presentation:r}=t;e.patch({presentation:{...r,duration:n}})})}function h(e){return Math.exp(Math.log(.5)/e)}function g(e,t,n,r){let i=h(r)**n;return t*(1-i)+i*e}function _(e,t,n){return t===0?0:e/(1-h(n)**t)}const v={fastHalfLife:2,slowHalfLife:5,minTotalBytes:128e3,minBytes:16e3,minDuration:5};function ee(e,t,n,r=v){let i=e.bytesSampled+n;if(n<r.minBytes||t<r.minDuration)return{...e,bytesSampled:i};let a=8e3*n/t,o=t/1e3;return{fastEstimate:g(e.fastEstimate,a,o,r.fastHalfLife),fastTotalWeight:e.fastTotalWeight+o,slowEstimate:g(e.slowEstimate,a,o,r.slowHalfLife),slowTotalWeight:e.slowTotalWeight+o,bytesSampled:i}}function te(e,t,n=v){if(e.bytesSampled<n.minTotalBytes)return t;let r=_(e.fastEstimate,e.fastTotalWeight,n.fastHalfLife),i=_(e.slowEstimate,e.slowTotalWeight,n.slowHalfLife);return Math.min(r,i)}const ne={safetyMargin:.85};function y(e,t,n=ne){if(e.length===0)return;let r=e.slice().sort((e,t)=>e.bandwidth-t.bandwidth),i;for(let e of r)t>=e.bandwidth/n.safetyMargin&&(!i||e.bandwidth>i.bandwidth||e.bandwidth===i.bandwidth&&re(e,i))&&(i=e);return i??r[0]}function re(e,t){return(e.width??0)*(e.height??0)>(t.width??0)*(t.height??0)}const b={safetyMargin:.85,minUpgradeInterval:8e3,defaultBandwidth:5e6};function ie(e){return(e.selectionSets?.find(e=>e.type===`video`))?.switchingSets[0]?.tracks??[]}function ae({state:e},t={}){let n=t.safetyMargin??b.safetyMargin,r=t.minUpgradeInterval??b.minUpgradeInterval,i=t.defaultBandwidth??b.defaultBandwidth,a=Date.now(),o=!0;return e.subscribe(t=>{let{presentation:s,bandwidthState:c,selectedVideoTrackId:l,abrDisabled:u}=t;if(u===!0||!s||!c)return;let d=ie(s);if(d.length===0)return;let f=o;o=!1;let p=y(d,te(c,i),{safetyMargin:n});if(!p||p.id===l)return;let m=d.find(e=>e.id===l);if(!m||p.bandwidth>m.bandwidth){let e=Date.now();if(!f&&e-a<r)return;a=e}e.patch({selectedVideoTrackId:p.id})})}async function x(e,t){let n=new Headers(t?.headers);if(e.byteRange){let{start:t,end:r}=e.byteRange;n.set(`Range`,`bytes=${t}-${r}`)}let r=new Request(e.url,{method:`GET`,headers:n,...t});return fetch(r)}async function S(e,t){return(await x(e,t)).arrayBuffer()}function C(e){return e.text()}function w(){return`${Date.now()}-${Math.floor(Math.random()*1e6)}`}function oe(e){let t=new Map;for(let n of e.matchAll(/([A-Z0-9-]+)=(?:"([^"]*)"|([^,]*))/g)){let e=n[1],r=n[2]??n[3]??``;e&&t.set(e,r)}return t}function se(e){let t=/^(\d+)x(\d+)$/.exec(e);return t?{width:Number.parseInt(t[1],10),height:Number.parseInt(t[2],10)}:null}function ce(e){let t=Number.parseFloat(e);if(!(Number.isNaN(t)||t<=0))return Math.abs(t-23.976)<.01?{frameRateNumerator:24e3,frameRateDenominator:1001}:Math.abs(t-29.97)<.01?{frameRateNumerator:3e4,frameRateDenominator:1001}:Math.abs(t-59.94)<.01?{frameRateNumerator:6e4,frameRateDenominator:1001}:(t%1,{frameRateNumerator:Math.round(t)})}function T(e){let t=e.split(`,`).map(e=>e.trim()),n={};for(let e of t)e.startsWith(`avc1.`)||e.startsWith(`hvc1.`)||e.startsWith(`hev1.`)?n.video=e:e.startsWith(`mp4a.`)&&(n.audio=e);return n}function le(e){let t=e.split(`,`)[0]??e,n=Number.parseFloat(t);return Number.isNaN(n)?0:n}function E(e,t){let n=/^(\d+)(?:@(\d+))?$/.exec(e);if(!n)return null;let r=Number.parseInt(n[1],10);if(Number.isNaN(r))return null;let i;if(n[2]!==void 0){if(i=Number.parseInt(n[2],10),Number.isNaN(i))return null}else if(t!==void 0)i=t;else return null;return{start:i,end:i+r-1}}function ue(e){let t=oe(e);return{get(e){return t.get(e)},getInt(e,n){let r=t.get(e);if(r===void 0)return n;let i=Number.parseInt(r,10);return Number.isNaN(i)?n:i},getFloat(e,n){let r=t.get(e);if(r===void 0)return n;let i=Number.parseFloat(r);return Number.isNaN(i)?n:i},getBool(e){return t.get(e)===`YES`},getResolution(e){let n=t.get(e);if(n)return se(n)??void 0},getFrameRate(e){let n=t.get(e);if(n)return ce(n)}}}function D(e,t){let n=`#${t}:`;return e.startsWith(n)?ue(e.slice(n.length)):null}function O(e,t){return new URL(e,t).href}function de(e,t){let n=t.url,r=e.split(/\r?\n/),i=[],a=[],o=[],s=null;for(let e of r){let t=e.trim();if(!t||t.startsWith(`#`)&&!t.startsWith(`#EXT`)||t===`#EXTM3U`||t.startsWith(`#EXT-X-VERSION:`)||t.startsWith(`#EXT-X-INDEPENDENT-SEGMENTS`))continue;let r=D(t,`EXT-X-MEDIA`);if(r){let e=r.get(`TYPE`),t=r.get(`GROUP-ID`),i=r.get(`NAME`);if(e===`AUDIO`&&t&&i){let e=r.get(`URI`);a.push({groupId:t,name:i,language:r.get(`LANGUAGE`),uri:e?O(e,n):void 0,default:r.getBool(`DEFAULT`),autoselect:r.getBool(`AUTOSELECT`)})}if(e===`SUBTITLES`&&t&&i){let e=r.get(`URI`);e&&o.push({groupId:t,name:i,language:r.get(`LANGUAGE`),uri:O(e,n),default:r.getBool(`DEFAULT`),autoselect:r.getBool(`AUTOSELECT`),forced:r.getBool(`FORCED`)})}continue}let c=D(t,`EXT-X-STREAM-INF`);if(c){s={bandwidth:c.getInt(`BANDWIDTH`,0),resolution:c.getResolution(`RESOLUTION`),codecs:c.get(`CODECS`),frameRate:c.getFrameRate(`FRAME-RATE`),audioGroupId:c.get(`AUDIO`)};continue}!t.startsWith(`#`)&&s&&(i.push({...s,uri:O(t,n)}),s=null)}let c=[],l=[];for(let e of i){if(!e.codecs){c.push(e);continue}let t=T(e.codecs);e.codecs.split(`,`).length===1&&t.audio&&!t.video?l.push(e):c.push(e)}let u=c.map(e=>{let t=e.codecs?T(e.codecs):void 0,n={type:`video`,id:w(),url:e.uri,bandwidth:e.bandwidth,mimeType:`video/mp4`,codecs:[]};return e.resolution?.width!==void 0&&(n.width=e.resolution.width),e.resolution?.height!==void 0&&(n.height=e.resolution.height),t?.video&&(n.codecs=[t.video]),e.frameRate&&(n.frameRate=e.frameRate),e.audioGroupId&&(n.audioGroupId=e.audioGroupId),n}),d=l.map(e=>{let t=e.codecs?T(e.codecs):void 0;return{type:`audio`,id:w(),url:e.uri,bandwidth:e.bandwidth,mimeType:`audio/mp4`,codecs:t?.audio?[t.audio]:[],groupId:e.audioGroupId||`default`,name:`Default`,sampleRate:48e3,channels:2}}),f=[...a.map(e=>{let t;for(let n of i)if(n.audioGroupId===e.groupId&&n.codecs){let e=T(n.codecs);if(e.audio){t=[e.audio];break}}let n={type:`audio`,id:w(),url:e.uri??``,groupId:e.groupId,name:e.name,mimeType:`audio/mp4`,bandwidth:0,sampleRate:48e3,channels:2,codecs:[]};return e.language&&(n.language=e.language),t&&(n.codecs=t),e.default&&(n.default=e.default),e.autoselect&&(n.autoselect=e.autoselect),n}),...d],p=o.map(e=>{let t={type:`text`,id:w(),url:e.uri,groupId:e.groupId,label:e.name,kind:`subtitles`,mimeType:`text/vtt`,bandwidth:0};return e.language&&(t.language=e.language),e.default&&e.autoselect&&(t.default=!0),e.autoselect&&(t.autoselect=e.autoselect),e.forced&&(t.forced=e.forced),t}),m=[];if(u.length>0){let e={id:w(),type:`video`,tracks:u},t={id:w(),type:`video`,switchingSets:[e]};m.push(t)}if(f.length>0){let e={id:w(),type:`audio`,tracks:f},t={id:w(),type:`audio`,switchingSets:[e]};m.push(t)}if(p.length>0){let e={id:w(),type:`text`,tracks:p},t={id:w(),type:`text`,switchingSets:[e]};m.push(t)}return{id:w(),url:t.url,startTime:0,selectionSets:m}}function fe(e){return e!==void 0&&`url`in e&&!(`id`in e)}function pe(e){return fe(e.presentation)}function me(e,t){let{preload:n}=e;return[`auto`,`metadata`].includes(n)||t.type===`play`}function he(e,t){return t.subscribe(t=>{let n=t.mediaElement?.preload||void 0;e.patch({preload:n})})}function ge({state:e,events:t}){let n=!1,r=null,i=a([e,t]).subscribe(async([t,i])=>{if(!(!pe(t)||!me(t,i)||n))try{n=!0,r=new AbortController;let{presentation:i}=t,a=de(await C(await x(i,{signal:r.signal})),i);e.patch({presentation:a})}catch(e){if(e instanceof Error&&e.name===`AbortError`)return;throw e}finally{n=!1,r=null}});return()=>{r?.abort(),i()}}function _e(e,t){let n=e.split(/\r?\n/),r=t.url,i=[],a,o,s=0,c,l=0,u=0,d;for(let e of n){let t=e.trim();if(!t||t.startsWith(`#`)&&!t.startsWith(`#EXT`)||t===`#EXTM3U`||t.startsWith(`#EXT-X-VERSION:`)||t.startsWith(`#EXT-X-TARGETDURATION:`)||t.startsWith(`#EXT-X-PLAYLIST-TYPE:`)||t.startsWith(`#EXT-X-INDEPENDENT-SEGMENTS`))continue;let n=D(t,`EXT-X-MAP`);if(n){let e=n.get(`URI`);if(e){a=O(e,r);let t=n.get(`BYTERANGE`);t&&(o=E(t,0)??void 0)}continue}if(t.startsWith(`#EXTINF:`)){s=le(t.slice(8));continue}if(t.startsWith(`#EXT-X-BYTERANGE:`)){c=E(t.slice(17),d)??void 0;continue}if(t!==`#EXT-X-ENDLIST`&&!t.startsWith(`#`)&&s>0){let e={id:`segment-${u}`,url:O(t,r),duration:s,startTime:l};c?(e.byteRange=c,d=c.end+1):d=void 0,i.push(e),l+=s,u++,s=0,c=void 0}}let f=l,p=t.type===`text`&&!a?void 0:a?{url:a,...o?{byteRange:o}:{}}:{url:``};return{...t,startTime:0,duration:f,segments:i,initialization:p}}var k=class{id;#e;#t=new AbortController;#n;#r=`pending`;#i=void 0;#a=void 0;constructor(e,t){this.#e=e;let n=t?.id;this.id=typeof n==`function`?n():n??w(),this.#n=t?.signal?AbortSignal.any([this.#t.signal,t.signal]):this.#t.signal}get status(){return this.#r}get value(){return this.#i}get error(){return this.#a}async run(){this.#r=`running`;try{let e=await this.#e(this.#n);return this.#i=e,this.#r=`done`,e}catch(e){throw this.#a=e,this.#r=`error`,e}}abort(){this.#t.abort()}},ve=class{#e=new Map;schedule(e){this.#e.has(e.id)||(this.#e.set(e.id,e),e.run().catch(e=>{if(!(e instanceof Error&&e.name===`AbortError`))throw e}).finally(()=>{this.#e.delete(e.id)}))}abortAll(){for(let e of this.#e.values())e.abort();this.#e.clear()}},ye=class{#e=Promise.resolve();#t=new Set;#n=null;schedule(e){let t=e;this.#t.add(t);let n=this.#e.then(()=>(this.#t.delete(t),this.#n=t,e.run())).finally(()=>{this.#n=null});return this.#e=n.then(()=>{},()=>{}),n}abortAll(){for(let e of this.#t)e.abort();this.#t.clear(),this.#n?.abort()}destroy(){this.abortAll()}};function be(e,t){let n=u(e,t.type);return n?!o(n):!1}function xe(e,t){return!0}function A(e,t){let n=t.id;return{...e,selectionSets:e.selectionSets.map(e=>({...e,switchingSets:e.switchingSets.map(e=>({...e,tracks:e.tracks.map(e=>e.id===n?t:e)}))}))}}function j({state:e,events:t},n){let r=new ve,i=a([e,t]).subscribe(([t,i])=>{if(!be(t,n)||!xe(t,i))return;let a=u(t,n.type);if(!a)return;let o=a;r.schedule(new k(async t=>{let n=_e(await C(await x(o,{signal:t})),o),r=e.current.presentation,i=A(r,n);e.patch({presentation:i})},{id:a.id}))});return()=>{r.abortAll(),i()}}function M(e,t){let n=e.selectionSets.find(e=>e.type===`text`);if(!n?.switchingSets?.[0]?.tracks.length)return;let r=n.switchingSets[0].tracks,i=t.includeForcedTracks?r:r.filter(e=>!e.forced);if(i.length===0)return;let{preferredSubtitleLanguage:a,enableDefaultTrack:o=!1}=t;if(a){let e=i.find(e=>e.language===a);if(e)return e.id}if(o){let e=i.find(e=>e.default===!0);if(e)return e.id}}function N(e,t){return!!e?.presentation?.selectionSets?.find(({type:e})=>e===t.type)?.switchingSets?.[0]?.tracks.length}function P(e,t){return!e[c[t.type]]}function Se({state:e},t={type:`video`}){let n=!1;return e.subscribe(async r=>{if(!(!N(r,t)||!P(r,t)||n))try{n=!0;let i=r.presentation?.selectionSets.find(({type:e})=>e===t.type)?.switchingSets[0]?.tracks[0]?.id;if(i){let n=c[t.type];e.patch({[n]:i})}}finally{n=!1}})}function Ce({state:e},t={type:`audio`}){let n=!1;return e.subscribe(async r=>{if(!(!N(r,t)||!P(r,t)||n))try{n=!0;let t=r.presentation?.selectionSets.find(({type:e})=>e===`audio`)?.switchingSets[0]?.tracks[0]?.id;t&&e.patch({selectedAudioTrackId:t})}finally{n=!1}})}function we({state:e},t={type:`text`}){let n=!1;return e.subscribe(async r=>{if(!(!N(r,t)||!P(r,t)||n))try{n=!0;let i=M(r.presentation,t);i&&e.patch({selectedTextTrackId:i})}finally{n=!1}})}const Te=Symbol(`@videojs/spf/state`);function Ee(e,t){return Object.is(e,t)}var De=class{[Te]=!0;#e;#t=null;#n=!1;#r;#i=new Set;#a=new Set;constructor(e,t){this.#e=typeof e==`object`&&e?{...e}:e,this.#r=t?.equalityFn??Ee}get current(){return this.#t??this.#e}patch(e){let t=this.#t??this.#e;if(typeof t!=`object`||!t){let n=e;Object.is(t,n)||(this.#t=n,this.#o());return}let n={...t},r=!1;for(let i in e){if(!Object.hasOwn(e,i))continue;let a=e[i];Object.is(t[i],a)||(n[i]=a,r=!0)}r&&(this.#t=n,this.#o())}subscribe(e,t,n){if(t===void 0){let t=e;return this.#i.add(t),t(this.current),()=>{this.#i.delete(t)}}let r=e,i=t,a={selector:r,listener:i,options:n??{}};return this.#a.add(a),i(r(this.current)),()=>{this.#a.delete(a)}}flush(){if(this.#t===null)return;let e=this.#e,t=this.#t;if(this.#t=null,this.#n=!1,!this.#r(e,t)){this.#e=t;for(let e of this.#i)e(this.#e);for(let t of this.#a){let n=t.selector(e),r=t.selector(this.#e);(t.options.equalityFn??Object.is)(n,r)||t.listener(r)}}}#o(){this.#n||(this.#n=!0,queueMicrotask(()=>this.flush()))}};function F(e,t){return new De(e,t)}function I(e,t){if(e.length===0)return!0;let n=e[e.length-1];return n?t?.snapshot.context.segments.some(e=>e.id===n.id)??!1:!1}function Oe(e,t){let n=e.selectedVideoTrackId?u(e,`video`):void 0,r=e.selectedAudioTrackId?u(e,`audio`):void 0;return!(n&&!o(n)||r&&!o(r)||n&&o(n)&&!I(n.segments,t.videoBufferActor)||r&&o(r)&&!I(r.segments,t.audioBufferActor))}function ke(e,t){return!!(t.mediaSource&&e.presentation)}function Ae(e,t){if(!ke(e,t))return!1;let{mediaSource:n,mediaElement:r}=t;if(n.readyState!==`open`||r&&r.readyState<HTMLMediaElement.HAVE_METADATA)return!1;let i=!!e.selectedVideoTrackId,a=!!e.selectedAudioTrackId;if(i&&!t.videoBuffer||a&&!t.audioBuffer||t.videoBufferActor?.snapshot.status===`updating`||t.audioBufferActor?.snapshot.status===`updating`||!Oe(e,t))return!1;if(r){let t=i?u(e,`video`):void 0,n=a?u(e,`audio`):void 0,s=t&&o(t)?t:n&&o(n)?n:void 0;if(s&&s.segments.length>0){let e=s.segments[s.segments.length-1];if(r.currentTime<e.startTime)return!1}}return!0}function je(e){let t=[e.videoBufferActor,e.audioBufferActor].filter(e=>e!==void 0&&e.snapshot.status===`updating`);return t.length===0?Promise.resolve():Promise.all(t.map(e=>new Promise(t=>{let n=e.subscribe(e=>{e.status!==`updating`&&(n(),t())})}))).then(()=>void 0)}function Me(e){let t=0;for(let n of[e.videoBuffer,e.audioBuffer])if(n&&n.buffered.length>0){let e=n.buffered.end(n.buffered.length-1);e>t&&(t=e)}return t}const Ne=async({currentOwners:e},t)=>{let{mediaSource:n}=e;if(n.readyState===`ended`||(await je(e),n.readyState!==`open`))return;let r=Me(e);r>0&&(n.duration=r),n.endOfStream(),await new Promise(e=>requestAnimationFrame(e))};function Pe({state:e,owners:t}){let n=!1,r=[],i=async()=>{let r=e.current,i=t.current;if(n){if(i.mediaSource?.readyState!==`open`)return;n=!1}if(Ae(r,i)){n=!0;try{await Ne({currentOwners:i},{})}catch(e){console.error(`Failed to call endOfStream:`,e)}}},o=t.subscribe(e=>{r.forEach(e=>e()),r.length=0;for(let t of[e.videoBufferActor,e.audioBufferActor]){if(!t)continue;let e=!0;r.push(t.subscribe(()=>{if(e){e=!1;return}i()}))}}),s=a([e,t]).subscribe(async()=>i());return()=>{r.forEach(e=>e()),o(),s()}}const Fe={keepSegments:2};function Ie(e,t,n=Fe){if(e.length===0)return 0;let r=e.filter(e=>e.startTime<t);if(r.length===0)return 0;let i=r.length-n.keepSegments;return i<=0?0:i>=r.length?t:r[i].startTime}const L={bufferDuration:30};function Le(e,t,n=L){if(e.length===0)return 1/0;let r=t+n.bufferDuration,i=e.filter(e=>e.startTime>=r);return i.length===0?1/0:Math.min(...i.map(e=>e.startTime))}function R(e,t,n,r=L){if(e.length===0)return[];let i=n+r.bufferDuration,a=new Set(t.map(e=>e.startTime));return e.filter(e=>{let t=e.startTime+e.duration,r=e.startTime<i&&t>n,o=!a.has(e.startTime);return r&&o})}function z(){return typeof MediaSource<`u`}function B(){return typeof ManagedMediaSource<`u`}function Re(e={}){let{preferManaged:t=!1}=e;if(t&&B())return new ManagedMediaSource;if(z())return new MediaSource;throw Error(`MediaSource API is not supported`)}function ze(e,t){if(B()&&e instanceof ManagedMediaSource)return t.srcObject=e,{url:``,detach:()=>{t.srcObject=null,t.load()}};let n=URL.createObjectURL(e);return t.src=n,{url:n,detach:()=>{t.removeAttribute(`src`),t.load(),URL.revokeObjectURL(n)}}}function Be(e,t){return new Promise((n,r)=>{if(e.readyState===`open`){n();return}if(t?.aborted){r(new DOMException(`Aborted`,`AbortError`));return}let i=new AbortController,a={signal:i.signal};e.addEventListener(`sourceopen`,()=>{i.abort(),n()},a),t?.addEventListener(`abort`,()=>{i.abort(),r(new DOMException(`Aborted`,`AbortError`))},a)})}function Ve(e,t){if(e.readyState!==`open`)throw Error(`MediaSource is not open`);if(!He(t))throw Error(`Codec not supported: ${t}`);return e.addSourceBuffer(t)}function He(e){return z()?MediaSource.isTypeSupported(e):!1}function Ue(e,t){let n=null,r=null,i=null,a=null,o=!1,s=!1,c=t=>{let n=new Set(e.snapshot.context.segments.map(e=>e.id));return t.filter(e=>n.has(e.id))},l=t=>{let{track:n,range:r}=t,i=e.snapshot.context,a=c(n.segments),o=r?.start??0,s=[];if(r){let e=Le(a,o);e<1/0&&s.push({type:`remove`,start:e,end:1/0});let t=Ie(a,o);t>0&&s.push({type:`remove`,start:0,end:t})}if(i.initTrackId!==n.id&&s.push({type:`append-init`,meta:{trackId:n.id},url:n.initialization.url}),r){let e=R(n.segments,a,o).filter(e=>{let t=i.segments.find(t=>Math.abs(t.startTime-e.startTime)<1e-4);return!t?.trackBandwidth||!n.bandwidth?!0:n.bandwidth>t.trackBandwidth});for(let t of e)s.push({type:`append-segment`,meta:{id:t.id,startTime:t.startTime,duration:t.duration,trackId:n.id,trackBandwidth:n.bandwidth},url:t.url})}return s},u=async o=>{let s=a.signal;try{if(o.type===`remove`){await e.send(o,s);return}if(o.type===`append-init`){if(r=o.meta.trackId,!s.aborted){let r=await t(o,{signal:s}),i=n?.some(e=>e.type===`append-init`&&e.meta.trackId!==o.meta.trackId);if(!s.aborted||!i){let t=s.aborted?new AbortController().signal:s;await e.send({type:`append-init`,data:r,meta:o.meta},t)}}return}if(i=o.meta.id,!s.aborted){let n=await t(o,{signal:s});s.aborted||await e.send({type:`append-segment`,data:n,meta:o.meta},s)}}finally{r=null,i=null}},d=async e=>{o=!0,a=new AbortController;let t=e;for(;t.length>0&&!s;){let e=t[0];t=t.slice(1);try{await u(e)}catch(e){e instanceof Error&&e.name===`AbortError`||(console.error(`Unexpected error in segment loader:`,e),t=[])}if(n!==null)t=n,n=null,a=new AbortController;else if(a.signal.aborted)break}a=null,o=!1};return{send(e){if(s)return;let t=l(e);if(!o){if(t.length===0)return;d(t);return}i!==null&&t.some(e=>e.type===`append-segment`&&e.meta.id===i)||r!==null&&t.some(e=>e.type===`append-init`&&e.meta.trackId===r)?n=t.filter(e=>!(e.type===`append-segment`&&e.meta.id===i)&&!(e.type===`append-init`&&e.meta.trackId===r)):(n=t,a?.abort())},destroy(){s=!0,a?.abort()}}}const We={video:`videoBufferActor`,audio:`audioBufferActor`};function Ge(e,t){return async(n,r)=>{let i=performance.now(),a=await S(n,r),o=performance.now()-i,s=ee(e.current,o,a.byteLength);return e.patch(s),e.flush(),t?.(s),a}}function Ke([e,t],n){let{playbackInitiated:r,preload:i,currentTime:a}=t;return{playbackInitiated:r,preload:i,currentTime:a,track:u(t,n),segmentsCanLoad:e}}const V=(e,t)=>{if(e!=null)return t?.segments.find(({startTime:t,duration:n},r,i)=>e>=t&&(e<t+n||r===i.length-1))?.startTime};function qe(e,t){return t.segmentsCanLoad?t.playbackInitiated?!e.playbackInitiated&&t.playbackInitiated&&e.preload!==`auto`?!1:!t.track||!o(t.track)?!0:e.track?.id!==t.track.id&&o(t.track)?!1:V(e.currentTime,t.track)===V(t.currentTime,t.track):t.preload===`none`?!0:t.preload===e.preload:!0}function H({state:e,owners:t},n){let{type:r}=n,i=We[r],s=e.current.bandwidthState,c=F(s??{fastEstimate:0,fastTotalWeight:0,slowEstimate:0,slowTotalWeight:0,bytesSampled:0}),l=r===`video`?Ge(c,s===void 0?void 0:t=>{e.patch({bandwidthState:t}),e.flush()}):S,d=F(void 0),f=t.subscribe(e=>e[i],e=>(e?d.patch(Ue(e,l)):!e&&d.current&&(d.current.destroy(),d.patch(void 0)),()=>{d.current?.destroy(),d.patch(void 0)})),p=F(!1),m=a([e,d]).subscribe(([e,t])=>{let n=u(e,r),i=!!n&&o(n),a=!!t;p.patch(i&&a)}),h=a([p,e]).subscribe(([e,t])=>Ke([e,t],r),({preload:e,playbackInitiated:t,currentTime:n,track:r})=>{e===`auto`||t?d.current?.send({type:`load`,track:r,range:{start:n,end:n+L.bufferDuration}}):d.current?.send({type:`load`,track:r})},{equalityFn:qe});return()=>{m(),h(),f()}}let U=null;function Je(){return U||(U=document.createElement(`video`),U.muted=!0,U.preload=`none`,U.style.display=`none`,U.crossOrigin=`anonymous`),U}function Ye(e){let t=Je(),n=document.createElement(`track`);return n.kind=`subtitles`,n.default=!0,new Promise((r,i)=>{let a=()=>{let e=[],t=n.track;if(t.cues)for(let n=0;n<t.cues.length;n++){let r=t.cues[n];r&&e.push(r)}s(),r(e)},o=()=>{s(),i(Error(`Failed to load VTT segment: ${e}`))},s=()=>{n.removeEventListener(`load`,a),n.removeEventListener(`error`,o),t.removeChild(n)};n.addEventListener(`load`,a),n.addEventListener(`error`,o),t.appendChild(n),n.src=e})}function Xe(){U=null}function Ze(e,t){let{cues:n}=t;if(!n)return!1;for(let t=0;t<n.length;t++){let r=n[t];if(r.startTime===e.startTime&&r.endTime===e.endTime&&r.text===e.text)return!0}return!1}const Qe=async({segment:e},t)=>{let n=await Ye(e.url);for(let e of n)Ze(e,t.textTrack)||t.textTrack.addCue(e)},$e=async({currentState:e},t)=>{let n=W(e);if(!n||!o(n))return;let{segments:r}=n;if(r.length===0)return;let i=n.id,a=new Set((e.textBufferState?.[i]?.segments??[]).map(e=>e.id)),s=R(r,r.filter(e=>a.has(e.id)),e.currentTime??0).filter(e=>!a.has(e.id));if(s.length!==0){for(let e of s){if(t.signal.aborted)break;try{await Qe({segment:e},{textTrack:t.textTrack});let n=t.state.current.textBufferState??{},r=n[i]??{segments:[]};t.state.patch({textBufferState:{...n,[i]:{segments:[...r.segments,{id:e.id}]}}})}catch(e){if(e instanceof Error&&e.name===`AbortError`)break;console.error(`Failed to load VTT segment:`,e)}}await new Promise(e=>requestAnimationFrame(e))}};function W(e){if(!e.presentation||!e.selectedTextTrackId)return;let t=e.presentation.selectionSets.find(e=>e.type===`text`);if(t?.switchingSets?.[0]?.tracks)return t.switchingSets[0].tracks.find(t=>t.id===e.selectedTextTrackId)}function G(e,t){let n=e.selectedTextTrackId;if(!(!n||!t.textTracks))return t.textTracks.get(n)?.track}function et(e,t){return!!e.selectedTextTrackId&&!!t.textTracks&&t.textTracks.has(e.selectedTextTrackId)}function tt(e,t){if(!et(e,t))return!1;let n=W(e);return!(!n||!o(n)||n.segments.length===0||!G(e,t))}function nt({state:e,owners:t}){let n=null,r=null,i;return a([e,t]).subscribe(async([t,a])=>{if(t.selectedTextTrackId!==i&&(i=t.selectedTextTrackId,r?.abort(),n=null),n||!tt(t,a))return;let o=G(t,a);o&&(r=new AbortController,n=$e({currentState:t},{signal:r.signal,textTrack:o,state:e}).finally(()=>{n=null}))})}function rt(t,n){return!e(n.mediaElement)&&!e(t.presentation?.url)}function it(t,n){return e(n.mediaSource)}function at({state:e,owners:t}){let n=!1;return a([e,t]).subscribe(async([e,r])=>{if(!(!rt(e,r)||!it(e,r)||n))try{n=!0;let e=Re({preferManaged:!0});ze(e,r.mediaElement),await Be(e),t.patch({mediaSource:e})}finally{n=!1}})}async function K(e,t){return e.updating&&await new Promise(t=>{let n=()=>{e.removeEventListener(`updateend`,n),t()};e.addEventListener(`updateend`,n)}),new Promise((n,r)=>{let i=()=>{o(),n()},a=e=>{o(),r(Error(`SourceBuffer append error: ${e.type}`))},o=()=>{e.removeEventListener(`updateend`,i),e.removeEventListener(`error`,a)};e.addEventListener(`updateend`,i),e.addEventListener(`error`,a);try{e.appendBuffer(t)}catch(e){o(),r(e)}})}async function ot(e,t,n){return e.updating&&await new Promise(t=>{let n=()=>{e.removeEventListener(`updateend`,n),t()};e.addEventListener(`updateend`,n)}),new Promise((r,i)=>{let a=()=>{s(),r()},o=e=>{s(),i(Error(`SourceBuffer remove error: ${e.type}`))},s=()=>{e.removeEventListener(`updateend`,a),e.removeEventListener(`error`,o)};e.addEventListener(`updateend`,a),e.addEventListener(`error`,o);try{e.remove(t,n)}catch(e){s(),i(e)}})}var q=class extends Error{constructor(e){super(e),this.name=`SourceBufferActorError`}};function J(e){let t=[];for(let n=0;n<e.length;n++)t.push({start:e.start(n),end:e.end(n)});return t}function st(e,{signal:t,getCtx:n,sourceBuffer:r}){return new k(async t=>{let i=n();return t.aborted?i:(await K(r,e.data),{...i,initTrackId:e.meta.trackId})},{signal:t})}function ct(e,{signal:t,getCtx:n,sourceBuffer:r}){return new k(async t=>{let i=n();if(t.aborted)return i;await K(r,e.data);let{meta:a}=e,o=i.segments.filter(e=>Math.abs(e.startTime-a.startTime)>=1e-4);return{...i,segments:[...o,{id:a.id,startTime:a.startTime,duration:a.duration,trackId:a.trackId,...a.trackBandwidth!==void 0&&{trackBandwidth:a.trackBandwidth}}],bufferedRanges:J(r.buffered)}},{signal:t})}function lt(e,{signal:t,getCtx:n,sourceBuffer:r}){return new k(async t=>{let i=n();if(t.aborted)return i;await ot(r,e.start,e.end);let a=J(r.buffered),o=i.segments.filter(e=>{let t=e.startTime+e.duration/2;return a.some(e=>t>=e.start&&t<e.end)});return{...i,segments:o,bufferedRanges:a}},{signal:t})}const ut={"append-init":st,"append-segment":ct,remove:lt};function Y(e,t){let n=ut[e.type];return n(e,t)}function dt(e,t){let n=F({status:`idle`,context:{segments:[],bufferedRanges:[],initTrackId:void 0,...t}}),r=new ye;function i(e){let t=n.current.status===`destroyed`?`destroyed`:`idle`;n.patch({status:t,context:e}),n.flush()}function a(e){let t=n.current.status===`destroyed`?`destroyed`:`idle`;throw n.patch({status:t}),n.flush(),e}return{get snapshot(){return n.current},subscribe(e){return n.subscribe(e)},send(t,o){if(n.current.status!==`idle`)return Promise.reject(new q(`send() called while actor is ${n.current.status}`));n.patch({status:`updating`});let s=Y(t,{signal:o,getCtx:()=>n.current.context,sourceBuffer:e});return r.schedule(s).then(i).catch(a)},batch(t,o){if(n.current.status!==`idle`)return Promise.reject(new q(`batch() called while actor is ${n.current.status}`));if(t.length===0)return Promise.resolve();n.patch({status:`updating`});let s=n.current.context;for(let n of t.slice(0,-1)){let t=Y(n,{signal:o,getCtx:()=>s,sourceBuffer:e});r.schedule(t).then(e=>{s=e})}let c=Y(t[t.length-1],{signal:o,getCtx:()=>s,sourceBuffer:e});return r.schedule(c).then(i).catch(a)},destroy(){n.patch({status:`destroyed`}),n.flush(),r.destroy()}}}const ft={video:`videoBufferActor`,audio:`audioBufferActor`},pt=async({currentState:e,currentOwners:t},n)=>{let r=u(e,n.config.type);if(!r||!o(r)||!r.codecs||r.codecs.length===0)return;let i=mt(r),a=Ve(t.mediaSource,i),s=dt(a),c=l[n.config.type],d=ft[n.config.type];n.owners.patch({[c]:a,[d]:s}),await new Promise(e=>requestAnimationFrame(e))};function mt(e){let t=e.codecs?.join(`,`)??``;return`${e.mimeType}; codecs="${t}"`}function ht(e,t,n){return!(!t.mediaSource||!u(e,n))}function gt(e,n){let r=l[n];return t(e[r])}function X({state:e,owners:t},n){let r=null;return a([e,t]).subscribe(async([e,i])=>{if(!r&&!(!ht(e,i,n.type)||!gt(i,n.type))){r=pt({currentState:e,currentOwners:i},{owners:t,config:n});try{await r}finally{r=null}}})}function Z(e){if(!e?.selectionSets)return[];let t=e.selectionSets.find(e=>e.type===`text`);return t?.switchingSets?.[0]?.tracks?t.switchingSets[0].tracks:[]}function _t(e,t){return!!t.mediaElement&&!!Z(e.presentation).length}function vt(e){return!e.textTracks}function yt(e){let t=document.createElement(`track`);return t.id=e.id,t.kind=e.kind,t.label=e.label,e.language&&(t.srclang=e.language),e.default&&(t.default=!0),t.src=e.url,t}function bt({state:e,owners:t}){let n=!1,r=[],i=a([e,t]).subscribe(([e,i])=>{if(n||!_t(e,i)||!vt(i))return;n=!0;let a=Z(e.presentation);if(a.length===0)return;let o=new Map;for(let e of a){let t=yt(e);i.mediaElement.appendChild(t),o.set(e.id,t),r.push(t)}t.patch({textTracks:o})});return()=>{for(let e of r)e.remove();r=[],i()}}function Q(e){return!!e.textTracks&&e.textTracks.size>0}function xt({state:e,owners:t}){return a([e,t]).subscribe(([e,t])=>{if(!Q(t))return;let n=e.selectedTextTrackId;for(let[e,r]of t.textTracks)e===n?r.track.mode=`showing`:r.track.mode=`hidden`})}function St({state:e,owners:t}){let r,i=null,a=t.subscribe(t=>{let{mediaElement:a}=t;if(a===r||(i?.(),i=null,r=a,!a))return;e.patch({currentTime:a.currentTime});let o=()=>e.patch({currentTime:a.currentTime}),s=n(a,`timeupdate`,o),c=n(a,`seeking`,o);i=()=>{s(),c()}});return()=>{i?.(),a()}}function Ct({state:e,owners:t,events:r}){let i,a=null,o,s=e.subscribe(t=>{let n=t.presentation?.url;n!==o&&(o!==void 0&&e.patch({playbackInitiated:!1}),o=n)}),c=t.subscribe(t=>{let{mediaElement:o}=t;o!==i&&(a?.(),a=null,i=o,o&&(a=n(o,`play`,()=>{e.patch({playbackInitiated:!0}),r.dispatch({type:`play`})})))});return()=>{a?.(),s(),c()}}function wt(e,t){return!!(t.mediaSource&&e.presentation&&s(e.presentation))}function Tt(e){let t=0,n=[e.videoSourceBuffer,e.audioSourceBuffer].filter(e=>e!==void 0);for(let e of n){let{buffered:n}=e;if(n.length>0){let e=n.end(n.length-1);e>t&&(t=e)}}return t}function Et(e,t){if(!wt(e,t))return!1;let{mediaSource:n}=t,{presentation:r}=e;if(n.readyState!==`open`)return!1;let i=r.duration;return!Number.isFinite(i)||Number.isNaN(i)||i<=0?!1:isNaN(n.duration)}function Dt(e){let t=[e.videoSourceBuffer,e.audioSourceBuffer].filter(e=>e!==void 0&&e.updating);return t.length===0?Promise.resolve():Promise.all(t.map(e=>new Promise(t=>e.addEventListener(`updateend`,()=>t(),{once:!0})))).then(()=>void 0)}function Ot({state:e,owners:t}){return a([e,t]).subscribe(async([e,t])=>{if(!Et(e,t))return;let{mediaSource:n}=t;if(await Dt(t),n.readyState!==`open`)return;let r=e.presentation.duration,i=Tt(t);i>r&&(r=i),n.duration=r})}function $(e={}){let t=F({bandwidthState:{fastEstimate:0,fastTotalWeight:0,slowEstimate:0,slowTotalWeight:0,bytesSampled:0}}),n=F({}),r=i(),a=[he(t,n),Ct({state:t,owners:n,events:r}),ge({state:t,events:r}),Se({state:t,owners:n,events:r},{type:`video`,...e.initialBandwidth!==void 0&&{initialBandwidth:e.initialBandwidth}}),Ce({state:t,owners:n,events:r},{type:`audio`,...e.preferredAudioLanguage!==void 0&&{preferredAudioLanguage:e.preferredAudioLanguage}}),we({state:t,owners:n,events:r},{type:`text`,...e.preferredSubtitleLanguage!==void 0&&{preferredSubtitleLanguage:e.preferredSubtitleLanguage},...e.includeForcedTracks!==void 0&&{includeForcedTracks:e.includeForcedTracks},...e.enableDefaultTrack!==void 0&&{enableDefaultTrack:e.enableDefaultTrack}}),j({state:t,events:r},{type:`video`}),j({state:t,events:r},{type:`audio`}),j({state:t,events:r},{type:`text`}),m({state:t}),at({state:t,owners:n}),Ot({state:t,owners:n}),X({state:t,owners:n},{type:`video`}),X({state:t,owners:n},{type:`audio`}),St({state:t,owners:n}),ae({state:t}),H({state:t,owners:n},{type:`video`}),H({state:t,owners:n},{type:`audio`}),Pe({state:t,owners:n}),bt({state:t,owners:n}),xt({state:t,owners:n}),nt({state:t,owners:n})];return r.dispatch({type:`@@INITIALIZE@@`}),{state:t,owners:n,events:r,destroy:()=>{a.forEach(e=>e()),Xe()}}}var kt=class{engine;#e=null;constructor(e={}){this.engine=$(e)}attach(e){this.engine.owners.patch({mediaElement:e})}detach(){this.#t(),this.engine.owners.patch({mediaElement:void 0})}destroy(){this.#t(),this.engine.destroy()}get src(){return this.engine.state.current.presentation?.url??``}set src(e){this.engine.state.patch({presentation:e?{url:e}:void 0})}play(){let{mediaElement:e}=this.engine.owners.current;return e?(this.engine.state.patch({playbackInitiated:!0}),e.play().catch(t=>{if(this.src)return new Promise((t,n)=>{let r=()=>{this.#e=null,e.play().then(t,n)};this.#e=r,e.addEventListener(`loadstart`,r,{once:!0})});throw t})):Promise.reject(Error(`SpfMedia: no media element attached`))}#t(){if(!this.#e)return;let{mediaElement:e}=this.engine.owners.current;e?.removeEventListener(`loadstart`,this.#e),this.#e=null}};export{kt as SpfMedia,$ as createPlaybackEngine};
1
+ import { t as VERSION } from "./src-DRsS_H80.js";
2
+
3
+ export { VERSION };
@@ -0,0 +1,14 @@
1
+ //#region src/index.ts
2
+ /**
3
+ * Stream Processing Framework (SPF) for Video.js 10
4
+ *
5
+ * Bundle size target: < 20KB (minified + gzipped)
6
+ * Primary use case: CMAF HLS playback with Video.js v10
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ const VERSION = "0.1.0";
11
+
12
+ //#endregion
13
+ export { VERSION as t };
14
+ //# sourceMappingURL=src-DRsS_H80.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"src-DRsS_H80.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Stream Processing Framework (SPF) for Video.js 10\n *\n * Bundle size target: < 20KB (minified + gzipped)\n * Primary use case: CMAF HLS playback with Video.js v10\n *\n * @packageDocumentation\n */\n\n// Public API exports will be added here as features are implemented\n\nexport const VERSION = '0.1.0';\n"],"mappings":";;;;;;;;;AAWA,MAAa,UAAU"}
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@videojs/spf",
3
3
  "type": "module",
4
- "version": "0.1.0-alpha.2",
4
+ "version": "10.0.0-beta.1",
5
5
  "description": "Stream Processing Framework for Video.js 10",
6
6
  "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/videojs/v10",
10
+ "directory": "packages/spf"
11
+ },
7
12
  "keywords": [
8
13
  "video",
9
14
  "hls",
@@ -34,19 +39,8 @@
34
39
  "files": [
35
40
  "dist"
36
41
  ],
37
- "scripts": {
38
- "build": "tsc --build && tsdown",
39
- "build:watch": "tsdown --watch --silent",
40
- "dev": "pnpm run build:watch",
41
- "test": "vitest run",
42
- "test:ci": "vitest run --project=core --project=dom --project=utils",
43
- "test:watch": "vitest",
44
- "clean": "rm -rf dist types",
45
- "size": "node scripts/measure-size.js --playback-engine",
46
- "size:all": "node scripts/measure-size.js --all"
47
- },
48
42
  "dependencies": {
49
- "@videojs/utils": "workspace:*"
43
+ "@videojs/utils": "10.0.0-beta.1"
50
44
  },
51
45
  "devDependencies": {
52
46
  "@vitest/browser": "^3.2.4",
@@ -59,5 +53,16 @@
59
53
  },
60
54
  "publishConfig": {
61
55
  "access": "public"
56
+ },
57
+ "scripts": {
58
+ "build": "tsc --build && tsdown",
59
+ "build:watch": "tsdown --watch --silent",
60
+ "dev": "pnpm run build:watch",
61
+ "test": "vitest run",
62
+ "test:ci": "vitest run --project=core --project=dom --project=utils",
63
+ "test:watch": "vitest",
64
+ "clean": "rm -rf dist types",
65
+ "size": "node scripts/measure-size.js --playback-engine",
66
+ "size:all": "node scripts/measure-size.js --all"
62
67
  }
63
- }
68
+ }