@norskvideo/moq-watch 0.1.8 → 0.2.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.
Files changed (76) hide show
  1. package/README.md +43 -31
  2. package/audio/config.d.ts +19 -0
  3. package/audio/config.d.ts.map +1 -0
  4. package/audio/decoder.d.ts +9 -2
  5. package/audio/decoder.d.ts.map +1 -1
  6. package/audio/emitter.d.ts +6 -1
  7. package/audio/emitter.d.ts.map +1 -1
  8. package/audio/latency.d.ts +11 -0
  9. package/audio/latency.d.ts.map +1 -0
  10. package/audio/ring-buffer.d.ts.map +1 -1
  11. package/audio/shared-ring-buffer.d.ts +8 -1
  12. package/audio/shared-ring-buffer.d.ts.map +1 -1
  13. package/audio/source.d.ts.map +1 -1
  14. package/audio/terminal.d.ts +1 -0
  15. package/audio/terminal.d.ts.map +1 -1
  16. package/broadcast.d.ts +19 -5
  17. package/broadcast.d.ts.map +1 -1
  18. package/duration.d.ts +2 -0
  19. package/duration.d.ts.map +1 -0
  20. package/element.d.ts +50 -26
  21. package/element.d.ts.map +1 -1
  22. package/element.js +142 -160
  23. package/element.js.map +1 -1
  24. package/index.d.ts +4 -2
  25. package/index.d.ts.map +1 -1
  26. package/index.js +25 -17
  27. package/index.js.map +1 -1
  28. package/media.d.ts +2 -0
  29. package/media.d.ts.map +1 -0
  30. package/msf.d.ts.map +1 -1
  31. package/package.json +12 -7
  32. package/player-C19uf7Dc.js +2172 -0
  33. package/player-C19uf7Dc.js.map +1 -0
  34. package/player.d.ts +78 -0
  35. package/player.d.ts.map +1 -0
  36. package/sync.d.ts +27 -41
  37. package/sync.d.ts.map +1 -1
  38. package/text/index.d.ts +9 -0
  39. package/text/index.d.ts.map +1 -0
  40. package/text/renderer.d.ts +31 -0
  41. package/text/renderer.d.ts.map +1 -0
  42. package/text/source.d.ts +30 -0
  43. package/text/source.d.ts.map +1 -0
  44. package/ui/components/captions-button.d.ts +11 -0
  45. package/ui/components/captions-button.d.ts.map +1 -0
  46. package/ui/components/captions.d.ts +5 -0
  47. package/ui/components/captions.d.ts.map +1 -0
  48. package/ui/components/control-bar.d.ts.map +1 -1
  49. package/ui/components/hidden-indicator.d.ts +5 -0
  50. package/ui/components/hidden-indicator.d.ts.map +1 -0
  51. package/ui/components/latency.d.ts +1 -1
  52. package/ui/components/latency.d.ts.map +1 -1
  53. package/ui/components/settings-panel.d.ts.map +1 -1
  54. package/ui/element.d.ts.map +1 -1
  55. package/ui/element.js +257 -193
  56. package/ui/element.js.map +1 -1
  57. package/ui/icons.d.ts +2 -1
  58. package/ui/icons.d.ts.map +1 -1
  59. package/ui/state.d.ts +1 -1
  60. package/ui/state.d.ts.map +1 -1
  61. package/video/decoder.d.ts +10 -11
  62. package/video/decoder.d.ts.map +1 -1
  63. package/video/playhead.d.ts +14 -4
  64. package/video/playhead.d.ts.map +1 -1
  65. package/video/renderer.d.ts +6 -1
  66. package/video/renderer.d.ts.map +1 -1
  67. package/video/source.d.ts +1 -1
  68. package/video/source.d.ts.map +1 -1
  69. package/audio/subscription.d.ts +0 -10
  70. package/audio/subscription.d.ts.map +0 -1
  71. package/audio/unlock.d.ts +0 -20
  72. package/audio/unlock.d.ts.map +0 -1
  73. package/source-BeABanvB.js +0 -1723
  74. package/source-BeABanvB.js.map +0 -1
  75. package/sync-DNQkgnlX.js +0 -132
  76. package/sync-DNQkgnlX.js.map +0 -1
@@ -0,0 +1,2172 @@
1
+ import { Announce as e, Error as t, Path as n, Time as r } from "@norskvideo/moq-net";
2
+ import { Effect as i, Signal as a, getter as o, readonlys as s } from "@norskvideo/moq-signals";
3
+ import * as c from "@norskvideo/moq-hang/catalog";
4
+ import { u53 as l } from "@norskvideo/moq-hang/catalog";
5
+ import * as u from "@norskvideo/moq-hang/container";
6
+ import * as d from "@norskvideo/moq-hang/util";
7
+ import * as f from "@norskvideo/moq-json";
8
+ import * as p from "@norskvideo/moq-msf";
9
+ import { CaptionsRenderer as ee, VTTCue as m, parseText as h } from "media-captions";
10
+ //#region src/base64.ts
11
+ function g(e) {
12
+ let t = atob(e), n = new Uint8Array(t.length);
13
+ for (let e = 0; e < t.length; e++) n[e] = t.charCodeAt(e);
14
+ return n;
15
+ }
16
+ //#endregion
17
+ //#region src/media.ts
18
+ function _(e, t) {
19
+ if (e.get(t.broadcast.closed) !== void 0) return;
20
+ let n = t.broadcast.track(t.track).subscribe({
21
+ priority: t.priority,
22
+ maxAge: t.maxAge.peek()
23
+ });
24
+ return e.cleanup(() => n.close()), e.run((e) => {
25
+ n.update({
26
+ priority: t.priority,
27
+ maxAge: e.get(t.maxAge)
28
+ });
29
+ }), n;
30
+ }
31
+ async function v(e) {
32
+ try {
33
+ return await e.next();
34
+ } catch (e) {
35
+ if (!(e instanceof t.Stream)) throw e;
36
+ console.debug("media subscription ended", e);
37
+ return;
38
+ }
39
+ }
40
+ //#endregion
41
+ //#region src/audio/shared-ring-buffer.ts
42
+ var y = 0, b = 1, x = 2, S = 3, te = 4, ne = 4294967295n;
43
+ function C(e, t) {
44
+ return BigInt(e >>> 0) << 32n | BigInt(t >>> 0);
45
+ }
46
+ function w(e) {
47
+ return Number(e >> 32n) | 0;
48
+ }
49
+ function re(e) {
50
+ return !!(w(e) & 1);
51
+ }
52
+ function T(e) {
53
+ return Number(e & ne) | 0;
54
+ }
55
+ function ie(e) {
56
+ return e <= 1 ? 1 : 1 << 32 - Math.clz32(e - 1);
57
+ }
58
+ function ae(e, t, n, r = !1) {
59
+ if (e <= 0) throw Error("invalid channels");
60
+ if (t <= 0 || t > 2 ** 30) throw Error("invalid capacity");
61
+ if (n <= 0) throw Error("invalid sample rate");
62
+ t = ie(t);
63
+ let i = new SharedArrayBuffer(e * t * Float32Array.BYTES_PER_ELEMENT), a = new SharedArrayBuffer(te * Int32Array.BYTES_PER_ELEMENT), o = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT), s = new Int32Array(a);
64
+ return Atomics.store(s, x, 1), {
65
+ channels: e,
66
+ capacity: t,
67
+ rate: n,
68
+ samples: i,
69
+ control: a,
70
+ state: o,
71
+ buffered: r
72
+ };
73
+ }
74
+ function E(e, t) {
75
+ return (e - t | 0) > 0 ? e : t;
76
+ }
77
+ function D(e, t) {
78
+ return e & t - 1;
79
+ }
80
+ var oe = class e {
81
+ channels;
82
+ capacity;
83
+ rate;
84
+ buffered;
85
+ init;
86
+ #e;
87
+ #t;
88
+ #n;
89
+ #r = !1;
90
+ #i = 0;
91
+ #a = 0;
92
+ #o = 0;
93
+ constructor(e, t) {
94
+ this.channels = e.channels, this.capacity = e.capacity, this.rate = e.rate, this.buffered = e.buffered, this.init = e, this.#e = new Int32Array(e.control), this.#t = new BigInt64Array(e.state), this.#n = [];
95
+ for (let t = 0; t < this.channels; t++) this.#n.push(new Float32Array(e.samples, t * this.capacity * Float32Array.BYTES_PER_ELEMENT, this.capacity));
96
+ t !== void 0 && this.#s(t);
97
+ }
98
+ #s(e) {
99
+ if (e.channels !== this.channels || e.rate !== this.rate) return;
100
+ let t = Atomics.load(e.#e, S), n = Atomics.load(e.#t, 0);
101
+ for (;;) {
102
+ let e = Atomics.load(this.#t, 0);
103
+ if (Atomics.load(this.#e, S) !== t || (T(n) - T(e) | 0) <= 0) return;
104
+ let r = C(w(e), T(n));
105
+ if (Atomics.compareExchange(this.#t, 0, e, r) === e) return;
106
+ }
107
+ }
108
+ #c(e) {
109
+ for (;;) {
110
+ let t = Atomics.load(this.#t, 0);
111
+ if ((e - T(t) | 0) <= 0) return;
112
+ let n = C(w(t), e);
113
+ if (Atomics.compareExchange(this.#t, 0, t, n) === t) return;
114
+ }
115
+ }
116
+ #l(e) {
117
+ for (;;) {
118
+ let t = Atomics.load(this.#t, 0), n = C(w(t) + e | 0, T(t));
119
+ if (Atomics.compareExchange(this.#t, 0, t, n) === t) return;
120
+ }
121
+ }
122
+ insert(e, t) {
123
+ if (t.length !== this.channels) throw Error("wrong number of channels");
124
+ let n = Math.round(r.Second.fromMicro(e) * this.rate), i = t[0].length, a = 0;
125
+ if (!this.#r) {
126
+ this.#i = n;
127
+ let e = w(Atomics.load(this.#t, 0));
128
+ Atomics.add(this.#e, S, 1), Atomics.store(this.#t, 0, C(e + 2 | 0, 0)), Atomics.store(this.#e, y, 0), this.#r = !0, this.#a = 0, this.#o = 0;
129
+ }
130
+ n = n - this.#i | 0;
131
+ let o = n + i | 0, s = T(Atomics.load(this.#t, 0)), c = s - n | 0;
132
+ if (c > 0) {
133
+ if (c >= i) return;
134
+ a = c, n = n + c | 0;
135
+ }
136
+ let l = i - a;
137
+ (o - s | 0) > this.capacity && this.#c(o - this.capacity | 0);
138
+ let u = Atomics.load(this.#e, y), d = n - u | 0;
139
+ if (d > 0) {
140
+ let e = Math.min(d, this.capacity);
141
+ for (let t = 0; t < this.channels; t++) {
142
+ let n = this.#n[t];
143
+ for (let t = 0; t < e; t++) n[D(u + t | 0, this.capacity)] = 0;
144
+ }
145
+ }
146
+ for (let e = 0; e < this.channels; e++) {
147
+ let r = t[e], i = this.#n[e];
148
+ for (let e = 0; e < l; e++) i[D(n + e | 0, this.capacity)] = r[a + e];
149
+ }
150
+ Atomics.store(this.#e, y, E(Atomics.load(this.#e, y), o)), this.#u();
151
+ }
152
+ #u() {
153
+ let e = T(Atomics.load(this.#t, 0)), t = Atomics.load(this.#e, y), n = Atomics.load(this.#e, b);
154
+ (t - e | 0) >= n && n > 0 && Atomics.store(this.#e, x, 0);
155
+ }
156
+ read(e) {
157
+ let t = Atomics.load(this.#t, 0);
158
+ if (Atomics.load(this.#e, x) === 1 || re(t)) return 0;
159
+ let n = T(t), r = Atomics.load(this.#e, y), i = Atomics.load(this.#e, b), a = r - n | 0;
160
+ if (!this.buffered && i > 0 && a > i) {
161
+ let e = r - i | 0;
162
+ (e - n | 0) > 0 && (n = e);
163
+ }
164
+ let o = r - n | 0, s = Math.min(o, e[0].length);
165
+ if (s <= 0) return (n - T(t) | 0) > 0 && Atomics.compareExchange(this.#t, 0, t, C(w(t), n)), 0;
166
+ for (let t = 0; t < this.channels; t++) {
167
+ let r = this.#n[t], i = e[t];
168
+ for (let e = 0; e < s; e++) i[e] = r[D(n + e | 0, this.capacity)];
169
+ }
170
+ let c = C(w(t), n + s | 0);
171
+ if (Atomics.compareExchange(this.#t, 0, t, c) !== t) {
172
+ for (let t = 0; t < this.channels; t++) e[t].fill(0, 0, s);
173
+ return 0;
174
+ }
175
+ return s;
176
+ }
177
+ setLatency(e) {
178
+ let t = Atomics.exchange(this.#e, b, e);
179
+ t > 0 && e > t && (Atomics.store(this.#e, x, 1), this.#l(2)), this.#u();
180
+ }
181
+ truncate(e) {
182
+ let t = Math.round(r.Second.fromMicro(e) * this.rate) - this.#i | 0;
183
+ if (!((Atomics.load(this.#e, y) - t | 0) <= 0)) {
184
+ for (this.#l(1);;) {
185
+ let e = Atomics.load(this.#e, y), n = E(t, T(Atomics.load(this.#t, 0)));
186
+ if ((e - n | 0) <= 0 || Atomics.compareExchange(this.#e, y, e, n) === e) break;
187
+ }
188
+ this.#l(1);
189
+ }
190
+ }
191
+ reset() {
192
+ this.#r = !1, Atomics.store(this.#e, x, 1);
193
+ let e = Atomics.load(this.#e, y), t = Atomics.load(this.#t, 0);
194
+ Atomics.store(this.#t, 0, C(w(t), e));
195
+ }
196
+ resize(t) {
197
+ let n = ae(this.channels, t, this.rate, this.buffered), r = new e(n);
198
+ r.#r = this.#r, r.#i = this.#i;
199
+ let i = Atomics.load(this.#t, 0), a = T(i), o = Atomics.load(this.#e, y), s = Atomics.load(this.#e, b), c = Atomics.load(this.#e, x), l = o - a | 0, u = Math.max(0, Math.min(l, r.capacity)), d = o - u | 0;
200
+ for (let e = 0; e < this.channels; e++) {
201
+ let t = this.#n[e], n = r.#n[e];
202
+ for (let e = 0; e < u; e++) {
203
+ let i = d + e | 0;
204
+ n[D(i, r.capacity)] = t[D(i, this.capacity)];
205
+ }
206
+ }
207
+ return Atomics.store(r.#e, S, Atomics.load(this.#e, S)), Atomics.store(r.#t, 0, C(w(i), d)), Atomics.store(r.#e, y, o), Atomics.store(r.#e, b, s), Atomics.store(r.#e, x, c), r.#a = this.#d(a) + (d - a | 0), r.#o = d, r;
208
+ }
209
+ #d(e) {
210
+ return this.#a += e - this.#o | 0, this.#o = e, this.#a;
211
+ }
212
+ #f() {
213
+ return this.#d(T(Atomics.load(this.#t, 0)));
214
+ }
215
+ get timestamp() {
216
+ return r.Micro.fromSecond((this.#i + this.#f()) / this.rate);
217
+ }
218
+ get stalled() {
219
+ return Atomics.load(this.#e, x) === 1;
220
+ }
221
+ get length() {
222
+ return Atomics.load(this.#e, y) - T(Atomics.load(this.#t, 0)) | 0;
223
+ }
224
+ }, se = class {
225
+ #e;
226
+ #t;
227
+ #n = [];
228
+ constructor(e, t) {
229
+ this.#e = e, this.#t = t;
230
+ }
231
+ setHeadroom(e) {
232
+ this.#t = e;
233
+ }
234
+ wait(e, t) {
235
+ return !this.#e || t >= (e - this.#t | 0) ? Promise.resolve() : new Promise((t) => this.#n.push({
236
+ timestamp: e,
237
+ resolve: t
238
+ }));
239
+ }
240
+ advance(e) {
241
+ this.#n.length !== 0 && (this.#n = this.#n.filter(({ timestamp: t, resolve: n }) => e < (t - this.#t | 0) || (n(), !1)));
242
+ }
243
+ flush() {
244
+ for (let { resolve: e } of this.#n) e();
245
+ this.#n = [];
246
+ }
247
+ };
248
+ function O(e, t) {
249
+ return r.Micro.fromSecond(e / t);
250
+ }
251
+ function ce() {
252
+ return !(typeof SharedArrayBuffer > "u" || typeof crossOriginIsolated < "u" && !crossOriginIsolated);
253
+ }
254
+ function le(e, t, n, r, i = !1) {
255
+ return ce() ? (console.log("[audio] using SharedArrayBuffer audio buffer"), new ue(e, t, n, r, i)) : (console.warn("[audio] SharedArrayBuffer unavailable, falling back to the higher latency postMessage audio buffer. Serve the page cross-origin isolated (Cross-Origin-Opener-Policy: same-origin, Cross-Origin-Embedder-Policy: require-corp) to avoid this."), new de(e, t, n, r, i));
256
+ }
257
+ var ue = class {
258
+ rate;
259
+ channels;
260
+ #e;
261
+ #t;
262
+ #n = new a(0);
263
+ timestamp = this.#n;
264
+ #r = new a(!0);
265
+ stalled = this.#r;
266
+ #i;
267
+ #a = new i();
268
+ constructor(e, t, n, r, i) {
269
+ this.#e = e, this.channels = t, this.rate = n;
270
+ let a = Math.max(n, r * 2);
271
+ this.#i = new se(i, O(r, n));
272
+ let o = ae(t, a, n, i);
273
+ this.#t = new oe(o), this.#t.setLatency(r);
274
+ let s = {
275
+ type: "init-shared",
276
+ ...o
277
+ };
278
+ e.port.postMessage(s), this.#a.interval(() => {
279
+ let e = this.#t.stalled;
280
+ this.#n.set(this.#t.timestamp), this.#r.set(e), e ? this.#i.flush() : this.#i.advance(this.#t.timestamp);
281
+ }, 50);
282
+ }
283
+ insert(e, t) {
284
+ this.#t.insert(e, t);
285
+ }
286
+ setLatency(e) {
287
+ if (this.#i.setHeadroom(O(e, this.rate)), this.#t.setLatency(e), this.#t.capacity < e * 1.5) {
288
+ let t = Math.max(this.rate, e * 2);
289
+ this.#t = this.#t.resize(t);
290
+ let n = {
291
+ type: "init-shared",
292
+ ...this.#t.init
293
+ };
294
+ this.#e.port.postMessage(n);
295
+ }
296
+ }
297
+ truncate(e) {
298
+ this.#t.truncate(e);
299
+ }
300
+ reset() {
301
+ this.#t.reset(), this.#i.flush();
302
+ }
303
+ wait(e) {
304
+ return this.#t.stalled ? Promise.resolve() : this.#i.wait(e, this.#t.timestamp);
305
+ }
306
+ close() {
307
+ this.#i.flush(), this.#a.close();
308
+ }
309
+ }, de = class {
310
+ rate;
311
+ channels;
312
+ #e;
313
+ #t = new a(0);
314
+ timestamp = this.#t;
315
+ #n = new a(!0);
316
+ stalled = this.#n;
317
+ #r;
318
+ #i = new i();
319
+ constructor(e, t, n, i, a) {
320
+ this.#e = e, this.channels = t, this.rate = n, this.#r = new se(a, O(i, n));
321
+ let o = {
322
+ type: "init-post",
323
+ channels: t,
324
+ rate: n,
325
+ latency: r.Milli.fromSecond(i / n),
326
+ buffered: a
327
+ };
328
+ e.port.postMessage(o), this.#i.event(e.port, "message", (e) => {
329
+ let t = e.data;
330
+ t?.type === "state" && (this.#t.set(t.timestamp), this.#n.set(t.stalled), t.stalled ? this.#r.flush() : this.#r.advance(t.timestamp));
331
+ }), e.port.start();
332
+ }
333
+ insert(e, t) {
334
+ let n = {
335
+ type: "data",
336
+ data: t,
337
+ timestamp: e
338
+ };
339
+ this.#e.port.postMessage(n, t.map((e) => e.buffer));
340
+ }
341
+ setLatency(e) {
342
+ this.#r.setHeadroom(O(e, this.rate));
343
+ let t = {
344
+ type: "latency",
345
+ latency: r.Milli.fromSecond(e / this.rate)
346
+ };
347
+ this.#e.port.postMessage(t);
348
+ }
349
+ truncate(e) {
350
+ let t = {
351
+ type: "truncate",
352
+ timestamp: e
353
+ };
354
+ this.#e.port.postMessage(t);
355
+ }
356
+ reset() {
357
+ this.#e.port.postMessage({ type: "reset" }), this.#r.flush();
358
+ }
359
+ wait(e) {
360
+ return this.#n.peek() ? Promise.resolve() : this.#r.wait(e, this.#t.peek());
361
+ }
362
+ close() {
363
+ this.#r.flush(), this.#i.close();
364
+ }
365
+ }, fe = 128, pe = 20, me = 1024, he = 1152, ge = 576, _e = 32e3;
366
+ function k(e) {
367
+ return {
368
+ codec: e.codec,
369
+ container: e.container,
370
+ description: e.description,
371
+ sampleRate: e.sampleRate,
372
+ numberOfChannels: e.numberOfChannels
373
+ };
374
+ }
375
+ function ve(e) {
376
+ return {
377
+ broadcast: e.broadcast,
378
+ decoder: k(e)
379
+ };
380
+ }
381
+ function ye(e) {
382
+ let t = (e.jitter || be(e)) ?? 0, n = Math.ceil(fe / e.sampleRate * 1e3);
383
+ return r.Milli((e.delay ?? 0) + t + n);
384
+ }
385
+ function be(e) {
386
+ if (e.codec.startsWith("opus")) return pe;
387
+ if (e.codec.startsWith("mp4a")) return Math.ceil(me / e.sampleRate * 1e3);
388
+ if (e.codec === "mp3") {
389
+ let t = e.sampleRate >= _e ? he : ge;
390
+ return Math.ceil(t / e.sampleRate * 1e3);
391
+ }
392
+ }
393
+ //#endregion
394
+ //#region src/audio/handover.ts
395
+ var xe = class {
396
+ #e = !1;
397
+ #t = !1;
398
+ opened() {
399
+ this.#e && (this.#t = !0), this.#e = !0;
400
+ }
401
+ takeover() {
402
+ let e = this.#t;
403
+ return this.#t = !1, e;
404
+ }
405
+ }, Se = 128;
406
+ function A(e, t) {
407
+ return Math.max(Se, Math.ceil(e * r.Second.fromMilli(t)));
408
+ }
409
+ //#endregion
410
+ //#region src/audio/render-worklet.ts?worklet
411
+ var Ce = new Blob(["var __defProp = Object.defineProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\n\n// ../net/src/time.ts\nvar time_exports = {};\n__export(time_exports, {\n Micro: () => Micro,\n Milli: () => Milli,\n Nano: () => Nano,\n Second: () => Second,\n Timescale: () => Timescale,\n Timestamp: () => Timestamp\n});\nvar Nano = Object.assign((value) => value, {\n zero: 0,\n fromMicro: (us) => us * 1e3,\n fromMilli: (ms) => ms * 1e6,\n fromSecond: (s) => s * 1e9,\n toMicro: (ns) => ns / 1e3,\n toMilli: (ns) => ns / 1e6,\n toSecond: (ns) => ns / 1e9,\n now: () => performance.now() * 1e6,\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\nvar Micro = Object.assign((value) => value, {\n zero: 0,\n fromNano: (ns) => ns / 1e3,\n fromMilli: (ms) => ms * 1e3,\n fromSecond: (s) => s * 1e6,\n toNano: (us) => us * 1e3,\n toMilli: (us) => us / 1e3,\n toSecond: (us) => us / 1e6,\n now: () => performance.now() * 1e3,\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\nvar Milli = Object.assign((value) => value, {\n zero: 0,\n fromNano: (ns) => ns / 1e6,\n fromMicro: (us) => us / 1e3,\n fromSecond: (s) => s * 1e3,\n toNano: (ms) => ms * 1e6,\n toMicro: (ms) => ms * 1e3,\n toSecond: (ms) => ms / 1e3,\n now: () => performance.now(),\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\nvar Timescale = Object.assign(\n (unitsPerSecond) => {\n if (!Number.isSafeInteger(unitsPerSecond) || unitsPerSecond <= 0) {\n throw new RangeError(`invalid timescale: ${unitsPerSecond}`);\n }\n return unitsPerSecond;\n },\n {\n /** One unit per second. */\n SECOND: 1,\n /** 1,000 units per second. */\n MILLI: 1e3,\n /** 1,000,000 units per second. */\n MICRO: 1e6,\n /** 1,000,000,000 units per second. */\n NANO: 1e9\n }\n);\nfunction assertTimestampValue(value) {\n if (!Number.isFinite(value) || value < 0 || value > Number.MAX_SAFE_INTEGER) {\n throw new RangeError(`invalid timestamp: ${value}`);\n }\n}\nvar Timestamp = class _Timestamp {\n /** The raw value, in `scale` units. */\n value;\n /** Units per second the {@link value} is measured in. */\n scale;\n /** Build a timestamp of `value` units at `scale`. */\n constructor(value, scale) {\n assertTimestampValue(value);\n this.value = value;\n this.scale = Timescale(scale);\n }\n /** Monotonic now (`performance.now()`, milliseconds since page load), not wall-clock time. */\n static now() {\n return new _Timestamp(performance.now(), Timescale.MILLI);\n }\n /** A timestamp of `ms` milliseconds. */\n static fromMillis(ms) {\n return new _Timestamp(ms, Timescale.MILLI);\n }\n /** A timestamp of `us` microseconds. */\n static fromMicros(us) {\n return new _Timestamp(us, Timescale.MICRO);\n }\n /** This timestamp's value re-expressed at `scale`; throws if the result is not in the safe range. */\n as(scale) {\n const dest = Timescale(scale);\n const converted = dest === this.scale ? this.value : this.value * dest / this.scale;\n assertTimestampValue(converted);\n return converted;\n }\n /** The value in milliseconds. */\n asMillis() {\n return this.as(Timescale.MILLI);\n }\n /** The value in microseconds. */\n asMicros() {\n return this.as(Timescale.MICRO);\n }\n};\nvar Second = Object.assign((value) => value, {\n zero: 0,\n fromNano: (ns) => ns / 1e9,\n fromMicro: (us) => us / 1e6,\n fromMilli: (ms) => ms / 1e3,\n toNano: (s) => s * 1e9,\n toMicro: (s) => s * 1e6,\n toMilli: (s) => s * 1e3,\n now: () => performance.now() / 1e3,\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\n\n// src/audio/ring-buffer.ts\nvar AudioRingBuffer = class {\n #buffer;\n #writeIndex = 0;\n #readIndex = 0;\n rate;\n channels;\n #stalled = true;\n // Buffered mode: play through everything buffered without skipping ahead.\n #buffered;\n // Un-stall threshold in samples (how much to buffer before playback starts).\n #latencySamples;\n // Whether the read/write indices have been anchored to the first inserted sample.\n #anchored = false;\n constructor(props) {\n if (props.channels <= 0) throw new Error(\"invalid channels\");\n if (props.rate <= 0) throw new Error(\"invalid sample rate\");\n if (props.latency <= 0) throw new Error(\"invalid latency\");\n this.#latencySamples = Math.ceil(props.rate * time_exports.Second.fromMilli(props.latency));\n if (this.#latencySamples === 0) throw new Error(\"empty buffer\");\n this.rate = props.rate;\n this.channels = props.channels;\n this.#buffered = props.buffered ?? false;\n const capacity = this.#capacityFor(this.#latencySamples);\n this.#buffer = [];\n for (let i = 0; i < this.channels; i++) {\n this.#buffer[i] = new Float32Array(capacity);\n }\n }\n #capacityFor(latencySamples) {\n return this.#buffered ? latencySamples * 2 : latencySamples;\n }\n get stalled() {\n return this.#stalled;\n }\n get timestamp() {\n return time_exports.Micro.fromSecond(this.#readIndex / this.rate);\n }\n get length() {\n return this.#writeIndex - this.#readIndex;\n }\n get capacity() {\n return this.#buffer[0]?.length;\n }\n resize(latency) {\n const latencySamples = Math.ceil(this.rate * time_exports.Second.fromMilli(latency));\n if (latencySamples > this.#latencySamples) this.#stalled = true;\n this.#latencySamples = latencySamples;\n const newCapacity = this.#capacityFor(this.#latencySamples);\n if (newCapacity !== this.capacity) this.#reallocate(newCapacity);\n if (latencySamples > 0 && this.length >= latencySamples) this.#stalled = false;\n }\n #reallocate(newCapacity) {\n if (newCapacity === 0) throw new Error(\"empty buffer\");\n const newBuffer = [];\n for (let i = 0; i < this.channels; i++) {\n newBuffer[i] = new Float32Array(newCapacity);\n }\n const samplesToKeep = Math.min(this.length, newCapacity);\n if (samplesToKeep > 0) {\n const copyStart = this.#writeIndex - samplesToKeep;\n for (let channel = 0; channel < this.channels; channel++) {\n const src = this.#buffer[channel];\n const dst = newBuffer[channel];\n for (let i = 0; i < samplesToKeep; i++) {\n const srcPos = (copyStart + i) % src.length;\n const dstPos = (copyStart + i) % dst.length;\n dst[dstPos] = src[srcPos];\n }\n }\n }\n this.#buffer = newBuffer;\n this.#readIndex = this.#writeIndex - samplesToKeep;\n if (samplesToKeep === 0) this.#stalled = true;\n }\n write(timestamp, data) {\n if (data.length !== this.channels) throw new Error(\"wrong number of channels\");\n let start = Math.round(time_exports.Second.fromMicro(timestamp) * this.rate);\n let samples = data[0].length;\n if (!this.#anchored) {\n this.#readIndex = start;\n this.#writeIndex = start;\n this.#anchored = true;\n }\n let offset = this.#readIndex - start;\n if (offset > samples) {\n return;\n } else if (offset > 0) {\n samples -= offset;\n start += offset;\n } else {\n offset = 0;\n }\n const end = start + samples;\n const overflow = end - this.#readIndex - this.#buffer[0].length;\n if (overflow >= 0) {\n this.#stalled = false;\n this.#readIndex += overflow;\n }\n if (start > this.#writeIndex) {\n const gapSize = Math.min(start - this.#writeIndex, this.#buffer[0].length);\n if (gapSize === 1) {\n console.warn(\"floating point inaccuracy detected\");\n }\n for (let channel = 0; channel < this.channels; channel++) {\n const dst = this.#buffer[channel];\n for (let i = 0; i < gapSize; i++) {\n const writePos = (this.#writeIndex + i) % dst.length;\n dst[writePos] = 0;\n }\n }\n }\n for (let channel = 0; channel < this.channels; channel++) {\n let src = data[channel];\n src = src.subarray(src.length - samples);\n const dst = this.#buffer[channel];\n if (src.length !== samples) throw new Error(\"mismatching number of samples\");\n for (let i = 0; i < samples; i++) {\n const writePos = (start + i) % dst.length;\n dst[writePos] = src[i];\n }\n }\n if (end > this.#writeIndex) {\n this.#writeIndex = end;\n }\n if (this.#buffered && this.length >= this.#latencySamples) {\n this.#stalled = false;\n }\n }\n /**\n * Drop buffered samples at or after `timestamp`, keeping whatever is already due.\n *\n * A successor track overwrites the slots its own samples land on, but anything the previous\n * track wrote beyond them would otherwise still play once the successor runs out.\n */\n truncate(timestamp) {\n const target = Math.round(time_exports.Second.fromMicro(timestamp) * this.rate);\n if (target >= this.#writeIndex) return;\n this.#writeIndex = Math.max(target, this.#readIndex);\n }\n // Flush all buffered samples and re-stall, ready to anchor the next utterance.\n reset() {\n this.#readIndex = 0;\n this.#writeIndex = 0;\n this.#stalled = true;\n this.#anchored = false;\n }\n read(output) {\n if (output.length !== this.channels) throw new Error(\"wrong number of channels\");\n if (this.#stalled) return 0;\n const samples = Math.min(this.#writeIndex - this.#readIndex, output[0].length);\n if (samples === 0) return 0;\n for (let channel = 0; channel < this.channels; channel++) {\n const dst = output[channel];\n const src = this.#buffer[channel];\n if (dst.length !== output[0].length) throw new Error(\"mismatching number of samples\");\n for (let i = 0; i < samples; i++) {\n const readPos = (this.#readIndex + i) % src.length;\n dst[i] = src[readPos];\n }\n }\n this.#readIndex += samples;\n return samples;\n }\n};\n\n// src/audio/shared-ring-buffer.ts\nvar WRITE = 0;\nvar LATENCY = 1;\nvar STALLED = 2;\nvar TIMELINE = 3;\nvar CONTROL_SLOTS = 4;\nvar CURSOR_MASK = 0xffffffffn;\nfunction pack(epoch, read) {\n return BigInt(epoch >>> 0) << 32n | BigInt(read >>> 0);\n}\nfunction epochOf(state) {\n return Number(state >> 32n) | 0;\n}\nfunction retreating(state) {\n return (epochOf(state) & 1) !== 0;\n}\nfunction readOf(state) {\n return Number(state & CURSOR_MASK) | 0;\n}\nfunction ceilPow2(n) {\n return n <= 1 ? 1 : 1 << 32 - Math.clz32(n - 1);\n}\nfunction allocSharedRingBuffer(channels, capacity, rate, buffered = false) {\n if (channels <= 0) throw new Error(\"invalid channels\");\n if (capacity <= 0 || capacity > 2 ** 30) throw new Error(\"invalid capacity\");\n if (rate <= 0) throw new Error(\"invalid sample rate\");\n capacity = ceilPow2(capacity);\n const samples = new SharedArrayBuffer(channels * capacity * Float32Array.BYTES_PER_ELEMENT);\n const control = new SharedArrayBuffer(CONTROL_SLOTS * Int32Array.BYTES_PER_ELEMENT);\n const state = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT);\n const ctrl = new Int32Array(control);\n Atomics.store(ctrl, STALLED, 1);\n return { channels, capacity, rate, samples, control, state, buffered };\n}\nfunction i32Max(a, b) {\n return (a - b | 0) > 0 ? a : b;\n}\nfunction slot(idx, capacity) {\n return idx & capacity - 1;\n}\nvar SharedRingBuffer = class _SharedRingBuffer {\n channels;\n capacity;\n rate;\n buffered;\n init;\n #control;\n #state;\n #samples;\n // Whether READ/WRITE have been anchored to the first inserted sample.\n #anchored = false;\n // Absolute sample index of that first sample. READ/WRITE are stored relative to it, so\n // `timestamp` adds it back to recover media time. Main-thread only: the worklet reads by\n // difference and never needs an absolute position.\n #anchor = 0;\n // Unwrapped READ, in anchor-relative samples, plus the raw i32 it was last derived from.\n // READ is Int32 and wraps every ~13.5h at 44.1kHz. That is harmless for the modular\n // comparisons the ring runs on, but reading the negative half as a magnitude would report\n // the playhead jumping back 2^32 samples, so accumulate deltas here instead. Main-thread\n // only, and only accurate while `timestamp` is observed more often than READ can advance\n // 2^31 samples, which the 50ms poll in `buffer.ts` satisfies by six orders of magnitude.\n #position = 0;\n #lastRead = 0;\n /**\n * Wrap the shared memory described by `init`.\n *\n * Pass `previous` in the worklet when this ring replaces one already being read. `resize`\n * snapshots the playhead on the main thread and hands the replacement over by message, so the\n * reader keeps draining the old ring in the meantime. Carrying its cursor across means those\n * samples are not played twice.\n */\n constructor(init, previous) {\n this.channels = init.channels;\n this.capacity = init.capacity;\n this.rate = init.rate;\n this.buffered = init.buffered;\n this.init = init;\n this.#control = new Int32Array(init.control);\n this.#state = new BigInt64Array(init.state);\n this.#samples = [];\n for (let i = 0; i < this.channels; i++) {\n this.#samples.push(\n new Float32Array(init.samples, i * this.capacity * Float32Array.BYTES_PER_ELEMENT, this.capacity)\n );\n }\n if (previous !== void 0) this.#handoff(previous);\n }\n /**\n * Carry `source`'s playhead across, if the replacement is still the timeline it belongs to.\n *\n * Truncation changes the mutation epoch but preserves timeline identity. Sample state before\n * identity: a re-anchor publishes identity first, then replaces state. Either the identity\n * check rejects the old cursor, the exchange fails, or the re-anchor overwrites the carried\n * cursor. A truncate only forces a retry, preserving audio consumed since the resize.\n */\n #handoff(source) {\n if (source.channels !== this.channels || source.rate !== this.rate) return;\n const timeline = Atomics.load(source.#control, TIMELINE);\n const from = Atomics.load(source.#state, 0);\n for (; ; ) {\n const state = Atomics.load(this.#state, 0);\n if (Atomics.load(this.#control, TIMELINE) !== timeline) return;\n if ((readOf(from) - readOf(state) | 0) <= 0) return;\n const next = pack(epochOf(state), readOf(from));\n if (Atomics.compareExchange(this.#state, 0, state, next) === state) return;\n }\n }\n /**\n * Move the playhead forward to `candidate`, staying on whatever timeline is current.\n *\n * Retries while the word changes under it, and never steps backwards. Used by the writer's\n * overflow path; the reader publishes with its own exchange so it can tell a rebase apart\n * from losing a race.\n */\n #advance(candidate) {\n for (; ; ) {\n const state = Atomics.load(this.#state, 0);\n if ((candidate - readOf(state) | 0) <= 0) return;\n const next = pack(epochOf(state), candidate);\n if (Atomics.compareExchange(this.#state, 0, state, next) === state) return;\n }\n }\n /**\n * Step the epoch by `by`, leaving the playhead wherever the reader has taken it.\n *\n * Retries while the word changes under it: only the epoch half is the writer's to move.\n */\n #step(by) {\n for (; ; ) {\n const state = Atomics.load(this.#state, 0);\n const next = pack(epochOf(state) + by | 0, readOf(state));\n if (Atomics.compareExchange(this.#state, 0, state, next) === state) return;\n }\n }\n /**\n * Insert audio samples at the given timestamp.\n * Main thread only. Handles out-of-order writes, gap filling, and overflow.\n */\n insert(timestamp, data) {\n if (data.length !== this.channels) throw new Error(\"wrong number of channels\");\n let start = Math.round(time_exports.Second.fromMicro(timestamp) * this.rate);\n const originalLength = data[0].length;\n let offset = 0;\n if (!this.#anchored) {\n this.#anchor = start;\n const epoch = epochOf(Atomics.load(this.#state, 0));\n Atomics.add(this.#control, TIMELINE, 1);\n Atomics.store(this.#state, 0, pack(epoch + 2 | 0, 0));\n Atomics.store(this.#control, WRITE, 0);\n this.#anchored = true;\n this.#position = 0;\n this.#lastRead = 0;\n }\n start = start - this.#anchor | 0;\n const end = start + originalLength | 0;\n const read = readOf(Atomics.load(this.#state, 0));\n const behind = read - start | 0;\n if (behind > 0) {\n if (behind >= originalLength) {\n return;\n }\n offset = behind;\n start = start + behind | 0;\n }\n const samples = originalLength - offset;\n if ((end - read | 0) > this.capacity) {\n this.#advance(end - this.capacity | 0);\n }\n const write = Atomics.load(this.#control, WRITE);\n const gap = start - write | 0;\n if (gap > 0) {\n const gapSize = Math.min(gap, this.capacity);\n for (let channel = 0; channel < this.channels; channel++) {\n const dst = this.#samples[channel];\n for (let i = 0; i < gapSize; i++) {\n dst[slot(write + i | 0, this.capacity)] = 0;\n }\n }\n }\n for (let channel = 0; channel < this.channels; channel++) {\n const src = data[channel];\n const dst = this.#samples[channel];\n for (let i = 0; i < samples; i++) {\n dst[slot(start + i | 0, this.capacity)] = src[offset + i];\n }\n }\n Atomics.store(this.#control, WRITE, i32Max(Atomics.load(this.#control, WRITE), end));\n this.#resume();\n }\n // Un-stall once the buffered data covers LATENCY.\n #resume() {\n const read = readOf(Atomics.load(this.#state, 0));\n const write = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n if ((write - read | 0) >= latency && latency > 0) {\n Atomics.store(this.#control, STALLED, 0);\n }\n }\n /**\n * Read audio samples into the output buffers.\n * AudioWorklet only. Returns the number of samples read.\n */\n read(output) {\n const state = Atomics.load(this.#state, 0);\n if (Atomics.load(this.#control, STALLED) === 1) return 0;\n if (retreating(state)) return 0;\n let read = readOf(state);\n const write = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n const buffered = write - read | 0;\n if (!this.buffered && latency > 0 && buffered > latency) {\n const skipTo = write - latency | 0;\n if ((skipTo - read | 0) > 0) read = skipTo;\n }\n const available = write - read | 0;\n const count = Math.min(available, output[0].length);\n if (count <= 0) {\n if ((read - readOf(state) | 0) > 0) {\n Atomics.compareExchange(this.#state, 0, state, pack(epochOf(state), read));\n }\n return 0;\n }\n for (let channel = 0; channel < this.channels; channel++) {\n const src = this.#samples[channel];\n const dst = output[channel];\n for (let i = 0; i < count; i++) {\n dst[i] = src[slot(read + i | 0, this.capacity)];\n }\n }\n const next = pack(epochOf(state), read + count | 0);\n if (Atomics.compareExchange(this.#state, 0, state, next) !== state) {\n for (let channel = 0; channel < this.channels; channel++) output[channel].fill(0, 0, count);\n return 0;\n }\n return count;\n }\n /**\n * Update the target latency in samples. Main thread only.\n *\n * A deeper floor parks playback until it refills. Video holds the extra delay on its own, so\n * audio that kept draining at the old depth would run ahead by the difference. Parking keeps\n * what is buffered, so a rise costs only its own size in silence, and none if the buffer\n * already covers the new floor.\n */\n setLatency(samples) {\n const previous = Atomics.exchange(this.#control, LATENCY, samples);\n if (previous > 0 && samples > previous) {\n Atomics.store(this.#control, STALLED, 1);\n this.#step(2);\n }\n this.#resume();\n }\n /**\n * Drop buffered samples at or after `timestamp`, keeping whatever is already due.\n * Main thread only.\n *\n * A successor track overwrites the slots its own samples land on, but anything the previous\n * track wrote beyond them would otherwise still play once the successor runs out.\n */\n truncate(timestamp) {\n const target = Math.round(time_exports.Second.fromMicro(timestamp) * this.rate) - this.#anchor | 0;\n if ((Atomics.load(this.#control, WRITE) - target | 0) <= 0) return;\n this.#step(1);\n for (; ; ) {\n const write = Atomics.load(this.#control, WRITE);\n const clamped = i32Max(target, readOf(Atomics.load(this.#state, 0)));\n if ((write - clamped | 0) <= 0) break;\n if (Atomics.compareExchange(this.#control, WRITE, write, clamped) === write) break;\n }\n this.#step(1);\n }\n /**\n * Flush buffered samples and re-stall, ready to anchor the next utterance (buffered mode).\n * Main thread only. The worklet reader sees STALLED and stops until the next insert.\n */\n reset() {\n this.#anchored = false;\n Atomics.store(this.#control, STALLED, 1);\n const write = Atomics.load(this.#control, WRITE);\n const state = Atomics.load(this.#state, 0);\n Atomics.store(this.#state, 0, pack(epochOf(state), write));\n }\n /**\n * Allocate a new ring with `newCapacity` samples and copy the unread window\n * [READ, WRITE) plus control state into it. Used when growing capacity so\n * we don't drop buffered audio. If `newCapacity` is smaller than the unread\n * span, the oldest samples are truncated.\n *\n * Main thread only. `resize()` reads from the source `SharedRingBuffer` and\n * writes into a freshly allocated buffer from `allocSharedRingBuffer`, so it\n * relies on the same invariant as `insert()`: no concurrent main-thread\n * writers. The AudioWorklet reader is tolerated via the CAS discipline used\n * by READ/WRITE elsewhere.\n */\n resize(newCapacity) {\n const init = allocSharedRingBuffer(this.channels, newCapacity, this.rate, this.buffered);\n const dst = new _SharedRingBuffer(init);\n dst.#anchored = this.#anchored;\n dst.#anchor = this.#anchor;\n const state = Atomics.load(this.#state, 0);\n const read = readOf(state);\n const write = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n const stalled = Atomics.load(this.#control, STALLED);\n const available = write - read | 0;\n const copyCount = Math.max(0, Math.min(available, dst.capacity));\n const copyStart = write - copyCount | 0;\n for (let channel = 0; channel < this.channels; channel++) {\n const src = this.#samples[channel];\n const out = dst.#samples[channel];\n for (let i = 0; i < copyCount; i++) {\n const idx = copyStart + i | 0;\n out[slot(idx, dst.capacity)] = src[slot(idx, this.capacity)];\n }\n }\n Atomics.store(dst.#control, TIMELINE, Atomics.load(this.#control, TIMELINE));\n Atomics.store(dst.#state, 0, pack(epochOf(state), copyStart));\n Atomics.store(dst.#control, WRITE, write);\n Atomics.store(dst.#control, LATENCY, latency);\n Atomics.store(dst.#control, STALLED, stalled);\n dst.#position = this.#foldRead(read) + (copyStart - read | 0);\n dst.#lastRead = copyStart;\n return dst;\n }\n /**\n * Fold an observed READ into `#position`, so the returned offset keeps counting up across\n * the i32 wrap. Idempotent: folding the same value twice adds a zero delta.\n */\n #foldRead(read) {\n this.#position += read - this.#lastRead | 0;\n this.#lastRead = read;\n return this.#position;\n }\n /** `#foldRead` against the current READ. */\n #unwrapRead() {\n return this.#foldRead(readOf(Atomics.load(this.#state, 0)));\n }\n /**\n * Current playback timestamp derived from READ position.\n *\n * Main thread only, and stateful: it advances the unwrapped read position, so it has to be\n * polled rather than sampled once. See `#position`.\n */\n get timestamp() {\n return time_exports.Micro.fromSecond((this.#anchor + this.#unwrapRead()) / this.rate);\n }\n /** Whether the buffer is stalled (waiting to fill). */\n get stalled() {\n return Atomics.load(this.#control, STALLED) === 1;\n }\n /**\n * Number of buffered samples (WRITE - READ).\n *\n * Non-atomic: WRITE and READ are loaded separately, so a concurrent\n * writer/reader can make the two loads inconsistent. Intended for\n * tests and diagnostics, not control-flow decisions.\n */\n get length() {\n return Atomics.load(this.#control, WRITE) - readOf(Atomics.load(this.#state, 0)) | 0;\n }\n};\n\n// src/audio/render-worklet.ts\nvar Render = class extends AudioWorkletProcessor {\n // Set after init, depending on which path the main thread chose.\n #backend;\n #underflow = 0;\n #stateCounter = 0;\n constructor() {\n super();\n this.port.onmessage = (event) => {\n const msg = event.data;\n if (msg.type === \"init-shared\") {\n console.log(\"[audio-worklet] init-shared: using SharedArrayBuffer path\");\n const previous = this.#backend instanceof SharedRingBuffer ? this.#backend : void 0;\n this.#backend = new SharedRingBuffer(msg, previous);\n this.#underflow = 0;\n } else if (msg.type === \"init-post\") {\n console.log(\"[audio-worklet] init-post: using postMessage path\");\n this.#backend = new AudioRingBuffer(msg);\n this.#underflow = 0;\n } else if (msg.type === \"data\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.write(msg.timestamp, msg.data);\n } else if (msg.type === \"latency\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.resize(msg.latency);\n } else if (msg.type === \"truncate\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.truncate(msg.timestamp);\n } else if (msg.type === \"reset\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.reset();\n }\n };\n }\n process(_inputs, outputs, _parameters) {\n const output = outputs[0];\n const backend = this.#backend;\n const samplesRead = backend?.read(output) ?? 0;\n if (samplesRead < output[0].length) {\n this.#underflow += output[0].length - samplesRead;\n } else if (this.#underflow > 0 && backend) {\n console.debug(`audio underflow: ${Math.round(1e3 * this.#underflow / backend.rate)}ms`);\n this.#underflow = 0;\n }\n if (backend instanceof AudioRingBuffer) {\n this.#stateCounter++;\n if (this.#stateCounter >= 5) {\n this.#stateCounter = 0;\n const state = {\n type: \"state\",\n timestamp: backend.timestamp,\n stalled: backend.stalled\n };\n this.port.postMessage(state);\n }\n }\n return true;\n }\n};\nregisterProcessor(\"render\", Render);\n"], { type: "application/javascript" }), we = URL.createObjectURL(Ce), Te = class {
412
+ #e = 0;
413
+ #t;
414
+ #n;
415
+ #r;
416
+ #i = 0;
417
+ #a;
418
+ get end() {
419
+ return this.#t;
420
+ }
421
+ clear(e = 0) {
422
+ this.#e = 0, this.#t = void 0, this.#i = e, this.#o();
423
+ }
424
+ update(e) {
425
+ let t = e.discontinuity !== this.#e;
426
+ return t && (this.#e = e.discontinuity, this.#t = void 0, this.#o()), e.frame && e.group !== this.#n && (this.#t = void 0), e.frame && this.#r === void 0 && (this.#r = e.frame.timestamp), e.end !== void 0 && (this.#t = e.end, this.#n = e.group), t;
427
+ }
428
+ span(e) {
429
+ let t = this.#r ?? e.timestamp;
430
+ this.#r = t;
431
+ let n = Math.floor(this.#i * e.sampleRate / 48e3), r = this.#a ?? n, i = Math.min(r, e.numberOfFrames);
432
+ this.#a = r - i;
433
+ let a = Math.round(n * 1e6 / e.sampleRate), o = Math.max(t, e.timestamp - a), s = e.numberOfFrames - i;
434
+ if (this.#t !== void 0) {
435
+ if (this.#t <= o) s = 0;
436
+ else {
437
+ let t = this.#t - o, n = Math.round(t * e.sampleRate / 1e6);
438
+ s = Math.min(s, n);
439
+ }
440
+ }
441
+ return {
442
+ timestamp: o,
443
+ frameOffset: i,
444
+ frames: s
445
+ };
446
+ }
447
+ #o() {
448
+ this.#r = void 0, this.#a = void 0;
449
+ }
450
+ }, Ee = class {
451
+ #e;
452
+ constructor(e) {
453
+ this.#e = e;
454
+ }
455
+ drop() {
456
+ return this.#e !== 0 && (this.#e--, !0);
457
+ }
458
+ }, De = 3, j = class {
459
+ in;
460
+ source;
461
+ sync;
462
+ #e = {
463
+ context: new a(void 0),
464
+ root: new a(void 0),
465
+ sampleRate: new a(void 0),
466
+ stats: new a(void 0),
467
+ timestamp: new a(void 0),
468
+ stalled: new a(!0),
469
+ buffered: new a([])
470
+ };
471
+ out = s(this.#e);
472
+ #t = new a([]);
473
+ #n;
474
+ #r = new a(void 0);
475
+ #i = new Te();
476
+ #a = new xe();
477
+ #o = new i();
478
+ #s;
479
+ #c;
480
+ constructor(e) {
481
+ this.in = { enabled: o(e?.enabled ?? !0) }, this.source = e.source, this.sync = e.sync, this.#o.cleanup(this.sync.register(this.source.out.jitter)), this.#s = this.#o.computed((e) => {
482
+ let t = e.get(this.source.out.config);
483
+ return t ? ve(t) : void 0;
484
+ }), this.#c = this.#o.computed((e) => {
485
+ let t = e.get(this.source.out.config);
486
+ return t ? k(t) : void 0;
487
+ }), this.#o.run(this.#l.bind(this)), this.#o.run(this.#u.bind(this)), this.#o.run(this.#d.bind(this)), this.#o.run(this.#f.bind(this));
488
+ }
489
+ #l(e) {
490
+ let t = e.get(this.#c);
491
+ if (!t) return;
492
+ let n = e.get(this.#r) ?? t.sampleRate, i = t.numberOfChannels;
493
+ e.set(this.#e.sampleRate, n);
494
+ let a = new AudioContext({
495
+ latencyHint: "interactive",
496
+ sampleRate: n
497
+ });
498
+ e.set(this.#e.context, a), e.cleanup(() => a.close()), e.spawn(async () => {
499
+ if (!await e.race(a.audioWorklet.addModule(we).then(() => !0))) return;
500
+ let t = new AudioWorkletNode(a, "render", {
501
+ channelCount: i,
502
+ channelCountMode: "explicit",
503
+ outputChannelCount: [i]
504
+ });
505
+ e.cleanup(() => t.disconnect());
506
+ let o = this.sync.out.delay.peek(), s = A(n, o), c = this.sync.out.buffered.peek(), l = le(t, i, n, s, c);
507
+ this.#n = l, e.cleanup(() => {
508
+ l.close(), this.#n = void 0;
509
+ }), e.run((e) => {
510
+ let t = r.Milli.fromMicro(e.get(l.timestamp));
511
+ this.#e.timestamp.set(t), this.#v(t);
512
+ }), e.run((e) => {
513
+ this.#e.stalled.set(e.get(l.stalled));
514
+ }), e.set(this.#e.root, t);
515
+ });
516
+ }
517
+ #u(e) {
518
+ if (!e.get(this.in.enabled)) return;
519
+ if (e.get(this.sync.in.delay) === "instant") {
520
+ this.reset();
521
+ return;
522
+ }
523
+ let t = e.get(this.#e.context);
524
+ t && d.Gesture.unlock(e, t);
525
+ }
526
+ #d(e) {
527
+ if (!e.get(this.#e.root)) return;
528
+ let t = this.#n;
529
+ if (!t) return;
530
+ let n = e.get(this.sync.out.delay);
531
+ t.setLatency(A(t.rate, n));
532
+ }
533
+ #f(e) {
534
+ if (!e.get(this.in.enabled) || e.get(this.sync.in.delay) === "instant") return;
535
+ let t = e.get(this.source.in.broadcast);
536
+ if (!t) return;
537
+ let n = e.get(this.source.out.track);
538
+ if (!n) return;
539
+ let r = e.get(this.#s);
540
+ if (!r) return;
541
+ let i = r.decoder, a = t.relativeBroadcast(e, r.broadcast);
542
+ if (!a) return;
543
+ this.#a.opened();
544
+ let o = _(e, {
545
+ broadcast: a,
546
+ track: n,
547
+ priority: c.PRIORITY.audio,
548
+ maxAge: this.sync.out.maxAge
549
+ });
550
+ o && (i.container.kind === "cmaf" ? this.#m(e, o, i) : this.#p(e, o, i));
551
+ }
552
+ #p(e, t, n) {
553
+ let i = n.codec === "opus" && n.description ? d.Opus.preSkip(d.Hex.toBytes(n.description)) : 0;
554
+ this.#i.clear(i);
555
+ let a = n.container.kind === "loc" ? new u.Loc.Format("audio") : new u.Legacy.Format(n), o = new u.Consumer(t, {
556
+ format: a,
557
+ maxAge: this.sync.out.maxAge
558
+ });
559
+ e.cleanup(() => o.close()), e.run((e) => {
560
+ let t = e.get(o.buffered), n = e.get(this.#t);
561
+ this.#e.buffered.update(() => u.mergeBufferedRanges(t, n));
562
+ }), e.spawn(async () => {
563
+ if (!await d.Libav.polyfill()) return;
564
+ let t = new Ee(De), i = new AudioDecoder({
565
+ output: (e) => {
566
+ let n = this.#i.span(e);
567
+ if (t.drop()) {
568
+ e.close();
569
+ return;
570
+ }
571
+ this.#h(e, n);
572
+ },
573
+ error: (e) => console.error("audio decoder error", e)
574
+ });
575
+ e.cleanup(() => {
576
+ i.state !== "closed" && i.close();
577
+ });
578
+ let a = n.codec === "opus" ? void 0 : n.description ? d.Hex.toBytes(n.description) : void 0, s = {
579
+ codec: n.codec,
580
+ sampleRate: n.sampleRate,
581
+ numberOfChannels: n.numberOfChannels,
582
+ description: a
583
+ };
584
+ for (i.configure(s);;) {
585
+ let e = await v(o);
586
+ if (!e) break;
587
+ if (this.#y(e) && (i.reset(), i.configure(s)), e.end !== void 0) continue;
588
+ let { frame: t } = e;
589
+ if (!t) continue;
590
+ let n = r.Milli.fromMicro(t.timestamp);
591
+ this.sync.received(n, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) + t.payload.byteLength })), await this.#n?.wait(t.timestamp);
592
+ let a = new EncodedAudioChunk({
593
+ type: t.keyframe ? "key" : "delta",
594
+ data: t.payload,
595
+ timestamp: t.timestamp
596
+ });
597
+ if (i.state === "closed") break;
598
+ i.decode(a);
599
+ }
600
+ });
601
+ }
602
+ #m(e, t, n) {
603
+ if (n.container.kind !== "cmaf") return;
604
+ let i = g(n.container.init), a = u.Cmaf.decodeInitSegment(i), o = n.description ? d.Hex.toBytes(n.description) : a.description, s = n.codec === "opus" && o ? d.Opus.preSkip(o) : 0;
605
+ this.#i.clear(s);
606
+ let c = n.codec === "opus" ? void 0 : n.description ? d.Hex.toBytes(n.description) : a.description, l = new u.Consumer(t, {
607
+ format: new u.Cmaf.Format(a),
608
+ maxAge: this.sync.out.maxAge
609
+ });
610
+ e.cleanup(() => l.close()), e.run((e) => {
611
+ let t = e.get(l.buffered), n = e.get(this.#t);
612
+ this.#e.buffered.update(() => u.mergeBufferedRanges(t, n));
613
+ }), e.spawn(async () => {
614
+ if (!await d.Libav.polyfill()) return;
615
+ let t = new AudioDecoder({
616
+ output: (e) => this.#h(e),
617
+ error: (e) => console.error("audio decoder error", e)
618
+ });
619
+ e.cleanup(() => {
620
+ t.state !== "closed" && t.close();
621
+ });
622
+ let i = {
623
+ codec: n.codec,
624
+ sampleRate: n.sampleRate,
625
+ numberOfChannels: n.numberOfChannels,
626
+ description: c
627
+ };
628
+ for (t.configure(i);;) {
629
+ let e = await v(l);
630
+ if (!e) break;
631
+ this.#y(e) && (t.reset(), t.configure(i));
632
+ let { frame: n } = e;
633
+ if (!n) continue;
634
+ let a = r.Milli.fromMicro(n.timestamp);
635
+ if (this.sync.received(a, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) + n.payload.byteLength })), await this.#n?.wait(n.timestamp), t.state === "closed") break;
636
+ t.decode(new EncodedAudioChunk({
637
+ type: n.keyframe ? "key" : "delta",
638
+ data: n.payload,
639
+ timestamp: n.timestamp
640
+ }));
641
+ }
642
+ });
643
+ }
644
+ #h(e, t = this.#i.span(e)) {
645
+ let { timestamp: n, frameOffset: i, frames: a } = t, o = r.Milli.fromMicro(n);
646
+ if (a === 0) {
647
+ e.close();
648
+ return;
649
+ }
650
+ let s = this.#n;
651
+ if (!s) {
652
+ e.close();
653
+ return;
654
+ }
655
+ if (e.sampleRate !== s.rate) {
656
+ this.#r.set(e.sampleRate), e.close();
657
+ return;
658
+ }
659
+ let c = a / e.sampleRate * 1e6, l = r.Milli.fromMicro(c), u = r.Milli.add(o, l);
660
+ this.#a.takeover() && (s.truncate(n), this.#_(o)), this.#g(o, u);
661
+ let d = Math.min(e.numberOfChannels, s.channels), f = [];
662
+ for (let t = 0; t < d; t++) {
663
+ let n = new Float32Array(a);
664
+ e.copyTo(n, {
665
+ format: "f32-planar",
666
+ planeIndex: t,
667
+ frameOffset: i,
668
+ frameCount: a
669
+ }), f.push(n);
670
+ }
671
+ s.insert(n, f), e.close();
672
+ }
673
+ #g(e, t) {
674
+ e > t || this.#t.mutate((n) => {
675
+ for (let i of n) if (e <= i.end + 1 && t >= i.start) {
676
+ i.start = r.Milli.min(i.start, e), i.end = r.Milli.max(i.end, t);
677
+ return;
678
+ }
679
+ n.push({
680
+ start: e,
681
+ end: t
682
+ }), n.sort((e, t) => e.start - t.start);
683
+ });
684
+ }
685
+ #_(e) {
686
+ this.#t.mutate((t) => {
687
+ for (; t.length > 0 && t[t.length - 1].start >= e;) t.pop();
688
+ let n = t[t.length - 1];
689
+ n && n.end > e && (n.end = e);
690
+ });
691
+ }
692
+ #v(e) {
693
+ this.#t.mutate((t) => {
694
+ for (; t.length > 0;) {
695
+ if (t[0].end >= e) {
696
+ t[0].start = r.Milli.max(t[0].start, e);
697
+ break;
698
+ }
699
+ t.shift();
700
+ }
701
+ });
702
+ }
703
+ reset() {
704
+ this.#n?.reset();
705
+ }
706
+ #y(e) {
707
+ return this.#i.update(e) ? (this.#n?.reset(), this.sync.reset(), !0) : !1;
708
+ }
709
+ close() {
710
+ this.#o.close();
711
+ }
712
+ static supported = Oe;
713
+ };
714
+ async function Oe(e) {
715
+ if (!c.containerSupported(e.container)) {
716
+ let t = e.container.kind === "unknown" ? e.container.raw.kind : e.container.kind;
717
+ return console.warn(`audio: ignoring rendition with unknown container: ${t}`), !1;
718
+ }
719
+ e.codec === "opus" && !d.Opus.supportsRate(e.sampleRate) && console.warn(`audio: opus advertised at ${e.sampleRate}Hz, which some browsers cannot decode`);
720
+ let t;
721
+ if (e.codec !== "opus") {
722
+ if (e.description) t = d.Hex.toBytes(e.description);
723
+ else if (e.container.kind === "cmaf") try {
724
+ t = u.Cmaf.decodeInitSegment(g(e.container.init)).description;
725
+ } catch (t) {
726
+ return console.warn(`audio: malformed CMAF init segment for codec ${e.codec}`, t), !1;
727
+ }
728
+ }
729
+ return (await AudioDecoder.isConfigSupported({
730
+ ...e,
731
+ description: t
732
+ })).supported ?? !1;
733
+ }
734
+ //#endregion
735
+ //#region src/audio/emitter.ts
736
+ var ke = .001, M = .2, Ae = class {
737
+ source;
738
+ in;
739
+ #e = { enabled: new a(!1) };
740
+ out = s(this.#e);
741
+ #t = new i();
742
+ #n = new a(void 0);
743
+ constructor(e) {
744
+ this.source = e.source, this.in = {
745
+ volume: o(e?.volume ?? .5),
746
+ muted: o(e?.muted ?? !1),
747
+ paused: o(e?.paused ?? !1)
748
+ }, this.#t.run((e) => {
749
+ let t = !e.get(this.in.paused) && !e.get(this.in.muted);
750
+ this.#e.enabled.set(t);
751
+ }), this.#t.run((e) => {
752
+ let t = e.get(this.source.out.root);
753
+ if (!t) return;
754
+ let n = new GainNode(t.context, { gain: e.get(this.in.volume) });
755
+ t.connect(n), e.set(this.#n, n), e.run((e) => {
756
+ e.get(this.#e.enabled) && (n.connect(t.context.destination), e.cleanup(() => n.disconnect()));
757
+ });
758
+ }), this.#t.run((e) => {
759
+ let t = e.get(this.#n);
760
+ if (!t) return;
761
+ e.cleanup(() => t.gain.cancelScheduledValues(t.context.currentTime));
762
+ let n = e.get(this.in.volume);
763
+ n < ke ? (t.gain.exponentialRampToValueAtTime(ke, t.context.currentTime + M), t.gain.setValueAtTime(0, t.context.currentTime + M + .01)) : t.gain.exponentialRampToValueAtTime(n, t.context.currentTime + M);
764
+ });
765
+ }
766
+ close() {
767
+ this.#t.close();
768
+ }
769
+ }, N = class {
770
+ in;
771
+ #e = {
772
+ catalog: new a(void 0),
773
+ available: new a({}),
774
+ track: new a(void 0),
775
+ config: new a(void 0),
776
+ jitter: new a(void 0)
777
+ };
778
+ out = s(this.#e);
779
+ #t = new i();
780
+ constructor(e) {
781
+ this.in = {
782
+ broadcast: o(e?.broadcast),
783
+ target: o(e?.target),
784
+ supported: o(e?.supported)
785
+ }, this.#t.run(this.#n.bind(this)), this.#t.run(this.#r.bind(this)), this.#t.run(this.#i.bind(this));
786
+ }
787
+ #n(e) {
788
+ let t = e.get(this.in.broadcast);
789
+ if (!t) return;
790
+ let n = e.get(t.out.catalog)?.audio;
791
+ n && e.set(this.#e.catalog, n);
792
+ }
793
+ #r(e) {
794
+ let t = e.get(this.#e.catalog)?.renditions ?? {}, n = e.get(this.in.supported);
795
+ n && e.spawn(async () => {
796
+ let r = {};
797
+ for (let [i, a] of Object.entries(t)) {
798
+ let t = await e.race(n(a));
799
+ if (e.abort.aborted) return;
800
+ t && (r[i] = a);
801
+ }
802
+ Object.keys(r).length === 0 && Object.keys(t).length > 0 && console.warn("no supported audio renditions found:", t), this.#e.available.set(r);
803
+ });
804
+ }
805
+ #i(e) {
806
+ let t = e.get(this.#e.available);
807
+ if (Object.keys(t).length === 0) return;
808
+ let n = e.get(this.in.target), r;
809
+ if (n?.name && n.name in t) r = {
810
+ track: n.name,
811
+ config: t[n.name]
812
+ };
813
+ else if (r = this.#a(t), !r) return;
814
+ e.set(this.#e.track, r.track), e.set(this.#e.config, r.config), e.set(this.#e.jitter, ye(r.config));
815
+ }
816
+ #a(e) {
817
+ let t = Object.entries(e);
818
+ if (t.length !== 0) {
819
+ for (let [e, n] of t) if (n.container.kind === "legacy") return {
820
+ track: e,
821
+ config: n
822
+ };
823
+ for (let [e, n] of t) if (n.container.kind === "loc") return {
824
+ track: e,
825
+ config: n
826
+ };
827
+ for (let [e, n] of t) if (n.container.kind === "cmaf") return {
828
+ track: e,
829
+ config: n
830
+ };
831
+ }
832
+ }
833
+ close() {
834
+ this.#t.close();
835
+ }
836
+ }, je = 48e3, P = 2;
837
+ function Me(e) {
838
+ let t = "";
839
+ for (let n = 0; n < e.length; n++) t += e[n].toString(16).padStart(2, "0");
840
+ return t;
841
+ }
842
+ function F(e) {
843
+ let t;
844
+ try {
845
+ t = e.initData ? g(e.initData) : void 0;
846
+ } catch {
847
+ t = void 0;
848
+ }
849
+ let n = t ? Me(t) : void 0;
850
+ switch (e.packaging) {
851
+ case "cmaf": return !e.initData || !t ? void 0 : {
852
+ container: {
853
+ kind: "cmaf",
854
+ init: e.initData
855
+ },
856
+ description: void 0
857
+ };
858
+ case "loc": return {
859
+ container: { kind: "loc" },
860
+ description: n
861
+ };
862
+ case "legacy": return {
863
+ container: { kind: "legacy" },
864
+ description: n
865
+ };
866
+ default: return;
867
+ }
868
+ }
869
+ function I(e) {
870
+ if (!(e <= 0)) return l(Math.ceil(e));
871
+ }
872
+ function Ne(e) {
873
+ if (!e.codec) return;
874
+ let t = F(e);
875
+ if (!t) return;
876
+ let { container: n, description: r } = t;
877
+ return {
878
+ codec: e.codec,
879
+ container: n,
880
+ description: r,
881
+ codedWidth: e.width == null ? void 0 : l(e.width),
882
+ codedHeight: e.height == null ? void 0 : l(e.height),
883
+ framerate: e.framerate,
884
+ bitrate: e.bitrate == null ? void 0 : l(e.bitrate),
885
+ stalled: e.stalled,
886
+ jitter: e.jitter == null ? void 0 : l(e.jitter),
887
+ delay: e.delay == null ? void 0 : I(e.delay)
888
+ };
889
+ }
890
+ function Pe(e) {
891
+ if (!e.codec) return;
892
+ let t = (() => {
893
+ if (!e.channelConfig) return P;
894
+ let t = Number.parseInt(e.channelConfig, 10);
895
+ return Number.isFinite(t) ? t : P;
896
+ })(), n = F(e);
897
+ if (!n) return;
898
+ let { container: r, description: i } = n;
899
+ return {
900
+ codec: e.codec,
901
+ container: r,
902
+ description: i,
903
+ sampleRate: l(e.samplerate ?? je),
904
+ numberOfChannels: l(t),
905
+ bitrate: e.bitrate == null ? void 0 : l(e.bitrate),
906
+ jitter: e.jitter == null ? void 0 : l(e.jitter),
907
+ delay: e.delay == null ? void 0 : I(e.delay),
908
+ language: e.lang
909
+ };
910
+ }
911
+ function Fe(e) {
912
+ let t = {}, n = {};
913
+ for (let r of e.tracks) if (r.role === "video") {
914
+ let e = Ne(r);
915
+ e && (t[r.name] = e);
916
+ } else if (r.role === "audio") {
917
+ let e = Pe(r);
918
+ e && (n[r.name] = e);
919
+ }
920
+ let r = {};
921
+ return Object.keys(t).length > 0 && (r.video = { renditions: t }), Object.keys(n).length > 0 && (r.audio = { renditions: n }), r;
922
+ }
923
+ //#endregion
924
+ //#region src/broadcast.ts
925
+ function L(e, t) {
926
+ return Object.fromEntries(Object.entries(e).filter(([, e]) => t(e.broadcast)));
927
+ }
928
+ function Ie(e, t) {
929
+ return {
930
+ ...e,
931
+ video: e.video ? {
932
+ ...e.video,
933
+ renditions: L(e.video.renditions, t)
934
+ } : void 0,
935
+ audio: e.audio ? {
936
+ ...e.audio,
937
+ renditions: L(e.audio.renditions, t)
938
+ } : void 0,
939
+ text: e.text ? {
940
+ ...e.text,
941
+ renditions: L(e.text.renditions, t)
942
+ } : void 0,
943
+ json: e.json ? {
944
+ ...e.json,
945
+ tracks: L(e.json.tracks, t)
946
+ } : void 0,
947
+ binary: e.binary ? {
948
+ ...e.binary,
949
+ tracks: L(e.binary.tracks, t)
950
+ } : void 0
951
+ };
952
+ }
953
+ var Le = [
954
+ ...c.FORMATS,
955
+ "hangz",
956
+ "manual"
957
+ ], R = class {
958
+ in;
959
+ #e = {
960
+ status: new a("offline"),
961
+ active: new a(void 0),
962
+ catalog: new a(void 0)
963
+ };
964
+ out = s(this.#e);
965
+ #t = new a(void 0);
966
+ #n = new a(!1);
967
+ #r = new a(void 0);
968
+ #i;
969
+ constructor(e) {
970
+ if (e && "reload" in e) throw Error("Watch.Broadcast: `reload` was renamed to `announced`");
971
+ this.#i = new i(), this.in = {
972
+ origin: o(e?.origin),
973
+ name: o(e?.name ?? n.empty()),
974
+ enabled: o(e?.enabled ?? !0),
975
+ announced: o(e?.announced ?? !0),
976
+ catalogFormat: o(e?.catalogFormat),
977
+ catalog: o(e?.catalog)
978
+ }, this.#i.run(this.#a.bind(this)), this.#i.run(this.#l.bind(this)), this.#i.run(this.#u.bind(this)), this.#i.run(this.#o.bind(this));
979
+ }
980
+ #a(t) {
981
+ if (this.#t.set(void 0), !t.get(this.#n) || !t.get(this.in.announced)) return;
982
+ let n = t.get(this.in.origin);
983
+ if (!n) return;
984
+ let r = n.announced();
985
+ t.cleanup(() => r.close()), this.#t.set(/* @__PURE__ */ new Set()), t.spawn(async () => {
986
+ for (;;) {
987
+ let n = await t.race(r.next());
988
+ if (!n) break;
989
+ this.#t.mutate((t) => {
990
+ t && (e.isActive(n.kind) ? t.add(n.prefix) : t.delete(n.prefix));
991
+ });
992
+ }
993
+ });
994
+ }
995
+ #o(e) {
996
+ let t = e.get(this.#r);
997
+ e.set(this.#e.catalog, t ? Ie(t, (t) => this.#d(e, t) !== void 0) : void 0);
998
+ }
999
+ #s(e, t) {
1000
+ this.#n.set(!0);
1001
+ let r = e.get(this.#t);
1002
+ if (!r) return !1;
1003
+ if (r.has(t)) return !0;
1004
+ for (let e of r) if (n.hasPrefix(e, t)) return !0;
1005
+ return !1;
1006
+ }
1007
+ #c(e, t, n) {
1008
+ let r = t.request(n);
1009
+ return e.cleanup(() => r.close()), e.get(r.active);
1010
+ }
1011
+ #l(e) {
1012
+ if (!e.get(this.in.enabled)) return;
1013
+ let t = e.get(this.in.origin);
1014
+ if (!t) return;
1015
+ let n = e.get(this.in.name);
1016
+ if (!e.get(this.in.announced)) {
1017
+ e.set(this.#e.active, this.#c(e, t, n), void 0);
1018
+ return;
1019
+ }
1020
+ let r = t.request(n, { announced: !0 });
1021
+ e.cleanup(() => r.close()), e.run((e) => {
1022
+ e.set(this.#e.active, e.get(r.active), void 0);
1023
+ });
1024
+ }
1025
+ #u(e) {
1026
+ if (!e.get(this.in.enabled)) return;
1027
+ let n = e.get(this.in.catalogFormat), r = e.get(this.in.name), i = n ?? c.detectFormat(r) ?? c.DEFAULT_FORMAT;
1028
+ if (i === "manual") {
1029
+ let t = e.get(this.in.catalog), n;
1030
+ try {
1031
+ n = t && c.checkResolvable(c.checkRenditions(t), r);
1032
+ } catch (e) {
1033
+ console.error("rejecting catalog", r, e);
1034
+ }
1035
+ this.#r.set(n, !0), e.cleanup(() => this.#r.set(void 0, !0)), this.#e.status.set(n ? "live" : "loading");
1036
+ return;
1037
+ }
1038
+ let a = e.get(this.out.active);
1039
+ if (!a || e.get(a.closed) !== void 0) return;
1040
+ this.#e.status.set("loading");
1041
+ let o = i === "hang" ? c.TRACK : i === "hangz" ? c.TRACK_COMPRESSED : "catalog", s = a.track(o).subscribe({ priority: c.PRIORITY.catalog });
1042
+ e.cleanup(() => s.close());
1043
+ let l;
1044
+ if (i === "hang" || i === "hangz") {
1045
+ let e = new f.Snapshot.Consumer({
1046
+ track: s,
1047
+ schema: c.RootSchema,
1048
+ compression: i === "hangz" ? "deflate" : "none"
1049
+ });
1050
+ l = () => e.next();
1051
+ } else {
1052
+ let e = s.ordered();
1053
+ l = async () => {
1054
+ let t = await p.fetch(e);
1055
+ return t ? Fe(t) : void 0;
1056
+ };
1057
+ }
1058
+ e.spawn(async () => {
1059
+ try {
1060
+ for (;;) {
1061
+ let t = await e.race(l());
1062
+ if (!t) break;
1063
+ console.debug("received catalog", i, this.in.name.peek(), t), this.#r.set(c.checkResolvable(c.checkRenditions(t), r), !0), this.#e.status.set("live");
1064
+ }
1065
+ } catch (e) {
1066
+ e instanceof t.Stream ? console.debug("catalog subscription ended", this.in.name.peek(), e) : console.error("error fetching catalog", this.in.name.peek(), e);
1067
+ } finally {
1068
+ this.#r.set(void 0), this.#e.status.set("offline");
1069
+ }
1070
+ });
1071
+ }
1072
+ #d(e, t) {
1073
+ if (!t) return { local: !0 };
1074
+ let r = e.get(this.in.name), i = n.tryResolve(r, t);
1075
+ if (i === void 0) {
1076
+ console.warn("ignoring rendition: broadcast reference escapes the root", r, t);
1077
+ return;
1078
+ }
1079
+ if (i === r) return { local: !0 };
1080
+ let a = e.get(this.in.origin);
1081
+ if (!a || !(e.get(this.in.announced) && e.get(a.discovery) !== !1 && !this.#s(e, i))) return {
1082
+ local: !1,
1083
+ path: i
1084
+ };
1085
+ }
1086
+ relativeBroadcast(e, t) {
1087
+ let n = this.#d(e, t);
1088
+ if (!n) return;
1089
+ if (n.local) return e.get(this.out.active);
1090
+ if (!e.get(this.in.enabled)) return;
1091
+ let r = e.get(this.in.origin);
1092
+ if (r) return this.#c(e, r, n.path);
1093
+ }
1094
+ close() {
1095
+ this.#i.close();
1096
+ }
1097
+ }, Re = r.Milli(20), z = r.Milli(100), B = class e {
1098
+ in;
1099
+ #e = {
1100
+ reference: new a(void 0),
1101
+ delay: new a(r.Milli.zero),
1102
+ jitter: new a(z),
1103
+ timestamp: new a(void 0),
1104
+ buffered: new a(!1),
1105
+ maxAge: new a(r.Milli.zero)
1106
+ };
1107
+ out = s(this.#e);
1108
+ #t = /* @__PURE__ */ new Map();
1109
+ #n;
1110
+ #r = new a([]);
1111
+ #i = new i();
1112
+ constructor(e) {
1113
+ this.in = {
1114
+ delay: o(e?.delay ?? "auto"),
1115
+ buffer: o(e?.buffer ?? r.Milli.zero),
1116
+ probe: o(e?.probe)
1117
+ }, this.#i.run(this.#o.bind(this)), this.#i.run(this.#s.bind(this)), this.#i.run(this.#a.bind(this));
1118
+ }
1119
+ register(e) {
1120
+ let t = { jitter: e };
1121
+ return this.#r.update((e) => [...e, t]), () => this.#r.update((e) => e.filter((e) => e !== t));
1122
+ }
1123
+ #a(e) {
1124
+ let t = e.get(this.#e.delay), n = e.get(this.in.delay) === "instant" ? r.Milli.zero : e.get(this.in.buffer);
1125
+ this.#e.buffered.set(n > 0), this.#e.maxAge.set(r.Milli.add(t, n));
1126
+ }
1127
+ #o(e) {
1128
+ let t = e.get(this.in.delay);
1129
+ if (t === "instant") {
1130
+ this.#n = void 0, this.#e.jitter.set(r.Milli.zero);
1131
+ return;
1132
+ }
1133
+ if (typeof t == "number") {
1134
+ this.#n = void 0, this.#e.jitter.set(t);
1135
+ return;
1136
+ }
1137
+ let n = e.get(this.in.probe)?.rtt;
1138
+ if (n !== void 0) {
1139
+ this.#n = this.#n === void 0 ? n : Math.min(this.#n, n);
1140
+ let e = r.Milli(Math.max(Re, this.#n * 1.25));
1141
+ this.#e.jitter.set(e);
1142
+ return;
1143
+ }
1144
+ this.#n = void 0, this.#e.jitter.set(z);
1145
+ }
1146
+ #s(e) {
1147
+ let t = e.get(this.#e.jitter), n = r.Milli.zero;
1148
+ for (let t of e.get(this.#r)) n = r.Milli.max(n, e.get(t.jitter) ?? r.Milli.zero);
1149
+ let i = e.get(this.in.delay) === "instant" ? r.Milli.zero : r.Milli.add(n, t);
1150
+ this.#e.delay.set(i);
1151
+ }
1152
+ received(t, n = "") {
1153
+ this.#e.timestamp.update((e) => e === void 0 || t > e ? t : e);
1154
+ let i = r.Milli.now(), a = r.Milli.sub(i, t), o = this.#e.reference.peek();
1155
+ if (o === void 0) {
1156
+ this.#e.reference.set(a);
1157
+ return;
1158
+ }
1159
+ let s = this.#e.delay.peek(), c = r.Milli.add(r.Milli.sub(o, a), s);
1160
+ if (c < 0) {
1161
+ let e = this.#t.get(n);
1162
+ e ? (e.count++, e.maxMs = Math.max(e.maxMs, -c)) : this.#t.set(n, {
1163
+ count: 1,
1164
+ maxMs: -c
1165
+ });
1166
+ } else {
1167
+ let t = this.#t.get(n);
1168
+ if (t) {
1169
+ let r = n ? `sync[${n}]` : "sync", i = e.#l(t.maxMs);
1170
+ console.debug(`${r}: ${t.count} late frame(s), max ${i} behind`), this.#t.delete(n);
1171
+ }
1172
+ }
1173
+ if (a >= o) return;
1174
+ let l = this.#e.maxAge.peek();
1175
+ c <= l || this.#e.reference.set(r.Milli.add(a, r.Milli.sub(l, s)));
1176
+ }
1177
+ reset() {
1178
+ this.#e.reference.set(void 0), this.#t.clear();
1179
+ }
1180
+ now() {
1181
+ let e = this.#e.reference.peek();
1182
+ if (e !== void 0) return r.Milli.sub(r.Milli.sub(r.Milli.now(), e), this.#e.delay.peek());
1183
+ }
1184
+ async wait(e) {
1185
+ if (this.in.delay.peek() !== "instant") {
1186
+ if (this.#e.reference.peek() === void 0) throw Error("reference not set; call received() first");
1187
+ for (;;) {
1188
+ if (this.in.delay.peek() === "instant") return;
1189
+ let t = r.Milli.now(), n = r.Milli.sub(t, e), i = this.#e.reference.peek();
1190
+ if (i === void 0) return;
1191
+ let a = r.Milli.add(r.Milli.sub(i, n), this.#e.delay.peek());
1192
+ if (a <= 0 || a < 5 || await this.#c(a)) return;
1193
+ }
1194
+ }
1195
+ }
1196
+ #c(e) {
1197
+ return new Promise((t) => {
1198
+ let n = (e) => {
1199
+ clearTimeout(r);
1200
+ for (let e of i) e();
1201
+ t(e);
1202
+ }, r = setTimeout(() => n(!0), e), i = [
1203
+ this.in.delay.changed(() => n(!1)),
1204
+ this.#e.delay.changed(() => n(!1)),
1205
+ this.#e.reference.changed(() => n(!1))
1206
+ ];
1207
+ });
1208
+ }
1209
+ static #l(e) {
1210
+ if (e = Math.round(e), e < 1e3) return `${e}ms`;
1211
+ let t = e / 1e3;
1212
+ if (t < 60) return `${Math.round(t * 10) / 10}s`;
1213
+ let n = t / 60;
1214
+ return `${Math.round(n * 10) / 10}m`;
1215
+ }
1216
+ close() {
1217
+ this.#i.close();
1218
+ }
1219
+ }, ze = ":where([part=captions]){--overlay-padding:1%;--cue-color:white;--cue-bg-color:#000c;--cue-font-size:calc(var(--overlay-height) / 100 * 5);--cue-line-height:calc(var(--cue-font-size) * 1.2);--cue-padding-x:calc(var(--cue-font-size) * .6);--cue-padding-y:calc(var(--cue-font-size) * .4);z-index:1;contain:content;margin:var(--overlay-padding);font-size:var(--cue-font-size);box-sizing:border-box;pointer-events:none;user-select:none;word-spacing:normal;word-break:break-word;font-family:sans-serif;position:absolute;inset:0}:where([part=captions]>[part=cue-display]){contain:content;top:var(--cue-top);left:var(--cue-left);right:var(--cue-right);bottom:var(--cue-bottom);width:var(--cue-width,auto);height:var(--cue-height,auto);box-sizing:border-box;transform:var(--cue-transform);text-align:var(--cue-text-align);writing-mode:var(--cue-writing-mode,unset);white-space:pre-line;direction:ltr;unicode-bidi:plaintext;min-width:min-content;min-height:min-content;position:absolute;overflow:visible}:where([data-dir=rtl] [part=cue-display]){direction:rtl}:where([part=captions] [part=cue]){padding:var(--cue-padding-y) var(--cue-padding-x);line-height:var(--cue-line-height);background-color:var(--cue-bg-color);box-sizing:border-box;color:var(--cue-color);box-shadow:var(--cue-box-shadow);white-space:var(--cue-white-space,pre-wrap);outline:var(--cue-outline);text-shadow:var(--cue-text-shadow);display:inline-block}:where([part=captions] [part=cue-display][data-vertical] [part=cue]){padding:var(--cue-padding-x) var(--cue-padding-y)}\n:where([part=captions] [part=region]){width:var(--region-width);height:var(--region-height);min-height:0;max-height:var(--region-height);writing-mode:horizontal-tb;top:calc(var(--region-top,var(--overlay-height) * var(--region-viewport-anchor-y) / 100 - var(--region-height) * var(--region-anchor-y) / 100));left:var(--region-left,calc(calc(var(--region-viewport-anchor-x) * 1%) - calc(var(--region-width) * var(--region-anchor-x) / 100)));right:var(--region-right);bottom:var(--region-bottom);overflow-wrap:break-word;box-sizing:border-box;flex-flow:column;justify-content:flex-start;display:inline-flex;position:absolute;overflow:hidden}:where([part=captions] [part=region][data-scroll=up]){justify-content:end}:where([part=captions] [part=region][data-active][data-scroll=up]){transition:top .433s}:where([part=captions] [part=region]>[part=cue-display]){width:auto;left:var(--cue-offset);height:var(--cue-height,auto);text-align:var(--cue-text-align);unicode-bidi:plaintext;margin-top:1px;position:relative}:where([part=captions] [part=region] [part=cue]){padding:calc(var(--cue-padding-y) / 2) var(--cue-padding-x);border-radius:0;position:relative}", Be = r.Milli(3e4), Ve = r.Milli(3e4), He = r.Milli(1e3);
1220
+ function V(e) {
1221
+ return e.replaceAll("&", "&amp;amp;").replaceAll("<", "&amp;lt;").replaceAll(">", "&amp;gt;").replaceAll("\"", "&amp;quot;");
1222
+ }
1223
+ function H(e, t) {
1224
+ let n = e.length;
1225
+ for (; n > 0 && e[n - 1].startTime > t.startTime;) n--;
1226
+ e.splice(n, 0, t);
1227
+ }
1228
+ function U(e, t) {
1229
+ let { cues: n, clears: r } = e, i = 0;
1230
+ for (let e of r) e >= t && (r[i++] = e);
1231
+ r.length = i;
1232
+ let a = 0;
1233
+ for (let e of n) e.endTime >= t && (n[a++] = e);
1234
+ return a !== n.length && (n.length = a, !0);
1235
+ }
1236
+ function W(e, t) {
1237
+ let { cues: n, clears: r } = e, i = n.indexOf(t), a = i > 0 ? n[i - 1] : void 0;
1238
+ a && a.endTime > t.startTime && (a.endTime = t.startTime);
1239
+ let o = n[i + 1];
1240
+ o && t.endTime > o.startTime && (t.endTime = o.startTime);
1241
+ let s = r.find((e) => e > t.startTime);
1242
+ s !== void 0 && t.endTime > s && (t.endTime = s);
1243
+ }
1244
+ function G(e, t) {
1245
+ let { cues: n, clears: r } = e, i = r.length;
1246
+ for (; i > 0 && r[i - 1] > t;) i--;
1247
+ r[i] !== t && r.splice(i, 0, t);
1248
+ for (let e = n.length - 1; e >= 0; e--) {
1249
+ let r = n[e];
1250
+ if (!(r.startTime > t)) {
1251
+ r.endTime > t && (r.endTime = t);
1252
+ return;
1253
+ }
1254
+ }
1255
+ }
1256
+ var K = class {
1257
+ source;
1258
+ sync;
1259
+ in;
1260
+ #e = new i();
1261
+ #t = !1;
1262
+ constructor(e) {
1263
+ this.source = e.source, this.sync = e.sync, this.in = {
1264
+ container: o(e?.container),
1265
+ enabled: o(e?.enabled ?? !0)
1266
+ }, this.#e.run(this.#n.bind(this));
1267
+ }
1268
+ #n(e) {
1269
+ let n = e.getAll([
1270
+ this.in.enabled,
1271
+ this.in.container,
1272
+ this.source.out.track,
1273
+ this.source.out.config,
1274
+ this.source.in.broadcast
1275
+ ]);
1276
+ if (!n) return;
1277
+ let [r, i, a, o, s] = n, l = s.relativeBroadcast(e, o.broadcast);
1278
+ if (!l) return;
1279
+ this.#t = !1;
1280
+ let d;
1281
+ if (o.container.kind === "legacy") d = new u.Legacy.Format("data");
1282
+ else if (o.container.kind === "loc") d = new u.Loc.Format();
1283
+ else {
1284
+ console.warn(`captions: unsupported container "${o.container.kind}" for track ${a}`);
1285
+ return;
1286
+ }
1287
+ let f = document.createElement("style");
1288
+ f.textContent = ze, i.appendChild(f), e.cleanup(() => f.remove());
1289
+ let p = document.createElement("div");
1290
+ p.style.position = "absolute", p.style.inset = "0", p.style.pointerEvents = "none", i.appendChild(p), e.cleanup(() => p.remove());
1291
+ let m = new ee(p);
1292
+ e.cleanup(() => m.destroy());
1293
+ let h = _(e, {
1294
+ broadcast: l,
1295
+ track: a,
1296
+ priority: c.PRIORITY.text,
1297
+ maxAge: this.sync.out.maxAge
1298
+ });
1299
+ if (!h) return;
1300
+ let g = {
1301
+ cues: [],
1302
+ regions: /* @__PURE__ */ new Map(),
1303
+ clears: []
1304
+ }, v = () => m.changeTrack({
1305
+ cues: [...g.cues],
1306
+ regions: [...g.regions.values()]
1307
+ }), y = () => {
1308
+ let t = this.sync.now();
1309
+ t !== void 0 && (m.currentTime = t / 1e3, U(g, (t - Be) / 1e3) && v()), e.animate(y);
1310
+ };
1311
+ e.animate(y), e.spawn(async () => {
1312
+ for (;;) {
1313
+ let n = await h.recvGroup().catch((e) => {
1314
+ if (!(e instanceof t.Stream)) throw e;
1315
+ console.debug("captions subscription ended", e);
1316
+ });
1317
+ if (!n) break;
1318
+ e.spawn(async () => {
1319
+ try {
1320
+ for (;;) {
1321
+ let e = await n.readFrame();
1322
+ if (!e) break;
1323
+ for (let t of d.decode(e)) await this.#r(o.format, t, g);
1324
+ }
1325
+ } catch (e) {
1326
+ if (!(e instanceof t.Stream)) throw e;
1327
+ } finally {
1328
+ n.close();
1329
+ }
1330
+ v();
1331
+ });
1332
+ }
1333
+ });
1334
+ }
1335
+ async #r(e, t, n) {
1336
+ let r = new TextDecoder().decode(t.payload), i = t.timestamp / 1e6;
1337
+ if (e === "utf8") {
1338
+ if (r.length === 0) {
1339
+ G(n, i);
1340
+ return;
1341
+ }
1342
+ let e = new m(i, i + Ve / 1e3, V(r));
1343
+ H(n.cues, e), W(n, e);
1344
+ return;
1345
+ }
1346
+ if (r.length === 0) return;
1347
+ let a;
1348
+ try {
1349
+ a = await h(r, { type: "vtt" });
1350
+ } catch (e) {
1351
+ console.warn("captions: failed to parse VTT cue", e);
1352
+ return;
1353
+ }
1354
+ let o = a.cues.at(0);
1355
+ !this.#t && o && Math.abs(o.startTime - i) > He / 1e3 && (this.#t = !0, console.warn(`captions: cue timing is ${(o.startTime - i).toFixed(3)}s off its frame timestamp; the payload must carry absolute times on the media clock`));
1356
+ for (let e of a.regions) n.regions.set(e.id, e);
1357
+ for (let e of a.cues) e.text = V(e.text), H(n.cues, e);
1358
+ }
1359
+ close() {
1360
+ this.#e.close();
1361
+ }
1362
+ }, Ue = /* @__PURE__ */ new Set(["vtt", "utf8"]);
1363
+ function q(e) {
1364
+ return Ue.has(e.format);
1365
+ }
1366
+ var J = class {
1367
+ in;
1368
+ #e = {
1369
+ catalog: new a(void 0),
1370
+ available: new a({}),
1371
+ track: new a(void 0),
1372
+ config: new a(void 0)
1373
+ };
1374
+ out = s(this.#e);
1375
+ #t = new i();
1376
+ constructor(e) {
1377
+ this.in = {
1378
+ broadcast: o(e?.broadcast),
1379
+ target: o(e?.target)
1380
+ }, this.#t.run(this.#n.bind(this)), this.#t.run(this.#r.bind(this));
1381
+ }
1382
+ #n(e) {
1383
+ let t = e.get(this.in.broadcast), n = t ? e.get(t.out.catalog)?.text : void 0;
1384
+ e.set(this.#e.catalog, n), this.#e.available.set(n?.renditions ?? {});
1385
+ }
1386
+ #r(e) {
1387
+ let t = e.get(this.#e.available), n = e.get(this.in.target), r = n ? t[n] : void 0;
1388
+ if (!n || !r) {
1389
+ e.set(this.#e.track, void 0), e.set(this.#e.config, void 0);
1390
+ return;
1391
+ }
1392
+ q(r) || console.warn(`captions: unsupported format ${JSON.stringify(r.format)} for track ${n}`), e.set(this.#e.track, n), e.set(this.#e.config, r);
1393
+ }
1394
+ close() {
1395
+ this.#t.close();
1396
+ }
1397
+ }, Y = Symbol("supportCacheKey");
1398
+ function X(e) {
1399
+ return {
1400
+ broadcast: e.broadcast,
1401
+ decoder: {
1402
+ codec: e.codec,
1403
+ container: e.container,
1404
+ description: e.description,
1405
+ displayAspectWidth: e.displayAspectWidth,
1406
+ displayAspectHeight: e.displayAspectHeight,
1407
+ optimizeForLatency: e.optimizeForLatency ?? !0
1408
+ }
1409
+ };
1410
+ }
1411
+ function We(e) {
1412
+ return JSON.stringify(X(e).decoder);
1413
+ }
1414
+ //#endregion
1415
+ //#region src/video/playhead.ts
1416
+ var Ge = r.Milli(100);
1417
+ function Ke(e) {
1418
+ let t;
1419
+ return e.jitter === void 0 ? e.framerate && (t = r.Milli(Math.ceil(1e3 / e.framerate))) : t = r.Milli(e.jitter), e.delay === void 0 ? t : r.Milli.add(r.Milli(e.delay), t ?? r.Milli.zero);
1420
+ }
1421
+ function qe(e) {
1422
+ return e.active === void 0 || r.Milli.add(e.playhead, Ge) >= e.active;
1423
+ }
1424
+ function Je(e) {
1425
+ return e.active === void 0 ? e.pending : e.pending === void 0 ? e.active : r.Milli.max(e.active, e.pending);
1426
+ }
1427
+ //#endregion
1428
+ //#region src/video/presentation.ts
1429
+ function Ye(e = 0) {
1430
+ let t = (e % 360 + 360) % 360;
1431
+ return Math.round(t / 90) % 4 * 90;
1432
+ }
1433
+ function Xe(e, t = 0) {
1434
+ let n = Ye(t);
1435
+ return n === 90 || n === 270 ? {
1436
+ width: e.height,
1437
+ height: e.width
1438
+ } : {
1439
+ width: e.width,
1440
+ height: e.height
1441
+ };
1442
+ }
1443
+ function Z(e) {
1444
+ return Object.is(e, -0) ? 0 : e;
1445
+ }
1446
+ function Ze(e, t) {
1447
+ let [n, r, i, a, o, s] = e;
1448
+ return [
1449
+ Z(-n),
1450
+ Z(r),
1451
+ Z(-i),
1452
+ Z(a),
1453
+ Z(t - o),
1454
+ Z(s)
1455
+ ];
1456
+ }
1457
+ function Qe(e, t) {
1458
+ let n = Ye(t?.rotation), r = Xe(e, n), i;
1459
+ switch (n) {
1460
+ case 90:
1461
+ i = [
1462
+ 0,
1463
+ 1,
1464
+ -1,
1465
+ 0,
1466
+ e.width,
1467
+ 0
1468
+ ];
1469
+ break;
1470
+ case 180:
1471
+ i = [
1472
+ -1,
1473
+ 0,
1474
+ 0,
1475
+ -1,
1476
+ e.width,
1477
+ e.height
1478
+ ];
1479
+ break;
1480
+ case 270:
1481
+ i = [
1482
+ 0,
1483
+ -1,
1484
+ 1,
1485
+ 0,
1486
+ 0,
1487
+ e.height
1488
+ ];
1489
+ break;
1490
+ default: i = [
1491
+ 1,
1492
+ 0,
1493
+ 0,
1494
+ 1,
1495
+ 0,
1496
+ 0
1497
+ ];
1498
+ }
1499
+ return t?.flip && (i = Ze(i, e.width)), {
1500
+ matrix: i,
1501
+ source: r
1502
+ };
1503
+ }
1504
+ //#endregion
1505
+ //#region src/video/decoder.ts
1506
+ var $e = r.Milli(500), Q = class {
1507
+ in;
1508
+ source;
1509
+ sync;
1510
+ #e = {
1511
+ frame: new a(void 0),
1512
+ timestamp: new a(void 0),
1513
+ display: new a(void 0),
1514
+ stalled: new a(!1),
1515
+ stats: new a(void 0),
1516
+ jitter: new a(void 0),
1517
+ buffered: new a([])
1518
+ };
1519
+ out = s(this.#e);
1520
+ #t = new a(void 0);
1521
+ #n = new a(void 0);
1522
+ #r;
1523
+ #i = new i();
1524
+ #a() {
1525
+ this.#e.frame.update((e) => {
1526
+ e?.close();
1527
+ }), this.#e.timestamp.set(void 0);
1528
+ }
1529
+ constructor(e) {
1530
+ this.in = { enabled: o(e?.enabled ?? !0) }, this.source = e.source, this.sync = e.sync, this.#i.cleanup(this.sync.register(this.out.jitter)), this.#r = this.#i.computed((e) => {
1531
+ let t = e.get(this.source.out.config);
1532
+ return t ? X(t) : void 0;
1533
+ }), this.#i.run(this.#o.bind(this)), this.#i.run(this.#s.bind(this)), this.#i.run(this.#c.bind(this)), this.#i.run(this.#l.bind(this)), this.#i.run(this.#u.bind(this));
1534
+ }
1535
+ #o(e) {
1536
+ let t = (t, n) => {
1537
+ if (t === void 0 || n === void 0) return;
1538
+ let r = e.get(n)?.video?.renditions?.[t];
1539
+ return r && Ke(r);
1540
+ }, n = e.get(this.#t), r = t(n?.track, n?.catalog), i = e.get(this.#n), a = t(i?.track, i?.catalog);
1541
+ e.set(this.#e.jitter, Je({
1542
+ active: r,
1543
+ pending: a
1544
+ }));
1545
+ }
1546
+ #s(e) {
1547
+ let t = e.getAll([
1548
+ this.in.enabled,
1549
+ this.source.in.broadcast,
1550
+ this.source.out.track,
1551
+ this.#r
1552
+ ]);
1553
+ if (!t) {
1554
+ this.#t.set(void 0);
1555
+ return;
1556
+ }
1557
+ let [n, r, i, a] = t, o = r.relativeBroadcast(e, a.broadcast);
1558
+ if (!o) {
1559
+ this.#t.set(void 0), this.#a(), this.#e.buffered.set([]);
1560
+ return;
1561
+ }
1562
+ let s = new et({
1563
+ sync: this.sync,
1564
+ broadcast: o,
1565
+ track: i,
1566
+ config: a.decoder,
1567
+ stats: this.#e.stats,
1568
+ catalog: r.out.catalog
1569
+ });
1570
+ e.set(this.#n, {
1571
+ track: i,
1572
+ catalog: r.out.catalog
1573
+ }), e.cleanup(() => s?.close()), e.run((e) => {
1574
+ if (!s) return;
1575
+ let t = e.get(this.#t);
1576
+ if (t) {
1577
+ let n = e.get(s.timestamp);
1578
+ if (n === void 0 || !qe({
1579
+ playhead: n,
1580
+ active: e.get(t.timestamp)
1581
+ })) return;
1582
+ }
1583
+ this.#t.set(s), this.#n.set(void 0), s = void 0, e.close();
1584
+ });
1585
+ }
1586
+ #c(e) {
1587
+ let t = e.get(this.#t);
1588
+ if (!t) {
1589
+ this.#e.buffered.set([]);
1590
+ return;
1591
+ }
1592
+ e.cleanup(() => t.close()), e.run((e) => {
1593
+ let n = e.get(t.frame);
1594
+ n && (this.#e.timestamp.set(r.Milli.fromMicro(n.timestamp)), this.#e.frame.update((e) => (e?.close(), n.clone())));
1595
+ }), e.proxy(this.#e.buffered, t.buffered);
1596
+ }
1597
+ #l(e) {
1598
+ let t = e.get(this.source.out.catalog);
1599
+ if (!t) return;
1600
+ let n = t.display;
1601
+ if (n) {
1602
+ e.set(this.#e.display, {
1603
+ width: n.width,
1604
+ height: n.height
1605
+ });
1606
+ return;
1607
+ }
1608
+ let r = e.get(this.#e.frame);
1609
+ r && e.set(this.#e.display, Xe({
1610
+ width: r.displayWidth,
1611
+ height: r.displayHeight
1612
+ }, t.rotation));
1613
+ }
1614
+ #u(e) {
1615
+ if (e.get(this.in.enabled)) {
1616
+ if (!e.get(this.#e.frame)) {
1617
+ this.#e.stalled.set(!0);
1618
+ return;
1619
+ }
1620
+ this.#e.stalled.set(!1), e.timer(() => {
1621
+ this.#e.stalled.set(!0);
1622
+ }, $e);
1623
+ }
1624
+ }
1625
+ close() {
1626
+ this.#a(), this.#i.close();
1627
+ }
1628
+ static supported = tt;
1629
+ }, et = class {
1630
+ sync;
1631
+ broadcast;
1632
+ track;
1633
+ config;
1634
+ catalog;
1635
+ stats;
1636
+ timestamp = new a(void 0);
1637
+ frame = new a(void 0);
1638
+ buffered = new a([]);
1639
+ #e = new a([]);
1640
+ #t = 0;
1641
+ #n = new i();
1642
+ constructor(e) {
1643
+ this.sync = e.sync, this.broadcast = e.broadcast, this.track = e.track, this.config = e.config, this.catalog = e.catalog, this.stats = e.stats, this.#n.run(this.#r.bind(this));
1644
+ }
1645
+ #r(e) {
1646
+ let t = _(e, {
1647
+ broadcast: this.broadcast,
1648
+ track: this.track,
1649
+ priority: c.PRIORITY.video,
1650
+ maxAge: this.sync.out.maxAge
1651
+ });
1652
+ if (!t) return;
1653
+ let n = new VideoDecoder({
1654
+ output: async (t) => {
1655
+ try {
1656
+ let n = this.#t, i = r.Milli.fromMicro(t.timestamp);
1657
+ if (i < (this.timestamp.peek() ?? 0) || this.sync.out.reference.peek() === void 0 || (this.frame.peek() === void 0 && this.frame.set(t.clone()), !await e.race(this.sync.wait(i).then(() => !0))) || n !== this.#t || i < (this.timestamp.peek() ?? 0)) return;
1658
+ this.timestamp.set(i), this.#c(i), this.frame.update((e) => (e?.close(), t.clone()));
1659
+ } finally {
1660
+ t.close();
1661
+ }
1662
+ },
1663
+ error: (t) => {
1664
+ console.error("video decoder error", t), e.close();
1665
+ }
1666
+ });
1667
+ e.cleanup(() => {
1668
+ n.state !== "closed" && n.close();
1669
+ }), this.config.container.kind === "cmaf" ? this.#a(e, t, n) : this.#i(e, t, n);
1670
+ }
1671
+ #i(e, t, n) {
1672
+ let i = this.config.container.kind === "loc" ? new u.Loc.Format("video") : new u.Legacy.Format(this.config), a = new u.Consumer(t, {
1673
+ format: i,
1674
+ maxAge: this.sync.out.maxAge
1675
+ });
1676
+ e.cleanup(() => a.close()), e.run((e) => {
1677
+ let t = e.get(a.buffered), n = e.get(this.#e);
1678
+ this.buffered.update(() => u.mergeBufferedRanges(t, n));
1679
+ }), n.configure({
1680
+ codec: this.config.codec,
1681
+ description: this.config.description ? d.Hex.toBytes(this.config.description) : void 0,
1682
+ displayAspectWidth: this.config.displayAspectWidth,
1683
+ displayAspectHeight: this.config.displayAspectHeight,
1684
+ optimizeForLatency: this.config.optimizeForLatency,
1685
+ flip: !1
1686
+ });
1687
+ let o, s;
1688
+ e.spawn(async () => {
1689
+ for (;;) {
1690
+ let e = await v(a);
1691
+ if (!e) break;
1692
+ this.#o(e.discontinuity) && (o = void 0);
1693
+ let { frame: t } = e;
1694
+ if (!t) continue;
1695
+ let i = s !== void 0 && e.group < s;
1696
+ if (this.stats.update((e) => ({
1697
+ frameCount: (e?.frameCount ?? 0) + +!i,
1698
+ bytesReceived: (e?.bytesReceived ?? 0) + t.payload.byteLength
1699
+ })), i) continue;
1700
+ let c = r.Milli.fromMicro(t.timestamp);
1701
+ this.sync.received(c, "video");
1702
+ let l = new EncodedVideoChunk({
1703
+ type: t.keyframe ? "key" : "delta",
1704
+ data: t.payload,
1705
+ timestamp: t.timestamp
1706
+ });
1707
+ o !== void 0 && e.continuous && this.#s(r.Milli.fromMicro(o), r.Milli.fromMicro(t.timestamp)), o = t.timestamp, s = e.group, n.decode(l);
1708
+ }
1709
+ });
1710
+ }
1711
+ #a(e, t, n) {
1712
+ let i = this.config.container;
1713
+ if (i.kind !== "cmaf") return;
1714
+ let a = g(i.init), o = u.Cmaf.decodeInitSegment(a), s = this.config.description ? d.Hex.toBytes(this.config.description) : o.description, c = new u.Consumer(t, {
1715
+ format: new u.Cmaf.Format(o),
1716
+ maxAge: this.sync.out.maxAge
1717
+ });
1718
+ e.cleanup(() => c.close()), e.run((e) => {
1719
+ let t = e.get(c.buffered), n = e.get(this.#e);
1720
+ this.buffered.update(() => u.mergeBufferedRanges(t, n));
1721
+ }), n.configure({
1722
+ codec: this.config.codec,
1723
+ description: s,
1724
+ displayAspectWidth: this.config.displayAspectWidth,
1725
+ displayAspectHeight: this.config.displayAspectHeight,
1726
+ optimizeForLatency: this.config.optimizeForLatency,
1727
+ flip: !1
1728
+ });
1729
+ let l, f;
1730
+ e.spawn(async () => {
1731
+ for (;;) {
1732
+ let e = await v(c);
1733
+ if (!e) break;
1734
+ this.#o(e.discontinuity) && (l = void 0);
1735
+ let { frame: t } = e;
1736
+ if (!t) continue;
1737
+ let i = f !== void 0 && e.group < f;
1738
+ if (this.stats.update((e) => ({
1739
+ frameCount: (e?.frameCount ?? 0) + +!i,
1740
+ bytesReceived: (e?.bytesReceived ?? 0) + t.payload.byteLength
1741
+ })), i) continue;
1742
+ let a = r.Milli.fromMicro(t.timestamp);
1743
+ if (this.sync.received(a, "video"), l !== void 0 && e.continuous && this.#s(r.Milli.fromMicro(l), r.Milli.fromMicro(t.timestamp)), l = t.timestamp, n.state === "closed") break;
1744
+ f = e.group, n.decode(new EncodedVideoChunk({
1745
+ type: t.keyframe ? "key" : "delta",
1746
+ data: t.payload,
1747
+ timestamp: t.timestamp
1748
+ }));
1749
+ }
1750
+ });
1751
+ }
1752
+ #o(e) {
1753
+ return e !== this.#t && (this.#t = e, this.timestamp.set(void 0), this.#e.set([]), this.sync.reset(), !0);
1754
+ }
1755
+ #s(e, t) {
1756
+ e > t || this.#e.mutate((n) => {
1757
+ for (let i of n) if (i.start <= t && i.end >= e) {
1758
+ i.start = r.Milli.min(i.start, e), i.end = r.Milli.max(i.end, t);
1759
+ return;
1760
+ }
1761
+ n.push({
1762
+ start: e,
1763
+ end: t
1764
+ }), n.sort((e, t) => e.start - t.start);
1765
+ });
1766
+ }
1767
+ #c(e) {
1768
+ this.#e.mutate((t) => {
1769
+ for (; t.length > 0;) {
1770
+ if (t[0].end >= e) {
1771
+ t[0].start = r.Milli.max(t[0].start, e);
1772
+ break;
1773
+ }
1774
+ t.shift();
1775
+ }
1776
+ });
1777
+ }
1778
+ close() {
1779
+ this.#n.close(), this.frame.update((e) => {
1780
+ e?.close();
1781
+ });
1782
+ }
1783
+ };
1784
+ async function tt(e) {
1785
+ if (!c.containerSupported(e.container)) {
1786
+ let t = e.container.kind === "unknown" ? e.container.raw.kind : e.container.kind;
1787
+ return console.warn(`video: ignoring rendition with unknown container: ${t}`), !1;
1788
+ }
1789
+ let t;
1790
+ if (e.description) t = d.Hex.toBytes(e.description);
1791
+ else if (e.container.kind === "cmaf") try {
1792
+ t = u.Cmaf.decodeInitSegment(g(e.container.init)).description;
1793
+ } catch (t) {
1794
+ return console.warn(`video: malformed CMAF init segment for codec ${e.codec}`, t), !1;
1795
+ }
1796
+ let { supported: n } = await VideoDecoder.isConfigSupported({
1797
+ codec: e.codec,
1798
+ description: t,
1799
+ displayAspectWidth: e.displayAspectWidth,
1800
+ displayAspectHeight: e.displayAspectHeight,
1801
+ optimizeForLatency: e.optimizeForLatency ?? !0
1802
+ });
1803
+ if (n) return !0;
1804
+ if (e.codec.startsWith("avc3.")) {
1805
+ let n = `avc1.${e.codec.slice(5)}`;
1806
+ if ((await VideoDecoder.isConfigSupported({
1807
+ codec: n,
1808
+ description: t,
1809
+ displayAspectWidth: e.displayAspectWidth,
1810
+ displayAspectHeight: e.displayAspectHeight,
1811
+ optimizeForLatency: e.optimizeForLatency ?? !0
1812
+ })).supported) return e.codec = n, !0;
1813
+ }
1814
+ return !1;
1815
+ }
1816
+ Object.assign(tt, { [Y]: We });
1817
+ //#endregion
1818
+ //#region src/video/renderer.ts
1819
+ var nt = .01, rt = class {
1820
+ decoder;
1821
+ in;
1822
+ #e = {
1823
+ frame: new a(void 0),
1824
+ timestamp: new a(void 0),
1825
+ visible: new a(!1)
1826
+ };
1827
+ out = s(this.#e);
1828
+ #t = new a(void 0);
1829
+ #n = new i();
1830
+ constructor(e) {
1831
+ this.decoder = e.decoder, this.in = {
1832
+ canvas: o(e?.canvas),
1833
+ visible: o(e?.visible ?? "20%")
1834
+ }, this.#n.run((e) => {
1835
+ let t = e.get(this.in.canvas);
1836
+ this.#t.set(t?.getContext("2d") ?? void 0);
1837
+ }), this.#n.run(this.#i.bind(this)), this.#n.run(this.#a.bind(this)), this.#n.run(this.#r.bind(this));
1838
+ }
1839
+ #r(e) {
1840
+ let t = e.getAll([this.in.canvas, this.decoder.out.display]);
1841
+ if (!t) return;
1842
+ let [n, r] = t;
1843
+ (n.width !== r.width || n.height !== r.height) && (n.width = r.width, n.height = r.height);
1844
+ }
1845
+ #i(e) {
1846
+ let t = e.get(this.in.visible);
1847
+ if (t === "never") {
1848
+ this.#e.visible.set(!1);
1849
+ return;
1850
+ }
1851
+ if (t === "always") {
1852
+ this.#e.visible.set(!0), e.cleanup(() => this.#e.visible.set(!1));
1853
+ return;
1854
+ }
1855
+ let n = e.get(this.in.canvas);
1856
+ if (!n) {
1857
+ this.#e.visible.set(!1);
1858
+ return;
1859
+ }
1860
+ let r = !1, i = () => {
1861
+ this.#e.visible.set(r && !document.hidden);
1862
+ }, a = (e) => {
1863
+ for (let t of e) r = t.isIntersecting, i();
1864
+ }, o;
1865
+ try {
1866
+ o = new IntersectionObserver(a, {
1867
+ threshold: nt,
1868
+ rootMargin: t
1869
+ });
1870
+ } catch {
1871
+ console.warn(`moq-watch: invalid visible margin "${t}", using "0px"`), o = new IntersectionObserver(a, { threshold: nt });
1872
+ }
1873
+ i(), e.event(document, "visibilitychange", i), o.observe(n), e.cleanup(() => o.disconnect()), e.cleanup(() => this.#e.visible.set(!1));
1874
+ }
1875
+ #a(e) {
1876
+ let t = e.get(this.#t);
1877
+ if (!t) return;
1878
+ let n = e.get(this.decoder.out.frame), i = e.get(this.decoder.source.out.catalog), a = requestAnimationFrame(() => {
1879
+ this.#o(t, n, i), n ? (this.#e.frame.update((e) => (e?.close(), n.clone())), this.#e.timestamp.set(r.Milli.fromMicro(n.timestamp))) : (this.#e.frame.update((e) => {
1880
+ e?.close();
1881
+ }), this.#e.timestamp.set(void 0)), a = void 0;
1882
+ });
1883
+ e.cleanup(() => {
1884
+ a !== void 0 && cancelAnimationFrame(a);
1885
+ });
1886
+ }
1887
+ #o(e, t, n) {
1888
+ if (!t) {
1889
+ e.fillStyle = "#000", e.fillRect(0, 0, e.canvas.width, e.canvas.height);
1890
+ return;
1891
+ }
1892
+ if (e.save(), e.fillStyle = "#000", e.fillRect(0, 0, e.canvas.width, e.canvas.height), !n?.rotation) n?.flip && (e.scale(-1, 1), e.translate(-e.canvas.width, 0)), e.drawImage(t, 0, 0, e.canvas.width, e.canvas.height);
1893
+ else {
1894
+ let r = Qe(e.canvas, n);
1895
+ e.setTransform(...r.matrix), e.drawImage(t, 0, 0, r.source.width, r.source.height);
1896
+ }
1897
+ e.restore();
1898
+ }
1899
+ close() {
1900
+ this.#e.frame.update((e) => {
1901
+ e?.close();
1902
+ }), this.#e.timestamp.set(void 0), this.#n.close();
1903
+ }
1904
+ };
1905
+ //#endregion
1906
+ //#region src/video/source.ts
1907
+ function it(e) {
1908
+ return (t) => {
1909
+ let n = [], r = [];
1910
+ for (let [i, a] of t) if (a.codedWidth && a.codedHeight) {
1911
+ let t = a.codedWidth * a.codedHeight;
1912
+ t <= e ? n.push({
1913
+ name: i,
1914
+ size: t
1915
+ }) : r.push({
1916
+ name: i,
1917
+ size: t
1918
+ });
1919
+ }
1920
+ return n.sort((e, t) => t.size - e.size), n.length > 0 ? n.map((e) => e.name) : r.length > 0 ? (r.sort((e, t) => e.size - t.size), [r[0].name]) : t.map(([e]) => e);
1921
+ };
1922
+ }
1923
+ function at(e, t) {
1924
+ return (n) => {
1925
+ let r = [], i = [];
1926
+ for (let [a, o] of n) {
1927
+ if (!o.codedWidth || !o.codedHeight) continue;
1928
+ let n = o.codedWidth * o.codedHeight, s = e == null || o.codedWidth <= e, c = t == null || o.codedHeight <= t;
1929
+ s && c ? r.push({
1930
+ name: a,
1931
+ size: n
1932
+ }) : i.push({
1933
+ name: a,
1934
+ size: n
1935
+ });
1936
+ }
1937
+ return r.sort((e, t) => t.size - e.size), r.length > 0 ? r.map((e) => e.name) : i.length > 0 ? (i.sort((e, t) => e.size - t.size), [i[0].name]) : n.map(([e]) => e);
1938
+ };
1939
+ }
1940
+ function $(e) {
1941
+ return (t) => {
1942
+ let n = [], r = [];
1943
+ for (let [i, a] of t) a.bitrate != null && a.bitrate <= e ? n.push({
1944
+ name: i,
1945
+ bitrate: a.bitrate
1946
+ }) : a.bitrate != null && r.push({
1947
+ name: i,
1948
+ bitrate: a.bitrate
1949
+ });
1950
+ return n.sort((e, t) => t.bitrate - e.bitrate), n.length > 0 ? n.map((e) => e.name) : r.length > 0 ? (r.sort((e, t) => e.bitrate - t.bitrate), [r[0].name]) : t.map(([e]) => e);
1951
+ };
1952
+ }
1953
+ function ot(e) {
1954
+ let t = e[0];
1955
+ for (let n of e) {
1956
+ let [, e] = n, [, r] = t, i = (e.codedWidth ?? 0) * (e.codedHeight ?? 0), a = (r.codedWidth ?? 0) * (r.codedHeight ?? 0);
1957
+ if (i !== a) {
1958
+ i > a && (t = n);
1959
+ continue;
1960
+ }
1961
+ (e.bitrate ?? 0) > (r.bitrate ?? 0) && (t = n);
1962
+ }
1963
+ return t[0];
1964
+ }
1965
+ function st(e) {
1966
+ let t = Object.entries(e).filter(([, e]) => !e.stalled);
1967
+ if (t.length > 0) return Object.fromEntries(t);
1968
+ let n = Object.entries(e);
1969
+ if (n.length === 0) return {};
1970
+ let r = $(0)(n), i = r.length === 1 ? r[0] : at(0, 0)(n)[0];
1971
+ return { [i]: e[i] };
1972
+ }
1973
+ var ct = class {
1974
+ in;
1975
+ #e = {
1976
+ catalog: new a(void 0),
1977
+ available: new a({}),
1978
+ error: new a(void 0),
1979
+ track: new a(void 0),
1980
+ config: new a(void 0)
1981
+ };
1982
+ out = s(this.#e);
1983
+ #t = new i();
1984
+ #n = /* @__PURE__ */ new WeakMap();
1985
+ constructor(e) {
1986
+ this.in = {
1987
+ broadcast: o(e?.broadcast),
1988
+ target: o(e?.target),
1989
+ supported: o(e?.supported),
1990
+ probe: o(e?.probe)
1991
+ }, this.#t.run(this.#r.bind(this)), this.#t.run(this.#i.bind(this)), this.#t.run(this.#a.bind(this));
1992
+ }
1993
+ #r(e) {
1994
+ let t = e.get(this.in.broadcast);
1995
+ if (!t) return;
1996
+ let n = e.get(t.out.catalog)?.video;
1997
+ n && e.set(this.#e.catalog, n);
1998
+ }
1999
+ #i(e) {
2000
+ let t = e.get(this.in.supported);
2001
+ if (!t) {
2002
+ this.#e.error.set(void 0);
2003
+ return;
2004
+ }
2005
+ let n = e.get(this.#e.catalog)?.renditions ?? {};
2006
+ this.#e.error.set(void 0);
2007
+ let r = this.#n.get(t);
2008
+ r || (r = /* @__PURE__ */ new Map(), this.#n.set(t, r));
2009
+ let i = new Set(Object.keys(n));
2010
+ for (let e of r.keys()) i.has(e) || r.delete(e);
2011
+ e.spawn(async () => {
2012
+ let i = {};
2013
+ for (let [a, o] of Object.entries(n)) {
2014
+ let n = t[Y], s = n ? n(o) : JSON.stringify(o), c = r.get(a), l = !1;
2015
+ if (c?.key === s) l = c.supported;
2016
+ else {
2017
+ let i = !1;
2018
+ try {
2019
+ l = await e.race(t(o));
2020
+ } catch (e) {
2021
+ i = !0, console.warn(`[Source] video rendition ${a} (${o.codec}) support probe failed; treating as unsupported`, e);
2022
+ }
2023
+ !i && l !== void 0 && r.set(a, {
2024
+ key: n ? n(o) : JSON.stringify(o),
2025
+ supported: l
2026
+ });
2027
+ }
2028
+ if (e.abort.aborted) return;
2029
+ l && (i[a] = o);
2030
+ }
2031
+ let a = Object.keys(i).length === 0 && Object.keys(n).length > 0 ? "unsupported" : void 0;
2032
+ a === "unsupported" && console.warn("[Source] No supported video renditions found:", n), this.#e.error.set(a), this.#e.available.set(i);
2033
+ });
2034
+ }
2035
+ #a(e) {
2036
+ let t = e.get(this.#e.available), n = e.get(this.in.target);
2037
+ if (n?.name && n.name in t) {
2038
+ let r = t[n.name];
2039
+ e.set(this.#e.track, n.name), e.set(this.#e.config, r);
2040
+ return;
2041
+ }
2042
+ let r = st(t);
2043
+ if (Object.keys(r).length === 0) return;
2044
+ let i = n;
2045
+ if (!n?.bitrate) {
2046
+ let t = e.get(this.in.probe)?.estimatedRecvRate;
2047
+ if (t != null) {
2048
+ let e = Math.round(t * .8);
2049
+ i = {
2050
+ ...n,
2051
+ bitrate: e
2052
+ };
2053
+ }
2054
+ }
2055
+ let a = this.#o(r, i);
2056
+ if (!a) return;
2057
+ let o = r[a];
2058
+ e.set(this.#e.track, a), e.set(this.#e.config, o);
2059
+ }
2060
+ #o(e, t) {
2061
+ let n = Object.entries(e);
2062
+ if (n.length === 0) return;
2063
+ if (n.length === 1) return n[0][0];
2064
+ let r = [];
2065
+ if (t?.pixels != null && r.push(it(t.pixels)), (t?.width != null || t?.height != null) && r.push(at(t.width, t.height)), t?.bitrate != null && r.push($(t.bitrate)), r.length === 0) return ot(n);
2066
+ let i = r.map((e) => e(n)), a = i.map((e) => new Set(e));
2067
+ for (let e of i[0]) if (a.every((t) => t.has(e))) return e;
2068
+ console.warn("conflicting rendition filters, no rendition satisfies all criteria");
2069
+ }
2070
+ close() {
2071
+ this.#t.close();
2072
+ }
2073
+ }, lt = class {
2074
+ in;
2075
+ broadcast;
2076
+ sync;
2077
+ text;
2078
+ video;
2079
+ audio;
2080
+ renderer;
2081
+ emitter;
2082
+ textRenderer;
2083
+ #e = new a(!1);
2084
+ #t = new a(!1);
2085
+ #n = new a(!1);
2086
+ #r = new i();
2087
+ constructor(e = {}) {
2088
+ this.in = s({
2089
+ origin: o(e.origin),
2090
+ name: o(e.name ?? n.empty()),
2091
+ enabled: o(e.enabled ?? !0),
2092
+ announced: o(e.announced ?? !0),
2093
+ catalogFormat: o(e.catalogFormat),
2094
+ catalog: o(e.catalog),
2095
+ probe: o(e.probe),
2096
+ canvas: o(e.canvas),
2097
+ container: o(e.container),
2098
+ paused: o(e.paused ?? !1),
2099
+ volume: o(e.volume ?? .5),
2100
+ muted: o(e.muted ?? !1),
2101
+ visible: o(e.visible ?? "20%"),
2102
+ delay: o(e.delay ?? "auto"),
2103
+ buffer: o(e.buffer ?? r.Milli.zero),
2104
+ target: o(e.target),
2105
+ audioTarget: o(e.audioTarget),
2106
+ captions: o(e.captions)
2107
+ }), this.broadcast = new R(this.in), this.#r.cleanup(() => this.broadcast.close());
2108
+ let t = new ct({
2109
+ broadcast: this.broadcast,
2110
+ target: this.in.target,
2111
+ supported: Q.supported,
2112
+ probe: this.in.probe
2113
+ }), i = new N({
2114
+ broadcast: this.broadcast,
2115
+ target: this.in.audioTarget,
2116
+ supported: j.supported
2117
+ });
2118
+ this.#r.cleanup(() => {
2119
+ t.close(), i.close();
2120
+ }), this.text = new J({
2121
+ broadcast: this.broadcast,
2122
+ target: this.in.captions
2123
+ }), this.#r.cleanup(() => this.text.close()), this.sync = new B({
2124
+ delay: this.in.delay,
2125
+ buffer: this.in.buffer,
2126
+ probe: this.in.probe
2127
+ }), this.#r.cleanup(() => this.sync.close()), this.video = new Q({
2128
+ source: t,
2129
+ sync: this.sync,
2130
+ enabled: this.#e
2131
+ }), this.audio = new j({
2132
+ source: i,
2133
+ sync: this.sync,
2134
+ enabled: this.#t
2135
+ }), this.#r.cleanup(() => {
2136
+ this.video.close(), this.audio.close();
2137
+ }), this.emitter = new Ae({
2138
+ source: this.audio,
2139
+ volume: this.in.volume,
2140
+ muted: this.in.muted,
2141
+ paused: this.in.paused
2142
+ }), this.renderer = new rt({
2143
+ decoder: this.video,
2144
+ canvas: this.in.canvas,
2145
+ visible: this.in.visible
2146
+ }), this.#r.cleanup(() => {
2147
+ this.emitter.close(), this.renderer.close();
2148
+ }), this.textRenderer = new K({
2149
+ source: this.text,
2150
+ sync: this.sync,
2151
+ container: this.in.container,
2152
+ enabled: this.#n
2153
+ }), this.#r.cleanup(() => this.textRenderer.close()), this.#r.run((e) => {
2154
+ this.#n.set(e.get(this.in.enabled) && !e.get(this.in.paused));
2155
+ }), this.#r.run((e) => {
2156
+ this.#t.set(e.get(this.in.enabled) && e.get(this.emitter.out.enabled));
2157
+ }), this.#r.run((e) => {
2158
+ let t = e.get(this.renderer.out.visible);
2159
+ e.get(this.in.enabled) ? e.get(this.in.paused) ? this.#e.set(t && !e.get(this.renderer.out.frame)) : this.#e.set(t) : this.#e.set(!1);
2160
+ });
2161
+ }
2162
+ reset() {
2163
+ this.sync.reset(), this.audio.reset();
2164
+ }
2165
+ close() {
2166
+ this.#r.close();
2167
+ }
2168
+ };
2169
+ //#endregion
2170
+ export { Ae as _, J as a, G as c, W as d, V as f, N as g, Le as h, Q as i, H as l, R as m, ct as n, q as o, B as p, rt as r, K as s, lt as t, U as u, j as v };
2171
+
2172
+ //# sourceMappingURL=player-C19uf7Dc.js.map