@moq/watch 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/audio/decoder.d.ts +1 -1
- package/audio/decoder.d.ts.map +1 -1
- package/element.js +1 -1
- package/index.js +1 -1
- package/package.json +2 -2
- package/{source-CWtgjSC_.js → source-CPHBHrLc.js} +470 -369
- package/source-CPHBHrLc.js.map +1 -0
- package/video/decoder.d.ts.map +1 -1
- package/video/presentation.d.ts +16 -0
- package/video/presentation.d.ts.map +1 -0
- package/video/presentation.test.d.ts +2 -0
- package/video/presentation.test.d.ts.map +1 -0
- package/video/renderer.d.ts.map +1 -1
- package/video/renderer.test.d.ts +2 -0
- package/video/renderer.test.d.ts.map +1 -0
- package/source-CWtgjSC_.js.map +0 -1
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import * as l from "@moq/hang/
|
|
7
|
-
import * as u from "@moq/
|
|
8
|
-
import * as d from "@moq/
|
|
1
|
+
import { n as e } from "./sync-zdwVEj9u.js";
|
|
2
|
+
import { Path as t, Time as n } from "@moq/net";
|
|
3
|
+
import { Effect as r, Signal as i, getter as a, readonlys as o } from "@moq/signals";
|
|
4
|
+
import * as s from "@moq/hang/catalog";
|
|
5
|
+
import { u53 as c } from "@moq/hang/catalog";
|
|
6
|
+
import * as l from "@moq/hang/container";
|
|
7
|
+
import * as u from "@moq/hang/util";
|
|
8
|
+
import * as d from "@moq/json";
|
|
9
|
+
import * as f from "@moq/msf";
|
|
9
10
|
//#region src/base64.ts
|
|
10
|
-
function
|
|
11
|
+
function p(e) {
|
|
11
12
|
let t = atob(e), n = new Uint8Array(t.length);
|
|
12
13
|
for (let e = 0; e < t.length; e++) n[e] = t.charCodeAt(e);
|
|
13
14
|
return n;
|
|
14
15
|
}
|
|
15
16
|
//#endregion
|
|
16
17
|
//#region src/audio/shared-ring-buffer.ts
|
|
17
|
-
var
|
|
18
|
-
function
|
|
18
|
+
var m = 0, h = 1, g = 2, _ = 3, v = 4;
|
|
19
|
+
function y(e, t, n, r = !1) {
|
|
19
20
|
if (e <= 0) throw Error("invalid channels");
|
|
20
21
|
if (t <= 0) throw Error("invalid capacity");
|
|
21
22
|
if (n <= 0) throw Error("invalid sample rate");
|
|
22
|
-
let i = new SharedArrayBuffer(e * t * Float32Array.BYTES_PER_ELEMENT), a = new SharedArrayBuffer(
|
|
23
|
-
return Atomics.store(o,
|
|
23
|
+
let i = new SharedArrayBuffer(e * t * Float32Array.BYTES_PER_ELEMENT), a = new SharedArrayBuffer(v * Int32Array.BYTES_PER_ELEMENT), o = new Int32Array(a);
|
|
24
|
+
return Atomics.store(o, _, 1), {
|
|
24
25
|
channels: e,
|
|
25
26
|
capacity: t,
|
|
26
27
|
rate: n,
|
|
@@ -29,20 +30,20 @@ function v(e, t, n, r = !1) {
|
|
|
29
30
|
buffered: r
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
|
-
function
|
|
33
|
+
function b(e, t) {
|
|
33
34
|
return (e - t | 0) > 0 ? e : t;
|
|
34
35
|
}
|
|
35
|
-
function
|
|
36
|
+
function x(e, t) {
|
|
36
37
|
return (e % t + t) % t;
|
|
37
38
|
}
|
|
38
|
-
function
|
|
39
|
+
function S(e, t, n) {
|
|
39
40
|
for (;;) {
|
|
40
41
|
let r = Atomics.load(e, t);
|
|
41
42
|
if ((n - r | 0) <= 0) return r;
|
|
42
43
|
if (Atomics.compareExchange(e, t, r, n) === r) return n;
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
|
-
var
|
|
46
|
+
var C = class e {
|
|
46
47
|
channels;
|
|
47
48
|
capacity;
|
|
48
49
|
rate;
|
|
@@ -55,80 +56,80 @@ var S = class e {
|
|
|
55
56
|
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 = [];
|
|
56
57
|
for (let t = 0; t < this.channels; t++) this.#t.push(new Float32Array(e.samples, t * this.capacity * Float32Array.BYTES_PER_ELEMENT, this.capacity));
|
|
57
58
|
}
|
|
58
|
-
insert(e,
|
|
59
|
-
if (
|
|
60
|
-
let r = Math.round(
|
|
61
|
-
this.buffered && !this.#n && (Atomics.store(this.#e,
|
|
62
|
-
let o = r + i | 0, s = Atomics.load(this.#e,
|
|
59
|
+
insert(e, t) {
|
|
60
|
+
if (t.length !== this.channels) throw Error("wrong number of channels");
|
|
61
|
+
let r = Math.round(n.Second.fromMicro(e) * this.rate), i = t[0].length, a = 0;
|
|
62
|
+
this.buffered && !this.#n && (Atomics.store(this.#e, h, r | 0), Atomics.store(this.#e, m, r | 0), this.#n = !0);
|
|
63
|
+
let o = r + i | 0, s = Atomics.load(this.#e, h), c = s - r | 0;
|
|
63
64
|
if (c > 0) {
|
|
64
65
|
if (c >= i) return;
|
|
65
66
|
a = c, r = r + c | 0;
|
|
66
67
|
}
|
|
67
68
|
let l = i - a;
|
|
68
|
-
(o - s | 0) > this.capacity &&
|
|
69
|
-
let u = Atomics.load(this.#e,
|
|
69
|
+
(o - s | 0) > this.capacity && S(this.#e, h, o - this.capacity | 0);
|
|
70
|
+
let u = Atomics.load(this.#e, m), d = r - u | 0;
|
|
70
71
|
if (d > 0) {
|
|
71
72
|
let e = Math.min(d, this.capacity);
|
|
72
73
|
for (let t = 0; t < this.channels; t++) {
|
|
73
74
|
let n = this.#t[t];
|
|
74
|
-
for (let t = 0; t < e; t++) n[
|
|
75
|
+
for (let t = 0; t < e; t++) n[x(u + t | 0, this.capacity)] = 0;
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
for (let e = 0; e < this.channels; e++) {
|
|
78
|
-
let
|
|
79
|
-
for (let e = 0; e < l; e++) i[
|
|
79
|
+
let n = t[e], i = this.#t[e];
|
|
80
|
+
for (let e = 0; e < l; e++) i[x(r + e | 0, this.capacity)] = n[a + e];
|
|
80
81
|
}
|
|
81
|
-
Atomics.store(this.#e,
|
|
82
|
-
let f = Atomics.load(this.#e,
|
|
83
|
-
(
|
|
82
|
+
Atomics.store(this.#e, m, b(Atomics.load(this.#e, m), o));
|
|
83
|
+
let f = Atomics.load(this.#e, h), p = Atomics.load(this.#e, m), v = Atomics.load(this.#e, g);
|
|
84
|
+
(p - f | 0) >= v && v > 0 && Atomics.store(this.#e, _, 0);
|
|
84
85
|
}
|
|
85
86
|
read(e) {
|
|
86
|
-
if (Atomics.load(this.#e,
|
|
87
|
-
let t = Atomics.load(this.#e,
|
|
87
|
+
if (Atomics.load(this.#e, _) === 1) return 0;
|
|
88
|
+
let t = Atomics.load(this.#e, h), n = Atomics.load(this.#e, m), r = Atomics.load(this.#e, g), i = n - t | 0;
|
|
88
89
|
if (!this.buffered && r > 0 && i > r) {
|
|
89
90
|
let e = n - r | 0;
|
|
90
|
-
t =
|
|
91
|
+
t = S(this.#e, h, e);
|
|
91
92
|
}
|
|
92
93
|
let a = n - t | 0, o = Math.min(a, e[0].length);
|
|
93
94
|
if (o <= 0) return 0;
|
|
94
95
|
for (let n = 0; n < this.channels; n++) {
|
|
95
96
|
let r = this.#t[n], i = e[n];
|
|
96
|
-
for (let e = 0; e < o; e++) i[e] = r[
|
|
97
|
+
for (let e = 0; e < o; e++) i[e] = r[x(t + e | 0, this.capacity)];
|
|
97
98
|
}
|
|
98
|
-
return
|
|
99
|
+
return S(this.#e, h, t + o | 0), o;
|
|
99
100
|
}
|
|
100
101
|
setLatency(e) {
|
|
101
|
-
Atomics.store(this.#e,
|
|
102
|
+
Atomics.store(this.#e, g, e);
|
|
102
103
|
}
|
|
103
104
|
reset() {
|
|
104
|
-
this.#n = !1, Atomics.store(this.#e,
|
|
105
|
-
let e = Atomics.load(this.#e,
|
|
106
|
-
Atomics.store(this.#e,
|
|
105
|
+
this.#n = !1, Atomics.store(this.#e, _, 1);
|
|
106
|
+
let e = Atomics.load(this.#e, m);
|
|
107
|
+
Atomics.store(this.#e, h, e);
|
|
107
108
|
}
|
|
108
109
|
resize(t) {
|
|
109
|
-
let n =
|
|
110
|
+
let n = y(this.channels, t, this.rate, this.buffered), r = new e(n);
|
|
110
111
|
r.#n = this.#n;
|
|
111
|
-
let i = Atomics.load(this.#e,
|
|
112
|
+
let i = Atomics.load(this.#e, h), a = Atomics.load(this.#e, m), o = Atomics.load(this.#e, g), s = Atomics.load(this.#e, _), c = a - i | 0, l = Math.max(0, Math.min(c, r.capacity)), u = a - l | 0;
|
|
112
113
|
for (let e = 0; e < this.channels; e++) {
|
|
113
114
|
let t = this.#t[e], n = r.#t[e];
|
|
114
115
|
for (let e = 0; e < l; e++) {
|
|
115
116
|
let i = u + e | 0;
|
|
116
|
-
n[
|
|
117
|
+
n[x(i, r.capacity)] = t[x(i, this.capacity)];
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
|
-
return Atomics.store(r.#e,
|
|
120
|
+
return Atomics.store(r.#e, h, u), Atomics.store(r.#e, m, a), Atomics.store(r.#e, g, o), Atomics.store(r.#e, _, s), r;
|
|
120
121
|
}
|
|
121
122
|
get timestamp() {
|
|
122
|
-
let e = Atomics.load(this.#e,
|
|
123
|
-
return
|
|
123
|
+
let e = Atomics.load(this.#e, h);
|
|
124
|
+
return n.Micro.fromSecond(e / this.rate);
|
|
124
125
|
}
|
|
125
126
|
get stalled() {
|
|
126
|
-
return Atomics.load(this.#e,
|
|
127
|
+
return Atomics.load(this.#e, _) === 1;
|
|
127
128
|
}
|
|
128
129
|
get length() {
|
|
129
|
-
return Atomics.load(this.#e,
|
|
130
|
+
return Atomics.load(this.#e, m) - Atomics.load(this.#e, h) | 0;
|
|
130
131
|
}
|
|
131
|
-
},
|
|
132
|
+
}, w = class {
|
|
132
133
|
#e;
|
|
133
134
|
#t;
|
|
134
135
|
#n = [];
|
|
@@ -152,32 +153,32 @@ var S = class e {
|
|
|
152
153
|
this.#n = [];
|
|
153
154
|
}
|
|
154
155
|
};
|
|
155
|
-
function
|
|
156
|
-
return
|
|
156
|
+
function T(e, t) {
|
|
157
|
+
return n.Micro.fromSecond(e / t);
|
|
157
158
|
}
|
|
158
|
-
function
|
|
159
|
+
function E() {
|
|
159
160
|
return !(typeof SharedArrayBuffer > "u" || typeof crossOriginIsolated < "u" && !crossOriginIsolated);
|
|
160
161
|
}
|
|
161
|
-
function
|
|
162
|
-
return
|
|
162
|
+
function D(e, t, n, r, i = !1) {
|
|
163
|
+
return E() ? (console.log("[audio] using SharedArrayBuffer audio buffer"), new O(e, t, n, r, i)) : (console.log("[audio] using postMessage audio buffer (SharedArrayBuffer unavailable)"), new k(e, t, n, r, i));
|
|
163
164
|
}
|
|
164
|
-
var
|
|
165
|
+
var O = class {
|
|
165
166
|
rate;
|
|
166
167
|
channels;
|
|
167
168
|
#e;
|
|
168
169
|
#t;
|
|
169
|
-
#n = new
|
|
170
|
+
#n = new i(0);
|
|
170
171
|
timestamp = this.#n;
|
|
171
|
-
#r = new
|
|
172
|
+
#r = new i(!0);
|
|
172
173
|
stalled = this.#r;
|
|
173
174
|
#i;
|
|
174
|
-
#a = new
|
|
175
|
+
#a = new r();
|
|
175
176
|
constructor(e, t, n, r, i) {
|
|
176
177
|
this.#e = e, this.channels = t, this.rate = n;
|
|
177
178
|
let a = Math.max(n, r * 2);
|
|
178
|
-
this.#i = new
|
|
179
|
-
let o =
|
|
180
|
-
this.#t = new
|
|
179
|
+
this.#i = new w(i, T(r, n));
|
|
180
|
+
let o = y(t, a, n, i);
|
|
181
|
+
this.#t = new C(o), this.#t.setLatency(r);
|
|
181
182
|
let s = {
|
|
182
183
|
type: "init-shared",
|
|
183
184
|
...o
|
|
@@ -191,7 +192,7 @@ var D = class {
|
|
|
191
192
|
this.#t.insert(e, t);
|
|
192
193
|
}
|
|
193
194
|
setLatency(e) {
|
|
194
|
-
if (this.#i.setHeadroom(
|
|
195
|
+
if (this.#i.setHeadroom(T(e, this.rate)), this.#t.capacity < e * 1.5) {
|
|
195
196
|
let t = Math.max(this.rate, e * 2);
|
|
196
197
|
this.#t = this.#t.resize(t), this.#t.setLatency(e);
|
|
197
198
|
let n = {
|
|
@@ -210,23 +211,23 @@ var D = class {
|
|
|
210
211
|
close() {
|
|
211
212
|
this.#i.flush(), this.#a.close();
|
|
212
213
|
}
|
|
213
|
-
},
|
|
214
|
+
}, k = class {
|
|
214
215
|
rate;
|
|
215
216
|
channels;
|
|
216
217
|
#e;
|
|
217
|
-
#t = new
|
|
218
|
+
#t = new i(0);
|
|
218
219
|
timestamp = this.#t;
|
|
219
|
-
#n = new
|
|
220
|
+
#n = new i(!0);
|
|
220
221
|
stalled = this.#n;
|
|
221
222
|
#r;
|
|
222
|
-
#i = new
|
|
223
|
-
constructor(e,
|
|
224
|
-
this.#e = e, this.channels =
|
|
223
|
+
#i = new r();
|
|
224
|
+
constructor(e, t, r, i, a) {
|
|
225
|
+
this.#e = e, this.channels = t, this.rate = r, this.#r = new w(a, T(i, r));
|
|
225
226
|
let o = {
|
|
226
227
|
type: "init-post",
|
|
227
|
-
channels:
|
|
228
|
+
channels: t,
|
|
228
229
|
rate: r,
|
|
229
|
-
latency:
|
|
230
|
+
latency: n.Milli.fromSecond(i / r),
|
|
230
231
|
buffered: a
|
|
231
232
|
};
|
|
232
233
|
e.port.postMessage(o), this.#i.event(e.port, "message", (e) => {
|
|
@@ -243,12 +244,12 @@ var D = class {
|
|
|
243
244
|
this.#e.port.postMessage(n, t.map((e) => e.buffer));
|
|
244
245
|
}
|
|
245
246
|
setLatency(e) {
|
|
246
|
-
this.#r.setHeadroom(
|
|
247
|
-
let
|
|
247
|
+
this.#r.setHeadroom(T(e, this.rate));
|
|
248
|
+
let t = {
|
|
248
249
|
type: "latency",
|
|
249
|
-
latency:
|
|
250
|
+
latency: n.Milli.fromSecond(e / this.rate)
|
|
250
251
|
};
|
|
251
|
-
this.#e.port.postMessage(
|
|
252
|
+
this.#e.port.postMessage(t);
|
|
252
253
|
}
|
|
253
254
|
reset() {
|
|
254
255
|
this.#e.port.postMessage({ type: "reset" }), this.#r.flush();
|
|
@@ -259,11 +260,11 @@ var D = class {
|
|
|
259
260
|
close() {
|
|
260
261
|
this.#r.flush(), this.#i.close();
|
|
261
262
|
}
|
|
262
|
-
}, k = 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.isInteger(unitsPerSecond) || unitsPerSecond <= 0) {\n throw new Error(`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);\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 if (!Number.isFinite(value) || value < 0) {\n throw new Error(`invalid timestamp: ${value}`);\n }\n this.value = value;\n this.scale = 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` (a raw number, not a new Timestamp). */\n as(scale) {\n return scale === this.scale ? this.value : this.value * scale / this.scale;\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: anchor to the first sample, play through 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 this.#latencySamples = Math.ceil(this.rate * time_exports.Second.fromMilli(latency));\n const newCapacity = this.#capacityFor(this.#latencySamples);\n if (newCapacity === this.capacity) return;\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.#buffered && !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 // 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 READ = 1;\nvar LATENCY = 2;\nvar STALLED = 3;\nvar CONTROL_SLOTS = 4;\nfunction allocSharedRingBuffer(channels, capacity, rate, buffered = false) {\n if (channels <= 0) throw new Error(\"invalid channels\");\n if (capacity <= 0) throw new Error(\"invalid capacity\");\n if (rate <= 0) throw new Error(\"invalid sample rate\");\n const samples = new SharedArrayBuffer(channels * capacity * Float32Array.BYTES_PER_ELEMENT);\n const control = new SharedArrayBuffer(CONTROL_SLOTS * Int32Array.BYTES_PER_ELEMENT);\n const ctrl = new Int32Array(control);\n Atomics.store(ctrl, STALLED, 1);\n return { channels, capacity, rate, samples, control, buffered };\n}\nfunction i32Max(a, b) {\n return (a - b | 0) > 0 ? a : b;\n}\nfunction slot(idx, capacity) {\n return (idx % capacity + capacity) % capacity;\n}\nfunction casAdvance(arr, idx, candidate) {\n for (; ; ) {\n const current = Atomics.load(arr, idx);\n if ((candidate - current | 0) <= 0) return current;\n const witnessed = Atomics.compareExchange(arr, idx, current, candidate);\n if (witnessed === current) return candidate;\n }\n}\nvar SharedRingBuffer = class _SharedRingBuffer {\n channels;\n capacity;\n rate;\n buffered;\n init;\n #control;\n #samples;\n // Whether READ/WRITE have been anchored to the first inserted sample (buffered mode).\n #anchored = false;\n constructor(init) {\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.#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 }\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.buffered && !this.#anchored) {\n Atomics.store(this.#control, READ, start | 0);\n Atomics.store(this.#control, WRITE, start | 0);\n this.#anchored = true;\n }\n const end = start + originalLength | 0;\n const read = Atomics.load(this.#control, READ);\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 casAdvance(this.#control, READ, 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 const currentRead = Atomics.load(this.#control, READ);\n const currentWrite = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n if ((currentWrite - currentRead | 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 if (Atomics.load(this.#control, STALLED) === 1) return 0;\n let read = Atomics.load(this.#control, READ);\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 read = casAdvance(this.#control, READ, skipTo);\n }\n const available = write - read | 0;\n const count = Math.min(available, output[0].length);\n if (count <= 0) return 0;\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 casAdvance(this.#control, READ, read + count | 0);\n return count;\n }\n /** Update the target latency in samples. */\n setLatency(samples) {\n Atomics.store(this.#control, LATENCY, samples);\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 Atomics.store(this.#control, READ, 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 const read = Atomics.load(this.#control, READ);\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, READ, copyStart);\n Atomics.store(dst.#control, WRITE, write);\n Atomics.store(dst.#control, LATENCY, latency);\n Atomics.store(dst.#control, STALLED, stalled);\n return dst;\n }\n /** Current playback timestamp derived from READ position. */\n get timestamp() {\n const read = Atomics.load(this.#control, READ);\n return time_exports.Micro.fromSecond(read / 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) - Atomics.load(this.#control, READ) | 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 this.#backend = new SharedRingBuffer(msg);\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 === \"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" }), ee = URL.createObjectURL(k);
|
|
263
|
+
}, A = 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.isInteger(unitsPerSecond) || unitsPerSecond <= 0) {\n throw new Error(`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);\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 if (!Number.isFinite(value) || value < 0) {\n throw new Error(`invalid timestamp: ${value}`);\n }\n this.value = value;\n this.scale = 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` (a raw number, not a new Timestamp). */\n as(scale) {\n return scale === this.scale ? this.value : this.value * scale / this.scale;\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: anchor to the first sample, play through 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 this.#latencySamples = Math.ceil(this.rate * time_exports.Second.fromMilli(latency));\n const newCapacity = this.#capacityFor(this.#latencySamples);\n if (newCapacity === this.capacity) return;\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.#buffered && !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 // 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 READ = 1;\nvar LATENCY = 2;\nvar STALLED = 3;\nvar CONTROL_SLOTS = 4;\nfunction allocSharedRingBuffer(channels, capacity, rate, buffered = false) {\n if (channels <= 0) throw new Error(\"invalid channels\");\n if (capacity <= 0) throw new Error(\"invalid capacity\");\n if (rate <= 0) throw new Error(\"invalid sample rate\");\n const samples = new SharedArrayBuffer(channels * capacity * Float32Array.BYTES_PER_ELEMENT);\n const control = new SharedArrayBuffer(CONTROL_SLOTS * Int32Array.BYTES_PER_ELEMENT);\n const ctrl = new Int32Array(control);\n Atomics.store(ctrl, STALLED, 1);\n return { channels, capacity, rate, samples, control, buffered };\n}\nfunction i32Max(a, b) {\n return (a - b | 0) > 0 ? a : b;\n}\nfunction slot(idx, capacity) {\n return (idx % capacity + capacity) % capacity;\n}\nfunction casAdvance(arr, idx, candidate) {\n for (; ; ) {\n const current = Atomics.load(arr, idx);\n if ((candidate - current | 0) <= 0) return current;\n const witnessed = Atomics.compareExchange(arr, idx, current, candidate);\n if (witnessed === current) return candidate;\n }\n}\nvar SharedRingBuffer = class _SharedRingBuffer {\n channels;\n capacity;\n rate;\n buffered;\n init;\n #control;\n #samples;\n // Whether READ/WRITE have been anchored to the first inserted sample (buffered mode).\n #anchored = false;\n constructor(init) {\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.#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 }\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.buffered && !this.#anchored) {\n Atomics.store(this.#control, READ, start | 0);\n Atomics.store(this.#control, WRITE, start | 0);\n this.#anchored = true;\n }\n const end = start + originalLength | 0;\n const read = Atomics.load(this.#control, READ);\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 casAdvance(this.#control, READ, 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 const currentRead = Atomics.load(this.#control, READ);\n const currentWrite = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n if ((currentWrite - currentRead | 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 if (Atomics.load(this.#control, STALLED) === 1) return 0;\n let read = Atomics.load(this.#control, READ);\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 read = casAdvance(this.#control, READ, skipTo);\n }\n const available = write - read | 0;\n const count = Math.min(available, output[0].length);\n if (count <= 0) return 0;\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 casAdvance(this.#control, READ, read + count | 0);\n return count;\n }\n /** Update the target latency in samples. */\n setLatency(samples) {\n Atomics.store(this.#control, LATENCY, samples);\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 Atomics.store(this.#control, READ, 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 const read = Atomics.load(this.#control, READ);\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, READ, copyStart);\n Atomics.store(dst.#control, WRITE, write);\n Atomics.store(dst.#control, LATENCY, latency);\n Atomics.store(dst.#control, STALLED, stalled);\n return dst;\n }\n /** Current playback timestamp derived from READ position. */\n get timestamp() {\n const read = Atomics.load(this.#control, READ);\n return time_exports.Micro.fromSecond(read / 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) - Atomics.load(this.#control, READ) | 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 this.#backend = new SharedRingBuffer(msg);\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 === \"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" }), j = URL.createObjectURL(A);
|
|
263
264
|
//#endregion
|
|
264
265
|
//#region src/audio/unlock.ts
|
|
265
|
-
function
|
|
266
|
-
let n = new
|
|
266
|
+
function ee(e, t) {
|
|
267
|
+
let n = new i(t.state === "running");
|
|
267
268
|
e.event(t, "statechange", () => n.set(t.state === "running")), e.run((e) => {
|
|
268
269
|
if (e.get(n)) return;
|
|
269
270
|
let r = () => {
|
|
@@ -274,72 +275,85 @@ function te(e, t) {
|
|
|
274
275
|
}
|
|
275
276
|
//#endregion
|
|
276
277
|
//#region src/audio/decoder.ts
|
|
277
|
-
var
|
|
278
|
+
var te = 150, ne = class {
|
|
278
279
|
in;
|
|
279
280
|
source;
|
|
280
281
|
sync;
|
|
281
282
|
#e = {
|
|
282
|
-
context: new
|
|
283
|
-
root: new
|
|
284
|
-
sampleRate: new
|
|
285
|
-
stats: new
|
|
286
|
-
timestamp: new
|
|
287
|
-
stalled: new
|
|
288
|
-
buffered: new
|
|
283
|
+
context: new i(void 0),
|
|
284
|
+
root: new i(void 0),
|
|
285
|
+
sampleRate: new i(void 0),
|
|
286
|
+
stats: new i(void 0),
|
|
287
|
+
timestamp: new i(void 0),
|
|
288
|
+
stalled: new i(!0),
|
|
289
|
+
buffered: new i([])
|
|
289
290
|
};
|
|
290
|
-
out =
|
|
291
|
-
#t = new
|
|
291
|
+
out = o(this.#e);
|
|
292
|
+
#t = new i([]);
|
|
292
293
|
#n;
|
|
293
|
-
#r = new
|
|
294
|
+
#r = new i(void 0);
|
|
294
295
|
#i = 0;
|
|
295
|
-
#a = new
|
|
296
|
-
#o
|
|
296
|
+
#a = new i(n.Milli.zero);
|
|
297
|
+
#o;
|
|
298
|
+
#s = new r();
|
|
297
299
|
constructor(e, t, n) {
|
|
298
|
-
this.in = { enabled:
|
|
300
|
+
this.in = { enabled: a(n?.enabled ?? !1) }, this.source = e, this.sync = t, this.#s.run((e) => {
|
|
299
301
|
this.#a.set(e.get(this.sync.out.maxBuffer));
|
|
300
|
-
}), this.#
|
|
302
|
+
}), this.#s.run(this.#c.bind(this)), this.#s.run(this.#l.bind(this)), this.#s.run(this.#u.bind(this)), this.#s.run(this.#d.bind(this)), this.#s.run(this.#f.bind(this));
|
|
301
303
|
}
|
|
302
|
-
#
|
|
303
|
-
let
|
|
304
|
-
if (!
|
|
305
|
-
let r = e.get(this.#r) ??
|
|
304
|
+
#c(e) {
|
|
305
|
+
let t = e.get(this.source.out.config);
|
|
306
|
+
if (!t) return;
|
|
307
|
+
let r = e.get(this.#r) ?? t.sampleRate, i = t.numberOfChannels;
|
|
306
308
|
e.set(this.#e.sampleRate, r);
|
|
307
309
|
let a = new AudioContext({
|
|
308
310
|
latencyHint: "interactive",
|
|
309
311
|
sampleRate: r
|
|
310
312
|
});
|
|
311
313
|
e.set(this.#e.context, a), e.cleanup(() => a.close()), e.spawn(async () => {
|
|
312
|
-
if (!await Promise.race([a.audioWorklet.addModule(
|
|
313
|
-
let
|
|
314
|
+
if (!await Promise.race([a.audioWorklet.addModule(j).then(() => !0), e.cancel])) return;
|
|
315
|
+
let t = new AudioWorkletNode(a, "render", {
|
|
314
316
|
channelCount: i,
|
|
315
317
|
channelCountMode: "explicit",
|
|
316
318
|
outputChannelCount: [i]
|
|
317
319
|
});
|
|
318
|
-
e.cleanup(() =>
|
|
319
|
-
let o = this.sync.out.buffer.peek(), s = Math.ceil(r *
|
|
320
|
+
e.cleanup(() => t.disconnect());
|
|
321
|
+
let o = this.sync.out.buffer.peek(), s = Math.ceil(r * n.Second.fromMilli(o)), c = this.sync.out.buffered.peek(), l = D(t, i, r, s, c);
|
|
320
322
|
this.#n = l, e.cleanup(() => {
|
|
321
323
|
l.close(), this.#n = void 0;
|
|
322
324
|
}), e.run((e) => {
|
|
323
|
-
let
|
|
324
|
-
this.#e.timestamp.set(
|
|
325
|
+
let t = n.Milli.fromMicro(e.get(l.timestamp));
|
|
326
|
+
this.#e.timestamp.set(t), this.#_(t);
|
|
325
327
|
}), e.run((e) => {
|
|
326
328
|
this.#e.stalled.set(e.get(l.stalled));
|
|
327
|
-
}), e.set(this.#e.root,
|
|
329
|
+
}), e.set(this.#e.root, t);
|
|
328
330
|
});
|
|
329
331
|
}
|
|
330
|
-
#
|
|
332
|
+
#l(e) {
|
|
331
333
|
if (!e.get(this.in.enabled)) return;
|
|
332
334
|
let t = e.get(this.#e.context);
|
|
333
|
-
t &&
|
|
335
|
+
t && ee(e, t);
|
|
334
336
|
}
|
|
335
|
-
#
|
|
337
|
+
#u(e) {
|
|
336
338
|
if (!e.get(this.#e.root)) return;
|
|
337
|
-
let
|
|
338
|
-
if (!
|
|
339
|
-
let r = e.get(this.sync.out.buffer), i = Math.ceil(
|
|
340
|
-
|
|
339
|
+
let t = this.#n;
|
|
340
|
+
if (!t) return;
|
|
341
|
+
let r = e.get(this.sync.out.buffer), i = Math.ceil(t.rate * n.Second.fromMilli(r));
|
|
342
|
+
t.setLatency(i);
|
|
341
343
|
}
|
|
342
|
-
#
|
|
344
|
+
#d(t) {
|
|
345
|
+
let n = e(t.get(this.sync.in.latency)).min;
|
|
346
|
+
if (this.#o === void 0) {
|
|
347
|
+
this.#o = n;
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
let r = this.#o;
|
|
351
|
+
t.timer(() => {
|
|
352
|
+
let e = (e) => e === "real-time" ? 0 : e;
|
|
353
|
+
e(n) > e(r) && this.reset(), this.#o = n;
|
|
354
|
+
}, te);
|
|
355
|
+
}
|
|
356
|
+
#f(e) {
|
|
343
357
|
if (!e.get(this.in.enabled)) return;
|
|
344
358
|
let t = e.get(this.source.in.broadcast);
|
|
345
359
|
if (!t) return;
|
|
@@ -349,72 +363,72 @@ var A = class {
|
|
|
349
363
|
if (!r) return;
|
|
350
364
|
let i = t.relativeBroadcast(e, r.broadcast);
|
|
351
365
|
if (!i) return;
|
|
352
|
-
let a = i.track(n).subscribe({ priority:
|
|
353
|
-
e.cleanup(() => a.close()), r.container.kind === "cmaf" ? this.#
|
|
366
|
+
let a = i.track(n).subscribe({ priority: s.PRIORITY.audio });
|
|
367
|
+
e.cleanup(() => a.close()), r.container.kind === "cmaf" ? this.#m(e, a, r) : this.#p(e, a, r);
|
|
354
368
|
}
|
|
355
|
-
#
|
|
356
|
-
let i = r.container.kind === "loc" ? new
|
|
369
|
+
#p(e, t, r) {
|
|
370
|
+
let i = r.container.kind === "loc" ? new l.Loc.Format() : new l.Legacy.Format(), a = new l.Consumer(t, {
|
|
357
371
|
format: i,
|
|
358
372
|
latency: this.#a
|
|
359
373
|
});
|
|
360
374
|
e.cleanup(() => a.close()), e.run((e) => {
|
|
361
375
|
let t = e.get(a.buffered), n = e.get(this.#t);
|
|
362
|
-
this.#e.buffered.update(() =>
|
|
376
|
+
this.#e.buffered.update(() => l.mergeBufferedRanges(t, n));
|
|
363
377
|
}), e.spawn(async () => {
|
|
364
|
-
if (!await
|
|
365
|
-
let
|
|
378
|
+
if (!await u.Libav.polyfill()) return;
|
|
379
|
+
let t = 0, i = new AudioDecoder({
|
|
366
380
|
output: (e) => {
|
|
367
|
-
if (
|
|
381
|
+
if (t++, t <= 3) {
|
|
368
382
|
e.close();
|
|
369
383
|
return;
|
|
370
384
|
}
|
|
371
|
-
this.#
|
|
385
|
+
this.#h(e);
|
|
372
386
|
},
|
|
373
387
|
error: (e) => console.error("audio decoder error", e)
|
|
374
388
|
});
|
|
375
389
|
e.cleanup(() => {
|
|
376
390
|
i.state !== "closed" && i.close();
|
|
377
391
|
});
|
|
378
|
-
let o = r.codec === "opus" ? void 0 : r.description ?
|
|
392
|
+
let o = r.codec === "opus" ? void 0 : r.description ? u.Hex.toBytes(r.description) : void 0;
|
|
379
393
|
for (i.configure({
|
|
380
394
|
...r,
|
|
381
395
|
description: o
|
|
382
396
|
});;) {
|
|
383
397
|
let e = await a.next();
|
|
384
398
|
if (!e) break;
|
|
385
|
-
this.#
|
|
386
|
-
let { frame:
|
|
387
|
-
if (!
|
|
388
|
-
let r =
|
|
389
|
-
this.sync.received(r, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) +
|
|
399
|
+
this.#v(e.discontinuity);
|
|
400
|
+
let { frame: t } = e;
|
|
401
|
+
if (!t) continue;
|
|
402
|
+
let r = n.Milli.fromMicro(t.timestamp);
|
|
403
|
+
this.sync.received(r, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) + t.payload.byteLength })), await this.#n?.wait(t.timestamp);
|
|
390
404
|
let o = new EncodedAudioChunk({
|
|
391
|
-
type:
|
|
392
|
-
data:
|
|
393
|
-
timestamp:
|
|
405
|
+
type: t.keyframe ? "key" : "delta",
|
|
406
|
+
data: t.payload,
|
|
407
|
+
timestamp: t.timestamp
|
|
394
408
|
});
|
|
395
409
|
if (i.state === "closed") break;
|
|
396
410
|
i.decode(o);
|
|
397
411
|
}
|
|
398
412
|
});
|
|
399
413
|
}
|
|
400
|
-
#
|
|
414
|
+
#m(e, t, r) {
|
|
401
415
|
if (r.container.kind !== "cmaf") return;
|
|
402
|
-
let i =
|
|
403
|
-
format: new
|
|
416
|
+
let i = p(r.container.init), a = l.Cmaf.decodeInitSegment(i), o = r.codec === "opus" ? void 0 : r.description ? u.Hex.toBytes(r.description) : a.description, s = new l.Consumer(t, {
|
|
417
|
+
format: new l.Cmaf.Format(a),
|
|
404
418
|
latency: this.#a
|
|
405
419
|
});
|
|
406
420
|
e.cleanup(() => s.close()), e.run((e) => {
|
|
407
421
|
let t = e.get(s.buffered), n = e.get(this.#t);
|
|
408
|
-
this.#e.buffered.update(() =>
|
|
422
|
+
this.#e.buffered.update(() => l.mergeBufferedRanges(t, n));
|
|
409
423
|
}), e.spawn(async () => {
|
|
410
|
-
if (!await
|
|
411
|
-
let
|
|
412
|
-
output: (e) => this.#
|
|
424
|
+
if (!await u.Libav.polyfill()) return;
|
|
425
|
+
let t = new AudioDecoder({
|
|
426
|
+
output: (e) => this.#h(e),
|
|
413
427
|
error: (e) => console.error("audio decoder error", e)
|
|
414
428
|
});
|
|
415
429
|
for (e.cleanup(() => {
|
|
416
|
-
|
|
417
|
-
}),
|
|
430
|
+
t.state !== "closed" && t.close();
|
|
431
|
+
}), t.configure({
|
|
418
432
|
codec: r.codec,
|
|
419
433
|
sampleRate: r.sampleRate,
|
|
420
434
|
numberOfChannels: r.numberOfChannels,
|
|
@@ -422,12 +436,12 @@ var A = class {
|
|
|
422
436
|
});;) {
|
|
423
437
|
let e = await s.next();
|
|
424
438
|
if (!e) break;
|
|
425
|
-
this.#
|
|
439
|
+
this.#v(e.discontinuity);
|
|
426
440
|
let { frame: r } = e;
|
|
427
441
|
if (!r) continue;
|
|
428
|
-
let i =
|
|
429
|
-
if (this.sync.received(i, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) + r.payload.byteLength })), await this.#n?.wait(r.timestamp),
|
|
430
|
-
|
|
442
|
+
let i = n.Milli.fromMicro(r.timestamp);
|
|
443
|
+
if (this.sync.received(i, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) + r.payload.byteLength })), await this.#n?.wait(r.timestamp), t.state === "closed") break;
|
|
444
|
+
t.decode(new EncodedAudioChunk({
|
|
431
445
|
type: r.keyframe ? "key" : "delta",
|
|
432
446
|
data: r.payload,
|
|
433
447
|
timestamp: r.timestamp
|
|
@@ -435,8 +449,8 @@ var A = class {
|
|
|
435
449
|
}
|
|
436
450
|
});
|
|
437
451
|
}
|
|
438
|
-
#
|
|
439
|
-
let
|
|
452
|
+
#h(e) {
|
|
453
|
+
let t = e.timestamp, r = n.Milli.fromMicro(t), i = this.#n;
|
|
440
454
|
if (!i) {
|
|
441
455
|
e.close();
|
|
442
456
|
return;
|
|
@@ -445,8 +459,8 @@ var A = class {
|
|
|
445
459
|
this.#r.set(e.sampleRate), e.close();
|
|
446
460
|
return;
|
|
447
461
|
}
|
|
448
|
-
let a = e.numberOfFrames / e.sampleRate * 1e6, o =
|
|
449
|
-
this.#
|
|
462
|
+
let a = e.numberOfFrames / e.sampleRate * 1e6, o = n.Milli.fromMicro(a), s = n.Milli.add(r, o);
|
|
463
|
+
this.#g(r, s);
|
|
450
464
|
let c = Math.min(e.numberOfChannels, i.channels), l = [];
|
|
451
465
|
for (let t = 0; t < c; t++) {
|
|
452
466
|
let n = new Float32Array(e.numberOfFrames);
|
|
@@ -455,53 +469,53 @@ var A = class {
|
|
|
455
469
|
planeIndex: t
|
|
456
470
|
}), l.push(n);
|
|
457
471
|
}
|
|
458
|
-
i.insert(
|
|
472
|
+
i.insert(t, l), e.close();
|
|
459
473
|
}
|
|
460
|
-
#
|
|
461
|
-
e >
|
|
462
|
-
for (let i of r) if (e <= i.end + 1 &&
|
|
463
|
-
i.start =
|
|
474
|
+
#g(e, t) {
|
|
475
|
+
e > t || this.#t.mutate((r) => {
|
|
476
|
+
for (let i of r) if (e <= i.end + 1 && t >= i.start) {
|
|
477
|
+
i.start = n.Milli.min(i.start, e), i.end = n.Milli.max(i.end, t);
|
|
464
478
|
return;
|
|
465
479
|
}
|
|
466
480
|
r.push({
|
|
467
481
|
start: e,
|
|
468
|
-
end:
|
|
482
|
+
end: t
|
|
469
483
|
}), r.sort((e, t) => e.start - t.start);
|
|
470
484
|
});
|
|
471
485
|
}
|
|
472
|
-
#
|
|
473
|
-
this.#t.mutate((
|
|
474
|
-
for (;
|
|
475
|
-
if (
|
|
476
|
-
|
|
486
|
+
#_(e) {
|
|
487
|
+
this.#t.mutate((t) => {
|
|
488
|
+
for (; t.length > 0;) {
|
|
489
|
+
if (t[0].end >= e) {
|
|
490
|
+
t[0].start = n.Milli.max(t[0].start, e);
|
|
477
491
|
break;
|
|
478
492
|
}
|
|
479
|
-
|
|
493
|
+
t.shift();
|
|
480
494
|
}
|
|
481
495
|
});
|
|
482
496
|
}
|
|
483
497
|
reset() {
|
|
484
498
|
this.#n?.reset();
|
|
485
499
|
}
|
|
486
|
-
#
|
|
500
|
+
#v(e) {
|
|
487
501
|
e !== this.#i && (this.#i = e, this.#n?.reset(), this.sync.reset());
|
|
488
502
|
}
|
|
489
503
|
close() {
|
|
490
|
-
this.#
|
|
504
|
+
this.#s.close();
|
|
491
505
|
}
|
|
492
|
-
static supported =
|
|
506
|
+
static supported = re;
|
|
493
507
|
};
|
|
494
|
-
async function
|
|
495
|
-
if (!
|
|
508
|
+
async function re(e) {
|
|
509
|
+
if (!s.containerSupported(e.container)) {
|
|
496
510
|
let t = e.container.kind === "unknown" ? e.container.raw.kind : e.container.kind;
|
|
497
511
|
return console.warn(`audio: ignoring rendition with unknown container: ${t}`), !1;
|
|
498
512
|
}
|
|
499
|
-
e.codec === "opus" && !
|
|
513
|
+
e.codec === "opus" && !u.Opus.supportsRate(e.sampleRate) && console.warn(`audio: opus advertised at ${e.sampleRate}Hz, which some browsers cannot decode`);
|
|
500
514
|
let t;
|
|
501
515
|
if (e.codec !== "opus") {
|
|
502
|
-
if (e.description) t =
|
|
516
|
+
if (e.description) t = u.Hex.toBytes(e.description);
|
|
503
517
|
else if (e.container.kind === "cmaf") try {
|
|
504
|
-
t =
|
|
518
|
+
t = l.Cmaf.decodeInitSegment(p(e.container.init)).description;
|
|
505
519
|
} catch (t) {
|
|
506
520
|
return console.warn(`audio: malformed CMAF init segment for codec ${e.codec}`, t), !1;
|
|
507
521
|
}
|
|
@@ -516,15 +530,15 @@ async function j(e) {
|
|
|
516
530
|
var M = .001, N = .2, P = class {
|
|
517
531
|
source;
|
|
518
532
|
in;
|
|
519
|
-
#e = { enabled: new
|
|
520
|
-
out =
|
|
521
|
-
#t = new
|
|
522
|
-
#n = new
|
|
533
|
+
#e = { enabled: new i(!1) };
|
|
534
|
+
out = o(this.#e);
|
|
535
|
+
#t = new r();
|
|
536
|
+
#n = new i(void 0);
|
|
523
537
|
constructor(e, t) {
|
|
524
538
|
this.source = e, this.in = {
|
|
525
|
-
volume:
|
|
526
|
-
muted:
|
|
527
|
-
paused:
|
|
539
|
+
volume: a(t?.volume ?? .5),
|
|
540
|
+
muted: a(t?.muted ?? !1),
|
|
541
|
+
paused: a(t?.paused ?? !1)
|
|
528
542
|
}, this.#t.run((e) => {
|
|
529
543
|
let t = !e.get(this.in.paused) && !e.get(this.in.muted);
|
|
530
544
|
this.#e.enabled.set(t);
|
|
@@ -549,19 +563,19 @@ var M = .001, N = .2, P = class {
|
|
|
549
563
|
}, F = 128, I = class {
|
|
550
564
|
in;
|
|
551
565
|
#e = {
|
|
552
|
-
catalog: new
|
|
553
|
-
available: new
|
|
554
|
-
track: new
|
|
555
|
-
config: new
|
|
556
|
-
jitter: new
|
|
566
|
+
catalog: new i(void 0),
|
|
567
|
+
available: new i({}),
|
|
568
|
+
track: new i(void 0),
|
|
569
|
+
config: new i(void 0),
|
|
570
|
+
jitter: new i(void 0)
|
|
557
571
|
};
|
|
558
|
-
out =
|
|
559
|
-
#t = new
|
|
572
|
+
out = o(this.#e);
|
|
573
|
+
#t = new r();
|
|
560
574
|
constructor(e) {
|
|
561
575
|
this.in = {
|
|
562
|
-
broadcast:
|
|
563
|
-
target:
|
|
564
|
-
supported:
|
|
576
|
+
broadcast: a(e?.broadcast),
|
|
577
|
+
target: a(e?.target),
|
|
578
|
+
supported: a(e?.supported)
|
|
565
579
|
}, this.#t.run(this.#n.bind(this)), this.#t.run(this.#r.bind(this)), this.#t.run(this.#i.bind(this));
|
|
566
580
|
}
|
|
567
581
|
#n(e) {
|
|
@@ -579,17 +593,17 @@ var M = .001, N = .2, P = class {
|
|
|
579
593
|
});
|
|
580
594
|
}
|
|
581
595
|
#i(e) {
|
|
582
|
-
let
|
|
583
|
-
if (Object.keys(
|
|
596
|
+
let t = e.get(this.#e.available);
|
|
597
|
+
if (Object.keys(t).length === 0) return;
|
|
584
598
|
let r = e.get(this.in.target), i;
|
|
585
|
-
if (r?.name && r.name in
|
|
599
|
+
if (r?.name && r.name in t) i = {
|
|
586
600
|
track: r.name,
|
|
587
|
-
config:
|
|
601
|
+
config: t[r.name]
|
|
588
602
|
};
|
|
589
|
-
else if (i = this.#a(
|
|
603
|
+
else if (i = this.#a(t), !i) return;
|
|
590
604
|
e.set(this.#e.track, i.track), e.set(this.#e.config, i.config);
|
|
591
605
|
let a = (i.config.jitter ?? L(i.config) ?? 0) + Math.ceil(F / i.config.sampleRate * 1e3);
|
|
592
|
-
e.set(this.#e.jitter,
|
|
606
|
+
e.set(this.#e.jitter, n.Milli(a));
|
|
593
607
|
}
|
|
594
608
|
#a(e) {
|
|
595
609
|
let t = Object.entries(e);
|
|
@@ -631,7 +645,7 @@ function B(e) {
|
|
|
631
645
|
function V(e) {
|
|
632
646
|
let t;
|
|
633
647
|
try {
|
|
634
|
-
t = e.initData ?
|
|
648
|
+
t = e.initData ? p(e.initData) : void 0;
|
|
635
649
|
} catch {
|
|
636
650
|
t = void 0;
|
|
637
651
|
}
|
|
@@ -653,11 +667,11 @@ function H(e) {
|
|
|
653
667
|
codec: e.codec,
|
|
654
668
|
container: t,
|
|
655
669
|
description: n,
|
|
656
|
-
codedWidth: e.width == null ? void 0 :
|
|
657
|
-
codedHeight: e.height == null ? void 0 :
|
|
670
|
+
codedWidth: e.width == null ? void 0 : c(e.width),
|
|
671
|
+
codedHeight: e.height == null ? void 0 : c(e.height),
|
|
658
672
|
framerate: e.framerate,
|
|
659
|
-
bitrate: e.bitrate == null ? void 0 :
|
|
660
|
-
jitter: e.jitter == null ? void 0 :
|
|
673
|
+
bitrate: e.bitrate == null ? void 0 : c(e.bitrate),
|
|
674
|
+
jitter: e.jitter == null ? void 0 : c(e.jitter)
|
|
661
675
|
};
|
|
662
676
|
}
|
|
663
677
|
function U(e) {
|
|
@@ -671,10 +685,10 @@ function U(e) {
|
|
|
671
685
|
codec: e.codec,
|
|
672
686
|
container: n,
|
|
673
687
|
description: r,
|
|
674
|
-
sampleRate:
|
|
675
|
-
numberOfChannels:
|
|
676
|
-
bitrate: e.bitrate == null ? void 0 :
|
|
677
|
-
jitter: e.jitter == null ? void 0 :
|
|
688
|
+
sampleRate: c(e.samplerate ?? R),
|
|
689
|
+
numberOfChannels: c(t),
|
|
690
|
+
bitrate: e.bitrate == null ? void 0 : c(e.bitrate),
|
|
691
|
+
jitter: e.jitter == null ? void 0 : c(e.jitter)
|
|
678
692
|
};
|
|
679
693
|
}
|
|
680
694
|
function W(e) {
|
|
@@ -696,45 +710,45 @@ function K(e) {
|
|
|
696
710
|
return e.discovery ? !1 : (G.has(e) || (G.add(e), console.warn("relay does not support broadcast discovery; ignoring reload signal.")), !0);
|
|
697
711
|
}
|
|
698
712
|
var q = [
|
|
699
|
-
...
|
|
713
|
+
...s.FORMATS,
|
|
700
714
|
"hangz",
|
|
701
715
|
"manual"
|
|
702
716
|
];
|
|
703
|
-
function
|
|
717
|
+
function ie(e) {
|
|
704
718
|
if (e !== null) return q.find((t) => t === e);
|
|
705
719
|
}
|
|
706
|
-
var
|
|
720
|
+
var J = class {
|
|
707
721
|
in;
|
|
708
722
|
#e = {
|
|
709
|
-
status: new
|
|
710
|
-
active: new
|
|
711
|
-
catalog: new
|
|
723
|
+
status: new i("offline"),
|
|
724
|
+
active: new i(void 0),
|
|
725
|
+
catalog: new i(void 0)
|
|
712
726
|
};
|
|
713
|
-
out =
|
|
714
|
-
#t = new
|
|
715
|
-
#n = new
|
|
716
|
-
#r = new
|
|
717
|
-
constructor(
|
|
727
|
+
out = o(this.#e);
|
|
728
|
+
#t = new i(void 0);
|
|
729
|
+
#n = new i(!1);
|
|
730
|
+
#r = new r();
|
|
731
|
+
constructor(e) {
|
|
718
732
|
this.in = {
|
|
719
|
-
connection:
|
|
720
|
-
name:
|
|
721
|
-
enabled:
|
|
722
|
-
reload:
|
|
723
|
-
catalogFormat:
|
|
724
|
-
catalog:
|
|
733
|
+
connection: a(e?.connection),
|
|
734
|
+
name: a(e?.name ?? t.empty()),
|
|
735
|
+
enabled: a(e?.enabled ?? !1),
|
|
736
|
+
reload: a(e?.reload ?? !0),
|
|
737
|
+
catalogFormat: a(e?.catalogFormat),
|
|
738
|
+
catalog: a(e?.catalog)
|
|
725
739
|
}, this.#r.run(this.#i.bind(this)), this.#r.run(this.#o.bind(this)), this.#r.run(this.#s.bind(this));
|
|
726
740
|
}
|
|
727
|
-
#i(
|
|
728
|
-
if (this.#t.set(void 0), !
|
|
729
|
-
let n =
|
|
741
|
+
#i(e) {
|
|
742
|
+
if (this.#t.set(void 0), !e.get(this.#n) || !e.get(this.in.reload)) return;
|
|
743
|
+
let n = e.get(this.in.connection);
|
|
730
744
|
if (!n || K(n)) return;
|
|
731
|
-
let r = n.announced(
|
|
732
|
-
|
|
745
|
+
let r = n.announced(t.empty());
|
|
746
|
+
e.cleanup(() => r.close()), this.#t.set(/* @__PURE__ */ new Set()), e.spawn(async () => {
|
|
733
747
|
for (;;) {
|
|
734
|
-
let
|
|
735
|
-
if (!
|
|
736
|
-
this.#t.mutate((
|
|
737
|
-
|
|
748
|
+
let t = await Promise.race([e.cancel, r.next()]);
|
|
749
|
+
if (!t) break;
|
|
750
|
+
this.#t.mutate((e) => {
|
|
751
|
+
e && (t.active ? e.add(t.path) : e.delete(t.path));
|
|
738
752
|
});
|
|
739
753
|
}
|
|
740
754
|
});
|
|
@@ -747,26 +761,26 @@ var Y = class {
|
|
|
747
761
|
let r = e.get(this.#t);
|
|
748
762
|
return r ? r.has(t) : !1;
|
|
749
763
|
}
|
|
750
|
-
#o(
|
|
751
|
-
if (!
|
|
752
|
-
let n =
|
|
764
|
+
#o(e) {
|
|
765
|
+
if (!e.get(this.in.enabled)) return;
|
|
766
|
+
let n = e.get(this.in.connection);
|
|
753
767
|
if (!n) return;
|
|
754
|
-
let r =
|
|
755
|
-
if (!
|
|
756
|
-
let
|
|
757
|
-
|
|
768
|
+
let r = e.get(this.in.name);
|
|
769
|
+
if (!e.get(this.in.reload) || K(n)) {
|
|
770
|
+
let t = n.consume(r);
|
|
771
|
+
e.cleanup(() => t.close()), e.set(this.#e.active, t, void 0);
|
|
758
772
|
return;
|
|
759
773
|
}
|
|
760
774
|
let i = n.announced(r);
|
|
761
|
-
|
|
775
|
+
e.cleanup(() => i.close());
|
|
762
776
|
let a;
|
|
763
|
-
|
|
777
|
+
e.cleanup(() => {
|
|
764
778
|
a?.close(), a = void 0, this.#e.active.set(void 0);
|
|
765
|
-
}),
|
|
779
|
+
}), e.spawn(async () => {
|
|
766
780
|
for (;;) {
|
|
767
|
-
let o = await Promise.race([
|
|
781
|
+
let o = await Promise.race([e.cancel, i.next()]);
|
|
768
782
|
if (!o) break;
|
|
769
|
-
if (o.path ===
|
|
783
|
+
if (o.path === t.empty()) if (o.active) {
|
|
770
784
|
if (a && a.closed.peek() === void 0) continue;
|
|
771
785
|
a?.close(), a = n.consume(r), this.#e.active.set(a);
|
|
772
786
|
} else a?.close(), a = void 0, this.#e.active.set(void 0);
|
|
@@ -775,7 +789,7 @@ var Y = class {
|
|
|
775
789
|
}
|
|
776
790
|
#s(e) {
|
|
777
791
|
if (!e.get(this.in.enabled)) return;
|
|
778
|
-
let t = e.get(this.in.catalogFormat), n = e.get(this.in.name), r = t ??
|
|
792
|
+
let t = e.get(this.in.catalogFormat), n = e.get(this.in.name), r = t ?? s.detectFormat(n) ?? s.DEFAULT_FORMAT;
|
|
779
793
|
if (r === "manual") {
|
|
780
794
|
let t = e.get(this.in.catalog);
|
|
781
795
|
e.set(this.#e.catalog, t, void 0), this.#e.status.set(t ? "live" : "loading");
|
|
@@ -784,17 +798,17 @@ var Y = class {
|
|
|
784
798
|
let i = e.get(this.out.active);
|
|
785
799
|
if (!i) return;
|
|
786
800
|
this.#e.status.set("loading");
|
|
787
|
-
let a = r === "hang" ?
|
|
788
|
-
e.cleanup(() =>
|
|
801
|
+
let a = r === "hang" ? s.TRACK : r === "hangz" ? s.TRACK_COMPRESSED : "catalog", o = i.track(a).subscribe({ priority: s.PRIORITY.catalog });
|
|
802
|
+
e.cleanup(() => o.close());
|
|
789
803
|
let c;
|
|
790
804
|
if (r === "hang" || r === "hangz") {
|
|
791
|
-
let e = new
|
|
792
|
-
schema:
|
|
805
|
+
let e = new d.Snapshot.Consumer(o, {
|
|
806
|
+
schema: s.RootSchema,
|
|
793
807
|
compression: r === "hangz"
|
|
794
808
|
});
|
|
795
809
|
c = () => e.next();
|
|
796
810
|
} else c = async () => {
|
|
797
|
-
let e = await
|
|
811
|
+
let e = await f.fetch(o);
|
|
798
812
|
return e ? W(e) : void 0;
|
|
799
813
|
};
|
|
800
814
|
e.spawn(async () => {
|
|
@@ -811,41 +825,123 @@ var Y = class {
|
|
|
811
825
|
}
|
|
812
826
|
});
|
|
813
827
|
}
|
|
814
|
-
relativeBroadcast(
|
|
815
|
-
if (!n) return
|
|
816
|
-
let r =
|
|
817
|
-
if (i === r || i ===
|
|
818
|
-
if (!
|
|
819
|
-
let a =
|
|
820
|
-
if (!a || !this.#a(
|
|
828
|
+
relativeBroadcast(e, n) {
|
|
829
|
+
if (!n) return e.get(this.out.active);
|
|
830
|
+
let r = e.get(this.in.name), i = t.resolve(r, n);
|
|
831
|
+
if (i === r || i === t.empty()) return e.get(this.out.active);
|
|
832
|
+
if (!e.get(this.in.enabled)) return;
|
|
833
|
+
let a = e.get(this.in.connection);
|
|
834
|
+
if (!a || !this.#a(e, i)) return;
|
|
821
835
|
let o = a.consume(i);
|
|
822
|
-
return
|
|
836
|
+
return e.cleanup(() => o.close()), o;
|
|
823
837
|
}
|
|
824
838
|
close() {
|
|
825
839
|
this.#r.close();
|
|
826
840
|
}
|
|
827
|
-
}
|
|
841
|
+
};
|
|
842
|
+
//#endregion
|
|
843
|
+
//#region src/video/presentation.ts
|
|
844
|
+
function Y(e = 0) {
|
|
845
|
+
let t = (e % 360 + 360) % 360;
|
|
846
|
+
return Math.round(t / 90) % 4 * 90;
|
|
847
|
+
}
|
|
848
|
+
function X(e, t = 0) {
|
|
849
|
+
let n = Y(t);
|
|
850
|
+
return n === 90 || n === 270 ? {
|
|
851
|
+
width: e.height,
|
|
852
|
+
height: e.width
|
|
853
|
+
} : {
|
|
854
|
+
width: e.width,
|
|
855
|
+
height: e.height
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
function Z(e) {
|
|
859
|
+
return Object.is(e, -0) ? 0 : e;
|
|
860
|
+
}
|
|
861
|
+
function ae(e, t) {
|
|
862
|
+
let [n, r, i, a, o, s] = e;
|
|
863
|
+
return [
|
|
864
|
+
Z(-n),
|
|
865
|
+
Z(r),
|
|
866
|
+
Z(-i),
|
|
867
|
+
Z(a),
|
|
868
|
+
Z(t - o),
|
|
869
|
+
Z(s)
|
|
870
|
+
];
|
|
871
|
+
}
|
|
872
|
+
function oe(e, t) {
|
|
873
|
+
let n = Y(t?.rotation), r = X(e, n), i;
|
|
874
|
+
switch (n) {
|
|
875
|
+
case 90:
|
|
876
|
+
i = [
|
|
877
|
+
0,
|
|
878
|
+
1,
|
|
879
|
+
-1,
|
|
880
|
+
0,
|
|
881
|
+
e.width,
|
|
882
|
+
0
|
|
883
|
+
];
|
|
884
|
+
break;
|
|
885
|
+
case 180:
|
|
886
|
+
i = [
|
|
887
|
+
-1,
|
|
888
|
+
0,
|
|
889
|
+
0,
|
|
890
|
+
-1,
|
|
891
|
+
e.width,
|
|
892
|
+
e.height
|
|
893
|
+
];
|
|
894
|
+
break;
|
|
895
|
+
case 270:
|
|
896
|
+
i = [
|
|
897
|
+
0,
|
|
898
|
+
-1,
|
|
899
|
+
1,
|
|
900
|
+
0,
|
|
901
|
+
0,
|
|
902
|
+
e.height
|
|
903
|
+
];
|
|
904
|
+
break;
|
|
905
|
+
default:
|
|
906
|
+
i = [
|
|
907
|
+
1,
|
|
908
|
+
0,
|
|
909
|
+
0,
|
|
910
|
+
1,
|
|
911
|
+
0,
|
|
912
|
+
0
|
|
913
|
+
];
|
|
914
|
+
break;
|
|
915
|
+
}
|
|
916
|
+
return t?.flip && (i = ae(i, e.width)), {
|
|
917
|
+
matrix: i,
|
|
918
|
+
source: r
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
//#endregion
|
|
922
|
+
//#region src/video/decoder.ts
|
|
923
|
+
var se = n.Milli(500), ce = n.Milli(100), le = class {
|
|
828
924
|
in;
|
|
829
925
|
source;
|
|
830
926
|
sync;
|
|
831
927
|
#e = {
|
|
832
|
-
frame: new
|
|
833
|
-
timestamp: new
|
|
834
|
-
display: new
|
|
835
|
-
stalled: new
|
|
836
|
-
stats: new
|
|
837
|
-
buffered: new
|
|
928
|
+
frame: new i(void 0),
|
|
929
|
+
timestamp: new i(void 0),
|
|
930
|
+
display: new i(void 0),
|
|
931
|
+
stalled: new i(!1),
|
|
932
|
+
stats: new i(void 0),
|
|
933
|
+
buffered: new i([])
|
|
838
934
|
};
|
|
839
|
-
out =
|
|
840
|
-
#t = new
|
|
841
|
-
#n = new
|
|
935
|
+
out = o(this.#e);
|
|
936
|
+
#t = new i(void 0);
|
|
937
|
+
#n = new r();
|
|
842
938
|
#r() {
|
|
843
939
|
this.#e.frame.update((e) => {
|
|
844
940
|
e?.close();
|
|
845
941
|
}), this.#e.timestamp.set(void 0);
|
|
846
942
|
}
|
|
847
943
|
constructor(e, t, n) {
|
|
848
|
-
this.in = { enabled:
|
|
944
|
+
this.in = { enabled: a(n?.enabled ?? !1) }, this.source = e, this.sync = t, this.#n.run(this.#i.bind(this)), this.#n.run(this.#a.bind(this)), this.#n.run(this.#o.bind(this)), this.#n.run(this.#s.bind(this));
|
|
849
945
|
}
|
|
850
946
|
#i(e) {
|
|
851
947
|
let t = e.getAll([
|
|
@@ -863,7 +959,7 @@ var Y = class {
|
|
|
863
959
|
this.#t.set(void 0), this.#r(), this.#e.buffered.set([]);
|
|
864
960
|
return;
|
|
865
961
|
}
|
|
866
|
-
let s = new
|
|
962
|
+
let s = new ue({
|
|
867
963
|
sync: this.sync,
|
|
868
964
|
broadcast: o,
|
|
869
965
|
track: i,
|
|
@@ -875,7 +971,7 @@ var Y = class {
|
|
|
875
971
|
let t = e.get(this.#t);
|
|
876
972
|
if (t) {
|
|
877
973
|
let n = e.get(s.timestamp), r = e.get(t.timestamp);
|
|
878
|
-
if (!n || r && r > n +
|
|
974
|
+
if (!n || r && r > n + ce) return;
|
|
879
975
|
}
|
|
880
976
|
this.#t.set(s), s = void 0, e.close();
|
|
881
977
|
});
|
|
@@ -903,10 +999,10 @@ var Y = class {
|
|
|
903
999
|
return;
|
|
904
1000
|
}
|
|
905
1001
|
let r = e.get(this.#e.frame);
|
|
906
|
-
r && e.set(this.#e.display, {
|
|
1002
|
+
r && e.set(this.#e.display, X({
|
|
907
1003
|
width: r.displayWidth,
|
|
908
1004
|
height: r.displayHeight
|
|
909
|
-
});
|
|
1005
|
+
}, t.rotation));
|
|
910
1006
|
}
|
|
911
1007
|
#s(e) {
|
|
912
1008
|
if (e.get(this.in.enabled)) {
|
|
@@ -916,43 +1012,43 @@ var Y = class {
|
|
|
916
1012
|
}
|
|
917
1013
|
this.#e.stalled.set(!1), e.timer(() => {
|
|
918
1014
|
this.#e.stalled.set(!0);
|
|
919
|
-
},
|
|
1015
|
+
}, se);
|
|
920
1016
|
}
|
|
921
1017
|
}
|
|
922
1018
|
close() {
|
|
923
1019
|
this.#r(), this.#n.close();
|
|
924
1020
|
}
|
|
925
|
-
static supported =
|
|
926
|
-
},
|
|
1021
|
+
static supported = Q;
|
|
1022
|
+
}, ue = class {
|
|
927
1023
|
sync;
|
|
928
1024
|
broadcast;
|
|
929
1025
|
track;
|
|
930
1026
|
config;
|
|
931
1027
|
stats;
|
|
932
|
-
timestamp = new
|
|
933
|
-
frame = new
|
|
934
|
-
buffered = new
|
|
935
|
-
#e = new
|
|
1028
|
+
timestamp = new i(void 0);
|
|
1029
|
+
frame = new i(void 0);
|
|
1030
|
+
buffered = new i([]);
|
|
1031
|
+
#e = new i([]);
|
|
936
1032
|
#t = 0;
|
|
937
|
-
#n = new
|
|
1033
|
+
#n = new r();
|
|
938
1034
|
constructor(e) {
|
|
939
1035
|
let { codedWidth: t, codedHeight: n, ...r } = e.config;
|
|
940
1036
|
this.sync = e.sync, this.broadcast = e.broadcast, this.track = e.track, this.config = r, this.stats = e.stats, this.#n.run(this.#r.bind(this));
|
|
941
1037
|
}
|
|
942
1038
|
#r(e) {
|
|
943
|
-
let
|
|
944
|
-
e.cleanup(() =>
|
|
1039
|
+
let t = this.broadcast.track(this.track).subscribe({ priority: s.PRIORITY.video });
|
|
1040
|
+
e.cleanup(() => t.close());
|
|
945
1041
|
let r = new VideoDecoder({
|
|
946
|
-
output: async (
|
|
1042
|
+
output: async (t) => {
|
|
947
1043
|
try {
|
|
948
|
-
let r = this.#t, i =
|
|
1044
|
+
let r = this.#t, i = n.Milli.fromMicro(t.timestamp);
|
|
949
1045
|
if (i < (this.timestamp.peek() ?? 0)) return;
|
|
950
|
-
this.frame.peek() === void 0 && this.frame.set(
|
|
1046
|
+
this.frame.peek() === void 0 && this.frame.set(t.clone());
|
|
951
1047
|
let a = this.sync.wait(i).then(() => !0);
|
|
952
1048
|
if (!await Promise.race([a, e.cancel]) || r !== this.#t || i < (this.timestamp.peek() ?? 0)) return;
|
|
953
|
-
this.timestamp.set(i), this.#c(i), this.frame.update((e) => (e?.close(),
|
|
1049
|
+
this.timestamp.set(i), this.#c(i), this.frame.update((e) => (e?.close(), t.clone()));
|
|
954
1050
|
} finally {
|
|
955
|
-
|
|
1051
|
+
t.close();
|
|
956
1052
|
}
|
|
957
1053
|
},
|
|
958
1054
|
error: (t) => {
|
|
@@ -961,19 +1057,19 @@ var Y = class {
|
|
|
961
1057
|
});
|
|
962
1058
|
e.cleanup(() => {
|
|
963
1059
|
r.state !== "closed" && r.close();
|
|
964
|
-
}), this.config.container.kind === "cmaf" ? this.#a(e,
|
|
1060
|
+
}), this.config.container.kind === "cmaf" ? this.#a(e, t, r) : this.#i(e, t, r);
|
|
965
1061
|
}
|
|
966
|
-
#i(e,
|
|
967
|
-
let i = this.config.container.kind === "loc" ? new
|
|
1062
|
+
#i(e, t, r) {
|
|
1063
|
+
let i = this.config.container.kind === "loc" ? new l.Loc.Format() : new l.Legacy.Format(), a = new l.Consumer(t, {
|
|
968
1064
|
format: i,
|
|
969
1065
|
latency: this.sync.out.buffer
|
|
970
1066
|
});
|
|
971
1067
|
e.cleanup(() => a.close()), e.run((e) => {
|
|
972
1068
|
let t = e.get(a.buffered), n = e.get(this.#e);
|
|
973
|
-
this.buffered.update(() =>
|
|
1069
|
+
this.buffered.update(() => l.mergeBufferedRanges(t, n));
|
|
974
1070
|
}), r.configure({
|
|
975
1071
|
...this.config,
|
|
976
|
-
description: this.config.description ?
|
|
1072
|
+
description: this.config.description ? u.Hex.toBytes(this.config.description) : void 0,
|
|
977
1073
|
optimizeForLatency: this.config.optimizeForLatency ?? !0,
|
|
978
1074
|
flip: !1
|
|
979
1075
|
});
|
|
@@ -983,45 +1079,45 @@ var Y = class {
|
|
|
983
1079
|
let e = await a.next();
|
|
984
1080
|
if (!e) break;
|
|
985
1081
|
this.#o(e.discontinuity) && (o = void 0);
|
|
986
|
-
let { frame:
|
|
987
|
-
if (!
|
|
1082
|
+
let { frame: t, group: i } = e;
|
|
1083
|
+
if (!t) {
|
|
988
1084
|
o && (o.final = !0);
|
|
989
1085
|
continue;
|
|
990
1086
|
}
|
|
991
|
-
let s =
|
|
1087
|
+
let s = n.Milli.fromMicro(t.timestamp);
|
|
992
1088
|
this.sync.received(s, "video");
|
|
993
1089
|
let c = new EncodedVideoChunk({
|
|
994
|
-
type:
|
|
995
|
-
data:
|
|
996
|
-
timestamp:
|
|
1090
|
+
type: t.keyframe ? "key" : "delta",
|
|
1091
|
+
data: t.payload,
|
|
1092
|
+
timestamp: t.timestamp
|
|
997
1093
|
});
|
|
998
1094
|
this.stats.update((e) => ({
|
|
999
1095
|
frameCount: (e?.frameCount ?? 0) + 1,
|
|
1000
|
-
bytesReceived: (e?.bytesReceived ?? 0) +
|
|
1096
|
+
bytesReceived: (e?.bytesReceived ?? 0) + t.payload.byteLength
|
|
1001
1097
|
}));
|
|
1002
1098
|
let l = o;
|
|
1003
1099
|
if (l && (l.group === i || l.final && l.group + 1 === i)) {
|
|
1004
|
-
let e =
|
|
1100
|
+
let e = n.Milli.fromMicro(l.timestamp), r = n.Milli.fromMicro(t.timestamp);
|
|
1005
1101
|
this.#s(e, r);
|
|
1006
1102
|
}
|
|
1007
1103
|
o = {
|
|
1008
|
-
timestamp:
|
|
1104
|
+
timestamp: t.timestamp,
|
|
1009
1105
|
group: i,
|
|
1010
1106
|
final: !1
|
|
1011
1107
|
}, r.decode(c);
|
|
1012
1108
|
}
|
|
1013
1109
|
});
|
|
1014
1110
|
}
|
|
1015
|
-
#a(e,
|
|
1111
|
+
#a(e, t, r) {
|
|
1016
1112
|
let i = this.config.container;
|
|
1017
1113
|
if (i.kind !== "cmaf") return;
|
|
1018
|
-
let a =
|
|
1019
|
-
format: new
|
|
1114
|
+
let a = p(i.init), o = l.Cmaf.decodeInitSegment(a), s = this.config.description ? u.Hex.toBytes(this.config.description) : o.description, c = new l.Consumer(t, {
|
|
1115
|
+
format: new l.Cmaf.Format(o),
|
|
1020
1116
|
latency: this.sync.out.buffer
|
|
1021
1117
|
});
|
|
1022
|
-
e.cleanup(() =>
|
|
1023
|
-
let t = e.get(
|
|
1024
|
-
this.buffered.update(() =>
|
|
1118
|
+
e.cleanup(() => c.close()), e.run((e) => {
|
|
1119
|
+
let t = e.get(c.buffered), n = e.get(this.#e);
|
|
1120
|
+
this.buffered.update(() => l.mergeBufferedRanges(t, n));
|
|
1025
1121
|
}), r.configure({
|
|
1026
1122
|
codec: this.config.codec,
|
|
1027
1123
|
description: s,
|
|
@@ -1031,33 +1127,33 @@ var Y = class {
|
|
|
1031
1127
|
let d;
|
|
1032
1128
|
e.spawn(async () => {
|
|
1033
1129
|
for (;;) {
|
|
1034
|
-
let e = await
|
|
1130
|
+
let e = await c.next();
|
|
1035
1131
|
if (!e) break;
|
|
1036
1132
|
this.#o(e.discontinuity) && (d = void 0);
|
|
1037
|
-
let { frame:
|
|
1038
|
-
if (!
|
|
1133
|
+
let { frame: t, group: i } = e;
|
|
1134
|
+
if (!t) {
|
|
1039
1135
|
d && (d.final = !0);
|
|
1040
1136
|
continue;
|
|
1041
1137
|
}
|
|
1042
|
-
let a =
|
|
1138
|
+
let a = n.Milli.fromMicro(t.timestamp);
|
|
1043
1139
|
this.sync.received(a, "video"), this.stats.update((e) => ({
|
|
1044
1140
|
frameCount: (e?.frameCount ?? 0) + 1,
|
|
1045
|
-
bytesReceived: (e?.bytesReceived ?? 0) +
|
|
1141
|
+
bytesReceived: (e?.bytesReceived ?? 0) + t.payload.byteLength
|
|
1046
1142
|
}));
|
|
1047
1143
|
let o = d;
|
|
1048
1144
|
if (o && (o.group === i || o.final && o.group + 1 === i)) {
|
|
1049
|
-
let e =
|
|
1145
|
+
let e = n.Milli.fromMicro(o.timestamp), r = n.Milli.fromMicro(t.timestamp);
|
|
1050
1146
|
this.#s(e, r);
|
|
1051
1147
|
}
|
|
1052
1148
|
if (d = {
|
|
1053
|
-
timestamp:
|
|
1149
|
+
timestamp: t.timestamp,
|
|
1054
1150
|
group: i,
|
|
1055
1151
|
final: !1
|
|
1056
1152
|
}, r.state === "closed") break;
|
|
1057
1153
|
r.decode(new EncodedVideoChunk({
|
|
1058
|
-
type:
|
|
1059
|
-
data:
|
|
1060
|
-
timestamp:
|
|
1154
|
+
type: t.keyframe ? "key" : "delta",
|
|
1155
|
+
data: t.payload,
|
|
1156
|
+
timestamp: t.timestamp
|
|
1061
1157
|
}));
|
|
1062
1158
|
}
|
|
1063
1159
|
});
|
|
@@ -1065,26 +1161,26 @@ var Y = class {
|
|
|
1065
1161
|
#o(e) {
|
|
1066
1162
|
return e === this.#t ? !1 : (this.#t = e, this.timestamp.set(void 0), this.#e.set([]), this.sync.reset(), !0);
|
|
1067
1163
|
}
|
|
1068
|
-
#s(e,
|
|
1069
|
-
e >
|
|
1070
|
-
for (let i of r) if (i.start <=
|
|
1071
|
-
i.start =
|
|
1164
|
+
#s(e, t) {
|
|
1165
|
+
e > t || this.#e.mutate((r) => {
|
|
1166
|
+
for (let i of r) if (i.start <= t && i.end >= e) {
|
|
1167
|
+
i.start = n.Milli.min(i.start, e), i.end = n.Milli.max(i.end, t);
|
|
1072
1168
|
return;
|
|
1073
1169
|
}
|
|
1074
1170
|
r.push({
|
|
1075
1171
|
start: e,
|
|
1076
|
-
end:
|
|
1172
|
+
end: t
|
|
1077
1173
|
}), r.sort((e, t) => e.start - t.start);
|
|
1078
1174
|
});
|
|
1079
1175
|
}
|
|
1080
1176
|
#c(e) {
|
|
1081
|
-
this.#e.mutate((
|
|
1082
|
-
for (;
|
|
1083
|
-
if (
|
|
1084
|
-
|
|
1177
|
+
this.#e.mutate((t) => {
|
|
1178
|
+
for (; t.length > 0;) {
|
|
1179
|
+
if (t[0].end >= e) {
|
|
1180
|
+
t[0].start = n.Milli.max(t[0].start, e);
|
|
1085
1181
|
break;
|
|
1086
1182
|
}
|
|
1087
|
-
|
|
1183
|
+
t.shift();
|
|
1088
1184
|
}
|
|
1089
1185
|
});
|
|
1090
1186
|
}
|
|
@@ -1094,15 +1190,15 @@ var Y = class {
|
|
|
1094
1190
|
});
|
|
1095
1191
|
}
|
|
1096
1192
|
};
|
|
1097
|
-
async function
|
|
1098
|
-
if (!
|
|
1193
|
+
async function Q(e) {
|
|
1194
|
+
if (!s.containerSupported(e.container)) {
|
|
1099
1195
|
let t = e.container.kind === "unknown" ? e.container.raw.kind : e.container.kind;
|
|
1100
1196
|
return console.warn(`video: ignoring rendition with unknown container: ${t}`), !1;
|
|
1101
1197
|
}
|
|
1102
1198
|
let t;
|
|
1103
|
-
if (e.description) t =
|
|
1199
|
+
if (e.description) t = u.Hex.toBytes(e.description);
|
|
1104
1200
|
else if (e.container.kind === "cmaf") try {
|
|
1105
|
-
t =
|
|
1201
|
+
t = l.Cmaf.decodeInitSegment(p(e.container.init)).description;
|
|
1106
1202
|
} catch (t) {
|
|
1107
1203
|
return console.warn(`video: malformed CMAF init segment for codec ${e.codec}`, t), !1;
|
|
1108
1204
|
}
|
|
@@ -1124,21 +1220,21 @@ async function ie(e) {
|
|
|
1124
1220
|
}
|
|
1125
1221
|
//#endregion
|
|
1126
1222
|
//#region src/video/renderer.ts
|
|
1127
|
-
var
|
|
1223
|
+
var $ = .01, de = class {
|
|
1128
1224
|
decoder;
|
|
1129
1225
|
in;
|
|
1130
1226
|
#e = {
|
|
1131
|
-
frame: new
|
|
1132
|
-
timestamp: new
|
|
1133
|
-
visible: new
|
|
1227
|
+
frame: new i(void 0),
|
|
1228
|
+
timestamp: new i(void 0),
|
|
1229
|
+
visible: new i(!1)
|
|
1134
1230
|
};
|
|
1135
|
-
out =
|
|
1136
|
-
#t = new
|
|
1137
|
-
#n = new
|
|
1231
|
+
out = o(this.#e);
|
|
1232
|
+
#t = new i(void 0);
|
|
1233
|
+
#n = new r();
|
|
1138
1234
|
constructor(e, t) {
|
|
1139
1235
|
this.decoder = e, this.in = {
|
|
1140
|
-
canvas:
|
|
1141
|
-
visible:
|
|
1236
|
+
canvas: a(t?.canvas),
|
|
1237
|
+
visible: a(t?.visible ?? "20%")
|
|
1142
1238
|
}, this.#n.run((e) => {
|
|
1143
1239
|
let t = e.get(this.in.canvas);
|
|
1144
1240
|
this.#t.set(t?.getContext("2d") ?? void 0);
|
|
@@ -1172,32 +1268,37 @@ var Q = .01, ae = class {
|
|
|
1172
1268
|
}, o;
|
|
1173
1269
|
try {
|
|
1174
1270
|
o = new IntersectionObserver(a, {
|
|
1175
|
-
threshold:
|
|
1271
|
+
threshold: $,
|
|
1176
1272
|
rootMargin: t
|
|
1177
1273
|
});
|
|
1178
1274
|
} catch {
|
|
1179
|
-
console.warn(`moq-watch: invalid visible margin "${t}", using "0px"`), o = new IntersectionObserver(a, { threshold:
|
|
1275
|
+
console.warn(`moq-watch: invalid visible margin "${t}", using "0px"`), o = new IntersectionObserver(a, { threshold: $ });
|
|
1180
1276
|
}
|
|
1181
1277
|
i(), e.event(document, "visibilitychange", i), o.observe(n), e.cleanup(() => o.disconnect()), e.cleanup(() => this.#e.visible.set(!1));
|
|
1182
1278
|
}
|
|
1183
1279
|
#a(e) {
|
|
1184
|
-
let
|
|
1185
|
-
if (!
|
|
1186
|
-
let r = e.get(this.decoder.out.frame), i = requestAnimationFrame(() => {
|
|
1187
|
-
this.#o(
|
|
1280
|
+
let t = e.get(this.#t);
|
|
1281
|
+
if (!t) return;
|
|
1282
|
+
let r = e.get(this.decoder.out.frame), i = e.get(this.decoder.source.out.catalog), a = requestAnimationFrame(() => {
|
|
1283
|
+
this.#o(t, r, i), r ? (this.#e.frame.update((e) => (e?.close(), r.clone())), this.#e.timestamp.set(n.Milli.fromMicro(r.timestamp))) : (this.#e.frame.update((e) => {
|
|
1188
1284
|
e?.close();
|
|
1189
|
-
}), this.#e.timestamp.set(void 0)),
|
|
1285
|
+
}), this.#e.timestamp.set(void 0)), a = void 0;
|
|
1190
1286
|
});
|
|
1191
1287
|
e.cleanup(() => {
|
|
1192
|
-
|
|
1288
|
+
a && cancelAnimationFrame(a);
|
|
1193
1289
|
});
|
|
1194
1290
|
}
|
|
1195
|
-
#o(e, t) {
|
|
1291
|
+
#o(e, t, n) {
|
|
1196
1292
|
if (!t) {
|
|
1197
1293
|
e.fillStyle = "#000", e.fillRect(0, 0, e.canvas.width, e.canvas.height);
|
|
1198
1294
|
return;
|
|
1199
1295
|
}
|
|
1200
|
-
e.save(), e.fillStyle = "#000", e.fillRect(0, 0, e.canvas.width, e.canvas.height),
|
|
1296
|
+
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);
|
|
1297
|
+
else {
|
|
1298
|
+
let r = oe(e.canvas, n);
|
|
1299
|
+
e.setTransform(...r.matrix), e.drawImage(t, 0, 0, r.source.width, r.source.height);
|
|
1300
|
+
}
|
|
1301
|
+
e.restore();
|
|
1201
1302
|
}
|
|
1202
1303
|
close() {
|
|
1203
1304
|
this.#e.frame.update((e) => {
|
|
@@ -1207,7 +1308,7 @@ var Q = .01, ae = class {
|
|
|
1207
1308
|
};
|
|
1208
1309
|
//#endregion
|
|
1209
1310
|
//#region src/video/source.ts
|
|
1210
|
-
function
|
|
1311
|
+
function fe(e) {
|
|
1211
1312
|
return (t) => {
|
|
1212
1313
|
let n = [], r = [];
|
|
1213
1314
|
for (let [i, a] of t) if (a.codedWidth && a.codedHeight) {
|
|
@@ -1223,7 +1324,7 @@ function oe(e) {
|
|
|
1223
1324
|
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);
|
|
1224
1325
|
};
|
|
1225
1326
|
}
|
|
1226
|
-
function
|
|
1327
|
+
function pe(e, t) {
|
|
1227
1328
|
return (n) => {
|
|
1228
1329
|
let r = [], i = [];
|
|
1229
1330
|
for (let [a, o] of n) {
|
|
@@ -1240,7 +1341,7 @@ function $(e, t) {
|
|
|
1240
1341
|
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);
|
|
1241
1342
|
};
|
|
1242
1343
|
}
|
|
1243
|
-
function
|
|
1344
|
+
function me(e) {
|
|
1244
1345
|
return (t) => {
|
|
1245
1346
|
let n = [], r = [];
|
|
1246
1347
|
for (let [i, a] of t) a.bitrate != null && a.bitrate <= e ? n.push({
|
|
@@ -1253,7 +1354,7 @@ function se(e) {
|
|
|
1253
1354
|
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);
|
|
1254
1355
|
};
|
|
1255
1356
|
}
|
|
1256
|
-
function
|
|
1357
|
+
function he(e) {
|
|
1257
1358
|
let t = e[0];
|
|
1258
1359
|
for (let n of e) {
|
|
1259
1360
|
let [, e] = n, [, r] = t, i = (e.codedWidth ?? 0) * (e.codedHeight ?? 0), a = (r.codedWidth ?? 0) * (r.codedHeight ?? 0);
|
|
@@ -1265,23 +1366,23 @@ function ce(e) {
|
|
|
1265
1366
|
}
|
|
1266
1367
|
return t[0];
|
|
1267
1368
|
}
|
|
1268
|
-
var
|
|
1369
|
+
var ge = class {
|
|
1269
1370
|
in;
|
|
1270
1371
|
#e = {
|
|
1271
|
-
catalog: new
|
|
1272
|
-
available: new
|
|
1273
|
-
error: new
|
|
1274
|
-
track: new
|
|
1275
|
-
config: new
|
|
1276
|
-
jitter: new
|
|
1372
|
+
catalog: new i(void 0),
|
|
1373
|
+
available: new i({}),
|
|
1374
|
+
error: new i(void 0),
|
|
1375
|
+
track: new i(void 0),
|
|
1376
|
+
config: new i(void 0),
|
|
1377
|
+
jitter: new i(void 0)
|
|
1277
1378
|
};
|
|
1278
|
-
out =
|
|
1279
|
-
#t = new
|
|
1379
|
+
out = o(this.#e);
|
|
1380
|
+
#t = new r();
|
|
1280
1381
|
constructor(e) {
|
|
1281
1382
|
this.in = {
|
|
1282
|
-
broadcast:
|
|
1283
|
-
target:
|
|
1284
|
-
supported:
|
|
1383
|
+
broadcast: a(e?.broadcast),
|
|
1384
|
+
target: a(e?.target),
|
|
1385
|
+
supported: a(e?.supported)
|
|
1285
1386
|
}, this.#t.run(this.#n.bind(this)), this.#t.run(this.#r.bind(this)), this.#t.run(this.#i.bind(this));
|
|
1286
1387
|
}
|
|
1287
1388
|
#n(e) {
|
|
@@ -1313,12 +1414,12 @@ var le = class {
|
|
|
1313
1414
|
});
|
|
1314
1415
|
}
|
|
1315
1416
|
#i(e) {
|
|
1316
|
-
let
|
|
1317
|
-
if (Object.keys(
|
|
1417
|
+
let t = e.get(this.#e.available);
|
|
1418
|
+
if (Object.keys(t).length === 0) return;
|
|
1318
1419
|
let r = e.get(this.in.target);
|
|
1319
|
-
if (r?.name && r.name in
|
|
1320
|
-
let i =
|
|
1321
|
-
e.set(this.#e.track, r.name), e.set(this.#e.config, i), e.set(this.#e.jitter, i.jitter === void 0 ? void 0 :
|
|
1420
|
+
if (r?.name && r.name in t) {
|
|
1421
|
+
let i = t[r.name];
|
|
1422
|
+
e.set(this.#e.track, r.name), e.set(this.#e.config, i), e.set(this.#e.jitter, i.jitter === void 0 ? void 0 : n.Milli(i.jitter));
|
|
1322
1423
|
return;
|
|
1323
1424
|
}
|
|
1324
1425
|
let i = r;
|
|
@@ -1332,19 +1433,19 @@ var le = class {
|
|
|
1332
1433
|
};
|
|
1333
1434
|
}
|
|
1334
1435
|
}
|
|
1335
|
-
let a = this.#a(
|
|
1436
|
+
let a = this.#a(t, i);
|
|
1336
1437
|
if (!a) return;
|
|
1337
|
-
let o =
|
|
1438
|
+
let o = t[a];
|
|
1338
1439
|
e.set(this.#e.track, a), e.set(this.#e.config, o);
|
|
1339
1440
|
let s = o.jitter ?? (o.framerate ? Math.ceil(1e3 / o.framerate) : void 0);
|
|
1340
|
-
e.set(this.#e.jitter, s === void 0 ? void 0 :
|
|
1441
|
+
e.set(this.#e.jitter, s === void 0 ? void 0 : n.Milli(s));
|
|
1341
1442
|
}
|
|
1342
1443
|
#a(e, t) {
|
|
1343
1444
|
let n = Object.entries(e);
|
|
1344
1445
|
if (n.length === 0) return;
|
|
1345
1446
|
if (n.length === 1) return n[0][0];
|
|
1346
1447
|
let r = [];
|
|
1347
|
-
if (t?.pixels != null && r.push(
|
|
1448
|
+
if (t?.pixels != null && r.push(fe(t.pixels)), (t?.width != null || t?.height != null) && r.push(pe(t.width, t.height)), t?.bitrate != null && r.push(me(t.bitrate)), r.length === 0) return he(n);
|
|
1348
1449
|
let i = r.map((e) => e(n)), a = i.map((e) => new Set(e));
|
|
1349
1450
|
for (let e of i[0]) if (a.every((t) => t.has(e))) return e;
|
|
1350
1451
|
console.warn("conflicting rendition filters, no rendition satisfies all criteria");
|
|
@@ -1354,6 +1455,6 @@ var le = class {
|
|
|
1354
1455
|
}
|
|
1355
1456
|
};
|
|
1356
1457
|
//#endregion
|
|
1357
|
-
export { q as a, P as c,
|
|
1458
|
+
export { q as a, P as c, J as i, ne as l, de as n, ie as o, le as r, I as s, ge as t };
|
|
1358
1459
|
|
|
1359
|
-
//# sourceMappingURL=source-
|
|
1460
|
+
//# sourceMappingURL=source-CPHBHrLc.js.map
|