@moq/watch 0.2.10 → 0.2.12
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/README.md +7 -7
- package/audio/backend.d.ts +1 -0
- package/audio/backend.d.ts.map +1 -1
- package/audio/buffer.d.ts +1 -1
- package/audio/buffer.d.ts.map +1 -1
- package/audio/decoder.d.ts +1 -1
- package/audio/decoder.d.ts.map +1 -1
- package/audio/mse.d.ts +1 -0
- package/audio/mse.d.ts.map +1 -1
- package/audio/render.d.ts +1 -1
- package/audio/render.d.ts.map +1 -1
- package/audio/ring-buffer.d.ts +1 -1
- package/audio/ring-buffer.d.ts.map +1 -1
- package/audio/shared-ring-buffer.d.ts +1 -1
- package/audio/shared-ring-buffer.d.ts.map +1 -1
- package/audio/source.d.ts.map +1 -1
- package/backend.d.ts +3 -2
- package/backend.d.ts.map +1 -1
- package/base64.d.ts +3 -0
- package/base64.d.ts.map +1 -0
- package/{broadcast-BImEYz4N.js → broadcast-CLjMphZS.js} +1652 -1432
- package/broadcast-CLjMphZS.js.map +1 -0
- package/broadcast.d.ts +8 -5
- package/broadcast.d.ts.map +1 -1
- package/chat/index.d.ts +1 -1
- package/chat/index.d.ts.map +1 -1
- package/chat/message.d.ts +1 -1
- package/chat/message.d.ts.map +1 -1
- package/chat/typing.d.ts +1 -1
- package/chat/typing.d.ts.map +1 -1
- package/dom-BsFrLb_F.js +35 -0
- package/dom-BsFrLb_F.js.map +1 -0
- package/element.d.ts +11 -4
- package/element.d.ts.map +1 -1
- package/element.js +65 -48
- package/element.js.map +1 -1
- package/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js +37 -35
- package/index.js.map +1 -1
- package/libav-opus-af-BlMWboA7.js.map +1 -1
- package/location/index.d.ts +1 -1
- package/location/index.d.ts.map +1 -1
- package/location/peers.d.ts +1 -1
- package/location/peers.d.ts.map +1 -1
- package/location/window.d.ts +1 -1
- package/location/window.d.ts.map +1 -1
- package/main-DGBFe0O7.js.map +1 -1
- package/msf.d.ts.map +1 -1
- package/package.json +7 -8
- package/preview.d.ts +1 -1
- package/preview.d.ts.map +1 -1
- package/support/element.js +49 -60
- package/support/element.js.map +1 -1
- package/sync.d.ts +6 -6
- package/sync.d.ts.map +1 -1
- package/ui/components/buffer-control.d.ts +5 -0
- package/ui/components/buffer-control.d.ts.map +1 -0
- package/ui/components/buffering-indicator.d.ts +4 -0
- package/ui/components/buffering-indicator.d.ts.map +1 -0
- package/ui/components/fullscreen-button.d.ts +4 -0
- package/ui/components/fullscreen-button.d.ts.map +1 -0
- package/ui/components/offline-indicator.d.ts +4 -0
- package/ui/components/offline-indicator.d.ts.map +1 -0
- package/ui/components/play-pause.d.ts +4 -0
- package/ui/components/play-pause.d.ts.map +1 -0
- package/ui/components/quality-selector.d.ts +4 -0
- package/ui/components/quality-selector.d.ts.map +1 -0
- package/ui/components/stats-button.d.ts +3 -0
- package/ui/components/stats-button.d.ts.map +1 -0
- package/ui/components/volume-slider.d.ts +4 -0
- package/ui/components/volume-slider.d.ts.map +1 -0
- package/ui/components/watch-status-indicator.d.ts +4 -0
- package/ui/components/watch-status-indicator.d.ts.map +1 -0
- package/ui/element.d.ts +11 -4
- package/ui/element.d.ts.map +1 -1
- package/ui/element.js +382 -0
- package/ui/element.js.map +1 -0
- package/ui/icons.d.ts +16 -0
- package/ui/icons.d.ts.map +1 -0
- package/ui/stats.d.ts +4 -0
- package/ui/stats.d.ts.map +1 -0
- package/video/backend.d.ts +1 -1
- package/video/backend.d.ts.map +1 -1
- package/video/decoder.d.ts +1 -1
- package/video/decoder.d.ts.map +1 -1
- package/video/mse.d.ts +1 -1
- package/video/mse.d.ts.map +1 -1
- package/video/renderer.d.ts +1 -1
- package/video/renderer.d.ts.map +1 -1
- package/video/source.d.ts +2 -0
- package/video/source.d.ts.map +1 -1
- package/broadcast-BImEYz4N.js.map +0 -1
- package/ui/components/BufferControl.d.ts +0 -8
- package/ui/components/BufferControl.d.ts.map +0 -1
- package/ui/components/BufferingIndicator.d.ts +0 -2
- package/ui/components/BufferingIndicator.d.ts.map +0 -1
- package/ui/components/FullscreenButton.d.ts +0 -2
- package/ui/components/FullscreenButton.d.ts.map +0 -1
- package/ui/components/PlayPauseButton.d.ts +0 -2
- package/ui/components/PlayPauseButton.d.ts.map +0 -1
- package/ui/components/QualitySelector.d.ts +0 -3
- package/ui/components/QualitySelector.d.ts.map +0 -1
- package/ui/components/StatsButton.d.ts +0 -5
- package/ui/components/StatsButton.d.ts.map +0 -1
- package/ui/components/VolumeSlider.d.ts +0 -2
- package/ui/components/VolumeSlider.d.ts.map +0 -1
- package/ui/components/WatchControls.d.ts +0 -2
- package/ui/components/WatchControls.d.ts.map +0 -1
- package/ui/components/WatchStatusIndicator.d.ts +0 -2
- package/ui/components/WatchStatusIndicator.d.ts.map +0 -1
- package/ui/context.d.ts +0 -44
- package/ui/context.d.ts.map +0 -1
- package/ui/hooks/use-watch-ui.d.ts +0 -3
- package/ui/hooks/use-watch-ui.d.ts.map +0 -1
- package/ui/index.d.ts +0 -7
- package/ui/index.d.ts.map +0 -1
- package/ui/index.js +0 -1058
- package/ui/index.js.map +0 -1
package/ui/element.js
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { Signal as R, Effect as T } from "@moq/signals";
|
|
2
|
+
import { c as v, r as C } from "../dom-BsFrLb_F.js";
|
|
3
|
+
const j = 0, E = 10, P = 4e3, F = 48;
|
|
4
|
+
function S(o, t, e, r, a) {
|
|
5
|
+
const n = o.getContext("2d");
|
|
6
|
+
if (!n) return;
|
|
7
|
+
const i = window.devicePixelRatio || 1, s = o.getBoundingClientRect(), l = s.width, c = s.height, p = Math.round(l * i), d = Math.round(c * i);
|
|
8
|
+
if ((o.width !== p || o.height !== d) && (o.width = p, o.height = d), n.setTransform(i, 0, 0, i, 0, 0), n.clearRect(0, 0, l, c), e === void 0) return;
|
|
9
|
+
const h = 2, f = c - h * 2, b = 2;
|
|
10
|
+
for (let m = 0; m < t.length; m++) {
|
|
11
|
+
const x = t[m], A = x.start - e, k = x.end - e, y = Math.max(0, A), N = Math.min(k, r);
|
|
12
|
+
if (N <= y) continue;
|
|
13
|
+
const u = y / r * l, g = Math.max(2, (N - y) / r * l);
|
|
14
|
+
if (n.globalAlpha = 0.85, n.fillStyle = a ? "#f87171" : m > 0 ? "#facc15" : "#4ade80", typeof n.roundRect == "function" ? (n.beginPath(), n.roundRect(u, h, g, f, b), n.fill()) : n.fillRect(u, h, g, f), k > r) {
|
|
15
|
+
const w = ((k - r) / 1e3).toFixed(1);
|
|
16
|
+
n.globalAlpha = 0.7, n.fillStyle = "black", n.font = "500 9px system-ui, sans-serif", n.textAlign = "right", n.textBaseline = "middle", n.fillText(`+${w}s`, u + g - 4, c / 2);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function V(o, t, e = P) {
|
|
21
|
+
const r = document.createElement("div");
|
|
22
|
+
r.className = "buffer";
|
|
23
|
+
const a = document.createElement("div");
|
|
24
|
+
a.className = "buffer-visualization", a.setAttribute("role", "slider"), a.tabIndex = 0, a.setAttribute("aria-valuemin", j.toString()), a.setAttribute("aria-valuemax", e.toString()), a.setAttribute("aria-label", "Buffer jitter");
|
|
25
|
+
const n = document.createElement("div");
|
|
26
|
+
n.className = "buffer-playhead";
|
|
27
|
+
const i = document.createElement("div");
|
|
28
|
+
i.className = "buffer-track buffer-track--video";
|
|
29
|
+
const s = document.createElement("span");
|
|
30
|
+
s.className = "buffer-track-label", s.textContent = "Video";
|
|
31
|
+
const l = document.createElement("canvas");
|
|
32
|
+
l.className = "buffer-canvas", i.append(s, l);
|
|
33
|
+
const c = document.createElement("div");
|
|
34
|
+
c.className = "buffer-track buffer-track--audio";
|
|
35
|
+
const p = document.createElement("span");
|
|
36
|
+
p.className = "buffer-track-label", p.textContent = "Audio";
|
|
37
|
+
const d = document.createElement("canvas");
|
|
38
|
+
d.className = "buffer-canvas", c.append(p, d);
|
|
39
|
+
const h = document.createElement("div");
|
|
40
|
+
h.className = "buffer-target-area";
|
|
41
|
+
const f = document.createElement("div");
|
|
42
|
+
f.className = "buffer-target-line";
|
|
43
|
+
const b = document.createElement("span");
|
|
44
|
+
b.className = "buffer-target-label", f.appendChild(b), h.appendChild(f);
|
|
45
|
+
const m = document.createElement("span");
|
|
46
|
+
m.className = "buffer-help", m.textContent = "click to change latency", a.append(n, i, c, h, m), r.appendChild(a);
|
|
47
|
+
let x = !1, A = !1;
|
|
48
|
+
o.run((u) => {
|
|
49
|
+
const g = u.get(t.backend.jitter), w = g / e * 100;
|
|
50
|
+
f.style.left = `${w}%`, b.textContent = `${Math.round(g)}ms`, a.setAttribute("aria-valuenow", g.toString());
|
|
51
|
+
});
|
|
52
|
+
const k = (u) => {
|
|
53
|
+
const g = a.getBoundingClientRect(), w = g.width - F, H = Math.max(0, Math.min(u - g.left - F, w)) / w * e, I = Math.round(H / E) * E, W = Math.max(j, Math.min(e, I));
|
|
54
|
+
t.backend.latency.set(W);
|
|
55
|
+
}, y = () => {
|
|
56
|
+
A || (A = !0, m.style.display = "none");
|
|
57
|
+
};
|
|
58
|
+
o.event(a, "mousedown", (u) => {
|
|
59
|
+
x = !0, a.classList.add("buffer-visualization--dragging"), y(), k(u.clientX);
|
|
60
|
+
}), o.event(document, "mousemove", (u) => {
|
|
61
|
+
x && k(u.clientX);
|
|
62
|
+
}), o.event(document, "mouseup", () => {
|
|
63
|
+
x && (x = !1, a.classList.remove("buffer-visualization--dragging"));
|
|
64
|
+
}), o.event(a, "keydown", (u) => {
|
|
65
|
+
let g = 0;
|
|
66
|
+
if (u.key === "ArrowRight" || u.key === "ArrowUp")
|
|
67
|
+
g = E;
|
|
68
|
+
else if (u.key === "ArrowLeft" || u.key === "ArrowDown")
|
|
69
|
+
g = -E;
|
|
70
|
+
else
|
|
71
|
+
return;
|
|
72
|
+
u.preventDefault(), y();
|
|
73
|
+
const w = t.backend.jitter.peek(), L = Math.max(j, Math.min(e, w + g));
|
|
74
|
+
t.backend.latency.set(L);
|
|
75
|
+
});
|
|
76
|
+
const N = () => {
|
|
77
|
+
const u = t.backend.sync.now(), g = t.backend.video.stalled.peek();
|
|
78
|
+
S(l, t.backend.video.buffered.peek(), u, e, g), S(d, t.backend.audio.buffered.peek(), u, e, g), o.animate(N);
|
|
79
|
+
};
|
|
80
|
+
return o.animate(N), r;
|
|
81
|
+
}
|
|
82
|
+
function O(o, t) {
|
|
83
|
+
const e = document.createElement("div");
|
|
84
|
+
e.className = "buffering";
|
|
85
|
+
const r = document.createElement("div");
|
|
86
|
+
return r.className = "buffering-spinner", e.appendChild(r), o.run((a) => {
|
|
87
|
+
const n = a.get(t.backend.video.stalled), i = a.get(t.broadcast.status) === "offline";
|
|
88
|
+
e.style.display = n && !i ? "" : "none";
|
|
89
|
+
}), e;
|
|
90
|
+
}
|
|
91
|
+
const U = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
92
|
+
<path d="M9 18V5l12-2v13" />
|
|
93
|
+
<circle cx="6" cy="18" r="3" />
|
|
94
|
+
<circle cx="18" cy="16" r="3" />
|
|
95
|
+
</svg>`, D = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
96
|
+
<path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2" />
|
|
97
|
+
</svg>`, _ = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
98
|
+
<path d="M8 3H5a2 2 0 0 0-2 2v3" />
|
|
99
|
+
<path d="M21 8V5a2 2 0 0 0-2-2h-3" />
|
|
100
|
+
<path d="M3 16v3a2 2 0 0 0 2 2h3" />
|
|
101
|
+
<path d="M16 21h3a2 2 0 0 0 2-2v-3" />
|
|
102
|
+
</svg>`, X = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
103
|
+
<path d="M8 3v3a2 2 0 0 1-2 2H3" />
|
|
104
|
+
<path d="M21 8h-3a2 2 0 0 1-2-2V3" />
|
|
105
|
+
<path d="M3 16h3a2 2 0 0 1 2 2v3" />
|
|
106
|
+
<path d="M16 21v-3a2 2 0 0 1 2-2h3" />
|
|
107
|
+
</svg>`, G = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="var(--color-white)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
108
|
+
<path d="M16 9a5 5 0 0 1 .95 2.293" />
|
|
109
|
+
<path d="M19.364 5.636a9 9 0 0 1 1.889 9.96" />
|
|
110
|
+
<path d="m2 2 20 20" />
|
|
111
|
+
<path d="m7 7-.587.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298V11" />
|
|
112
|
+
<path d="M9.828 4.172A.686.686 0 0 1 11 4.657v.686" />
|
|
113
|
+
</svg>`, Q = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
114
|
+
<path d="M16.247 7.761a6 6 0 0 1 0 8.478" />
|
|
115
|
+
<path d="M19.075 4.933a10 10 0 0 1 0 14.134" />
|
|
116
|
+
<path d="M4.925 19.067a10 10 0 0 1 0-14.134" />
|
|
117
|
+
<path d="M7.753 16.239a6 6 0 0 1 0-8.478" />
|
|
118
|
+
<circle cx="12" cy="12" r="2" />
|
|
119
|
+
</svg>`, J = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="var(--color-white)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
120
|
+
<rect x="14" y="3" width="5" height="18" rx="1" />
|
|
121
|
+
<rect x="5" y="3" width="5" height="18" rx="1" />
|
|
122
|
+
</svg>`, K = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="var(--color-white)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
123
|
+
<path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z" />
|
|
124
|
+
</svg>`, Y = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
125
|
+
<path d="M5 21v-6" />
|
|
126
|
+
<path d="M12 21V3" />
|
|
127
|
+
<path d="M19 21V9" />
|
|
128
|
+
</svg>`, Z = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
129
|
+
<path d="m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5" />
|
|
130
|
+
<rect x="2" y="6" width="14" height="12" rx="2" />
|
|
131
|
+
</svg>`, tt = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="var(--color-white)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
132
|
+
<path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z" />
|
|
133
|
+
<path d="M16 9a5 5 0 0 1 0 6" />
|
|
134
|
+
<path d="M19.364 18.364a9 9 0 0 0 0-12.728" />
|
|
135
|
+
</svg>`, et = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="var(--color-white)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
136
|
+
<path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z" />
|
|
137
|
+
</svg>`, at = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="var(--color-white)" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
138
|
+
<path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z" />
|
|
139
|
+
<path d="M16 9a5 5 0 0 1 0 6" />
|
|
140
|
+
</svg>`;
|
|
141
|
+
function M(o) {
|
|
142
|
+
const t = document.createElement("span");
|
|
143
|
+
return t.className = "flex-center", t.setAttribute("role", "img"), t.setAttribute("aria-hidden", "true"), t.innerHTML = o, t;
|
|
144
|
+
}
|
|
145
|
+
function ot(o, t) {
|
|
146
|
+
const e = document.createElement("button");
|
|
147
|
+
e.type = "button", e.className = "button flex-center", e.title = "Fullscreen", e.setAttribute("aria-label", "Fullscreen"), e.replaceChildren(M(_));
|
|
148
|
+
const r = () => {
|
|
149
|
+
const a = !!document.fullscreenElement;
|
|
150
|
+
e.replaceChildren(M(a ? X : _));
|
|
151
|
+
};
|
|
152
|
+
return o.event(document, "fullscreenchange", r), o.event(e, "click", () => {
|
|
153
|
+
document.fullscreenElement ? document.exitFullscreen() : t.requestFullscreen();
|
|
154
|
+
}), e;
|
|
155
|
+
}
|
|
156
|
+
function nt(o, t) {
|
|
157
|
+
const e = document.createElement("div");
|
|
158
|
+
e.className = "watch-ui__offline-indicator", e.setAttribute("role", "status"), e.setAttribute("aria-live", "polite");
|
|
159
|
+
const r = document.createElement("span");
|
|
160
|
+
return r.className = "watch-ui__offline-text", r.textContent = "OFFLINE", e.appendChild(r), o.run((a) => {
|
|
161
|
+
const n = a.get(t.broadcast.status) === "offline";
|
|
162
|
+
e.style.display = n ? "" : "none";
|
|
163
|
+
}), e;
|
|
164
|
+
}
|
|
165
|
+
function rt(o, t) {
|
|
166
|
+
const e = document.createElement("button");
|
|
167
|
+
return e.type = "button", e.className = "button button--playback flex-center", o.run((r) => {
|
|
168
|
+
const a = r.get(t.backend.paused);
|
|
169
|
+
e.title = a ? "Play" : "Pause", e.setAttribute("aria-label", a ? "Play" : "Pause"), e.replaceChildren(M(a ? K : J));
|
|
170
|
+
}), o.event(e, "click", () => {
|
|
171
|
+
t.paused = !t.paused;
|
|
172
|
+
}), e;
|
|
173
|
+
}
|
|
174
|
+
function it(o) {
|
|
175
|
+
return o >= 1e6 ? `${(o / 1e6).toFixed(1)} Mbps` : o >= 1e3 ? `${(o / 1e3).toFixed(0)} kbps` : `${o} bps`;
|
|
176
|
+
}
|
|
177
|
+
function st(o, t) {
|
|
178
|
+
const e = document.createElement("div");
|
|
179
|
+
e.className = "quality-selector";
|
|
180
|
+
const r = document.createElement("label");
|
|
181
|
+
r.htmlFor = "moq-watch-quality-select", r.className = "quality-label", r.textContent = "Quality: ";
|
|
182
|
+
const a = document.createElement("select");
|
|
183
|
+
return a.id = "moq-watch-quality-select", a.className = "quality-select", e.append(r, a), o.run((n) => {
|
|
184
|
+
const i = n.get(t.backend.video.source.catalog), s = n.get(t.backend.video.source.track), l = i?.renditions ?? {};
|
|
185
|
+
a.replaceChildren();
|
|
186
|
+
const c = document.createElement("option");
|
|
187
|
+
c.value = "", c.textContent = "Auto", a.appendChild(c);
|
|
188
|
+
for (const [p, d] of Object.entries(l)) {
|
|
189
|
+
const h = document.createElement("option");
|
|
190
|
+
h.value = p;
|
|
191
|
+
const f = d.codedWidth && d.codedHeight ? ` (${d.codedWidth}x${d.codedHeight})` : "", b = d.bitrate ? ` ${it(d.bitrate)}` : "";
|
|
192
|
+
h.textContent = `${p}${f}${b}`, a.appendChild(h);
|
|
193
|
+
}
|
|
194
|
+
a.value = s ?? "";
|
|
195
|
+
}), o.event(a, "change", () => {
|
|
196
|
+
const n = a.value || void 0;
|
|
197
|
+
t.backend.video.source.target.update((i) => ({ ...i, name: n }));
|
|
198
|
+
}), e;
|
|
199
|
+
}
|
|
200
|
+
function lt(o, t) {
|
|
201
|
+
const e = document.createElement("button");
|
|
202
|
+
return e.type = "button", e.className = "button flex-center", e.replaceChildren(M(Y)), o.run((r) => {
|
|
203
|
+
const a = r.get(t);
|
|
204
|
+
e.title = a ? "Hide stats" : "Show stats", e.setAttribute("aria-label", e.title);
|
|
205
|
+
}), o.event(e, "click", () => {
|
|
206
|
+
t.update((r) => !r);
|
|
207
|
+
}), e;
|
|
208
|
+
}
|
|
209
|
+
function ct(o, t) {
|
|
210
|
+
return t || o === 0 ? G : o <= 33 ? et : o <= 66 ? at : tt;
|
|
211
|
+
}
|
|
212
|
+
function dt(o, t) {
|
|
213
|
+
const e = document.createElement("div");
|
|
214
|
+
e.className = "volume-slider flex-center";
|
|
215
|
+
const r = document.createElement("button");
|
|
216
|
+
r.type = "button", r.className = "button flex-center";
|
|
217
|
+
const a = document.createElement("input");
|
|
218
|
+
a.type = "range", a.min = "0", a.max = "100";
|
|
219
|
+
const n = document.createElement("span");
|
|
220
|
+
return n.className = "volume-label", e.append(r, a, n), o.run((i) => {
|
|
221
|
+
const s = i.get(t.backend.audio.volume), l = i.get(t.backend.audio.muted), c = Math.round(s * 100);
|
|
222
|
+
a.value = c.toString(), n.textContent = c.toString(), r.title = l ? "Unmute" : "Mute", r.setAttribute("aria-label", r.title), r.replaceChildren(M(ct(c, l)));
|
|
223
|
+
}), o.event(a, "input", () => {
|
|
224
|
+
t.backend.audio.volume.set(Number.parseFloat(a.value) / 100);
|
|
225
|
+
}), o.event(r, "click", () => {
|
|
226
|
+
t.backend.audio.muted.update((i) => !i);
|
|
227
|
+
}), e;
|
|
228
|
+
}
|
|
229
|
+
function ut(o, t, e) {
|
|
230
|
+
return o ? t === "disconnected" ? { variant: "error", text: "Disconnected" } : t === "connecting" ? { variant: "connecting", text: "Connecting..." } : e === "offline" ? { variant: "error", text: "Offline" } : e === "loading" ? { variant: "loading", text: "Loading..." } : e === "live" ? { variant: "live", text: "Live" } : { variant: "connected", text: "Connected" } : { variant: "error", text: "No URL" };
|
|
231
|
+
}
|
|
232
|
+
function pt(o, t) {
|
|
233
|
+
const e = document.createElement("div");
|
|
234
|
+
e.className = "status-indicator flex-center";
|
|
235
|
+
const r = document.createElement("span"), a = document.createElement("span");
|
|
236
|
+
return e.append(r, a), o.run((n) => {
|
|
237
|
+
const i = n.get(t.connection.url), s = n.get(t.connection.status), l = n.get(t.broadcast.status), { variant: c, text: p } = ut(i, s, l);
|
|
238
|
+
r.className = `status-indicator-dot status-indicator-dot--${c}`, a.className = `status-indicator-text status-indicator-text--${c}`, a.textContent = p;
|
|
239
|
+
}), e;
|
|
240
|
+
}
|
|
241
|
+
const $ = 250;
|
|
242
|
+
function z(o, t, e) {
|
|
243
|
+
const r = v("div", { className: `stats-item stats-item--${o}` }), a = v("div", { className: "stats-icon-wrapper" });
|
|
244
|
+
a.appendChild(M(e));
|
|
245
|
+
const n = v("span", { className: "stats-item-title" }, t), i = v("span", { className: "stats-item-data" }, "N/A"), s = v("div", { className: "stats-item-detail" });
|
|
246
|
+
return s.append(n, i), r.append(a, s), { el: r, data: i };
|
|
247
|
+
}
|
|
248
|
+
function B(o) {
|
|
249
|
+
return o >= 1e6 ? `${(o / 1e6).toFixed(1)}Mbps` : o >= 1e3 ? `${(o / 1e3).toFixed(0)}kbps` : `${o.toFixed(0)}bps`;
|
|
250
|
+
}
|
|
251
|
+
function q(o, t) {
|
|
252
|
+
if (o === void 0 || o <= 0) return null;
|
|
253
|
+
const e = t === "down" ? "↓" : "↑";
|
|
254
|
+
return o >= 1e9 ? `${e} ${(o / 1e9).toFixed(1)}Gbps` : `${e} ${B(o)}`;
|
|
255
|
+
}
|
|
256
|
+
function ht(o, t) {
|
|
257
|
+
const { el: e, data: r } = z("network", "network", Q);
|
|
258
|
+
return o.interval(() => {
|
|
259
|
+
const a = t.connection.established.peek();
|
|
260
|
+
if (!a) {
|
|
261
|
+
r.textContent = "N/A";
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const n = a.rtt?.peek(), i = [
|
|
265
|
+
q(a.recvBandwidth?.peek(), "down"),
|
|
266
|
+
q(a.sendBandwidth?.peek(), "up"),
|
|
267
|
+
n !== void 0 && n > 0 ? `${n.toFixed(0)}ms` : null
|
|
268
|
+
].filter((s) => s !== null);
|
|
269
|
+
r.textContent = i.length > 0 ? i.join(`
|
|
270
|
+
`) : "N/A";
|
|
271
|
+
}, $), e;
|
|
272
|
+
}
|
|
273
|
+
function gt(o, t) {
|
|
274
|
+
const { el: e, data: r } = z("video", "video", Z);
|
|
275
|
+
let a = 0, n = 0, i = performance.now();
|
|
276
|
+
return o.interval(() => {
|
|
277
|
+
const s = t.backend.video.source.catalog.peek(), l = t.backend.video.stats.peek(), c = performance.now(), p = c - i;
|
|
278
|
+
let d;
|
|
279
|
+
if (l && a > 0 && p > 0) {
|
|
280
|
+
const m = l.frameCount - a;
|
|
281
|
+
m > 0 && (d = m / (p / 1e3));
|
|
282
|
+
}
|
|
283
|
+
let h;
|
|
284
|
+
if (l && n > 0 && p > 0) {
|
|
285
|
+
const m = l.bytesReceived - n;
|
|
286
|
+
m > 0 && (h = B(m * 8 * (1e3 / p)));
|
|
287
|
+
}
|
|
288
|
+
l && (a = l.frameCount, n = l.bytesReceived, i = c);
|
|
289
|
+
const { width: f, height: b } = s?.display ?? {};
|
|
290
|
+
r.textContent = [
|
|
291
|
+
f && b ? `${f}x${b}` : "N/A",
|
|
292
|
+
d !== void 0 ? `@${d.toFixed(1)} fps` : "N/A",
|
|
293
|
+
h ?? "N/A"
|
|
294
|
+
].join(`
|
|
295
|
+
`);
|
|
296
|
+
}, $), e;
|
|
297
|
+
}
|
|
298
|
+
function ft(o, t) {
|
|
299
|
+
const { el: e, data: r } = z("audio", "audio", U);
|
|
300
|
+
let a = 0, n = performance.now();
|
|
301
|
+
return o.interval(() => {
|
|
302
|
+
const i = t.backend.audio.source.track.peek(), s = t.backend.audio.source.config.peek(), l = t.backend.audio.stats.peek();
|
|
303
|
+
if (!i || !s) {
|
|
304
|
+
r.textContent = "N/A";
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const c = performance.now();
|
|
308
|
+
let p;
|
|
309
|
+
if (l && a > 0) {
|
|
310
|
+
const h = l.bytesReceived - a, f = c - n;
|
|
311
|
+
h > 0 && f > 0 && (p = B(h * 8 * (1e3 / f)));
|
|
312
|
+
}
|
|
313
|
+
l && (a = l.bytesReceived, n = c);
|
|
314
|
+
const d = [];
|
|
315
|
+
s.sampleRate && d.push(`${(s.sampleRate / 1e3).toFixed(1)}kHz`), s.numberOfChannels && d.push(`${s.numberOfChannels}ch`), d.push(p ?? "N/A"), s.codec && d.push(s.codec), r.textContent = d.length > 0 ? d.join(`
|
|
316
|
+
`) : "N/A";
|
|
317
|
+
}, $), e;
|
|
318
|
+
}
|
|
319
|
+
function mt(o, t) {
|
|
320
|
+
const { el: e, data: r } = z("buffer", "buffer", D);
|
|
321
|
+
return o.run((a) => {
|
|
322
|
+
const n = a.get(t.backend.jitter);
|
|
323
|
+
r.textContent = `${Math.round(n)}ms`;
|
|
324
|
+
}), e;
|
|
325
|
+
}
|
|
326
|
+
function vt(o, t, e) {
|
|
327
|
+
const r = v("div", { className: "stats" }), a = v("div", { className: "stats-panel" });
|
|
328
|
+
return r.appendChild(a), o.run((n) => {
|
|
329
|
+
const i = n.get(e);
|
|
330
|
+
r.style.display = i ? "" : "none", i && (C(n, a, ht(n, t)), C(n, a, gt(n, t)), C(n, a, ft(n, t)), C(n, a, mt(n, t)));
|
|
331
|
+
}), r;
|
|
332
|
+
}
|
|
333
|
+
const bt = ':host{--color-white: #ffffff;--color-white-alpha-05: rgba(255, 255, 255, .05);--color-white-alpha-10: rgba(255, 255, 255, .1);--color-white-alpha-15: rgba(255, 255, 255, .15);--color-white-alpha-20: rgba(255, 255, 255, .2);--color-white-alpha-25: rgba(255, 255, 255, .25);--color-white-alpha-30: rgba(255, 255, 255, .3);--color-white-alpha-40: rgba(255, 255, 255, .4);--color-white-alpha-70: rgba(255, 255, 255, .7);--color-white-alpha-90: rgba(255, 255, 255, .9);--color-gray-100: #9ca3af;--color-gray-950: #1a1a1a;--color-blue-400: #00dfff;--color-blue-500: #52a1ff;--color-blue-900: #1b3243;--color-purple-400: #a855f7;--color-purple-900: #31144a;--color-green-400: #65ee2e;--color-green-900: #3d4928;--color-yellow-400: #facc15;--color-orange-400: #ff9900;--color-orange-450: #fb923c;--color-orange-500: #f97316;--color-orange-900: #4d301b;--color-amber-600: #d97706;--color-orange-500-alpha-60: rgba(249, 115, 22, .6);--color-orange-500-alpha-80: rgba(249, 115, 22, .8);--color-black-alpha-08: rgba(0, 0, 0, .08);--color-black-alpha-10: rgba(0, 0, 0, .1);--color-black-alpha-40: rgba(0, 0, 0, .4);--color-black-alpha-85: rgba(0, 0, 0, .85);--spacing-1: .0625rem;--spacing-2: .125rem;--spacing-4: .25rem;--spacing-8: .5rem;--spacing-12: .75rem;--spacing-16: 1rem;--spacing-24: 1.5rem;--spacing-32: 2rem;--spacing-48: 3rem;--border-radius-sm: .5rem;--border-radius-md: .75rem;--border-radius-lg: 1rem}.flex-center{display:flex;justify-content:center;align-items:center}.flex-align-center{align-items:center}.button{color:var(--color-white);cursor:pointer;background-color:var(--color-white-alpha-10);border:var(--spacing-1) solid var(--color-white-alpha-20);border-radius:50%;width:2.25rem;height:2.25rem;transform-origin:center;transition:transform .1s cubic-bezier(.4,0,.2,1)}.button:hover:not(:disabled){transform:scale(1.02);background-color:var(--color-white-alpha-20);box-shadow:0 var(--spacing-2) var(--spacing-8) var(--color-black-alpha-10)}.button:active:not(:disabled){transform:scale(.98);box-shadow:0 var(--spacing-1) var(--spacing-4) var(--color-black-alpha-08)}.button:disabled{opacity:.5;cursor:default;color:var(--color-gray-100)}.stats{display:flex;align-items:center;justify-content:center;position:absolute;inset:0;pointer-events:none;z-index:2;width:100%;height:inherit;container-type:inline-size}.stats .stats-panel{position:absolute;display:flex;align-items:flex-start;justify-content:center;flex-direction:row;flex-wrap:wrap;gap:var(--spacing-12);max-width:240px;width:100%;background-color:var(--color-black-alpha-85);border:1px solid var(--color-white-alpha-25);border-radius:8px;padding:var(--spacing-12);pointer-events:auto;top:8px}@container (width > 480px) and (width <= 768px){.stats .stats-panel{max-width:360px;padding:var(--spacing-24)}}@container (width > 768px){.stats .stats-panel{max-width:600px;padding:var(--spacing-24)}}.stats .stats-panel .stats-item{display:flex;align-items:flex-start;justify-content:flex-start;flex-direction:row;height:auto;column-gap:var(--spacing-8);flex-basis:calc(50% - var(--spacing-12));flex-grow:1;flex-shrink:1}@container (width > 480px){.stats .stats-panel .stats-item{flex-basis:calc(25% - var(--spacing-12))}}.stats .stats-panel .stats-item .stats-icon-wrapper{display:none;padding:var(--spacing-8);border-radius:8px;width:fit-content;height:fit-content;flex-shrink:0}@container (width > 480px){.stats .stats-panel .stats-item .stats-icon-wrapper{width:24px;height:24px;display:flex;align-items:center;justify-content:center;flex-direction:row}}.stats .stats-panel .stats-item .stats-icon-wrapper svg{width:100%;height:100%}.stats .stats-panel .stats-item.stats-item--network .stats-icon-wrapper{background-color:var(--color-blue-900)}.stats .stats-panel .stats-item.stats-item--network,.stats .stats-panel .stats-item.stats-item--network .stats-item-data{color:var(--color-blue-400)}.stats .stats-panel .stats-item.stats-item--video .stats-icon-wrapper{background-color:var(--color-purple-900)}.stats .stats-panel .stats-item.stats-item--video,.stats .stats-panel .stats-item.stats-item--video .stats-item-data{color:var(--color-purple-400)}.stats .stats-panel .stats-item.stats-item--audio .stats-icon-wrapper{background-color:var(--color-green-900)}.stats .stats-panel .stats-item.stats-item--audio,.stats .stats-panel .stats-item.stats-item--audio .stats-item-data{color:var(--color-green-400)}.stats .stats-panel .stats-item.stats-item--buffer .stats-icon-wrapper{background-color:var(--color-orange-900)}.stats .stats-panel .stats-item.stats-item--buffer,.stats .stats-panel .stats-item.stats-item--buffer .stats-item-data{color:var(--color-orange-400)}.stats .stats-panel .stats-item .stats-item-detail{display:flex;align-items:flex-start;justify-content:space-evenly;flex-direction:column;gap:var(--spacing-4)}.stats .stats-panel .stats-item .stats-item-detail .stats-item-title{font-size:12px;font-weight:500;text-transform:capitalize;color:var(--color-gray-100);font-family:Segoe UI,Roboto,sans-serif;letter-spacing:1px;line-height:12px}.stats .stats-panel .stats-item .stats-item-detail .stats-item-data{font-size:16px;font-weight:700;font-family:Segoe UI,Roboto,sans-serif;white-space:pre-wrap;line-height:1.5}.video-container{display:block;position:relative;width:100%;height:auto;border-radius:var(--spacing-4);margin:0 auto;pointer-events:none}.controls{display:flex;flex-direction:column;gap:var(--spacing-24)}.button.button--playback{width:3rem;height:3rem;background:linear-gradient(to bottom right,var(--color-orange-400),var(--color-orange-500),var(--color-amber-600));box-shadow:0 0 var(--spacing-16) var(--color-orange-500-alpha-60);transition:box-shadow .15s cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden}.button.button--playback:hover:not(:disabled){box-shadow:0 0 var(--spacing-24) var(--color-orange-500-alpha-80);transform:scale(1.02)}.button.button--playback:active:not(:disabled){transform:scale(.98)}.button.button--playback:before{content:"";position:absolute;inset:0;background:linear-gradient(to bottom right,var(--color-white-alpha-30),transparent);opacity:0;transition:opacity .15s cubic-bezier(.4,0,.2,1);pointer-events:none}.button.button--playback:hover:before{opacity:1}.button.button--playback:after{content:"";position:absolute;inset:0;background-color:var(--color-white-alpha-20);border-radius:50%;filter:blur(var(--spacing-24));pointer-events:none}.playback-controls{display:flex;place-content:center space-around;gap:var(--spacing-8);padding:var(--spacing-8) 0}.latency-controls{display:flex;flex-direction:column;gap:var(--spacing-16)}.volume-slider{gap:var(--spacing-4)}.volume-label{width:var(--spacing-16);text-align:right}.quality-selector{display:flex;align-items:center;gap:var(--spacing-8);background:transparent;border-radius:var(--spacing-8)}.quality-label{font-size:1.25rem;font-weight:500;color:var(--color-white);white-space:nowrap}.quality-select{flex:0 1 auto;font-size:1rem;padding:var(--spacing-8);border-radius:var(--spacing-4);background:var(--color-white-alpha-10);color:var(--color-white);border:var(--spacing-1) solid var(--color-white-alpha-20);cursor:pointer;transition:background .2s ease}.quality-select:hover{background:var(--color-white-alpha-15)}.quality-select:focus{outline:var(--spacing-2) solid var(--color-white-alpha-30);outline-offset:var(--spacing-2)}.quality-select option{background:var(--color-gray-950);color:var(--color-white)}.buffer{width:100%}.buffer-visualization{position:relative;width:100%;height:3.75rem;background:var(--color-white-alpha-10);border-radius:var(--spacing-4);cursor:pointer;user-select:none;padding-left:var(--spacing-48);box-sizing:border-box}.buffer-playhead{position:absolute;left:var(--spacing-48);top:0;bottom:0;width:var(--spacing-2);background:var(--color-white);z-index:3}.buffer-track{display:flex;align-items:center;position:absolute;left:var(--spacing-48);right:0;height:var(--spacing-24)}.buffer-track--video{top:var(--spacing-4)}.buffer-track--audio{top:var(--spacing-32)}.buffer-track-label{position:absolute;left:-2.875rem;width:2.5rem;font-size:.625rem;color:var(--color-white-alpha-70);text-align:right;padding-right:var(--spacing-4);pointer-events:none;box-sizing:border-box}.buffer-canvas{position:absolute;top:0;left:0;width:100%;height:100%}.buffer-target-area{position:absolute;top:0;bottom:0;left:var(--spacing-48);right:0;pointer-events:none}.buffer-target-line{position:absolute;top:0;bottom:0;width:.1875rem;background:var(--color-orange-400, var(--color-orange-450));z-index:2;cursor:ew-resize;border-radius:var(--spacing-1);pointer-events:auto}.buffer-target-label{position:absolute;bottom:100%;left:50%;transform:translate(-50%);font-size:.6875rem;font-weight:500;color:var(--color-orange-400, var(--color-orange-450));white-space:nowrap;margin-bottom:var(--spacing-2);opacity:0;transition:opacity .15s ease;pointer-events:none}.buffer-visualization:hover .buffer-target-label,.buffer-visualization--dragging .buffer-target-label{opacity:1}.buffer-help{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:.75rem;color:var(--color-white-alpha-30, rgba(255, 255, 255, .3));pointer-events:none;white-space:nowrap}.buffering{position:absolute;display:flex;align-items:center;justify-content:center;width:100%;height:100%;top:0;left:0;z-index:1;background-color:var(--color-black-alpha-40);backdrop-filter:blur(var(--spacing-2));pointer-events:auto}.buffering-spinner{width:2.5rem;height:2.5rem;border:var(--spacing-4) solid var(--color-white-alpha-20);border-top:var(--spacing-4) solid var(--color-white);border-radius:50%;animation:buffer-spin 1s linear infinite}@keyframes buffer-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.watch-ui__offline-indicator{position:absolute;bottom:1rem;right:1rem;padding:.5rem 1rem;display:flex;align-items:center;justify-content:center;background-color:#000;z-index:4;pointer-events:auto;border-radius:.25rem}.watch-ui__offline-text{font-size:.875rem;font-weight:700;color:#fff;letter-spacing:.08em;text-shadow:none}@media(max-width:768px){.watch-ui__offline-indicator{bottom:.75rem;right:.75rem;padding:.375rem .75rem}.watch-ui__offline-text{font-size:.75rem}}@media(max-width:480px){.watch-ui__offline-indicator{bottom:.5rem;right:.5rem;padding:.25rem .5rem}.watch-ui__offline-text{font-size:.75rem}}.status-indicator{gap:var(--spacing-12);backdrop-filter:blur(var(--spacing-16))}.status-indicator-dot{position:relative;width:.75rem;height:.75rem;border-radius:50%;flex-shrink:0;z-index:1}.status-indicator-dot:after{content:"";position:absolute;inset:0;border-radius:50%;background:currentcolor;transform:scale(1);opacity:.5;animation:status-pulse 1.5s ease-out infinite;z-index:-1}.status-indicator-dot:after{display:none}.status-indicator-dot--live:after,.status-indicator-dot--connected:after,.status-indicator-dot--loading:after,.status-indicator-dot--connecting:after{display:block}.status-indicator-dot--error{background:var(--color-gray-100);color:var(--color-gray-100)}.status-indicator-text--error{color:var(--color-gray-100)}.status-indicator-dot--connecting{background:var(--color-yellow-400);color:var(--color-yellow-400)}.status-indicator-text--connecting{color:var(--color-yellow-400)}.status-indicator-dot--loading{background:var(--color-yellow-400);color:var(--color-yellow-400)}.status-indicator-text--loading{color:var(--color-yellow-400)}.status-indicator-dot--live{background:var(--color-green-400);color:var(--color-green-400)}.status-indicator-text--live{color:var(--color-green-400)}.status-indicator-dot--connected{background:var(--color-blue-500);color:var(--color-blue-500)}.status-indicator-text--connected{color:var(--color-blue-500)}.status-indicator-text{font-size:1rem;letter-spacing:.1rem}@keyframes status-pulse{0%{transform:scale(1);opacity:.5}70%{opacity:.25}to{transform:scale(2.5);opacity:0}}';
|
|
334
|
+
class wt extends HTMLElement {
|
|
335
|
+
#e;
|
|
336
|
+
#t;
|
|
337
|
+
#o = new R(void 0);
|
|
338
|
+
#a;
|
|
339
|
+
constructor() {
|
|
340
|
+
super(), this.#t = this.attachShadow({ mode: "open" });
|
|
341
|
+
const t = document.createElement("style");
|
|
342
|
+
t.textContent = bt, this.#t.appendChild(t), this.#a = new MutationObserver(() => this.#n());
|
|
343
|
+
}
|
|
344
|
+
connectedCallback() {
|
|
345
|
+
this.#n(), this.#a.observe(this, { childList: !0 });
|
|
346
|
+
const t = new T();
|
|
347
|
+
this.#e = t, t.run(this.#r.bind(this));
|
|
348
|
+
}
|
|
349
|
+
disconnectedCallback() {
|
|
350
|
+
this.#a.disconnect(), this.#e?.close(), this.#e = void 0;
|
|
351
|
+
}
|
|
352
|
+
#n() {
|
|
353
|
+
const t = this.querySelector("moq-watch");
|
|
354
|
+
this.#o.set(t ?? void 0);
|
|
355
|
+
}
|
|
356
|
+
#r(t) {
|
|
357
|
+
const e = t.get(this.#o);
|
|
358
|
+
if (!e) return;
|
|
359
|
+
const r = new R(!1), a = v("div", { className: "video-container" });
|
|
360
|
+
a.append(
|
|
361
|
+
v("slot"),
|
|
362
|
+
vt(t, e, r),
|
|
363
|
+
O(t, e),
|
|
364
|
+
nt(t, e)
|
|
365
|
+
);
|
|
366
|
+
const n = v("div", { className: "controls" }), i = v("div", { className: "playback-controls flex-align-center" });
|
|
367
|
+
i.append(
|
|
368
|
+
rt(t, e),
|
|
369
|
+
dt(t, e),
|
|
370
|
+
pt(t, e),
|
|
371
|
+
lt(t, r),
|
|
372
|
+
ot(t, e)
|
|
373
|
+
);
|
|
374
|
+
const s = v("div", { className: "latency-controls" });
|
|
375
|
+
s.append(V(t, e), st(t, e)), n.append(i, s), C(t, this.#t, a), C(t, this.#t, n);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
customElements.define("moq-watch-ui", wt);
|
|
379
|
+
export {
|
|
380
|
+
wt as default
|
|
381
|
+
};
|
|
382
|
+
//# sourceMappingURL=element.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.js","sources":["../../src/ui/components/buffer-control.ts","../../src/ui/components/buffering-indicator.ts","../../src/ui/icons/audio.svg?raw","../../src/ui/icons/buffer.svg?raw","../../src/ui/icons/fullscreen-enter.svg?raw","../../src/ui/icons/fullscreen-exit.svg?raw","../../src/ui/icons/mute.svg?raw","../../src/ui/icons/network.svg?raw","../../src/ui/icons/pause.svg?raw","../../src/ui/icons/play.svg?raw","../../src/ui/icons/stats.svg?raw","../../src/ui/icons/video.svg?raw","../../src/ui/icons/volume-high.svg?raw","../../src/ui/icons/volume-low.svg?raw","../../src/ui/icons/volume-medium.svg?raw","../../src/ui/icons.ts","../../src/ui/components/fullscreen-button.ts","../../src/ui/components/offline-indicator.ts","../../src/ui/components/play-pause.ts","../../src/ui/components/quality-selector.ts","../../src/ui/components/stats-button.ts","../../src/ui/components/volume-slider.ts","../../src/ui/components/watch-status-indicator.ts","../../src/ui/stats.ts","../../src/ui/element.ts"],"sourcesContent":["import type { Moq } from \"@moq/hang\";\nimport type { Effect } from \"@moq/signals\";\nimport type { BufferedRanges } from \"../..\";\nimport type MoqWatch from \"../../element\";\n\nconst MIN_RANGE = 0 as Moq.Time.Milli;\nconst RANGE_STEP = 10 as Moq.Time.Milli;\nconst DEFAULT_MAX = 4000 as Moq.Time.Milli;\nconst LABEL_WIDTH = 48;\n\nfunction drawRanges(\n\tcanvas: HTMLCanvasElement,\n\tranges: BufferedRanges,\n\ttimestamp: Moq.Time.Milli | undefined,\n\tmax: Moq.Time.Milli,\n\tisBuffering: boolean,\n) {\n\tconst ctx = canvas.getContext(\"2d\");\n\tif (!ctx) return;\n\n\tconst dpr = window.devicePixelRatio || 1;\n\tconst rect = canvas.getBoundingClientRect();\n\tconst width = rect.width;\n\tconst height = rect.height;\n\n\tconst canvasW = Math.round(width * dpr);\n\tconst canvasH = Math.round(height * dpr);\n\tif (canvas.width !== canvasW || canvas.height !== canvasH) {\n\t\tcanvas.width = canvasW;\n\t\tcanvas.height = canvasH;\n\t}\n\n\tctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\tctx.clearRect(0, 0, width, height);\n\n\tif (timestamp === undefined) return;\n\n\tconst padding = 2;\n\tconst rangeHeight = height - padding * 2;\n\tconst radius = 2;\n\n\tfor (let i = 0; i < ranges.length; i++) {\n\t\tconst range = ranges[i];\n\t\tconst startMs = (range.start - timestamp) as Moq.Time.Milli;\n\t\tconst endMs = (range.end - timestamp) as Moq.Time.Milli;\n\t\tconst visibleStart = Math.max(0, startMs);\n\t\tconst visibleEnd = Math.min(endMs, max);\n\n\t\tif (visibleEnd <= visibleStart) continue;\n\n\t\tconst x = (visibleStart / max) * width;\n\t\tconst w = Math.max(2, ((visibleEnd - visibleStart) / max) * width);\n\n\t\tctx.globalAlpha = 0.85;\n\t\tctx.fillStyle = isBuffering ? \"#f87171\" : i > 0 ? \"#facc15\" : \"#4ade80\";\n\n\t\tif (typeof ctx.roundRect === \"function\") {\n\t\t\tctx.beginPath();\n\t\t\tctx.roundRect(x, padding, w, rangeHeight, radius);\n\t\t\tctx.fill();\n\t\t} else {\n\t\t\tctx.fillRect(x, padding, w, rangeHeight);\n\t\t}\n\n\t\tif (endMs > max) {\n\t\t\tconst overflowSec = ((endMs - max) / 1000).toFixed(1);\n\t\t\tctx.globalAlpha = 0.7;\n\t\t\tctx.fillStyle = \"black\";\n\t\t\tctx.font = \"500 9px system-ui, sans-serif\";\n\t\t\tctx.textAlign = \"right\";\n\t\t\tctx.textBaseline = \"middle\";\n\t\t\tctx.fillText(`+${overflowSec}s`, x + w - 4, height / 2);\n\t\t}\n\t}\n}\n\nexport function bufferControl(parent: Effect, watch: MoqWatch, max: Moq.Time.Milli = DEFAULT_MAX): HTMLElement {\n\tconst wrapper = document.createElement(\"div\");\n\twrapper.className = \"buffer\";\n\n\tconst viz = document.createElement(\"div\");\n\tviz.className = \"buffer-visualization\";\n\tviz.setAttribute(\"role\", \"slider\");\n\tviz.tabIndex = 0;\n\tviz.setAttribute(\"aria-valuemin\", MIN_RANGE.toString());\n\tviz.setAttribute(\"aria-valuemax\", max.toString());\n\tviz.setAttribute(\"aria-label\", \"Buffer jitter\");\n\n\tconst playhead = document.createElement(\"div\");\n\tplayhead.className = \"buffer-playhead\";\n\n\tconst videoTrack = document.createElement(\"div\");\n\tvideoTrack.className = \"buffer-track buffer-track--video\";\n\tconst videoLabel = document.createElement(\"span\");\n\tvideoLabel.className = \"buffer-track-label\";\n\tvideoLabel.textContent = \"Video\";\n\tconst videoCanvas = document.createElement(\"canvas\");\n\tvideoCanvas.className = \"buffer-canvas\";\n\tvideoTrack.append(videoLabel, videoCanvas);\n\n\tconst audioTrack = document.createElement(\"div\");\n\taudioTrack.className = \"buffer-track buffer-track--audio\";\n\tconst audioLabel = document.createElement(\"span\");\n\taudioLabel.className = \"buffer-track-label\";\n\taudioLabel.textContent = \"Audio\";\n\tconst audioCanvas = document.createElement(\"canvas\");\n\taudioCanvas.className = \"buffer-canvas\";\n\taudioTrack.append(audioLabel, audioCanvas);\n\n\tconst targetArea = document.createElement(\"div\");\n\ttargetArea.className = \"buffer-target-area\";\n\tconst targetLine = document.createElement(\"div\");\n\ttargetLine.className = \"buffer-target-line\";\n\tconst targetLabel = document.createElement(\"span\");\n\ttargetLabel.className = \"buffer-target-label\";\n\ttargetLine.appendChild(targetLabel);\n\ttargetArea.appendChild(targetLine);\n\n\tconst help = document.createElement(\"span\");\n\thelp.className = \"buffer-help\";\n\thelp.textContent = \"click to change latency\";\n\n\tviz.append(playhead, videoTrack, audioTrack, targetArea, help);\n\twrapper.appendChild(viz);\n\n\tlet dragging = false;\n\tlet hasInteracted = false;\n\n\tparent.run((effect) => {\n\t\tconst jitter = effect.get(watch.backend.jitter);\n\t\tconst pct = (jitter / max) * 100;\n\t\ttargetLine.style.left = `${pct}%`;\n\t\ttargetLabel.textContent = `${Math.round(jitter)}ms`;\n\t\tviz.setAttribute(\"aria-valuenow\", jitter.toString());\n\t});\n\n\tconst updateFromX = (clientX: number) => {\n\t\tconst rect = viz.getBoundingClientRect();\n\t\tconst trackWidth = rect.width - LABEL_WIDTH;\n\t\tconst x = Math.max(0, Math.min(clientX - rect.left - LABEL_WIDTH, trackWidth));\n\t\tconst ms = (x / trackWidth) * max;\n\t\tconst snapped = (Math.round(ms / RANGE_STEP) * RANGE_STEP) as Moq.Time.Milli;\n\t\tconst clamped = Math.max(MIN_RANGE, Math.min(max, snapped)) as Moq.Time.Milli;\n\t\twatch.backend.latency.set(clamped);\n\t};\n\n\tconst interact = () => {\n\t\tif (!hasInteracted) {\n\t\t\thasInteracted = true;\n\t\t\thelp.style.display = \"none\";\n\t\t}\n\t};\n\n\tparent.event(viz, \"mousedown\", (e) => {\n\t\tdragging = true;\n\t\tviz.classList.add(\"buffer-visualization--dragging\");\n\t\tinteract();\n\t\tupdateFromX(e.clientX);\n\t});\n\n\tparent.event(document, \"mousemove\", (e) => {\n\t\tif (dragging) updateFromX(e.clientX);\n\t});\n\n\tparent.event(document, \"mouseup\", () => {\n\t\tif (!dragging) return;\n\t\tdragging = false;\n\t\tviz.classList.remove(\"buffer-visualization--dragging\");\n\t});\n\n\tparent.event(viz, \"keydown\", (e) => {\n\t\tlet delta = 0 as Moq.Time.Milli;\n\t\tif (e.key === \"ArrowRight\" || e.key === \"ArrowUp\") {\n\t\t\tdelta = RANGE_STEP;\n\t\t} else if (e.key === \"ArrowLeft\" || e.key === \"ArrowDown\") {\n\t\t\tdelta = -RANGE_STEP as Moq.Time.Milli;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\t\te.preventDefault();\n\t\tinteract();\n\t\tconst current = watch.backend.jitter.peek();\n\t\tconst value = Math.max(MIN_RANGE, Math.min(max, current + delta)) as Moq.Time.Milli;\n\t\twatch.backend.latency.set(value);\n\t});\n\n\tconst draw = () => {\n\t\tconst timestamp = watch.backend.sync.now();\n\t\tconst isBuffering = watch.backend.video.stalled.peek();\n\t\tdrawRanges(videoCanvas, watch.backend.video.buffered.peek(), timestamp, max, isBuffering);\n\t\tdrawRanges(audioCanvas, watch.backend.audio.buffered.peek(), timestamp, max, isBuffering);\n\t\tparent.animate(draw);\n\t};\n\tparent.animate(draw);\n\n\treturn wrapper;\n}\n","import type { Effect } from \"@moq/signals\";\nimport type MoqWatch from \"../../element\";\n\nexport function bufferingIndicator(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst container = document.createElement(\"div\");\n\tcontainer.className = \"buffering\";\n\tconst spinner = document.createElement(\"div\");\n\tspinner.className = \"buffering-spinner\";\n\tcontainer.appendChild(spinner);\n\n\tparent.run((effect) => {\n\t\tconst buffering = effect.get(watch.backend.video.stalled);\n\t\tconst offline = effect.get(watch.broadcast.status) === \"offline\";\n\t\tcontainer.style.display = buffering && !offline ? \"\" : \"none\";\n\t});\n\n\treturn container;\n}\n","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M9 18V5l12-2v13\\\" />\\n\\t<circle cx=\\\"6\\\" cy=\\\"18\\\" r=\\\"3\\\" />\\n\\t<circle cx=\\\"18\\\" cy=\\\"16\\\" r=\\\"3\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M8 3H5a2 2 0 0 0-2 2v3\\\" />\\n\\t<path d=\\\"M21 8V5a2 2 0 0 0-2-2h-3\\\" />\\n\\t<path d=\\\"M3 16v3a2 2 0 0 0 2 2h3\\\" />\\n\\t<path d=\\\"M16 21h3a2 2 0 0 0 2-2v-3\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M8 3v3a2 2 0 0 1-2 2H3\\\" />\\n\\t<path d=\\\"M21 8h-3a2 2 0 0 1-2-2V3\\\" />\\n\\t<path d=\\\"M3 16h3a2 2 0 0 1 2 2v3\\\" />\\n\\t<path d=\\\"M16 21v-3a2 2 0 0 1 2-2h3\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"var(--color-white)\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M16 9a5 5 0 0 1 .95 2.293\\\" />\\n\\t<path d=\\\"M19.364 5.636a9 9 0 0 1 1.889 9.96\\\" />\\n\\t<path d=\\\"m2 2 20 20\\\" />\\n\\t<path d=\\\"m7 7-.587.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298V11\\\" />\\n\\t<path d=\\\"M9.828 4.172A.686.686 0 0 1 11 4.657v.686\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M16.247 7.761a6 6 0 0 1 0 8.478\\\" />\\n\\t<path d=\\\"M19.075 4.933a10 10 0 0 1 0 14.134\\\" />\\n\\t<path d=\\\"M4.925 19.067a10 10 0 0 1 0-14.134\\\" />\\n\\t<path d=\\\"M7.753 16.239a6 6 0 0 1 0-8.478\\\" />\\n\\t<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"2\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"var(--color-white)\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<rect x=\\\"14\\\" y=\\\"3\\\" width=\\\"5\\\" height=\\\"18\\\" rx=\\\"1\\\" />\\n <rect x=\\\"5\\\" y=\\\"3\\\" width=\\\"5\\\" height=\\\"18\\\" rx=\\\"1\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"var(--color-white)\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M5 21v-6\\\" />\\n\\t<path d=\\\"M12 21V3\\\" />\\n\\t<path d=\\\"M19 21V9\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\\\" />\\n\\t<rect x=\\\"2\\\" y=\\\"6\\\" width=\\\"14\\\" height=\\\"12\\\" rx=\\\"2\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"var(--color-white)\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\\\" />\\n\\t<path d=\\\"M16 9a5 5 0 0 1 0 6\\\" />\\n\\t<path d=\\\"M19.364 18.364a9 9 0 0 0 0-12.728\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"var(--color-white)\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n\\t<path d=\\\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\\\" />\\n</svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"var(--color-white)\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\">\\n <path d=\\\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\\\" />\\n <path d=\\\"M16 9a5 5 0 0 1 0 6\\\" />\\n</svg>\"","import audio from \"./icons/audio.svg?raw\";\nimport buffer from \"./icons/buffer.svg?raw\";\nimport fullscreenEnter from \"./icons/fullscreen-enter.svg?raw\";\nimport fullscreenExit from \"./icons/fullscreen-exit.svg?raw\";\nimport mute from \"./icons/mute.svg?raw\";\nimport network from \"./icons/network.svg?raw\";\nimport pause from \"./icons/pause.svg?raw\";\nimport play from \"./icons/play.svg?raw\";\nimport stats from \"./icons/stats.svg?raw\";\nimport video from \"./icons/video.svg?raw\";\nimport volumeHigh from \"./icons/volume-high.svg?raw\";\nimport volumeLow from \"./icons/volume-low.svg?raw\";\nimport volumeMedium from \"./icons/volume-medium.svg?raw\";\n\nexport {\n\taudio,\n\tbuffer,\n\tfullscreenEnter,\n\tfullscreenExit,\n\tmute,\n\tnetwork,\n\tpause,\n\tplay,\n\tstats,\n\tvideo,\n\tvolumeHigh,\n\tvolumeLow,\n\tvolumeMedium,\n};\n\nexport function icon(svg: string): HTMLElement {\n\tconst span = document.createElement(\"span\");\n\tspan.className = \"flex-center\";\n\tspan.setAttribute(\"role\", \"img\");\n\tspan.setAttribute(\"aria-hidden\", \"true\");\n\tspan.innerHTML = svg;\n\treturn span;\n}\n","import type { Effect } from \"@moq/signals\";\nimport type MoqWatch from \"../../element\";\nimport { fullscreenEnter, fullscreenExit, icon } from \"../icons\";\n\nexport function fullscreenButton(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst button = document.createElement(\"button\");\n\tbutton.type = \"button\";\n\tbutton.className = \"button flex-center\";\n\tbutton.title = \"Fullscreen\";\n\tbutton.setAttribute(\"aria-label\", \"Fullscreen\");\n\tbutton.replaceChildren(icon(fullscreenEnter));\n\n\tconst updateIcon = () => {\n\t\tconst isFull = !!document.fullscreenElement;\n\t\tbutton.replaceChildren(icon(isFull ? fullscreenExit : fullscreenEnter));\n\t};\n\tparent.event(document, \"fullscreenchange\", updateIcon);\n\n\tparent.event(button, \"click\", () => {\n\t\tif (document.fullscreenElement) {\n\t\t\tdocument.exitFullscreen();\n\t\t} else {\n\t\t\twatch.requestFullscreen();\n\t\t}\n\t});\n\n\treturn button;\n}\n","import type { Effect } from \"@moq/signals\";\nimport type MoqWatch from \"../../element\";\n\nexport function offlineIndicator(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst container = document.createElement(\"div\");\n\tcontainer.className = \"watch-ui__offline-indicator\";\n\tcontainer.setAttribute(\"role\", \"status\");\n\tcontainer.setAttribute(\"aria-live\", \"polite\");\n\n\tconst text = document.createElement(\"span\");\n\ttext.className = \"watch-ui__offline-text\";\n\ttext.textContent = \"OFFLINE\";\n\tcontainer.appendChild(text);\n\n\tparent.run((effect) => {\n\t\tconst offline = effect.get(watch.broadcast.status) === \"offline\";\n\t\tcontainer.style.display = offline ? \"\" : \"none\";\n\t});\n\n\treturn container;\n}\n","import type { Effect } from \"@moq/signals\";\nimport type MoqWatch from \"../../element\";\nimport { icon, pause, play } from \"../icons\";\n\nexport function playPauseButton(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst button = document.createElement(\"button\");\n\tbutton.type = \"button\";\n\tbutton.className = \"button button--playback flex-center\";\n\n\tparent.run((effect) => {\n\t\tconst paused = effect.get(watch.backend.paused);\n\t\tbutton.title = paused ? \"Play\" : \"Pause\";\n\t\tbutton.setAttribute(\"aria-label\", paused ? \"Play\" : \"Pause\");\n\t\tbutton.replaceChildren(icon(paused ? play : pause));\n\t});\n\n\tparent.event(button, \"click\", () => {\n\t\twatch.paused = !watch.paused;\n\t});\n\n\treturn button;\n}\n","import type { Effect } from \"@moq/signals\";\nimport type MoqWatch from \"../../element\";\n\nfunction formatBitrate(bps: number): string {\n\tif (bps >= 1_000_000) return `${(bps / 1_000_000).toFixed(1)} Mbps`;\n\tif (bps >= 1_000) return `${(bps / 1_000).toFixed(0)} kbps`;\n\treturn `${bps} bps`;\n}\n\nexport function qualitySelector(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst wrapper = document.createElement(\"div\");\n\twrapper.className = \"quality-selector\";\n\n\tconst label = document.createElement(\"label\");\n\tlabel.htmlFor = \"moq-watch-quality-select\";\n\tlabel.className = \"quality-label\";\n\tlabel.textContent = \"Quality: \";\n\n\tconst select = document.createElement(\"select\");\n\tselect.id = \"moq-watch-quality-select\";\n\tselect.className = \"quality-select\";\n\n\twrapper.append(label, select);\n\n\tparent.run((effect) => {\n\t\tconst catalog = effect.get(watch.backend.video.source.catalog);\n\t\tconst active = effect.get(watch.backend.video.source.track);\n\t\tconst renditions = catalog?.renditions ?? {};\n\n\t\tselect.replaceChildren();\n\t\tconst auto = document.createElement(\"option\");\n\t\tauto.value = \"\";\n\t\tauto.textContent = \"Auto\";\n\t\tselect.appendChild(auto);\n\n\t\tfor (const [name, config] of Object.entries(renditions)) {\n\t\t\tconst opt = document.createElement(\"option\");\n\t\t\topt.value = name;\n\t\t\tconst dims = config.codedWidth && config.codedHeight ? ` (${config.codedWidth}x${config.codedHeight})` : \"\";\n\t\t\tconst rate = config.bitrate ? ` ${formatBitrate(config.bitrate)}` : \"\";\n\t\t\topt.textContent = `${name}${dims}${rate}`;\n\t\t\tselect.appendChild(opt);\n\t\t}\n\n\t\tselect.value = active ?? \"\";\n\t});\n\n\tparent.event(select, \"change\", () => {\n\t\tconst value = select.value || undefined;\n\t\twatch.backend.video.source.target.update((prev) => ({ ...prev, name: value }));\n\t});\n\n\treturn wrapper;\n}\n","import type { Effect, Signal } from \"@moq/signals\";\nimport { icon, stats } from \"../icons\";\n\nexport function statsButton(parent: Effect, visible: Signal<boolean>): HTMLElement {\n\tconst button = document.createElement(\"button\");\n\tbutton.type = \"button\";\n\tbutton.className = \"button flex-center\";\n\tbutton.replaceChildren(icon(stats));\n\n\tparent.run((effect) => {\n\t\tconst showing = effect.get(visible);\n\t\tbutton.title = showing ? \"Hide stats\" : \"Show stats\";\n\t\tbutton.setAttribute(\"aria-label\", button.title);\n\t});\n\n\tparent.event(button, \"click\", () => {\n\t\tvisible.update((v) => !v);\n\t});\n\n\treturn button;\n}\n","import type { Effect } from \"@moq/signals\";\nimport type MoqWatch from \"../../element\";\nimport { icon, mute, volumeHigh, volumeLow, volumeMedium } from \"../icons\";\n\nfunction volumeIcon(volumePct: number, muted: boolean): string {\n\tif (muted || volumePct === 0) return mute;\n\tif (volumePct <= 33) return volumeLow;\n\tif (volumePct <= 66) return volumeMedium;\n\treturn volumeHigh;\n}\n\nexport function volumeSlider(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst wrapper = document.createElement(\"div\");\n\twrapper.className = \"volume-slider flex-center\";\n\n\tconst button = document.createElement(\"button\");\n\tbutton.type = \"button\";\n\tbutton.className = \"button flex-center\";\n\n\tconst slider = document.createElement(\"input\");\n\tslider.type = \"range\";\n\tslider.min = \"0\";\n\tslider.max = \"100\";\n\n\tconst label = document.createElement(\"span\");\n\tlabel.className = \"volume-label\";\n\n\twrapper.append(button, slider, label);\n\n\tparent.run((effect) => {\n\t\tconst volume = effect.get(watch.backend.audio.volume);\n\t\tconst muted = effect.get(watch.backend.audio.muted);\n\t\tconst pct = Math.round(volume * 100);\n\t\tslider.value = pct.toString();\n\t\tlabel.textContent = pct.toString();\n\t\tbutton.title = muted ? \"Unmute\" : \"Mute\";\n\t\tbutton.setAttribute(\"aria-label\", button.title);\n\t\tbutton.replaceChildren(icon(volumeIcon(pct, muted)));\n\t});\n\n\tparent.event(slider, \"input\", () => {\n\t\twatch.backend.audio.volume.set(Number.parseFloat(slider.value) / 100);\n\t});\n\n\tparent.event(button, \"click\", () => {\n\t\twatch.backend.audio.muted.update((m) => !m);\n\t});\n\n\treturn wrapper;\n}\n","import type { Effect } from \"@moq/signals\";\nimport type MoqWatch from \"../../element\";\n\ntype StatusConfig = { variant: string; text: string };\n\nfunction deriveStatus(\n\turl: URL | undefined,\n\tconnection: \"connecting\" | \"connected\" | \"disconnected\",\n\tbroadcast: \"offline\" | \"loading\" | \"live\",\n): StatusConfig {\n\tif (!url) return { variant: \"error\", text: \"No URL\" };\n\tif (connection === \"disconnected\") return { variant: \"error\", text: \"Disconnected\" };\n\tif (connection === \"connecting\") return { variant: \"connecting\", text: \"Connecting...\" };\n\tif (broadcast === \"offline\") return { variant: \"error\", text: \"Offline\" };\n\tif (broadcast === \"loading\") return { variant: \"loading\", text: \"Loading...\" };\n\tif (broadcast === \"live\") return { variant: \"live\", text: \"Live\" };\n\treturn { variant: \"connected\", text: \"Connected\" };\n}\n\nexport function watchStatusIndicator(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst wrapper = document.createElement(\"div\");\n\twrapper.className = \"status-indicator flex-center\";\n\n\tconst dot = document.createElement(\"span\");\n\tconst text = document.createElement(\"span\");\n\twrapper.append(dot, text);\n\n\tparent.run((effect) => {\n\t\tconst url = effect.get(watch.connection.url);\n\t\tconst conn = effect.get(watch.connection.status);\n\t\tconst broadcast = effect.get(watch.broadcast.status);\n\t\tconst { variant, text: label } = deriveStatus(url, conn, broadcast);\n\n\t\tdot.className = `status-indicator-dot status-indicator-dot--${variant}`;\n\t\ttext.className = `status-indicator-text status-indicator-text--${variant}`;\n\t\ttext.textContent = label;\n\t});\n\n\treturn wrapper;\n}\n","import type { Effect, Signal } from \"@moq/signals\";\nimport * as DOM from \"@moq/signals/dom\";\nimport type MoqWatch from \"../element\";\nimport { audio, buffer, icon, network, video } from \"./icons\";\n\nconst POLL_MS = 250;\n\ntype Kind = \"network\" | \"video\" | \"audio\" | \"buffer\";\n\nfunction row(kind: Kind, label: string, svg: string): { el: HTMLElement; data: HTMLSpanElement } {\n\tconst el = DOM.create(\"div\", { className: `stats-item stats-item--${kind}` });\n\n\tconst iconWrap = DOM.create(\"div\", { className: \"stats-icon-wrapper\" });\n\ticonWrap.appendChild(icon(svg));\n\n\tconst title = DOM.create(\"span\", { className: \"stats-item-title\" }, label);\n\tconst data = DOM.create(\"span\", { className: \"stats-item-data\" }, \"N/A\");\n\n\tconst detail = DOM.create(\"div\", { className: \"stats-item-detail\" });\n\tdetail.append(title, data);\n\n\tel.append(iconWrap, detail);\n\treturn { el, data };\n}\n\nfunction formatBitrate(bps: number): string {\n\tif (bps >= 1_000_000) return `${(bps / 1_000_000).toFixed(1)}Mbps`;\n\tif (bps >= 1_000) return `${(bps / 1_000).toFixed(0)}kbps`;\n\treturn `${bps.toFixed(0)}bps`;\n}\n\nfunction formatBandwidth(bps: number | undefined, dir: \"up\" | \"down\"): string | null {\n\tif (bps === undefined || bps <= 0) return null;\n\tconst arrow = dir === \"down\" ? \"↓\" : \"↑\";\n\tif (bps >= 1_000_000_000) return `${arrow} ${(bps / 1_000_000_000).toFixed(1)}Gbps`;\n\treturn `${arrow} ${formatBitrate(bps)}`;\n}\n\nfunction networkRow(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst { el, data } = row(\"network\", \"network\", network);\n\n\tparent.interval(() => {\n\t\tconst conn = watch.connection.established.peek();\n\t\tif (!conn) {\n\t\t\tdata.textContent = \"N/A\";\n\t\t\treturn;\n\t\t}\n\t\tconst rtt = conn.rtt?.peek();\n\t\tconst parts = [\n\t\t\tformatBandwidth(conn.recvBandwidth?.peek(), \"down\"),\n\t\t\tformatBandwidth(conn.sendBandwidth?.peek(), \"up\"),\n\t\t\trtt !== undefined && rtt > 0 ? `${rtt.toFixed(0)}ms` : null,\n\t\t].filter((p): p is string => p !== null);\n\t\tdata.textContent = parts.length > 0 ? parts.join(\"\\n\") : \"N/A\";\n\t}, POLL_MS);\n\n\treturn el;\n}\n\nfunction videoRow(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst { el, data } = row(\"video\", \"video\", video);\n\tlet prevFrames = 0;\n\tlet prevBytes = 0;\n\tlet prevWhen = performance.now();\n\n\tparent.interval(() => {\n\t\tconst catalog = watch.backend.video.source.catalog.peek();\n\t\tconst stats = watch.backend.video.stats.peek();\n\t\tconst now = performance.now();\n\t\tconst elapsedMs = now - prevWhen;\n\n\t\tlet fps: number | undefined;\n\t\tif (stats && prevFrames > 0 && elapsedMs > 0) {\n\t\t\tconst delta = stats.frameCount - prevFrames;\n\t\t\tif (delta > 0) fps = delta / (elapsedMs / 1000);\n\t\t}\n\n\t\tlet bitrate: string | undefined;\n\t\tif (stats && prevBytes > 0 && elapsedMs > 0) {\n\t\t\tconst delta = stats.bytesReceived - prevBytes;\n\t\t\tif (delta > 0) bitrate = formatBitrate(delta * 8 * (1000 / elapsedMs));\n\t\t}\n\n\t\tif (stats) {\n\t\t\tprevFrames = stats.frameCount;\n\t\t\tprevBytes = stats.bytesReceived;\n\t\t\tprevWhen = now;\n\t\t}\n\n\t\tconst { width, height } = catalog?.display ?? {};\n\t\tdata.textContent = [\n\t\t\twidth && height ? `${width}x${height}` : \"N/A\",\n\t\t\tfps !== undefined ? `@${fps.toFixed(1)} fps` : \"N/A\",\n\t\t\tbitrate ?? \"N/A\",\n\t\t].join(\"\\n\");\n\t}, POLL_MS);\n\n\treturn el;\n}\n\nfunction audioRow(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst { el, data } = row(\"audio\", \"audio\", audio);\n\tlet prevBytes = 0;\n\tlet prevWhen = performance.now();\n\n\tparent.interval(() => {\n\t\tconst track = watch.backend.audio.source.track.peek();\n\t\tconst config = watch.backend.audio.source.config.peek();\n\t\tconst stats = watch.backend.audio.stats.peek();\n\n\t\tif (!track || !config) {\n\t\t\tdata.textContent = \"N/A\";\n\t\t\treturn;\n\t\t}\n\n\t\tconst now = performance.now();\n\t\tlet bitrate: string | undefined;\n\t\tif (stats && prevBytes > 0) {\n\t\t\tconst delta = stats.bytesReceived - prevBytes;\n\t\t\tconst elapsedMs = now - prevWhen;\n\t\t\tif (delta > 0 && elapsedMs > 0) bitrate = formatBitrate(delta * 8 * (1000 / elapsedMs));\n\t\t}\n\n\t\tif (stats) {\n\t\t\tprevBytes = stats.bytesReceived;\n\t\t\tprevWhen = now;\n\t\t}\n\n\t\tconst parts: string[] = [];\n\t\tif (config.sampleRate) parts.push(`${(config.sampleRate / 1000).toFixed(1)}kHz`);\n\t\tif (config.numberOfChannels) parts.push(`${config.numberOfChannels}ch`);\n\t\tparts.push(bitrate ?? \"N/A\");\n\t\tif (config.codec) parts.push(config.codec);\n\t\tdata.textContent = parts.length > 0 ? parts.join(\"\\n\") : \"N/A\";\n\t}, POLL_MS);\n\n\treturn el;\n}\n\nfunction bufferRow(parent: Effect, watch: MoqWatch): HTMLElement {\n\tconst { el, data } = row(\"buffer\", \"buffer\", buffer);\n\n\tparent.run((effect) => {\n\t\tconst jitter = effect.get(watch.backend.jitter);\n\t\tdata.textContent = `${Math.round(jitter)}ms`;\n\t});\n\n\treturn el;\n}\n\nexport function statsPanel(parent: Effect, watch: MoqWatch, visible: Signal<boolean>): HTMLElement {\n\tconst wrap = DOM.create(\"div\", { className: \"stats\" });\n\tconst panel = DOM.create(\"div\", { className: \"stats-panel\" });\n\twrap.appendChild(panel);\n\n\tparent.run((effect) => {\n\t\tconst showing = effect.get(visible);\n\t\twrap.style.display = showing ? \"\" : \"none\";\n\t\tif (!showing) return;\n\n\t\tDOM.render(effect, panel, networkRow(effect, watch));\n\t\tDOM.render(effect, panel, videoRow(effect, watch));\n\t\tDOM.render(effect, panel, audioRow(effect, watch));\n\t\tDOM.render(effect, panel, bufferRow(effect, watch));\n\t});\n\n\treturn wrap;\n}\n","import { Effect, Signal } from \"@moq/signals\";\nimport * as DOM from \"@moq/signals/dom\";\nimport type MoqWatch from \"../element\";\nimport { bufferControl } from \"./components/buffer-control\";\nimport { bufferingIndicator } from \"./components/buffering-indicator\";\nimport { fullscreenButton } from \"./components/fullscreen-button\";\nimport { offlineIndicator } from \"./components/offline-indicator\";\nimport { playPauseButton } from \"./components/play-pause\";\nimport { qualitySelector } from \"./components/quality-selector\";\nimport { statsButton } from \"./components/stats-button\";\nimport { volumeSlider } from \"./components/volume-slider\";\nimport { watchStatusIndicator } from \"./components/watch-status-indicator\";\nimport { statsPanel } from \"./stats\";\nimport styles from \"./styles/index.css?inline\";\n\nexport default class MoqWatchUi extends HTMLElement {\n\t#signals?: Effect;\n\t#root: ShadowRoot;\n\t#watch = new Signal<MoqWatch | undefined>(undefined);\n\t#observer: MutationObserver;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.#root = this.attachShadow({ mode: \"open\" });\n\n\t\tconst style = document.createElement(\"style\");\n\t\tstyle.textContent = styles;\n\t\tthis.#root.appendChild(style);\n\n\t\tthis.#observer = new MutationObserver(() => this.#updateWatch());\n\t}\n\n\tconnectedCallback() {\n\t\tthis.#updateWatch();\n\t\tthis.#observer.observe(this, { childList: true });\n\n\t\tconst signals = new Effect();\n\t\tthis.#signals = signals;\n\t\tsignals.run(this.#render.bind(this));\n\t}\n\n\tdisconnectedCallback() {\n\t\tthis.#observer.disconnect();\n\t\tthis.#signals?.close();\n\t\tthis.#signals = undefined;\n\t}\n\n\t#updateWatch() {\n\t\tconst watch = this.querySelector(\"moq-watch\") as MoqWatch | null;\n\t\tthis.#watch.set(watch ?? undefined);\n\t}\n\n\t#render(effect: Effect) {\n\t\tconst watch = effect.get(this.#watch);\n\t\tif (!watch) return;\n\n\t\tconst visible = new Signal(false);\n\n\t\tconst videoContainer = DOM.create(\"div\", { className: \"video-container\" });\n\t\tvideoContainer.append(\n\t\t\tDOM.create(\"slot\"),\n\t\t\tstatsPanel(effect, watch, visible),\n\t\t\tbufferingIndicator(effect, watch),\n\t\t\tofflineIndicator(effect, watch),\n\t\t);\n\n\t\tconst controls = DOM.create(\"div\", { className: \"controls\" });\n\n\t\tconst playback = DOM.create(\"div\", { className: \"playback-controls flex-align-center\" });\n\t\tplayback.append(\n\t\t\tplayPauseButton(effect, watch),\n\t\t\tvolumeSlider(effect, watch),\n\t\t\twatchStatusIndicator(effect, watch),\n\t\t\tstatsButton(effect, visible),\n\t\t\tfullscreenButton(effect, watch),\n\t\t);\n\n\t\tconst latency = DOM.create(\"div\", { className: \"latency-controls\" });\n\t\tlatency.append(bufferControl(effect, watch), qualitySelector(effect, watch));\n\n\t\tcontrols.append(playback, latency);\n\n\t\tDOM.render(effect, this.#root, videoContainer);\n\t\tDOM.render(effect, this.#root, controls);\n\t}\n}\n\ncustomElements.define(\"moq-watch-ui\", MoqWatchUi);\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t\"moq-watch-ui\": MoqWatchUi;\n\t}\n}\n"],"names":["MIN_RANGE","RANGE_STEP","DEFAULT_MAX","LABEL_WIDTH","drawRanges","canvas","ranges","timestamp","max","isBuffering","ctx","dpr","rect","width","height","canvasW","canvasH","padding","rangeHeight","radius","i","range","startMs","endMs","visibleStart","visibleEnd","x","w","overflowSec","bufferControl","parent","watch","wrapper","viz","playhead","videoTrack","videoLabel","videoCanvas","audioTrack","audioLabel","audioCanvas","targetArea","targetLine","targetLabel","help","dragging","hasInteracted","effect","jitter","pct","updateFromX","clientX","trackWidth","ms","snapped","clamped","interact","e","delta","current","value","draw","bufferingIndicator","container","spinner","buffering","offline","audio","buffer","fullscreenEnter","fullscreenExit","mute","network","pause","play","stats","video","volumeHigh","volumeLow","volumeMedium","icon","svg","span","fullscreenButton","button","updateIcon","isFull","offlineIndicator","text","playPauseButton","paused","formatBitrate","bps","qualitySelector","label","select","catalog","active","renditions","auto","name","config","opt","dims","rate","prev","statsButton","visible","showing","v","volumeIcon","volumePct","muted","volumeSlider","slider","volume","m","deriveStatus","url","connection","broadcast","watchStatusIndicator","dot","conn","variant","POLL_MS","row","kind","el","DOM.create","iconWrap","title","data","detail","formatBandwidth","dir","arrow","networkRow","rtt","parts","p","videoRow","prevFrames","prevBytes","prevWhen","now","elapsedMs","fps","bitrate","audioRow","track","bufferRow","statsPanel","wrap","panel","DOM.render","MoqWatchUi","#signals","#root","#watch","Signal","#observer","style","styles","#updateWatch","signals","Effect","#render","videoContainer","controls","playback","latency"],"mappings":"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"}
|
package/ui/icons.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import audio from "./icons/audio.svg?raw";
|
|
2
|
+
import buffer from "./icons/buffer.svg?raw";
|
|
3
|
+
import fullscreenEnter from "./icons/fullscreen-enter.svg?raw";
|
|
4
|
+
import fullscreenExit from "./icons/fullscreen-exit.svg?raw";
|
|
5
|
+
import mute from "./icons/mute.svg?raw";
|
|
6
|
+
import network from "./icons/network.svg?raw";
|
|
7
|
+
import pause from "./icons/pause.svg?raw";
|
|
8
|
+
import play from "./icons/play.svg?raw";
|
|
9
|
+
import stats from "./icons/stats.svg?raw";
|
|
10
|
+
import video from "./icons/video.svg?raw";
|
|
11
|
+
import volumeHigh from "./icons/volume-high.svg?raw";
|
|
12
|
+
import volumeLow from "./icons/volume-low.svg?raw";
|
|
13
|
+
import volumeMedium from "./icons/volume-medium.svg?raw";
|
|
14
|
+
export { audio, buffer, fullscreenEnter, fullscreenExit, mute, network, pause, play, stats, video, volumeHigh, volumeLow, volumeMedium, };
|
|
15
|
+
export declare function icon(svg: string): HTMLElement;
|
|
16
|
+
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/ui/icons.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,uBAAuB,CAAC;AAC1C,OAAO,MAAM,MAAM,wBAAwB,CAAC;AAC5C,OAAO,eAAe,MAAM,kCAAkC,CAAC;AAC/D,OAAO,cAAc,MAAM,iCAAiC,CAAC;AAC7D,OAAO,IAAI,MAAM,sBAAsB,CAAC;AACxC,OAAO,OAAO,MAAM,yBAAyB,CAAC;AAC9C,OAAO,KAAK,MAAM,uBAAuB,CAAC;AAC1C,OAAO,IAAI,MAAM,sBAAsB,CAAC;AACxC,OAAO,KAAK,MAAM,uBAAuB,CAAC;AAC1C,OAAO,KAAK,MAAM,uBAAuB,CAAC;AAC1C,OAAO,UAAU,MAAM,6BAA6B,CAAC;AACrD,OAAO,SAAS,MAAM,4BAA4B,CAAC;AACnD,OAAO,YAAY,MAAM,+BAA+B,CAAC;AAEzD,OAAO,EACN,KAAK,EACL,MAAM,EACN,eAAe,EACf,cAAc,EACd,IAAI,EACJ,OAAO,EACP,KAAK,EACL,IAAI,EACJ,KAAK,EACL,KAAK,EACL,UAAU,EACV,SAAS,EACT,YAAY,GACZ,CAAC;AAEF,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAO7C"}
|
package/ui/stats.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/ui/stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AAoJvC,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,WAAW,CAiBjG"}
|
package/video/backend.d.ts
CHANGED
package/video/backend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/video/backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/video/backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,UAAU,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC,MAAM,WAAW,OAAO;IAEvB,MAAM,EAAE,MAAM,CAAC;IAGf,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IAGjC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAGzB,QAAQ,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAGjC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,KAAK;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACtB"}
|
package/video/decoder.d.ts
CHANGED
package/video/decoder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/video/decoder.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/video/decoder.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAMvC,MAAM,MAAM,YAAY,GAAG;IAC1B,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;CACpC,CAAC;AAOF,qBAAa,OAAQ,YAAW,OAAO;;IACtC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IAOf,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC,CAAe;IAI7D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,CAAmB;IAIrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAiB;IAGxF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAiB;IAGlD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,CAAe;IAIxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,cAAc,CAAC,CAAkB;gBAY/C,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,YAAY;IA+HhD,KAAK;CAKL"}
|
package/video/mse.d.ts
CHANGED
package/video/mse.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mse.d.ts","sourceRoot":"","sources":["../../src/video/mse.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"mse.d.ts","sourceRoot":"","sources":["../../src/video/mse.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,EAAU,KAAK,MAAM,EAAU,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,YAAY,CAAC;AAEpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC;;;GAGG;AACH,qBAAa,GAAI,YAAW,OAAO;;IAClC,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IAIf,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,CAAe;IAGxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,cAAc,CAAC,CAAkB;IAG3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAiB;IAGlD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAmB;IAE7D,OAAO,qBAAgB;gBAEX,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM;IAoOxC,KAAK,IAAI,IAAI;CAIb"}
|
package/video/renderer.d.ts
CHANGED