@camstack/addon-pipeline 0.1.19 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/audio-analyzer/index.js +736 -716
  2. package/dist/audio-analyzer/index.mjs +726 -676
  3. package/dist/audio-codec-nodeav/index.js +304 -461
  4. package/dist/audio-codec-nodeav/index.mjs +300 -462
  5. package/dist/chunk-BdkLduGY.mjs +5 -0
  6. package/dist/chunk-D6vf50IK.js +28 -0
  7. package/dist/codec-runtime-BOk-13PN.js +202 -0
  8. package/dist/codec-runtime-BsqlEjPi.mjs +197 -0
  9. package/dist/constants-B_b0a-6h.mjs +3119 -0
  10. package/dist/{index-D_cl0Qqb.js → constants-D65v6yp6.js} +3107 -2935
  11. package/dist/decoder-nodeav/index.js +1374 -1444
  12. package/dist/decoder-nodeav/index.mjs +1369 -1425
  13. package/dist/detection-pipeline/index.js +6462 -5613
  14. package/dist/detection-pipeline/index.mjs +6451 -5574
  15. package/dist/dist-7ewQjTle.js +22454 -0
  16. package/dist/dist-C5jnNl0n.mjs +22089 -0
  17. package/dist/motion-wasm/index.js +469 -467
  18. package/dist/motion-wasm/index.mjs +464 -446
  19. package/dist/pipeline-runner/index.js +2035 -1836
  20. package/dist/pipeline-runner/index.mjs +2031 -1820
  21. package/dist/recorder/index.js +2097 -0
  22. package/dist/recorder/index.mjs +2095 -0
  23. package/dist/stream-broker/_stub.js +1818 -734
  24. package/dist/stream-broker/_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-D4-DHanK.mjs +156 -0
  25. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Tf-HACFd.mjs +26 -0
  26. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-C9WX5HNw.mjs +26 -0
  27. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-BO7TIbJV.mjs +26 -0
  28. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.js-C9j-2lBe.mjs +26 -0
  29. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-XO0-Pyu6.mjs +26 -0
  30. package/dist/stream-broker/dist-CYZr2fwk.mjs +2726 -0
  31. package/dist/stream-broker/hostInit-Di6vceAU.mjs +129 -0
  32. package/dist/stream-broker/index.js +17837 -12904
  33. package/dist/stream-broker/index.mjs +17826 -12896
  34. package/dist/stream-broker/remoteEntry.js +134 -2973
  35. package/dist/stream-broker/remoteEntry.ssr.js +33 -0
  36. package/dist/stream-broker/virtualExposes-dYNvIwoR.mjs +27 -0
  37. package/dist/stream-broker/virtual_mf-exposes-ssr___mfe_internal__addon_stream_broker_widgets__remoteEntry_js-Cmqfp4i_.mjs +10 -0
  38. package/embed-dist/assets/index-B8VlSD0-.js +150 -0
  39. package/embed-dist/assets/index-ZhDdp1Nd.css +2 -0
  40. package/embed-dist/index.html +13 -0
  41. package/package.json +75 -9
  42. package/wasm/assembly/index.ts +41 -16
  43. package/dist/audio-analyzer/index.js.map +0 -1
  44. package/dist/audio-analyzer/index.mjs.map +0 -1
  45. package/dist/audio-codec-nodeav/index.js.map +0 -1
  46. package/dist/audio-codec-nodeav/index.mjs.map +0 -1
  47. package/dist/decoder-nodeav/index.js.map +0 -1
  48. package/dist/decoder-nodeav/index.mjs.map +0 -1
  49. package/dist/detection-pipeline/index.js.map +0 -1
  50. package/dist/detection-pipeline/index.mjs.map +0 -1
  51. package/dist/index-BbPPvoCx.js +0 -14682
  52. package/dist/index-BbPPvoCx.js.map +0 -1
  53. package/dist/index-Bmlkm0Fd.mjs +0 -14683
  54. package/dist/index-Bmlkm0Fd.mjs.map +0 -1
  55. package/dist/index-D_cl0Qqb.js.map +0 -1
  56. package/dist/index-UbcdLS7a.mjs +0 -5790
  57. package/dist/index-UbcdLS7a.mjs.map +0 -1
  58. package/dist/motion-wasm/index.js.map +0 -1
  59. package/dist/motion-wasm/index.mjs.map +0 -1
  60. package/dist/pipeline-runner/index.js.map +0 -1
  61. package/dist/pipeline-runner/index.mjs.map +0 -1
  62. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/StreamBrokerPanel.d.ts +0 -21
  63. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/index.d.ts +0 -13
  64. package/dist/stream-broker/@mf-types/widgets.d.ts +0 -2
  65. package/dist/stream-broker/@mf-types.d.ts +0 -3
  66. package/dist/stream-broker/@mf-types.zip +0 -0
  67. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-h5aXOPSA.mjs +0 -12
  68. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-NjF4kxzW.mjs +0 -19
  69. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-BAv_5ISf.mjs +0 -20
  70. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.mjs-U1EUeEPs.mjs +0 -104
  71. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_trpc_mf_1_client__loadShare__.mjs-DeouEaSs.mjs +0 -85
  72. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.mjs-DHUwjbb9.mjs +0 -62
  73. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs-BsB2G7oY.mjs +0 -88
  74. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-xrRiPUpA.mjs +0 -29
  75. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-gBEZsQrp.mjs +0 -36
  76. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs-DYEKzzY-.mjs +0 -45
  77. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-C0E2yCzO.mjs +0 -6
  78. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom_mf_1_client__loadShare__.mjs-DICOtMTl.mjs +0 -34
  79. package/dist/stream-broker/_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CupRlwqG.mjs +0 -156
  80. package/dist/stream-broker/client-NPZqorv9.mjs +0 -9836
  81. package/dist/stream-broker/getErrorShape-BPSzUA7W-TlK8ipWe.mjs +0 -211
  82. package/dist/stream-broker/hostInit-Bh4w7o5_.mjs +0 -168
  83. package/dist/stream-broker/index-2Qp8vT3w.mjs +0 -185
  84. package/dist/stream-broker/index-BBcZvb5t.mjs +0 -435
  85. package/dist/stream-broker/index-CIJue-4t.mjs +0 -37880
  86. package/dist/stream-broker/index-CWkKuNLr.mjs +0 -232
  87. package/dist/stream-broker/index-Cc6QBqMk.mjs +0 -1655
  88. package/dist/stream-broker/index-D_1p2K9B.mjs +0 -2603
  89. package/dist/stream-broker/index-Dy2V7VOm.mjs +0 -14379
  90. package/dist/stream-broker/index-mX3Kgiv1.mjs +0 -725
  91. package/dist/stream-broker/index-xncRG7-x.mjs +0 -2713
  92. package/dist/stream-broker/index.js.map +0 -1
  93. package/dist/stream-broker/index.mjs.map +0 -1
  94. package/dist/stream-broker/jsx-runtime-lb0mH5st.mjs +0 -55
  95. package/dist/stream-broker/schemas-ClCuS4qa.mjs +0 -3594
  96. package/dist/stream-broker/virtualExposes-pCd777Rp.mjs +0 -42
@@ -1,752 +1,1836 @@
1
- import { _ as e, a as r, b as B } from "./__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-gBEZsQrp.mjs";
2
- import { _ as z, a as G } from "./__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.mjs-U1EUeEPs.mjs";
3
- import { a as R, b as S, c as k, d as y, e as I } from "./__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs-BsB2G7oY.mjs";
4
- import { _ as E, a as Q, b as W, c as X, d as T, e as Z, f as V, g as J, h as Y } from "./__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-BAv_5ISf.mjs";
5
- /**
6
- * @license lucide-react v0.511.0 - ISC
7
- *
8
- * This source code is licensed under the ISC license.
9
- * See the LICENSE file in the root directory of this source tree.
10
- */
11
- const ee = (s) => s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), te = (s) => s.replace(
12
- /^([A-Z])|[\s-_]+(\w)/g,
13
- (n, o, i) => i ? i.toUpperCase() : o.toLowerCase()
14
- ), A = (s) => {
15
- const n = te(s);
16
- return n.charAt(0).toUpperCase() + n.slice(1);
17
- }, L = (...s) => s.filter((n, o, i) => !!n && n.trim() !== "" && i.indexOf(n) === o).join(" ").trim(), se = (s) => {
18
- for (const n in s)
19
- if (n.startsWith("aria-") || n === "role" || n === "title")
20
- return !0;
21
- };
22
- /**
23
- * @license lucide-react v0.511.0 - ISC
24
- *
25
- * This source code is licensed under the ISC license.
26
- * See the LICENSE file in the root directory of this source tree.
27
- */
28
- var re = {
29
- xmlns: "http://www.w3.org/2000/svg",
30
- width: 24,
31
- height: 24,
32
- viewBox: "0 0 24 24",
33
- fill: "none",
34
- stroke: "currentColor",
35
- strokeWidth: 2,
36
- strokeLinecap: "round",
37
- strokeLinejoin: "round"
38
- };
39
- /**
40
- * @license lucide-react v0.511.0 - ISC
41
- *
42
- * This source code is licensed under the ISC license.
43
- * See the LICENSE file in the root directory of this source tree.
44
- */
45
- const ne = R(
46
- ({
47
- color: s = "currentColor",
48
- size: n = 24,
49
- strokeWidth: o = 2,
50
- absoluteStrokeWidth: i,
51
- className: c = "",
52
- children: t,
53
- iconNode: l,
54
- ...d
55
- }, u) => S(
56
- "svg",
57
- {
58
- ref: u,
59
- ...re,
60
- width: n,
61
- height: n,
62
- stroke: s,
63
- strokeWidth: i ? Number(o) * 24 / Number(n) : o,
64
- className: L("lucide", c),
65
- ...!t && !se(d) && { "aria-hidden": "true" },
66
- ...d
67
- },
68
- [
69
- ...l.map(([a, m]) => S(a, m)),
70
- ...Array.isArray(t) ? t : [t]
71
- ]
72
- )
73
- );
74
- /**
75
- * @license lucide-react v0.511.0 - ISC
76
- *
77
- * This source code is licensed under the ISC license.
78
- * See the LICENSE file in the root directory of this source tree.
79
- */
80
- const _ = (s, n) => {
81
- const o = R(
82
- ({ className: i, ...c }, t) => S(ne, {
83
- ref: t,
84
- iconNode: n,
85
- className: L(
86
- `lucide-${ee(A(s))}`,
87
- `lucide-${s}`,
88
- i
89
- ),
90
- ...c
91
- })
92
- );
93
- return o.displayName = A(s), o;
1
+ import { a as e, i as t, n, o as r, r as i, t as a } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.js-C9j-2lBe.mjs";
2
+ import { a as o, c as s, i as c, l, n as u, o as d, r as f, s as p, t as m, u as h } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-C9WX5HNw.mjs";
3
+ import { n as g, r as _, t as v } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-XO0-Pyu6.mjs";
4
+ import { n as y, t as b } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-BO7TIbJV.mjs";
5
+ import { t as x } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Tf-HACFd.mjs";
6
+ //#region ../../node_modules/lucide-react/dist/esm/shared/src/utils.js
7
+ var S = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), C = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), w = (e) => {
8
+ let t = C(e);
9
+ return t.charAt(0).toUpperCase() + t.slice(1);
10
+ }, T = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), E = (e) => {
11
+ for (let t in e) if (t.startsWith("aria-") || t === "role" || t === "title") return !0;
12
+ }, D = {
13
+ xmlns: "http://www.w3.org/2000/svg",
14
+ width: 24,
15
+ height: 24,
16
+ viewBox: "0 0 24 24",
17
+ fill: "none",
18
+ stroke: "currentColor",
19
+ strokeWidth: 2,
20
+ strokeLinecap: "round",
21
+ strokeLinejoin: "round"
22
+ }, O = n(({ color: e = "currentColor", size: t = 24, strokeWidth: n = 2, absoluteStrokeWidth: r, className: i = "", children: o, iconNode: s, ...c }, l) => a("svg", {
23
+ ref: l,
24
+ ...D,
25
+ width: t,
26
+ height: t,
27
+ stroke: e,
28
+ strokeWidth: r ? Number(n) * 24 / Number(t) : n,
29
+ className: T("lucide", i),
30
+ ...!o && !E(c) && { "aria-hidden": "true" },
31
+ ...c
32
+ }, [...s.map(([e, t]) => a(e, t)), ...Array.isArray(o) ? o : [o]])), k = (e, t) => {
33
+ let r = n(({ className: n, ...r }, i) => a(O, {
34
+ ref: i,
35
+ iconNode: t,
36
+ className: T(`lucide-${S(w(e))}`, `lucide-${e}`, n),
37
+ ...r
38
+ }));
39
+ return r.displayName = w(e), r;
40
+ }, A = k("chevron-down", [["path", {
41
+ d: "m6 9 6 6 6-6",
42
+ key: "qrunsl"
43
+ }]]), j = k("chevron-right", [["path", {
44
+ d: "m9 18 6-6-6-6",
45
+ key: "mthhwq"
46
+ }]]), ee = k("plus", [["path", {
47
+ d: "M5 12h14",
48
+ key: "1ays0h"
49
+ }], ["path", {
50
+ d: "M12 5v14",
51
+ key: "s699le"
52
+ }]]), te = k("radio", [
53
+ ["path", {
54
+ d: "M4.9 19.1C1 15.2 1 8.8 4.9 4.9",
55
+ key: "1vaf9d"
56
+ }],
57
+ ["path", {
58
+ d: "M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5",
59
+ key: "u1ii0m"
60
+ }],
61
+ ["circle", {
62
+ cx: "12",
63
+ cy: "12",
64
+ r: "2",
65
+ key: "1c9p78"
66
+ }],
67
+ ["path", {
68
+ d: "M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5",
69
+ key: "1j5fej"
70
+ }],
71
+ ["path", {
72
+ d: "M19.1 4.9C23 8.8 23 15.1 19.1 19",
73
+ key: "10b0cb"
74
+ }]
75
+ ]), ne = k("x", [["path", {
76
+ d: "M18 6 6 18",
77
+ key: "1bl5f8"
78
+ }], ["path", {
79
+ d: "m6 6 12 12",
80
+ key: "d8bk6v"
81
+ }]]);
82
+ //#endregion
83
+ //#region src/stream-broker/widgets/GeometryBuilder.tsx
84
+ function re(e) {
85
+ let t = [];
86
+ if (e.crop && t.push(`crop=${e.crop.w}:${e.crop.h}:${e.crop.x}:${e.crop.y}`), e.targetAspect && e.width !== void 0 && e.height !== void 0) {
87
+ let n = e.targetAspect.replace(":", "/");
88
+ e.mode === "pad" ? (t.push(`scale=${e.width}:${e.height}:force_original_aspect_ratio=decrease`), t.push(`pad=${e.width}:${e.height}:(ow-iw)/2:(oh-ih)/2`)) : (t.push(`scale=${e.width}:${e.height}:force_original_aspect_ratio=increase`), t.push(`crop=${e.width}:${e.height}`)), t.push(`setdar=${n}`);
89
+ }
90
+ return e.rotate === 90 ? t.push("transpose=1") : e.rotate === 270 ? t.push("transpose=2") : e.rotate === 180 && t.push("hflip", "vflip"), e.hflip && e.rotate !== 180 && t.push("hflip"), e.vflip && e.rotate !== 180 && t.push("vflip"), t.join(",");
91
+ }
92
+ function ie(e, t) {
93
+ let n = [];
94
+ for (let t = 0; t < e.length; t++) {
95
+ if (e[t] === "-vf") {
96
+ t++;
97
+ continue;
98
+ }
99
+ let r = e[t];
100
+ r !== void 0 && n.push(r);
101
+ }
102
+ return t.length > 0 && n.push("-vf", t), n;
103
+ }
104
+ var M = "text-[11px] uppercase tracking-wider text-foreground-subtle font-medium";
105
+ function ae({ outputArgs: e, onChange: t }) {
106
+ let [n, i] = r(""), [a, o] = r("pad"), [s, c] = r("1920"), [l, u] = r("1080"), [d, f] = r(!1), [p, m] = r("0"), [h, y] = r("0"), [b, x] = r("0"), [S, C] = r("0"), [w, T] = r(0), [E, D] = r(!1), [O, k] = r(!1), A = re((() => {
107
+ let e = {
108
+ rotate: w,
109
+ hflip: E,
110
+ vflip: O
111
+ };
112
+ return n !== "" && (e.targetAspect = n, e.mode = a, e.width = Number(s), e.height = Number(l)), d && (e.crop = {
113
+ x: Number(p),
114
+ y: Number(h),
115
+ w: Number(b),
116
+ h: Number(S)
117
+ }), e;
118
+ })());
119
+ return /* @__PURE__ */ _("div", {
120
+ className: "space-y-2 rounded border border-border/50 bg-surface-2/30 px-3 py-2",
121
+ children: [
122
+ /* @__PURE__ */ _("div", {
123
+ className: "flex items-center justify-between",
124
+ children: [/* @__PURE__ */ _("span", {
125
+ className: M,
126
+ children: ["Geometry / zoom", /* @__PURE__ */ g("span", {
127
+ className: "ml-2 text-[10px] normal-case text-foreground-subtle italic",
128
+ children: "composes a single -vf into output args"
129
+ })]
130
+ }), /* @__PURE__ */ g("button", {
131
+ type: "button",
132
+ onClick: () => t(ie(e, A)),
133
+ className: "rounded-md border border-border bg-surface-hover px-2 py-0.5 text-[10px] font-medium text-foreground hover:bg-surface-hover/70 transition-colors",
134
+ children: "Apply geometry"
135
+ })]
136
+ }),
137
+ /* @__PURE__ */ _("div", {
138
+ className: "flex flex-wrap items-center gap-2",
139
+ children: [
140
+ /* @__PURE__ */ g("label", {
141
+ className: M,
142
+ htmlFor: "geom-aspect",
143
+ children: "Aspect"
144
+ }),
145
+ /* @__PURE__ */ _("select", {
146
+ id: "geom-aspect",
147
+ value: n,
148
+ onChange: (e) => i(e.target.value),
149
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed appearance-none pr-6 min-w-[90px]",
150
+ children: [
151
+ /* @__PURE__ */ g("option", {
152
+ value: "",
153
+ children: "none"
154
+ }),
155
+ /* @__PURE__ */ g("option", {
156
+ value: "16:9",
157
+ children: "16:9"
158
+ }),
159
+ /* @__PURE__ */ g("option", {
160
+ value: "4:3",
161
+ children: "4:3"
162
+ }),
163
+ /* @__PURE__ */ g("option", {
164
+ value: "1:1",
165
+ children: "1:1"
166
+ })
167
+ ]
168
+ }),
169
+ n !== "" && /* @__PURE__ */ _(v, { children: [
170
+ /* @__PURE__ */ _("select", {
171
+ "aria-label": "Aspect mode",
172
+ value: a,
173
+ onChange: (e) => o(e.target.value),
174
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed appearance-none pr-6 min-w-[80px]",
175
+ children: [/* @__PURE__ */ g("option", {
176
+ value: "pad",
177
+ children: "pad"
178
+ }), /* @__PURE__ */ g("option", {
179
+ value: "crop",
180
+ children: "crop"
181
+ })]
182
+ }),
183
+ /* @__PURE__ */ g("input", {
184
+ type: "number",
185
+ "aria-label": "Aspect width",
186
+ value: s,
187
+ onChange: (e) => c(e.target.value),
188
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed w-20 text-right"
189
+ }),
190
+ /* @__PURE__ */ g("span", {
191
+ className: "text-[11px] text-foreground-subtle",
192
+ children: "×"
193
+ }),
194
+ /* @__PURE__ */ g("input", {
195
+ type: "number",
196
+ "aria-label": "Aspect height",
197
+ value: l,
198
+ onChange: (e) => u(e.target.value),
199
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed w-20 text-right"
200
+ })
201
+ ] })
202
+ ]
203
+ }),
204
+ /* @__PURE__ */ _("div", {
205
+ className: "flex flex-wrap items-center gap-2",
206
+ children: [/* @__PURE__ */ _("label", {
207
+ className: "text-[11px] uppercase tracking-wider text-foreground-subtle font-medium inline-flex items-center gap-1",
208
+ children: [/* @__PURE__ */ g("input", {
209
+ type: "checkbox",
210
+ checked: d,
211
+ onChange: (e) => f(e.target.checked)
212
+ }), "Crop / zoom"]
213
+ }), d && /* @__PURE__ */ _(v, { children: [
214
+ /* @__PURE__ */ g("input", {
215
+ type: "number",
216
+ "aria-label": "Crop x",
217
+ value: p,
218
+ onChange: (e) => m(e.target.value),
219
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed w-16 text-right",
220
+ placeholder: "x"
221
+ }),
222
+ /* @__PURE__ */ g("input", {
223
+ type: "number",
224
+ "aria-label": "Crop y",
225
+ value: h,
226
+ onChange: (e) => y(e.target.value),
227
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed w-16 text-right",
228
+ placeholder: "y"
229
+ }),
230
+ /* @__PURE__ */ g("input", {
231
+ type: "number",
232
+ "aria-label": "Crop width",
233
+ value: b,
234
+ onChange: (e) => x(e.target.value),
235
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed w-20 text-right",
236
+ placeholder: "w"
237
+ }),
238
+ /* @__PURE__ */ g("input", {
239
+ type: "number",
240
+ "aria-label": "Crop height",
241
+ value: S,
242
+ onChange: (e) => C(e.target.value),
243
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed w-20 text-right",
244
+ placeholder: "h"
245
+ })
246
+ ] })]
247
+ }),
248
+ /* @__PURE__ */ _("div", {
249
+ className: "flex flex-wrap items-center gap-2",
250
+ children: [
251
+ /* @__PURE__ */ g("label", {
252
+ className: M,
253
+ htmlFor: "geom-rotate",
254
+ children: "Rotate"
255
+ }),
256
+ /* @__PURE__ */ _("select", {
257
+ id: "geom-rotate",
258
+ value: String(w),
259
+ onChange: (e) => T(Number(e.target.value)),
260
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed appearance-none pr-6 min-w-[80px]",
261
+ children: [
262
+ /* @__PURE__ */ g("option", {
263
+ value: "0",
264
+ children: "0°"
265
+ }),
266
+ /* @__PURE__ */ g("option", {
267
+ value: "90",
268
+ children: "90°"
269
+ }),
270
+ /* @__PURE__ */ g("option", {
271
+ value: "180",
272
+ children: "180°"
273
+ }),
274
+ /* @__PURE__ */ g("option", {
275
+ value: "270",
276
+ children: "270°"
277
+ })
278
+ ]
279
+ }),
280
+ /* @__PURE__ */ _("label", {
281
+ className: "text-[11px] uppercase tracking-wider text-foreground-subtle font-medium inline-flex items-center gap-1",
282
+ children: [/* @__PURE__ */ g("input", {
283
+ type: "checkbox",
284
+ checked: E,
285
+ onChange: (e) => D(e.target.checked)
286
+ }), "hflip"]
287
+ }),
288
+ /* @__PURE__ */ _("label", {
289
+ className: "text-[11px] uppercase tracking-wider text-foreground-subtle font-medium inline-flex items-center gap-1",
290
+ children: [/* @__PURE__ */ g("input", {
291
+ type: "checkbox",
292
+ checked: O,
293
+ onChange: (e) => k(e.target.checked)
294
+ }), "vflip"]
295
+ })
296
+ ]
297
+ }),
298
+ /* @__PURE__ */ _("div", {
299
+ className: "font-mono text-[10px] text-foreground-subtle break-all",
300
+ children: ["-vf ", A.length > 0 ? A : /* @__PURE__ */ g("span", {
301
+ className: "italic",
302
+ children: "(empty)"
303
+ })]
304
+ })
305
+ ]
306
+ });
307
+ }
308
+ //#endregion
309
+ //#region src/stream-broker/widgets/FfmpegParamsField.tsx
310
+ var N = [
311
+ {
312
+ group: "Demuxer",
313
+ label: "-thread_queue_size 1024",
314
+ args: ["-thread_queue_size", "1024"],
315
+ description: "Larger input packet queue (helps with high-bitrate sources)"
316
+ },
317
+ {
318
+ group: "Demuxer",
319
+ label: "-fflags +genpts",
320
+ args: ["-fflags", "+genpts"],
321
+ description: "Generate PTS when the source lacks them"
322
+ },
323
+ {
324
+ group: "Demuxer",
325
+ label: "-re",
326
+ args: ["-re"],
327
+ description: "Read input at native frame rate (file replay)"
328
+ },
329
+ {
330
+ group: "Demuxer",
331
+ label: "-probesize 32",
332
+ args: ["-probesize", "32"],
333
+ description: "Minimal probe size — faster start"
334
+ },
335
+ {
336
+ group: "Demuxer",
337
+ label: "-analyzeduration 0",
338
+ args: ["-analyzeduration", "0"],
339
+ description: "Skip stream analysis — faster start"
340
+ },
341
+ {
342
+ group: "RTSP",
343
+ label: "-rtsp_transport tcp",
344
+ args: ["-rtsp_transport", "tcp"],
345
+ description: "Force TCP transport for RTSP source"
346
+ },
347
+ {
348
+ group: "RTSP",
349
+ label: "-stimeout 5000000",
350
+ args: ["-stimeout", "5000000"],
351
+ description: "Socket I/O timeout (microseconds, 5s)"
352
+ }
353
+ ], oe = [
354
+ {
355
+ group: "Muxer",
356
+ label: "-flush_packets 1",
357
+ args: ["-flush_packets", "1"],
358
+ description: "Flush each packet immediately"
359
+ },
360
+ {
361
+ group: "Muxer",
362
+ label: "-movflags +faststart",
363
+ args: ["-movflags", "+faststart"],
364
+ description: "Move MOOV atom to front (MP4)"
365
+ },
366
+ {
367
+ group: "Bitstream",
368
+ label: "-bsf:v h264_mp4toannexb",
369
+ args: ["-bsf:v", "h264_mp4toannexb"],
370
+ description: "Convert MP4-format H.264 to Annex-B"
371
+ },
372
+ {
373
+ group: "Bitstream",
374
+ label: "-bsf:v hevc_mp4toannexb",
375
+ args: ["-bsf:v", "hevc_mp4toannexb"],
376
+ description: "Convert MP4-format HEVC to Annex-B"
377
+ },
378
+ {
379
+ group: "x264",
380
+ label: "-x264-params keyint_min=15",
381
+ args: ["-x264-params", "keyint_min=15"],
382
+ description: "Force minimum keyframe interval to 15 frames"
383
+ },
384
+ {
385
+ group: "x264",
386
+ label: "-x264-params scenecut=0",
387
+ args: ["-x264-params", "scenecut=0"],
388
+ description: "Disable scene-change keyframes (predictable GOP)"
389
+ },
390
+ {
391
+ group: "x264",
392
+ label: "-x264-params nal-hrd=cbr",
393
+ args: ["-x264-params", "nal-hrd=cbr"],
394
+ description: "Force CBR HRD signalling (HomeKit-friendly)"
395
+ },
396
+ {
397
+ group: "x264",
398
+ label: "-aq-mode 3",
399
+ args: ["-aq-mode", "3"],
400
+ description: "Auto-variance adaptive quantisation (mode 3)"
401
+ },
402
+ {
403
+ group: "x265",
404
+ label: "-x265-params keyint=30",
405
+ args: ["-x265-params", "keyint=30"],
406
+ description: "Force maximum keyframe interval to 30 frames"
407
+ },
408
+ {
409
+ group: "x265",
410
+ label: "-x265-params no-scenecut=1",
411
+ args: ["-x265-params", "no-scenecut=1"],
412
+ description: "Disable scene-change keyframes"
413
+ },
414
+ {
415
+ group: "Global",
416
+ label: "-fps_mode passthrough",
417
+ args: ["-fps_mode", "passthrough"],
418
+ description: "Preserve source framerate exactly"
419
+ },
420
+ {
421
+ group: "Global",
422
+ label: "-copyts",
423
+ args: ["-copyts"],
424
+ description: "Preserve source timestamps"
425
+ }
426
+ ], se = {
427
+ video: { codec: "copy" },
428
+ audio: "passthrough"
429
+ }, P = "w-full rounded border border-border bg-surface-2 px-2 py-1.5 text-[11px] font-mono text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 read-only:opacity-60 min-h-[60px] resize-y", F = "flex items-center justify-between gap-3 py-1.5", I = "text-[11px] uppercase tracking-wider text-foreground-subtle font-medium", L = "rounded-lg border border-border bg-surface overflow-hidden", R = "border-b border-border px-3 py-1.5 flex items-center justify-between bg-surface-hover/30", z = "text-[11px] font-semibold text-foreground uppercase tracking-wider";
430
+ function ce({ config: t, value: n, onSave: i }) {
431
+ let [a, o] = r(!1), s = n ?? se, [c, l] = r(() => (s.inputArgs ?? []).join("\n")), [u, d] = r(() => (s.outputArgs ?? []).join("\n")), f = e(s);
432
+ f.current !== s && (f.current = s, l((s.inputArgs ?? []).join("\n")), d((s.outputArgs ?? []).join("\n")));
433
+ let p = (e) => {
434
+ i(e(s));
435
+ }, m = (e) => p((t) => ({
436
+ ...t,
437
+ video: {
438
+ ...t.video,
439
+ codec: e
440
+ }
441
+ })), h = (e) => p((t) => ({
442
+ ...t,
443
+ video: {
444
+ ...t.video,
445
+ width: e
446
+ }
447
+ })), y = (e) => p((t) => ({
448
+ ...t,
449
+ video: {
450
+ ...t.video,
451
+ height: e
452
+ }
453
+ })), b = (e) => p((t) => ({
454
+ ...t,
455
+ video: {
456
+ ...t.video,
457
+ fps: e
458
+ }
459
+ })), x = (e) => p((t) => ({
460
+ ...t,
461
+ video: {
462
+ ...t.video,
463
+ bitrateKbps: e
464
+ }
465
+ })), S = () => p((e) => ({
466
+ ...e,
467
+ audio: "passthrough"
468
+ })), C = (e) => p((t) => ({
469
+ ...t,
470
+ audio: typeof t.audio == "object" ? {
471
+ ...t.audio,
472
+ codec: e
473
+ } : { codec: e }
474
+ })), w = (e) => p((t) => ({
475
+ ...t,
476
+ audio: typeof t.audio == "object" ? {
477
+ ...t.audio,
478
+ bitrateKbps: e
479
+ } : {
480
+ codec: "opus",
481
+ bitrateKbps: e
482
+ }
483
+ })), T = (e) => p((t) => ({
484
+ ...t,
485
+ inputArgs: e.split("\n").map((e) => e.trim()).filter((e) => e.length > 0)
486
+ })), E = (e) => p((t) => ({
487
+ ...t,
488
+ outputArgs: e.split("\n").map((e) => e.trim()).filter((e) => e.length > 0)
489
+ })), D = (e, t) => {
490
+ let n = t.args.join(" ");
491
+ if (e === "input") {
492
+ let e = c.length === 0 ? n : `${c}\n${n}`;
493
+ l(e), T(e);
494
+ } else {
495
+ let e = u.length === 0 ? n : `${u}\n${n}`;
496
+ d(e), E(e);
497
+ }
498
+ };
499
+ return /* @__PURE__ */ _("div", {
500
+ className: "space-y-3",
501
+ children: [
502
+ t.sourceParams !== void 0 && /* @__PURE__ */ _("div", {
503
+ className: L,
504
+ children: [/* @__PURE__ */ _("div", {
505
+ className: R,
506
+ children: [/* @__PURE__ */ g("h3", {
507
+ className: z,
508
+ children: "Source (probed)"
509
+ }), /* @__PURE__ */ g("span", {
510
+ className: "text-[10px] text-foreground-subtle italic",
511
+ children: "From the publisher"
512
+ })]
513
+ }), /* @__PURE__ */ g("div", {
514
+ className: "px-3 py-2 flex flex-wrap gap-1.5",
515
+ children: /* @__PURE__ */ g(le, { profile: t.sourceParams })
516
+ })]
517
+ }),
518
+ /* @__PURE__ */ g("div", {
519
+ className: "@container",
520
+ children: /* @__PURE__ */ _("div", {
521
+ className: "grid grid-cols-1 @[480px]:grid-cols-2 gap-3",
522
+ children: [/* @__PURE__ */ _("div", {
523
+ className: L,
524
+ children: [/* @__PURE__ */ g("div", {
525
+ className: R,
526
+ children: /* @__PURE__ */ g("h3", {
527
+ className: z,
528
+ children: "Video"
529
+ })
530
+ }), /* @__PURE__ */ _("div", {
531
+ className: "px-3 py-2 divide-y divide-border/30",
532
+ children: [/* @__PURE__ */ _("div", {
533
+ className: F,
534
+ children: [/* @__PURE__ */ g("label", {
535
+ htmlFor: `${t.fieldKey}-video-codec`,
536
+ className: I,
537
+ children: "Codec"
538
+ }), /* @__PURE__ */ _("select", {
539
+ id: `${t.fieldKey}-video-codec`,
540
+ value: s.video.codec,
541
+ onChange: (e) => m(e.target.value),
542
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed read-only:opacity-60 read-only:cursor-not-allowed appearance-none pr-6 min-w-[120px]",
543
+ children: [
544
+ /* @__PURE__ */ g("option", {
545
+ value: "h264",
546
+ children: "h264"
547
+ }),
548
+ /* @__PURE__ */ g("option", {
549
+ value: "h265",
550
+ children: "h265"
551
+ }),
552
+ /* @__PURE__ */ g("option", {
553
+ value: "copy",
554
+ children: "copy (passthrough)"
555
+ })
556
+ ]
557
+ })]
558
+ }), s.video.codec !== "copy" && /* @__PURE__ */ _(v, { children: [
559
+ /* @__PURE__ */ _("div", {
560
+ className: F,
561
+ children: [/* @__PURE__ */ g("label", {
562
+ htmlFor: `${t.fieldKey}-video-width`,
563
+ className: I,
564
+ children: "Width"
565
+ }), /* @__PURE__ */ g("input", {
566
+ id: `${t.fieldKey}-video-width`,
567
+ type: "number",
568
+ "aria-label": "Width",
569
+ value: s.video.width ?? "",
570
+ onChange: (e) => h(Number(e.target.value)),
571
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed read-only:opacity-60 read-only:cursor-not-allowed w-24 text-right"
572
+ })]
573
+ }),
574
+ /* @__PURE__ */ _("div", {
575
+ className: F,
576
+ children: [/* @__PURE__ */ g("label", {
577
+ htmlFor: `${t.fieldKey}-video-height`,
578
+ className: I,
579
+ children: "Height"
580
+ }), /* @__PURE__ */ g("input", {
581
+ id: `${t.fieldKey}-video-height`,
582
+ type: "number",
583
+ value: s.video.height ?? "",
584
+ onChange: (e) => y(Number(e.target.value)),
585
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed read-only:opacity-60 read-only:cursor-not-allowed w-24 text-right"
586
+ })]
587
+ }),
588
+ /* @__PURE__ */ _("div", {
589
+ className: F,
590
+ children: [/* @__PURE__ */ g("label", {
591
+ htmlFor: `${t.fieldKey}-video-fps`,
592
+ className: I,
593
+ children: "FPS"
594
+ }), /* @__PURE__ */ g("input", {
595
+ id: `${t.fieldKey}-video-fps`,
596
+ type: "number",
597
+ value: s.video.fps ?? "",
598
+ onChange: (e) => b(Number(e.target.value)),
599
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed read-only:opacity-60 read-only:cursor-not-allowed w-24 text-right"
600
+ })]
601
+ }),
602
+ /* @__PURE__ */ _("div", {
603
+ className: F,
604
+ children: [/* @__PURE__ */ g("label", {
605
+ htmlFor: `${t.fieldKey}-video-bitrate`,
606
+ className: I,
607
+ children: "Bitrate (kbps)"
608
+ }), /* @__PURE__ */ g("input", {
609
+ id: `${t.fieldKey}-video-bitrate`,
610
+ type: "number",
611
+ value: s.video.bitrateKbps ?? "",
612
+ onChange: (e) => x(Number(e.target.value)),
613
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed read-only:opacity-60 read-only:cursor-not-allowed w-24 text-right"
614
+ })]
615
+ })
616
+ ] })]
617
+ })]
618
+ }), /* @__PURE__ */ _("div", {
619
+ className: L,
620
+ children: [/* @__PURE__ */ g("div", {
621
+ className: R,
622
+ children: /* @__PURE__ */ g("h3", {
623
+ className: z,
624
+ children: "Audio"
625
+ })
626
+ }), /* @__PURE__ */ g("div", {
627
+ className: "px-3 py-2",
628
+ children: s.audio === "passthrough" ? /* @__PURE__ */ _("div", {
629
+ className: "flex items-center justify-between gap-3",
630
+ children: [/* @__PURE__ */ g("span", {
631
+ className: "text-[11px] text-foreground-subtle italic",
632
+ children: "Source audio forwarded without re-encode."
633
+ }), /* @__PURE__ */ g("button", {
634
+ type: "button",
635
+ onClick: () => C("opus"),
636
+ className: "rounded-md border border-border bg-surface-hover px-2 py-1 text-[11px] text-foreground hover:bg-surface-hover/70 transition-colors",
637
+ children: "Switch to custom encode"
638
+ })]
639
+ }) : /* @__PURE__ */ _("div", {
640
+ className: "divide-y divide-border/30",
641
+ children: [
642
+ /* @__PURE__ */ _("div", {
643
+ className: F,
644
+ children: [/* @__PURE__ */ g("label", {
645
+ htmlFor: `${t.fieldKey}-audio-codec`,
646
+ className: I,
647
+ children: "Codec"
648
+ }), /* @__PURE__ */ _("select", {
649
+ id: `${t.fieldKey}-audio-codec`,
650
+ value: s.audio.codec,
651
+ onChange: (e) => C(e.target.value),
652
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed read-only:opacity-60 read-only:cursor-not-allowed appearance-none pr-6 min-w-[120px]",
653
+ children: [
654
+ /* @__PURE__ */ g("option", {
655
+ value: "opus",
656
+ children: "opus"
657
+ }),
658
+ /* @__PURE__ */ g("option", {
659
+ value: "aac",
660
+ children: "aac"
661
+ }),
662
+ /* @__PURE__ */ g("option", {
663
+ value: "pcmu",
664
+ children: "pcmu"
665
+ }),
666
+ /* @__PURE__ */ g("option", {
667
+ value: "pcma",
668
+ children: "pcma"
669
+ }),
670
+ /* @__PURE__ */ g("option", {
671
+ value: "copy",
672
+ children: "copy (passthrough)"
673
+ })
674
+ ]
675
+ })]
676
+ }),
677
+ /* @__PURE__ */ _("div", {
678
+ className: F,
679
+ children: [/* @__PURE__ */ g("label", {
680
+ htmlFor: `${t.fieldKey}-audio-bitrate`,
681
+ className: I,
682
+ children: "Bitrate (kbps)"
683
+ }), /* @__PURE__ */ g("input", {
684
+ id: `${t.fieldKey}-audio-bitrate`,
685
+ type: "number",
686
+ value: s.audio.bitrateKbps ?? "",
687
+ onChange: (e) => w(Number(e.target.value)),
688
+ className: "rounded border border-border bg-surface-2 px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-accent disabled:opacity-50 disabled:cursor-not-allowed read-only:opacity-60 read-only:cursor-not-allowed w-24 text-right"
689
+ })]
690
+ }),
691
+ /* @__PURE__ */ g("div", {
692
+ className: "pt-2",
693
+ children: /* @__PURE__ */ g("button", {
694
+ type: "button",
695
+ onClick: S,
696
+ className: "text-[11px] text-foreground-subtle hover:text-foreground underline-offset-2 hover:underline",
697
+ children: "Switch back to passthrough"
698
+ })
699
+ })
700
+ ]
701
+ })
702
+ })]
703
+ })]
704
+ })
705
+ }),
706
+ /* @__PURE__ */ _("div", {
707
+ className: L,
708
+ children: [/* @__PURE__ */ _("button", {
709
+ type: "button",
710
+ onClick: () => o((e) => !e),
711
+ className: "w-full px-3 py-1.5 flex items-center justify-between bg-surface-hover/30 hover:bg-surface-hover transition-colors",
712
+ children: [/* @__PURE__ */ _("span", {
713
+ className: "inline-flex items-center gap-1.5 text-[11px] font-semibold text-foreground uppercase tracking-wider",
714
+ children: [g(a ? A : j, { className: "h-3 w-3" }), "Advanced — raw ffmpeg args"]
715
+ }), /* @__PURE__ */ _("span", {
716
+ className: "text-[10px] text-foreground-subtle italic",
717
+ children: [(s.inputArgs?.length ?? 0) + (s.outputArgs?.length ?? 0), " args"]
718
+ })]
719
+ }), a && /* @__PURE__ */ _("div", {
720
+ className: "px-3 py-2 space-y-3 border-t border-border/50",
721
+ children: [
722
+ /* @__PURE__ */ _("div", {
723
+ className: "space-y-1.5",
724
+ children: [/* @__PURE__ */ _("div", {
725
+ className: "flex items-center justify-between",
726
+ children: [/* @__PURE__ */ _("label", {
727
+ htmlFor: `${t.fieldKey}-input-args`,
728
+ className: I,
729
+ children: ["Input args", /* @__PURE__ */ g("span", {
730
+ className: "ml-2 text-[10px] normal-case text-foreground-subtle italic",
731
+ children: "one per line · inserted between globals and -i"
732
+ })]
733
+ }), /* @__PURE__ */ g(B, {
734
+ id: `${t.fieldKey}-input-picker`,
735
+ disabled: !1,
736
+ catalogue: N,
737
+ onPick: (e) => D("input", e)
738
+ })]
739
+ }), /* @__PURE__ */ g("textarea", {
740
+ id: `${t.fieldKey}-input-args`,
741
+ value: c,
742
+ onChange: (e) => l(e.target.value),
743
+ onBlur: (e) => T(e.target.value),
744
+ placeholder: "-thread_queue_size 1024",
745
+ className: P
746
+ })]
747
+ }),
748
+ /* @__PURE__ */ g(ae, {
749
+ outputArgs: s.outputArgs ?? [],
750
+ onChange: (e) => {
751
+ d(e.join("\n")), E(e.join("\n"));
752
+ }
753
+ }),
754
+ /* @__PURE__ */ _("div", {
755
+ className: "space-y-1.5",
756
+ children: [/* @__PURE__ */ _("div", {
757
+ className: "flex items-center justify-between",
758
+ children: [/* @__PURE__ */ _("label", {
759
+ htmlFor: `${t.fieldKey}-output-args`,
760
+ className: I,
761
+ children: ["Output args", /* @__PURE__ */ g("span", {
762
+ className: "ml-2 text-[10px] normal-case text-foreground-subtle italic",
763
+ children: "one per line · inserted before the final muxer"
764
+ })]
765
+ }), /* @__PURE__ */ g(B, {
766
+ id: `${t.fieldKey}-output-picker`,
767
+ disabled: !1,
768
+ catalogue: oe,
769
+ onPick: (e) => D("output", e)
770
+ })]
771
+ }), /* @__PURE__ */ g("textarea", {
772
+ id: `${t.fieldKey}-output-args`,
773
+ value: u,
774
+ onChange: (e) => d(e.target.value),
775
+ onBlur: (e) => E(e.target.value),
776
+ placeholder: "-bsf:v h264_mp4toannexb",
777
+ className: P
778
+ })]
779
+ })
780
+ ]
781
+ })]
782
+ })
783
+ ]
784
+ });
785
+ }
786
+ function le({ profile: e }) {
787
+ let t = "inline-flex items-center gap-1 rounded-full bg-foreground-subtle/10 border border-border px-2 py-0.5 text-[11px] font-mono text-foreground-subtle", { video: n, audio: r } = e, i = n.width !== void 0 && n.height !== void 0 ? `${n.width}×${n.height}` : void 0;
788
+ return /* @__PURE__ */ _(v, { children: [
789
+ /* @__PURE__ */ _("span", {
790
+ className: t,
791
+ children: [/* @__PURE__ */ g("span", {
792
+ className: "opacity-60",
793
+ children: "codec"
794
+ }), n.codec]
795
+ }),
796
+ i !== void 0 && /* @__PURE__ */ _("span", {
797
+ className: t,
798
+ children: [/* @__PURE__ */ g("span", {
799
+ className: "opacity-60",
800
+ children: "res"
801
+ }), i]
802
+ }),
803
+ n.fps !== void 0 && /* @__PURE__ */ _("span", {
804
+ className: t,
805
+ children: [/* @__PURE__ */ g("span", {
806
+ className: "opacity-60",
807
+ children: "fps"
808
+ }), n.fps]
809
+ }),
810
+ n.bitrateKbps !== void 0 && /* @__PURE__ */ _("span", {
811
+ className: t,
812
+ children: [
813
+ /* @__PURE__ */ g("span", {
814
+ className: "opacity-60",
815
+ children: "bitrate"
816
+ }),
817
+ n.bitrateKbps,
818
+ "k"
819
+ ]
820
+ }),
821
+ r === "passthrough" ? /* @__PURE__ */ _("span", {
822
+ className: t,
823
+ children: [/* @__PURE__ */ g("span", {
824
+ className: "opacity-60",
825
+ children: "audio"
826
+ }), "passthrough"]
827
+ }) : /* @__PURE__ */ _(v, { children: [
828
+ /* @__PURE__ */ _("span", {
829
+ className: t,
830
+ children: [/* @__PURE__ */ g("span", {
831
+ className: "opacity-60",
832
+ children: "audio"
833
+ }), r.codec]
834
+ }),
835
+ r.bitrateKbps !== void 0 && /* @__PURE__ */ _("span", {
836
+ className: t,
837
+ children: [
838
+ /* @__PURE__ */ g("span", {
839
+ className: "opacity-60",
840
+ children: "a-bitrate"
841
+ }),
842
+ r.bitrateKbps,
843
+ "k"
844
+ ]
845
+ }),
846
+ r.sampleRateHz !== void 0 && /* @__PURE__ */ _("span", {
847
+ className: t,
848
+ children: [
849
+ /* @__PURE__ */ g("span", {
850
+ className: "opacity-60",
851
+ children: "a-sr"
852
+ }),
853
+ r.sampleRateHz,
854
+ "Hz"
855
+ ]
856
+ }),
857
+ r.channels !== void 0 && /* @__PURE__ */ _("span", {
858
+ className: t,
859
+ children: [/* @__PURE__ */ g("span", {
860
+ className: "opacity-60",
861
+ children: "a-ch"
862
+ }), r.channels]
863
+ })
864
+ ] })
865
+ ] });
866
+ }
867
+ function ue(e) {
868
+ let t = e.config ?? {}, n = m(), [a, o] = r(() => t.initialValue), s = i((r) => {
869
+ if (o(r), e.deviceId === void 0) return;
870
+ let i = t.writerCapName, a = t.writerAddonId, s = t.fieldKey;
871
+ if (i === void 0 || a === void 0 || s === void 0) {
872
+ console.warn(`[ffmpeg-params] widgetConfig is missing writerCapName/writerAddonId/fieldKey — field ${s ?? "(unknown)"} cannot be saved. Fix the contribution builder.`);
873
+ return;
874
+ }
875
+ n.mutate({
876
+ deviceId: e.deviceId,
877
+ writerCapName: i,
878
+ writerAddonId: a,
879
+ key: s,
880
+ value: r ?? null
881
+ });
882
+ }, [
883
+ e.deviceId,
884
+ t.fieldKey,
885
+ t.writerCapName,
886
+ t.writerAddonId,
887
+ n
888
+ ]);
889
+ if (e.deviceId === void 0) return /* @__PURE__ */ g("div", {
890
+ className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning",
891
+ children: "ffmpeg-params: no deviceId in widget context — this widget only renders inside a device tab."
892
+ });
893
+ let c = t.fieldKey;
894
+ return c === void 0 || c.length === 0 ? /* @__PURE__ */ g("div", {
895
+ className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning",
896
+ children: "ffmpeg-params: widgetConfig.fieldKey is required — fix the contribution builder."
897
+ }) : /* @__PURE__ */ g(ce, {
898
+ config: {
899
+ ...t,
900
+ fieldKey: c
901
+ },
902
+ value: a,
903
+ onSave: s
904
+ });
905
+ }
906
+ function B({ id: e, disabled: n, catalogue: i, onPick: a }) {
907
+ let [o, s] = r(!1), c = t(() => {
908
+ let e = /* @__PURE__ */ new Map();
909
+ for (let t of i) {
910
+ let n = e.get(t.group) ?? [];
911
+ n.push(t), e.set(t.group, n);
912
+ }
913
+ return e;
914
+ }, [i]);
915
+ return /* @__PURE__ */ _("div", {
916
+ className: "relative",
917
+ children: [/* @__PURE__ */ _("button", {
918
+ id: e,
919
+ type: "button",
920
+ disabled: n,
921
+ onClick: () => s((e) => !e),
922
+ className: "inline-flex items-center gap-1 rounded-md border border-border bg-surface-hover px-2 py-0.5 text-[10px] font-medium text-foreground-subtle hover:bg-surface-hover/70 disabled:opacity-40 disabled:cursor-not-allowed transition-colors",
923
+ children: [/* @__PURE__ */ g(ee, { className: "h-3 w-3" }), "Add flag…"]
924
+ }), o && !n && /* @__PURE__ */ _(v, { children: [/* @__PURE__ */ g("div", {
925
+ className: "fixed inset-0 z-40",
926
+ onClick: () => s(!1),
927
+ "aria-hidden": "true"
928
+ }), /* @__PURE__ */ g("div", {
929
+ className: "absolute right-0 top-full z-50 mt-1 max-h-72 w-72 overflow-y-auto rounded-lg border border-border bg-surface shadow-lg",
930
+ role: "menu",
931
+ children: Array.from(c.entries()).map(([e, t]) => /* @__PURE__ */ _("div", {
932
+ className: "border-b border-border/30 last:border-b-0",
933
+ children: [/* @__PURE__ */ g("div", {
934
+ className: "sticky top-0 bg-surface-hover/80 backdrop-blur px-2 py-1 text-[9px] font-semibold uppercase tracking-wider text-foreground-subtle",
935
+ children: e
936
+ }), t.map((e) => /* @__PURE__ */ _("button", {
937
+ type: "button",
938
+ onClick: () => {
939
+ a(e), s(!1);
940
+ },
941
+ className: "w-full text-left px-2 py-1.5 hover:bg-surface-hover transition-colors group",
942
+ children: [/* @__PURE__ */ g("div", {
943
+ className: "font-mono text-[11px] text-foreground",
944
+ children: e.label
945
+ }), e.description !== void 0 && /* @__PURE__ */ g("div", {
946
+ className: "text-[10px] text-foreground-subtle leading-snug mt-0.5",
947
+ children: e.description
948
+ })]
949
+ }, e.label))]
950
+ }, e))
951
+ })] })]
952
+ });
953
+ }
954
+ //#endregion
955
+ //#region src/stream-broker/widgets/format-ua.ts
956
+ var V = 24;
957
+ function H(e) {
958
+ return /\bEdg\b|\bEdgA\b|\bEdgiOS\b|Edge\//.test(e) ? "Edge" : /\bOPR\b|Opera/.test(e) ? "Opera" : /Firefox\/|\bFxiOS\b/.test(e) ? "Firefox" : /Chrome\/|\bCriOS\b/.test(e) ? "Chrome" : /Safari\//.test(e) ? "Safari" : null;
959
+ }
960
+ function de(e) {
961
+ return /iPhone|iPad|iPod|\biOS\b|CriOS|FxiOS/.test(e) ? "iOS" : /Mac OS X|Macintosh/.test(e) ? "macOS" : /Windows/.test(e) ? "Windows" : /Android/.test(e) ? "Android" : /Linux/.test(e) ? "Linux" : null;
962
+ }
963
+ function fe(e) {
964
+ let t = e.trim();
965
+ if (t.length === 0) return "";
966
+ let n = H(t), r = de(t);
967
+ return n && r ? `${n}/${r}` : n || r || (t.length > V ? `${t.slice(0, V)}…` : t);
968
+ }
969
+ //#endregion
970
+ //#region src/stream-broker/widgets/StreamBrokerPanel.tsx
971
+ function pe(e) {
972
+ let t = Math.floor(e / 1e3);
973
+ if (t < 60) return `${t}s`;
974
+ let n = Math.floor(t / 60);
975
+ return n < 60 ? `${n}m` : `${Math.floor(n / 60)}h ${n % 60}m`;
976
+ }
977
+ var U = {
978
+ high: "High",
979
+ mid: "Mid",
980
+ low: "Low"
981
+ }, W = [
982
+ "high",
983
+ "mid",
984
+ "low"
985
+ ], me = {
986
+ alexa: "bg-blue-500/15 text-blue-400",
987
+ homekit: "bg-purple-500/15 text-purple-400",
988
+ "webrtc-browser": "bg-emerald-500/15 text-emerald-400",
989
+ "webrtc-mobile": "bg-emerald-500/15 text-emerald-400",
990
+ "webrtc-whep": "bg-emerald-500/15 text-emerald-400",
991
+ "rtsp-listen": "bg-warning/15 text-warning",
992
+ "derived-broker": "bg-amber-500/15 text-amber-400",
993
+ recording: "bg-rose-500/15 text-rose-400",
994
+ pipeline: "bg-cyan-500/15 text-cyan-400",
995
+ snapshot: "bg-cyan-500/15 text-cyan-400",
996
+ warmup: "bg-foreground-subtle/10 text-foreground-subtle",
997
+ unknown: "bg-foreground-subtle/10 text-foreground-subtle"
998
+ }, G = {
999
+ alexa: "ALEXA",
1000
+ homekit: "HOMEKIT",
1001
+ "webrtc-browser": "BROWSER",
1002
+ "webrtc-mobile": "MOBILE",
1003
+ "webrtc-whep": "WHEP",
1004
+ "rtsp-listen": "RTSP",
1005
+ "derived-broker": "DERIVED",
1006
+ recording: "RECORD",
1007
+ pipeline: "PIPELINE",
1008
+ snapshot: "SNAP",
1009
+ warmup: "WARMUP",
1010
+ unknown: "—"
94
1011
  };
95
- /**
96
- * @license lucide-react v0.511.0 - ISC
97
- *
98
- * This source code is licensed under the ISC license.
99
- * See the LICENSE file in the root directory of this source tree.
100
- */
101
- const ae = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]], O = _("chevron-down", ae);
102
- /**
103
- * @license lucide-react v0.511.0 - ISC
104
- *
105
- * This source code is licensed under the ISC license.
106
- * See the LICENSE file in the root directory of this source tree.
107
- */
108
- const oe = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]], j = _("chevron-right", oe);
109
- /**
110
- * @license lucide-react v0.511.0 - ISC
111
- *
112
- * This source code is licensed under the ISC license.
113
- * See the LICENSE file in the root directory of this source tree.
114
- */
115
- const ie = [
116
- ["path", { d: "M4.9 19.1C1 15.2 1 8.8 4.9 4.9", key: "1vaf9d" }],
117
- ["path", { d: "M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5", key: "u1ii0m" }],
118
- ["circle", { cx: "12", cy: "12", r: "2", key: "1c9p78" }],
119
- ["path", { d: "M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5", key: "1j5fej" }],
120
- ["path", { d: "M19.1 4.9C23 8.8 23 15.1 19.1 19", key: "10b0cb" }]
121
- ], ce = _("radio", ie);
122
- /**
123
- * @license lucide-react v0.511.0 - ISC
124
- *
125
- * This source code is licensed under the ISC license.
126
- * See the LICENSE file in the root directory of this source tree.
127
- */
128
- const de = [
129
- ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
130
- ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
131
- ], le = _("x", de);
132
- function pe(s) {
133
- const n = Math.floor(s / 1e3);
134
- if (n < 60) return `${n}s`;
135
- const o = Math.floor(n / 60);
136
- return o < 60 ? `${o}m` : `${Math.floor(o / 60)}h ${o % 60}m`;
1012
+ function he(e) {
1013
+ return G[e] ?? e.toUpperCase().slice(0, 8);
137
1014
  }
138
- const F = {
139
- high: "High",
140
- mid: "Mid",
141
- low: "Low"
142
- }, D = ["high", "mid", "low"];
143
- function ue(s) {
144
- const n = s.config ?? {};
145
- return s.deviceId === void 0 ? /* @__PURE__ */ e("div", { className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning", children: "StreamBrokerPanel requires a deviceId" }) : /* @__PURE__ */ e(
146
- me,
147
- {
148
- deviceId: s.deviceId,
149
- title: n.title,
150
- variant: n.variant,
151
- hideEmpty: n.hideEmpty
152
- }
153
- );
1015
+ function ge(e) {
1016
+ return G[e] ?? e;
154
1017
  }
155
- function me({
156
- deviceId: s,
157
- title: n = "Stream Brokers",
158
- variant: o = "full",
159
- hideEmpty: i = !1
160
- }) {
161
- E(
162
- ["streamBroker", "listAllProfileSlots"],
163
- [
164
- "device.streams-registered",
165
- "device.streams-unregistered",
166
- "device.registered",
167
- "device.unregistered"
168
- ]
169
- );
170
- const { data: c } = Q(
171
- void 0,
172
- { staleTime: 3e4 }
173
- ), t = (c ?? []).filter((p) => p.deviceId === s && p.sourceCamStreamId !== null).slice().sort((p, N) => D.indexOf(p.profile) - D.indexOf(N.profile)), l = W(), d = X(l.trpcClient, s), { data: u } = z({
174
- queryKey: ["device", s, "cameraStreams.getCameraStreams"],
175
- queryFn: () => d?.cameraStreams?.getCameraStreams({}) ?? [],
176
- enabled: !!d,
177
- staleTime: 3e4
178
- }), a = /* @__PURE__ */ new Map();
179
- for (const p of u ?? []) a.set(p.camStreamId, p);
180
- const m = new Set(
181
- t.map((p) => p.sourceCamStreamId).filter((p) => p !== null)
182
- ), f = (u ?? []).filter(
183
- (p) => !m.has(p.camStreamId)
184
- ), x = t.length > 0, h = f.length > 0;
185
- return i && !x && !h ? null : o === "compact" ? x ? /* @__PURE__ */ e("div", { className: "divide-y divide-border/30", children: t.map((p) => /* @__PURE__ */ e(
186
- P,
187
- {
188
- slot: p,
189
- camStreams: a,
190
- compact: !0
191
- },
192
- p.brokerId
193
- )) }) : /* @__PURE__ */ e("div", { className: "text-[11px] text-foreground-subtle italic px-2 py-1", children: "No active profile slots" }) : /* @__PURE__ */ r("div", { className: "rounded-lg border border-border bg-surface overflow-hidden", children: [
194
- /* @__PURE__ */ r("div", { className: "border-b border-border px-4 py-2 flex items-center justify-between", children: [
195
- /* @__PURE__ */ e("h2", { className: "text-xs font-semibold text-foreground uppercase tracking-wider", children: n }),
196
- x && /* @__PURE__ */ r("span", { className: "inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-medium bg-foreground-subtle/10 text-foreground-subtle border border-border", children: [
197
- t.length,
198
- " assigned"
199
- ] })
200
- ] }),
201
- x ? /* @__PURE__ */ e("div", { className: "divide-y divide-border/30", children: t.map((p) => /* @__PURE__ */ e(
202
- P,
203
- {
204
- slot: p,
205
- camStreams: a,
206
- compact: !1
207
- },
208
- p.brokerId
209
- )) }) : /* @__PURE__ */ r("div", { className: "px-4 py-6 flex flex-col items-center text-center text-foreground-subtle", children: [
210
- /* @__PURE__ */ e(ce, { className: "h-5 w-5 mb-2 opacity-30" }),
211
- /* @__PURE__ */ e("p", { className: "text-xs", children: "No profile slots assigned for this device" })
212
- ] }),
213
- h && /* @__PURE__ */ e(
214
- fe,
215
- {
216
- deviceId: s,
217
- camStreamIds: f.map((p) => p.camStreamId),
218
- camStreams: a
219
- }
220
- )
221
- ] });
1018
+ function _e(e) {
1019
+ let t = e.config ?? {};
1020
+ return e.deviceId === void 0 ? /* @__PURE__ */ g("div", {
1021
+ className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning",
1022
+ children: "StreamBrokerPanel requires a deviceId"
1023
+ }) : /* @__PURE__ */ g(ve, {
1024
+ deviceId: e.deviceId,
1025
+ title: t.title,
1026
+ variant: t.variant,
1027
+ hideEmpty: t.hideEmpty
1028
+ });
222
1029
  }
223
- function fe({
224
- deviceId: s,
225
- camStreamIds: n,
226
- camStreams: o
227
- }) {
228
- const [i, c] = y(!1);
229
- return /* @__PURE__ */ r("div", { className: "border-t border-border/50", children: [
230
- /* @__PURE__ */ r(
231
- "button",
232
- {
233
- type: "button",
234
- onClick: () => c((t) => !t),
235
- className: "w-full px-4 py-1.5 flex items-center justify-between bg-surface-hover/30 hover:bg-surface-hover transition-colors",
236
- children: [
237
- /* @__PURE__ */ r("span", { className: "inline-flex items-center gap-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle", children: [
238
- i ? /* @__PURE__ */ e(O, { className: "h-3 w-3" }) : /* @__PURE__ */ e(j, { className: "h-3 w-3" }),
239
- "Other active streams"
240
- ] }),
241
- /* @__PURE__ */ e("span", { className: "rounded-full px-2 py-0.5 text-[10px] font-medium bg-foreground-subtle/10 text-foreground-subtle border border-border", children: n.length })
242
- ]
243
- }
244
- ),
245
- i && /* @__PURE__ */ e("div", { className: "divide-y divide-border/30", children: n.map((t) => /* @__PURE__ */ e(
246
- he,
247
- {
248
- deviceId: s,
249
- camStreamId: t,
250
- camStreams: o
251
- },
252
- t
253
- )) })
254
- ] });
1030
+ function ve({ deviceId: e, title: t = "Stream Brokers", variant: n = "full", hideEmpty: r = !1 }) {
1031
+ f(["streamBroker", "listAllProfileSlots"], [
1032
+ "device.streams-registered",
1033
+ "device.streams-unregistered",
1034
+ "device.registered",
1035
+ "device.unregistered"
1036
+ ]);
1037
+ let { data: i } = s(void 0, { staleTime: 3e4 }), a = (i ?? []).filter((t) => t.deviceId === e && t.sourceCamStreamId !== null).slice().toSorted((e, t) => W.indexOf(e.profile) - W.indexOf(t.profile)), o = u(h().trpcClient, e), { data: c } = b({
1038
+ queryKey: [
1039
+ "device",
1040
+ e,
1041
+ "cameraStreams.getCameraStreams"
1042
+ ],
1043
+ queryFn: () => o?.cameraStreams?.getCameraStreams({}) ?? [],
1044
+ enabled: !!o,
1045
+ staleTime: 3e4
1046
+ }), l = /* @__PURE__ */ new Map();
1047
+ for (let e of c ?? []) l.set(e.camStreamId, e);
1048
+ let d = new Set(a.map((e) => e.sourceCamStreamId).filter((e) => e !== null)), p = (c ?? []).filter((e) => !d.has(e.camStreamId)), m = a.length > 0, v = p.length > 0;
1049
+ return r && !m && !v ? null : n === "compact" ? m ? /* @__PURE__ */ g("div", {
1050
+ className: "divide-y divide-border/30",
1051
+ children: a.map((e) => /* @__PURE__ */ g(q, {
1052
+ slot: e,
1053
+ camStreams: l,
1054
+ compact: !0
1055
+ }, e.brokerId))
1056
+ }) : /* @__PURE__ */ g("div", {
1057
+ className: "text-[11px] text-foreground-subtle italic px-2 py-1",
1058
+ children: "No active profile slots"
1059
+ }) : /* @__PURE__ */ _("div", {
1060
+ className: "rounded-lg border border-border bg-surface overflow-hidden",
1061
+ children: [
1062
+ /* @__PURE__ */ _("div", {
1063
+ className: "border-b border-border px-4 py-2 flex items-center justify-between",
1064
+ children: [/* @__PURE__ */ g("h2", {
1065
+ className: "text-xs font-semibold text-foreground uppercase tracking-wider",
1066
+ children: t
1067
+ }), m && /* @__PURE__ */ _("span", {
1068
+ className: "inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-medium bg-foreground-subtle/10 text-foreground-subtle border border-border",
1069
+ children: [a.length, " assigned"]
1070
+ })]
1071
+ }),
1072
+ m ? /* @__PURE__ */ g("div", {
1073
+ className: "divide-y divide-border/30",
1074
+ children: a.map((e) => /* @__PURE__ */ g(q, {
1075
+ slot: e,
1076
+ camStreams: l,
1077
+ compact: !1
1078
+ }, e.brokerId))
1079
+ }) : /* @__PURE__ */ _("div", {
1080
+ className: "px-4 py-6 flex flex-col items-center text-center text-foreground-subtle",
1081
+ children: [/* @__PURE__ */ g(te, { className: "h-5 w-5 mb-2 opacity-30" }), /* @__PURE__ */ g("p", {
1082
+ className: "text-xs",
1083
+ children: "No profile slots assigned for this device"
1084
+ })]
1085
+ }),
1086
+ v && /* @__PURE__ */ g(ye, {
1087
+ deviceId: e,
1088
+ camStreamIds: p.map((e) => e.camStreamId),
1089
+ camStreams: l
1090
+ })
1091
+ ]
1092
+ });
255
1093
  }
256
- function he({ deviceId: s, camStreamId: n, camStreams: o }) {
257
- const i = `${s}/${n}`, t = T("stream-broker.metrics-snapshot", (u) => u.brokerId === i)?.stats, l = o.get(n), d = t?.status === "streaming";
258
- return /* @__PURE__ */ r("div", { className: "px-4 py-2", children: [
259
- /* @__PURE__ */ e("div", { className: "flex items-center justify-between mb-1", children: /* @__PURE__ */ r("div", { className: "flex items-center gap-1.5", children: [
260
- /* @__PURE__ */ e(
261
- "span",
262
- {
263
- className: `h-1.5 w-1.5 rounded-full ${d ? "bg-success" : "bg-foreground-subtle/40"}`
264
- }
265
- ),
266
- /* @__PURE__ */ e("span", { className: "text-[11px] font-medium text-foreground", children: l?.label ?? n }),
267
- l?.resolution && /* @__PURE__ */ r("span", { className: "text-[10px] text-foreground-subtle", children: [
268
- l.resolution.width,
269
- "×",
270
- l.resolution.height
271
- ] }),
272
- /* @__PURE__ */ e("span", { className: `text-[10px] ${d ? "text-success" : "text-foreground-subtle"}`, children: t?.status ?? "idle" })
273
- ] }) }),
274
- t && d && /* @__PURE__ */ r("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-[10px]", children: [
275
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
276
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "FPS:" }),
277
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.inputFps.toFixed(1) })
278
- ] }),
279
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
280
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Bitrate:" }),
281
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.bitrateKbps >= 1e3 ? `${(t.bitrateKbps / 1e3).toFixed(1)} Mbps` : `${t.bitrateKbps} kbps` })
282
- ] }),
283
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
284
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Codec:" }),
285
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.codec?.toUpperCase() ?? "—" })
286
- ] }),
287
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
288
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Pkts:" }),
289
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.packetCount > 1e3 ? `${(t.packetCount / 1e3).toFixed(1)}k` : t.packetCount })
290
- ] })
291
- ] })
292
- ] });
1094
+ function ye({ deviceId: e, camStreamIds: t, camStreams: n }) {
1095
+ let [i, a] = r(!1);
1096
+ return /* @__PURE__ */ _("div", {
1097
+ className: "border-t border-border/50",
1098
+ children: [/* @__PURE__ */ _("button", {
1099
+ type: "button",
1100
+ onClick: () => a((e) => !e),
1101
+ className: "w-full px-4 py-1.5 flex items-center justify-between bg-surface-hover/30 hover:bg-surface-hover transition-colors",
1102
+ children: [/* @__PURE__ */ _("span", {
1103
+ className: "inline-flex items-center gap-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
1104
+ children: [g(i ? A : j, { className: "h-3 w-3" }), "Other active streams"]
1105
+ }), /* @__PURE__ */ g("span", {
1106
+ className: "rounded-full px-2 py-0.5 text-[10px] font-medium bg-foreground-subtle/10 text-foreground-subtle border border-border",
1107
+ children: t.length
1108
+ })]
1109
+ }), i && /* @__PURE__ */ g("div", {
1110
+ className: "divide-y divide-border/30",
1111
+ children: t.map((t) => /* @__PURE__ */ g(be, {
1112
+ deviceId: e,
1113
+ camStreamId: t,
1114
+ camStreams: n
1115
+ }, t))
1116
+ })]
1117
+ });
293
1118
  }
294
- function M(s, n) {
295
- const o = (i) => {
296
- if (!i || typeof i != "object") return;
297
- const c = i;
298
- if (typeof c.key == "string" && c.key === n && "value" in c) return c.value;
299
- if (c.type === "group" && Array.isArray(c.fields))
300
- for (const t of c.fields) {
301
- const l = o(t);
302
- if (l !== void 0) return l;
303
- }
304
- else if (c.type === "sub-tabs" && Array.isArray(c.tabs)) {
305
- for (const t of c.tabs)
306
- if (Array.isArray(t.fields))
307
- for (const l of t.fields) {
308
- const d = o(l);
309
- if (d !== void 0) return d;
310
- }
311
- }
312
- };
313
- for (const i of s?.sections ?? [])
314
- if (Array.isArray(i.fields))
315
- for (const c of i.fields) {
316
- const t = o(c);
317
- if (t !== void 0) return t;
318
- }
1119
+ function be({ deviceId: e, camStreamId: t, camStreams: n }) {
1120
+ let r = x(e, t), i = c("stream-broker.metrics-snapshot", (e) => e.brokerId === r)?.stats, a = n.get(t), o = i?.status === "streaming";
1121
+ return /* @__PURE__ */ _("div", {
1122
+ className: "px-4 py-2",
1123
+ children: [/* @__PURE__ */ g("div", {
1124
+ className: "flex items-center justify-between mb-1",
1125
+ children: /* @__PURE__ */ _("div", {
1126
+ className: "flex items-center gap-1.5",
1127
+ children: [
1128
+ /* @__PURE__ */ g("span", { className: `h-1.5 w-1.5 rounded-full ${o ? "bg-success" : "bg-foreground-subtle/40"}` }),
1129
+ /* @__PURE__ */ g("span", {
1130
+ className: "text-[11px] font-medium text-foreground",
1131
+ children: a?.label ?? t
1132
+ }),
1133
+ a?.resolution && /* @__PURE__ */ _("span", {
1134
+ className: "text-[10px] text-foreground-subtle",
1135
+ children: [
1136
+ a.resolution.width,
1137
+ "×",
1138
+ a.resolution.height
1139
+ ]
1140
+ }),
1141
+ /* @__PURE__ */ g("span", {
1142
+ className: `text-[10px] ${o ? "text-success" : "text-foreground-subtle"}`,
1143
+ children: i?.status ?? "idle"
1144
+ })
1145
+ ]
1146
+ })
1147
+ }), i && o && /* @__PURE__ */ _("div", {
1148
+ className: "flex flex-wrap gap-x-3 gap-y-1 text-[10px]",
1149
+ children: [
1150
+ /* @__PURE__ */ _("span", {
1151
+ className: "inline-flex whitespace-nowrap gap-1",
1152
+ children: [/* @__PURE__ */ g("span", {
1153
+ className: "text-foreground-subtle",
1154
+ children: "FPS:"
1155
+ }), /* @__PURE__ */ g("span", {
1156
+ className: "text-foreground",
1157
+ children: i.inputFps.toFixed(1)
1158
+ })]
1159
+ }),
1160
+ /* @__PURE__ */ _("span", {
1161
+ className: "inline-flex whitespace-nowrap gap-1",
1162
+ children: [/* @__PURE__ */ g("span", {
1163
+ className: "text-foreground-subtle",
1164
+ children: "Bitrate:"
1165
+ }), /* @__PURE__ */ g("span", {
1166
+ className: "text-foreground",
1167
+ children: i.bitrateKbps >= 1e3 ? `${(i.bitrateKbps / 1e3).toFixed(1)} Mbps` : `${i.bitrateKbps} kbps`
1168
+ })]
1169
+ }),
1170
+ /* @__PURE__ */ _("span", {
1171
+ className: "inline-flex whitespace-nowrap gap-1",
1172
+ children: [/* @__PURE__ */ g("span", {
1173
+ className: "text-foreground-subtle",
1174
+ children: "Codec:"
1175
+ }), /* @__PURE__ */ g("span", {
1176
+ className: "text-foreground",
1177
+ children: i.codec?.toUpperCase() ?? "—"
1178
+ })]
1179
+ }),
1180
+ /* @__PURE__ */ _("span", {
1181
+ className: "inline-flex whitespace-nowrap gap-1",
1182
+ children: [/* @__PURE__ */ g("span", {
1183
+ className: "text-foreground-subtle",
1184
+ children: "Pkts:"
1185
+ }), /* @__PURE__ */ g("span", {
1186
+ className: "text-foreground",
1187
+ children: i.packetCount > 1e3 ? `${(i.packetCount / 1e3).toFixed(1)}k` : i.packetCount
1188
+ })]
1189
+ })
1190
+ ]
1191
+ })]
1192
+ });
319
1193
  }
320
- function P({ slot: s, camStreams: n, compact: o }) {
321
- const i = G(), t = T("stream-broker.metrics-snapshot", (b) => b.brokerId === s.brokerId)?.stats;
322
- E(["streamBroker", "listClients"], ["stream-broker.metrics-snapshot"]);
323
- const { data: l } = Z(
324
- { brokerId: s.brokerId },
325
- { enabled: t?.status === "streaming", staleTime: 2e3 }
326
- ), { data: d } = V(
327
- { deviceId: s.deviceId },
328
- { staleTime: 15e3 }
329
- ), u = s.sourceCamStreamId ?? s.profile, a = !!(M(d, `preBufferEnabled:${u}`) ?? !0), m = M(d, `preBufferSec:${u}`), f = J({
330
- onSuccess: () => {
331
- i.invalidateQueries({ queryKey: [["streamBroker", "getDeviceSettingsContribution"]] });
332
- }
333
- }), x = (b) => {
334
- f.mutate({
335
- deviceId: s.deviceId,
336
- patch: { [`preBufferEnabled:${u}`]: b }
337
- });
338
- }, h = Y({
339
- onSuccess: () => {
340
- i.invalidateQueries({ queryKey: [["streamBroker", "listClients"]] });
341
- }
342
- }), p = k(
343
- (b) => {
344
- h.mutate({ brokerId: s.brokerId, ...b });
345
- },
346
- [h, s.brokerId]
347
- ), w = (s.sourceCamStreamId ? n.get(s.sourceCamStreamId) : void 0)?.resolution ?? s.resolution, v = t?.status === "streaming", q = w ? `${F[s.profile]} (${w.width}×${w.height})` : F[s.profile], H = t ? t.encodedSubscribers + t.decodedSubscribers + (t.rtspClients ?? 0) + (t.pipeClients ?? 0) : 0;
348
- return /* @__PURE__ */ r(
349
- "div",
350
- {
351
- className: `@container ${o ? "px-3 py-1.5" : "px-4 py-2"}`,
352
- style: { containerType: "inline-size" },
353
- children: [
354
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between mb-1.5", children: [
355
- /* @__PURE__ */ r("div", { className: "flex items-center gap-1.5", children: [
356
- /* @__PURE__ */ e(
357
- "span",
358
- {
359
- className: `h-1.5 w-1.5 rounded-full ${v ? s.profile === "high" ? "bg-success" : s.profile === "mid" ? "bg-warning" : "bg-foreground-subtle" : "bg-foreground-subtle/40"}`
360
- }
361
- ),
362
- /* @__PURE__ */ e("span", { className: "text-[11px] font-medium text-foreground", children: q }),
363
- /* @__PURE__ */ e("span", { className: `text-[10px] ${v ? "text-success" : "text-foreground-subtle"}`, children: t?.status ?? "loading" }),
364
- s.sourceCamStreamId && /* @__PURE__ */ r("span", { className: "text-[10px] text-foreground-subtle", children: [
365
- "← ",
366
- s.sourceCamStreamId
367
- ] })
368
- ] }),
369
- /* @__PURE__ */ e("span", { className: "text-[10px] text-foreground-subtle", children: t && t.uptimeMs > 0 ? pe(t.uptimeMs) : "—" })
370
- ] }),
371
- t && v ? o ? /* @__PURE__ */ r("div", { className: "flex flex-wrap gap-x-3 gap-y-0.5 text-[10px]", children: [
372
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
373
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "FPS:" }),
374
- /* @__PURE__ */ r("span", { className: "text-foreground", children: [
375
- t.inputFps.toFixed(1),
376
- "/",
377
- t.decodeFps.toFixed(1)
378
- ] })
379
- ] }),
380
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
381
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Bitrate:" }),
382
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.bitrateKbps >= 1e3 ? `${(t.bitrateKbps / 1e3).toFixed(1)} Mbps` : `${t.bitrateKbps} kbps` })
383
- ] }),
384
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
385
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Codec:" }),
386
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.codec?.toUpperCase() ?? "—" })
387
- ] }),
388
- /* @__PURE__ */ r("span", { className: "inline-flex items-center whitespace-nowrap gap-1", children: [
389
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Clients:" }),
390
- /* @__PURE__ */ e("span", { className: "text-foreground font-semibold", children: H }),
391
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle/70", children: "(" }),
392
- /* @__PURE__ */ e(Ne, { count: t.encodedSubscribers + t.decodedSubscribers, clients: l, onKill: p }),
393
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle/70", children: "·" }),
394
- /* @__PURE__ */ e(ve, { count: t.rtspClients ?? 0, clients: l, onKill: p }),
395
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle/70", children: [
396
- "· pipe ",
397
- t.pipeClients ?? 0,
398
- ")"
399
- ] })
400
- ] })
401
- ] }) : /* @__PURE__ */ r(B, { children: [
402
- /* @__PURE__ */ r("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-[10px]", children: [
403
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
404
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "In:" }),
405
- /* @__PURE__ */ r("span", { className: "text-foreground", children: [
406
- t.inputFps.toFixed(1),
407
- " fps"
408
- ] })
409
- ] }),
410
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
411
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Dec:" }),
412
- /* @__PURE__ */ r("span", { className: "text-foreground", children: [
413
- t.decodeFps.toFixed(1),
414
- " fps"
415
- ] })
416
- ] }),
417
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
418
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Bitrate:" }),
419
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.bitrateKbps >= 1e3 ? `${(t.bitrateKbps / 1e3).toFixed(1)} Mbps` : `${t.bitrateKbps} kbps` })
420
- ] }),
421
- /* @__PURE__ */ r("span", { className: "hidden @[480px]:inline-flex whitespace-nowrap gap-1", children: [
422
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "IDR:" }),
423
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.idrIntervalMs > 0 ? `${(t.idrIntervalMs / 1e3).toFixed(1)}s` : "—" })
424
- ] }),
425
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
426
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Codec:" }),
427
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.codec?.toUpperCase() ?? "—" })
428
- ] }),
429
- /* @__PURE__ */ r("span", { className: "hidden @[480px]:inline-flex whitespace-nowrap gap-1 max-w-full overflow-hidden", children: [
430
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Decoder:" }),
431
- /* @__PURE__ */ e("span", { className: "text-foreground font-mono truncate", children: t.decoderNodeId ?? /* @__PURE__ */ e("span", { className: "text-foreground-subtle italic", children: "deferred" }) })
432
- ] }),
433
- /* @__PURE__ */ r("span", { className: "hidden @[640px]:inline-flex whitespace-nowrap gap-1", children: [
434
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Pipe:" }),
435
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.pipeClients ?? 0 })
436
- ] }),
437
- /* @__PURE__ */ r("span", { className: "hidden @[640px]:inline-flex whitespace-nowrap gap-1", children: [
438
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Packets:" }),
439
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.packetCount > 1e3 ? `${(t.packetCount / 1e3).toFixed(1)}k` : t.packetCount })
440
- ] }),
441
- /* @__PURE__ */ r("span", { className: "hidden @[640px]:inline-flex whitespace-nowrap gap-1", children: [
442
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Data:" }),
443
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.totalBytes > 1048576 ? `${(t.totalBytes / 1048576).toFixed(1)} MB` : `${(t.totalBytes / 1024).toFixed(0)} KB` })
444
- ] }),
445
- t.audio && /* @__PURE__ */ r("div", { className: "basis-full flex flex-wrap items-center gap-x-1.5 gap-y-0.5", children: [
446
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle whitespace-nowrap", children: "Audio:" }),
447
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap items-center gap-1.5", children: [
448
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.audio.codec.toUpperCase() }),
449
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "·" }),
450
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.audio.sampleRate >= 1e3 ? `${(t.audio.sampleRate / 1e3).toFixed(t.audio.sampleRate % 1e3 === 0 ? 0 : 1)}kHz` : `${t.audio.sampleRate}Hz` }),
451
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "·" }),
452
- /* @__PURE__ */ e("span", { className: "text-foreground", children: t.audio.channels === 1 ? "mono" : t.audio.channels === 2 ? "stereo" : `${t.audio.channels}ch` })
453
- ] }),
454
- /* @__PURE__ */ e("span", { className: `px-1 py-px rounded text-[8px] font-medium whitespace-nowrap ${t.audio.supported ? "bg-success/15 text-success" : "bg-amber-500/15 text-amber-500"}`, children: t.audio.supported ? "decoded" : "no decoder" })
455
- ] })
456
- ] }),
457
- /* @__PURE__ */ e(ge, { clients: l, encodedCount: t.encodedSubscribers, onKill: p })
458
- ] }) : /* @__PURE__ */ e("p", { className: "text-[10px] text-foreground-subtle italic", children: "No demand — stream suspended" }),
459
- /* @__PURE__ */ r("div", { className: "mt-1.5 flex items-center gap-1.5 text-[10px]", children: [
460
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Buffer:" }),
461
- /* @__PURE__ */ e(
462
- we,
463
- {
464
- enabled: a,
465
- onToggle: (b) => x(b),
466
- disabled: f.isPending
467
- }
468
- ),
469
- /* @__PURE__ */ r("span", { className: "text-foreground", children: [
470
- m ?? t?.preBufferSec ?? 0,
471
- "s",
472
- t && v ? ` (${t.preBufferPackets}p)` : ""
473
- ] })
474
- ] })
475
- ]
476
- }
477
- );
1194
+ function K(e, t) {
1195
+ let n = (e) => {
1196
+ if (!e || typeof e != "object") return;
1197
+ let r = e;
1198
+ if (typeof r.key == "string" && r.key === t && "value" in r) return r.value;
1199
+ if (r.type === "group" && Array.isArray(r.fields)) for (let e of r.fields) {
1200
+ let t = n(e);
1201
+ if (t !== void 0) return t;
1202
+ }
1203
+ else if (r.type === "sub-tabs" && Array.isArray(r.tabs)) {
1204
+ for (let e of r.tabs) if (Array.isArray(e.fields)) for (let t of e.fields) {
1205
+ let e = n(t);
1206
+ if (e !== void 0) return e;
1207
+ }
1208
+ }
1209
+ };
1210
+ for (let t of e?.sections ?? []) if (Array.isArray(t.fields)) for (let e of t.fields) {
1211
+ let t = n(e);
1212
+ if (t !== void 0) return t;
1213
+ }
478
1214
  }
479
- const xe = 280, be = 120;
480
- function K({ trigger: s, content: n, widthClass: o }) {
481
- const i = I(null), c = I(null), [t, l] = y(!1), [d, u] = y(!1), a = k(() => {
482
- c.current && (clearTimeout(c.current), c.current = null);
483
- }, []), m = k(() => {
484
- a(), c.current = setTimeout(() => l(!1), be);
485
- }, [a]), f = k(() => {
486
- a();
487
- const h = i.current;
488
- if (h) {
489
- const p = h.getBoundingClientRect(), N = window.innerHeight - p.bottom, w = p.top;
490
- u(N < xe && w > N);
491
- }
492
- l(!0);
493
- }, [a]);
494
- return /* @__PURE__ */ r(
495
- "span",
496
- {
497
- ref: i,
498
- className: "relative inline-block",
499
- onMouseEnter: f,
500
- onMouseLeave: m,
501
- children: [
502
- s,
503
- t && /* @__PURE__ */ e(
504
- "div",
505
- {
506
- className: `absolute left-0 ${d ? "bottom-full mb-1" : "top-full mt-1"} z-50 ${o} rounded-md border border-border bg-surface shadow-xl p-2 text-[10px] normal-case`,
507
- onMouseEnter: a,
508
- onMouseLeave: m,
509
- children: n
510
- }
511
- )
512
- ]
513
- }
514
- );
1215
+ function q({ slot: e, camStreams: t, compact: n }) {
1216
+ let r = y(), a = c("stream-broker.metrics-snapshot", (t) => t.brokerId === e.brokerId)?.stats;
1217
+ f(["streamBroker", "listClients"], ["stream-broker.metrics-snapshot"]);
1218
+ let { data: s } = l({ brokerId: e.brokerId }, {
1219
+ enabled: a?.status === "streaming",
1220
+ staleTime: 2e3
1221
+ }), { data: u } = d({ deviceId: e.deviceId }, { staleTime: 15e3 }), m = e.sourceCamStreamId ?? e.profile, h = !!(K(u, `preBufferEnabled:${m}`) ?? !0), b = K(u, `preBufferSec:${m}`), x = o({ onSuccess: () => {
1222
+ r.invalidateQueries({ queryKey: [["streamBroker", "getDeviceSettingsContribution"]] });
1223
+ } }), S = (t) => {
1224
+ x.mutate({
1225
+ deviceId: e.deviceId,
1226
+ patch: { [`preBufferEnabled:${m}`]: t }
1227
+ });
1228
+ }, C = p({ onSuccess: () => {
1229
+ r.invalidateQueries({ queryKey: [["streamBroker", "listClients"]] });
1230
+ } }), w = i((t) => {
1231
+ C.mutate({
1232
+ brokerId: e.brokerId,
1233
+ ...t
1234
+ });
1235
+ }, [C, e.brokerId]), T = (e.sourceCamStreamId ? t.get(e.sourceCamStreamId) : void 0)?.resolution ?? e.resolution, E = a?.status === "streaming", D = T ? `${U[e.profile]} (${T.width}×${T.height})` : U[e.profile], O = a ? a.encodedSubscribers + a.decodedSubscribers + (a.rtspClients ?? 0) + (a.pipeClients ?? 0) : 0;
1236
+ return /* @__PURE__ */ _("div", {
1237
+ className: `@container ${n ? "px-3 py-1.5" : "px-4 py-2"}`,
1238
+ style: { containerType: "inline-size" },
1239
+ children: [
1240
+ /* @__PURE__ */ _("div", {
1241
+ className: "flex items-center justify-between mb-1.5",
1242
+ children: [/* @__PURE__ */ _("div", {
1243
+ className: "flex items-center gap-1.5",
1244
+ children: [
1245
+ /* @__PURE__ */ g("span", { className: `h-1.5 w-1.5 rounded-full ${E ? e.profile === "high" ? "bg-success" : e.profile === "mid" ? "bg-warning" : "bg-foreground-subtle" : "bg-foreground-subtle/40"}` }),
1246
+ /* @__PURE__ */ g("span", {
1247
+ className: "text-[11px] font-medium text-foreground",
1248
+ children: D
1249
+ }),
1250
+ /* @__PURE__ */ g("span", {
1251
+ className: `text-[10px] ${E ? "text-success" : "text-foreground-subtle"}`,
1252
+ children: a?.status ?? "loading"
1253
+ }),
1254
+ e.sourceCamStreamId && /* @__PURE__ */ _("span", {
1255
+ className: "text-[10px] text-foreground-subtle",
1256
+ children: ["← ", e.sourceCamStreamId]
1257
+ })
1258
+ ]
1259
+ }), /* @__PURE__ */ g("span", {
1260
+ className: "text-[10px] text-foreground-subtle",
1261
+ children: a && a.uptimeMs > 0 ? pe(a.uptimeMs) : "—"
1262
+ })]
1263
+ }),
1264
+ a && E ? n ? /* @__PURE__ */ _("div", {
1265
+ className: "flex flex-wrap gap-x-3 gap-y-0.5 text-[10px]",
1266
+ children: [
1267
+ /* @__PURE__ */ _("span", {
1268
+ className: "inline-flex whitespace-nowrap gap-1",
1269
+ children: [/* @__PURE__ */ g("span", {
1270
+ className: "text-foreground-subtle",
1271
+ children: "FPS:"
1272
+ }), /* @__PURE__ */ _("span", {
1273
+ className: "text-foreground",
1274
+ children: [
1275
+ a.inputFps.toFixed(1),
1276
+ "/",
1277
+ a.decodeFps.toFixed(1)
1278
+ ]
1279
+ })]
1280
+ }),
1281
+ /* @__PURE__ */ _("span", {
1282
+ className: "inline-flex whitespace-nowrap gap-1",
1283
+ children: [/* @__PURE__ */ g("span", {
1284
+ className: "text-foreground-subtle",
1285
+ children: "Bitrate:"
1286
+ }), /* @__PURE__ */ g("span", {
1287
+ className: "text-foreground",
1288
+ children: a.bitrateKbps >= 1e3 ? `${(a.bitrateKbps / 1e3).toFixed(1)} Mbps` : `${a.bitrateKbps} kbps`
1289
+ })]
1290
+ }),
1291
+ /* @__PURE__ */ _("span", {
1292
+ className: "inline-flex whitespace-nowrap gap-1",
1293
+ children: [/* @__PURE__ */ g("span", {
1294
+ className: "text-foreground-subtle",
1295
+ children: "Codec:"
1296
+ }), /* @__PURE__ */ g("span", {
1297
+ className: "text-foreground",
1298
+ children: a.codec?.toUpperCase() ?? "—"
1299
+ })]
1300
+ }),
1301
+ /* @__PURE__ */ _("span", {
1302
+ className: "inline-flex items-center whitespace-nowrap gap-1",
1303
+ children: [
1304
+ /* @__PURE__ */ g("span", {
1305
+ className: "text-foreground-subtle",
1306
+ children: "Clients:"
1307
+ }),
1308
+ /* @__PURE__ */ g("span", {
1309
+ className: "text-foreground font-semibold",
1310
+ children: O
1311
+ }),
1312
+ /* @__PURE__ */ g("span", {
1313
+ className: "text-foreground-subtle/70",
1314
+ children: "("
1315
+ }),
1316
+ /* @__PURE__ */ g(Ce, {
1317
+ count: a.encodedSubscribers + a.decodedSubscribers,
1318
+ clients: s,
1319
+ onKill: w
1320
+ }),
1321
+ /* @__PURE__ */ g("span", {
1322
+ className: "text-foreground-subtle/70",
1323
+ children: "·"
1324
+ }),
1325
+ /* @__PURE__ */ g(Te, {
1326
+ count: a.rtspClients ?? 0,
1327
+ clients: s,
1328
+ onKill: w
1329
+ }),
1330
+ /* @__PURE__ */ _("span", {
1331
+ className: "text-foreground-subtle/70",
1332
+ children: [
1333
+ "· pipe ",
1334
+ a.pipeClients ?? 0,
1335
+ ")"
1336
+ ]
1337
+ })
1338
+ ]
1339
+ })
1340
+ ]
1341
+ }) : /* @__PURE__ */ _(v, { children: [/* @__PURE__ */ _("div", {
1342
+ className: "flex flex-wrap gap-x-3 gap-y-1 text-[10px]",
1343
+ children: [
1344
+ /* @__PURE__ */ _("span", {
1345
+ className: "inline-flex whitespace-nowrap gap-1",
1346
+ children: [/* @__PURE__ */ g("span", {
1347
+ className: "text-foreground-subtle",
1348
+ children: "In:"
1349
+ }), /* @__PURE__ */ _("span", {
1350
+ className: "text-foreground",
1351
+ children: [a.inputFps.toFixed(1), " fps"]
1352
+ })]
1353
+ }),
1354
+ /* @__PURE__ */ _("span", {
1355
+ className: "inline-flex whitespace-nowrap gap-1",
1356
+ children: [/* @__PURE__ */ g("span", {
1357
+ className: "text-foreground-subtle",
1358
+ children: "Dec:"
1359
+ }), /* @__PURE__ */ _("span", {
1360
+ className: "text-foreground",
1361
+ children: [a.decodeFps.toFixed(1), " fps"]
1362
+ })]
1363
+ }),
1364
+ /* @__PURE__ */ _("span", {
1365
+ className: "inline-flex whitespace-nowrap gap-1",
1366
+ children: [/* @__PURE__ */ g("span", {
1367
+ className: "text-foreground-subtle",
1368
+ children: "Bitrate:"
1369
+ }), /* @__PURE__ */ g("span", {
1370
+ className: "text-foreground",
1371
+ children: a.bitrateKbps >= 1e3 ? `${(a.bitrateKbps / 1e3).toFixed(1)} Mbps` : `${a.bitrateKbps} kbps`
1372
+ })]
1373
+ }),
1374
+ /* @__PURE__ */ _("span", {
1375
+ className: "hidden @[480px]:inline-flex whitespace-nowrap gap-1",
1376
+ children: [/* @__PURE__ */ g("span", {
1377
+ className: "text-foreground-subtle",
1378
+ children: "IDR:"
1379
+ }), /* @__PURE__ */ g("span", {
1380
+ className: "text-foreground",
1381
+ children: a.idrIntervalMs > 0 ? `${(a.idrIntervalMs / 1e3).toFixed(1)}s` : "—"
1382
+ })]
1383
+ }),
1384
+ /* @__PURE__ */ _("span", {
1385
+ className: "inline-flex whitespace-nowrap gap-1",
1386
+ children: [/* @__PURE__ */ g("span", {
1387
+ className: "text-foreground-subtle",
1388
+ children: "Codec:"
1389
+ }), /* @__PURE__ */ g("span", {
1390
+ className: "text-foreground",
1391
+ children: a.codec?.toUpperCase() ?? "—"
1392
+ })]
1393
+ }),
1394
+ /* @__PURE__ */ _("span", {
1395
+ className: "hidden @[480px]:inline-flex whitespace-nowrap gap-1 max-w-full overflow-hidden",
1396
+ children: [/* @__PURE__ */ g("span", {
1397
+ className: "text-foreground-subtle",
1398
+ children: "Decoder:"
1399
+ }), /* @__PURE__ */ g("span", {
1400
+ className: "text-foreground font-mono truncate",
1401
+ children: a.decoderNodeId ?? /* @__PURE__ */ g("span", {
1402
+ className: "text-foreground-subtle italic",
1403
+ children: "deferred"
1404
+ })
1405
+ })]
1406
+ }),
1407
+ /* @__PURE__ */ _("span", {
1408
+ className: "hidden @[640px]:inline-flex whitespace-nowrap gap-1",
1409
+ children: [/* @__PURE__ */ g("span", {
1410
+ className: "text-foreground-subtle",
1411
+ children: "Pipe:"
1412
+ }), /* @__PURE__ */ g("span", {
1413
+ className: "text-foreground",
1414
+ children: a.pipeClients ?? 0
1415
+ })]
1416
+ }),
1417
+ /* @__PURE__ */ _("span", {
1418
+ className: "hidden @[640px]:inline-flex whitespace-nowrap gap-1",
1419
+ children: [/* @__PURE__ */ g("span", {
1420
+ className: "text-foreground-subtle",
1421
+ children: "Packets:"
1422
+ }), /* @__PURE__ */ g("span", {
1423
+ className: "text-foreground",
1424
+ children: a.packetCount > 1e3 ? `${(a.packetCount / 1e3).toFixed(1)}k` : a.packetCount
1425
+ })]
1426
+ }),
1427
+ /* @__PURE__ */ _("span", {
1428
+ className: "hidden @[640px]:inline-flex whitespace-nowrap gap-1",
1429
+ children: [/* @__PURE__ */ g("span", {
1430
+ className: "text-foreground-subtle",
1431
+ children: "Data:"
1432
+ }), /* @__PURE__ */ g("span", {
1433
+ className: "text-foreground",
1434
+ children: a.totalBytes > 1048576 ? `${(a.totalBytes / 1048576).toFixed(1)} MB` : `${(a.totalBytes / 1024).toFixed(0)} KB`
1435
+ })]
1436
+ }),
1437
+ a.audio && /* @__PURE__ */ _("div", {
1438
+ className: "basis-full flex flex-wrap items-center gap-x-1.5 gap-y-0.5",
1439
+ children: [
1440
+ /* @__PURE__ */ g("span", {
1441
+ className: "text-foreground-subtle whitespace-nowrap",
1442
+ children: "Audio:"
1443
+ }),
1444
+ /* @__PURE__ */ _("span", {
1445
+ className: "inline-flex whitespace-nowrap items-center gap-1.5",
1446
+ children: [
1447
+ /* @__PURE__ */ g("span", {
1448
+ className: "text-foreground",
1449
+ children: a.audio.codec.toUpperCase()
1450
+ }),
1451
+ /* @__PURE__ */ g("span", {
1452
+ className: "text-foreground-subtle",
1453
+ children: "·"
1454
+ }),
1455
+ /* @__PURE__ */ g("span", {
1456
+ className: "text-foreground",
1457
+ children: a.audio.sampleRate >= 1e3 ? `${(a.audio.sampleRate / 1e3).toFixed(a.audio.sampleRate % 1e3 == 0 ? 0 : 1)}kHz` : `${a.audio.sampleRate}Hz`
1458
+ }),
1459
+ /* @__PURE__ */ g("span", {
1460
+ className: "text-foreground-subtle",
1461
+ children: "·"
1462
+ }),
1463
+ /* @__PURE__ */ g("span", {
1464
+ className: "text-foreground",
1465
+ children: a.audio.channels === 1 ? "mono" : a.audio.channels === 2 ? "stereo" : `${a.audio.channels}ch`
1466
+ })
1467
+ ]
1468
+ }),
1469
+ /* @__PURE__ */ g("span", {
1470
+ className: `px-1 py-px rounded text-[8px] font-medium whitespace-nowrap ${a.audio.supported ? "bg-success/15 text-success" : "bg-amber-500/15 text-amber-500"}`,
1471
+ children: a.audio.supported ? "decoded" : "no decoder"
1472
+ })
1473
+ ]
1474
+ })
1475
+ ]
1476
+ }), /* @__PURE__ */ g(Se, {
1477
+ clients: s,
1478
+ encodedCount: a.encodedSubscribers,
1479
+ onKill: w
1480
+ })] }) : /* @__PURE__ */ g("p", {
1481
+ className: "text-[10px] text-foreground-subtle italic",
1482
+ children: "No demand — stream suspended"
1483
+ }),
1484
+ /* @__PURE__ */ _("div", {
1485
+ className: "mt-1.5 flex items-center gap-1.5 text-[10px]",
1486
+ children: [
1487
+ /* @__PURE__ */ g("span", {
1488
+ className: "text-foreground-subtle",
1489
+ children: "Buffer:"
1490
+ }),
1491
+ /* @__PURE__ */ g(we, {
1492
+ enabled: h,
1493
+ onToggle: (e) => S(e),
1494
+ disabled: x.isPending
1495
+ }),
1496
+ /* @__PURE__ */ _("span", {
1497
+ className: "text-foreground",
1498
+ children: [
1499
+ b ?? a?.preBufferSec ?? 0,
1500
+ "s",
1501
+ a && E ? ` (${a.preBufferPackets}p)` : ""
1502
+ ]
1503
+ })
1504
+ ]
1505
+ })
1506
+ ]
1507
+ });
515
1508
  }
516
- function g(s) {
517
- if (s < 1e3) return `${s}ms`;
518
- const n = Math.floor(s / 1e3);
519
- if (n < 60) return `${n}s`;
520
- const o = Math.floor(n / 60);
521
- return o < 60 ? `${o}m ${n % 60}s` : `${Math.floor(o / 60)}h ${o % 60}m`;
1509
+ var xe = 280, J = 120;
1510
+ function Y({ trigger: t, content: n, widthClass: a }) {
1511
+ let o = e(null), s = e(null), [c, l] = r(!1), [u, d] = r(!1), f = i(() => {
1512
+ s.current &&= (clearTimeout(s.current), null);
1513
+ }, []), p = i(() => {
1514
+ f(), s.current = setTimeout(() => l(!1), J);
1515
+ }, [f]);
1516
+ return /* @__PURE__ */ _("span", {
1517
+ ref: o,
1518
+ className: "relative inline-block",
1519
+ onMouseEnter: i(() => {
1520
+ f();
1521
+ let e = o.current;
1522
+ if (e) {
1523
+ let t = e.getBoundingClientRect(), n = window.innerHeight - t.bottom, r = t.top;
1524
+ d(n < xe && r > n);
1525
+ }
1526
+ l(!0);
1527
+ }, [f]),
1528
+ onMouseLeave: p,
1529
+ children: [t, c && /* @__PURE__ */ g("div", {
1530
+ className: `absolute left-0 ${u ? "bottom-full mb-1" : "top-full mt-1"} z-50 ${a} rounded-md border border-border bg-surface shadow-xl p-2 text-[10px] normal-case`,
1531
+ onMouseEnter: f,
1532
+ onMouseLeave: p,
1533
+ children: n
1534
+ })]
1535
+ });
522
1536
  }
523
- function U(s) {
524
- return s < 1024 ? `${s} B` : s < 1048576 ? `${(s / 1024).toFixed(1)} KB` : s < 1073741824 ? `${(s / 1048576).toFixed(1)} MB` : `${(s / 1073741824).toFixed(2)} GB`;
1537
+ function X(e) {
1538
+ if (e < 1e3) return `${e}ms`;
1539
+ let t = Math.floor(e / 1e3);
1540
+ if (t < 60) return `${t}s`;
1541
+ let n = Math.floor(t / 60);
1542
+ return n < 60 ? `${n}m ${t % 60}s` : `${Math.floor(n / 60)}h ${n % 60}m`;
525
1543
  }
526
- function ge({ clients: s, encodedCount: n, onKill: o }) {
527
- const i = s?.decoded ?? [], c = s?.audio ?? [], t = s?.rtsp ?? [], l = i.length + c.length + t.length + n, [d, u] = y(!0);
528
- return l === 0 ? /* @__PURE__ */ e("div", { className: "mt-1.5 text-[10px] text-foreground-subtle italic", children: "No active subscribers" }) : /* @__PURE__ */ r("div", { className: "mt-1.5 border-t border-border/30 pt-1.5", children: [
529
- /* @__PURE__ */ r(
530
- "button",
531
- {
532
- type: "button",
533
- onClick: () => u((a) => !a),
534
- className: "flex items-center gap-1 text-[10px] text-foreground-subtle hover:text-foreground transition-colors",
535
- children: [
536
- d ? /* @__PURE__ */ e(O, { className: "h-3 w-3" }) : /* @__PURE__ */ e(j, { className: "h-3 w-3" }),
537
- /* @__PURE__ */ r("span", { className: "uppercase tracking-wider", children: [
538
- "Subscribers (",
539
- l,
540
- ")"
541
- ] })
542
- ]
543
- }
544
- ),
545
- d && /* @__PURE__ */ r("div", { className: "mt-1 divide-y divide-border/20", children: [
546
- i.map((a, m) => /* @__PURE__ */ e(
547
- $,
548
- {
549
- kind: "DECODED",
550
- kindClass: "bg-success/10 text-success",
551
- tag: a.tag || "unknown",
552
- metrics: [
553
- `${a.maxFps.toFixed(0)}fps`,
554
- `${a.framesDelivered} del`,
555
- ...a.framesDropped > 0 ? [{ text: `${a.framesDropped} drop`, warn: !0 }] : []
556
- ],
557
- age: Date.now() - a.subscribedAt,
558
- onKill: o && a.tag ? () => o({ channel: "decoded", handle: a.tag }) : void 0
559
- },
560
- `d-${m}`
561
- )),
562
- c.map((a, m) => /* @__PURE__ */ e(
563
- $,
564
- {
565
- kind: "AUDIO",
566
- kindClass: "bg-info/10 text-info",
567
- tag: a.tag || "unknown",
568
- metrics: [`${a.chunksDelivered} chunks`],
569
- age: Date.now() - a.subscribedAt,
570
- onKill: o && a.tag ? () => o({ channel: "audio", handle: a.tag }) : void 0
571
- },
572
- `a-${m}`
573
- )),
574
- t.map((a) => {
575
- const m = Date.now() - a.lastRtpAt, f = m > 5e3, x = a.playing ? f ? "stalled" : "playing" : "paused", h = a.playing ? f ? "bg-amber-400/10 text-amber-400" : "bg-success/10 text-success" : "bg-foreground-subtle/10 text-foreground-subtle";
576
- return /* @__PURE__ */ e(
577
- $,
578
- {
579
- kind: "RTSP",
580
- kindClass: "bg-warning/10 text-warning",
581
- tag: a.remoteAddr,
582
- state: { text: x + (a.muted ? " · muted" : ""), className: h },
583
- metrics: [U(a.bytesSent), `last rtp ${g(m)} ago`],
584
- age: Date.now() - a.connectedAt,
585
- onKill: o ? () => o({ channel: "rtsp", handle: a.sessionId }) : void 0
586
- },
587
- `r-${a.sessionId}`
588
- );
589
- }),
590
- n > 0 && /* @__PURE__ */ r("div", { className: "py-0.5 text-[10px] text-foreground-subtle", children: [
591
- /* @__PURE__ */ e("span", { className: "inline-block px-1 rounded text-[9px] font-bold bg-foreground-subtle/10 text-foreground-subtle mr-2", children: "ENCODED" }),
592
- n,
593
- " callback subscriber(s)"
594
- ] })
595
- ] })
596
- ] });
1544
+ function Z(e) {
1545
+ return e < 1024 ? `${e} B` : e < 1048576 ? `${(e / 1024).toFixed(1)} KB` : e < 1073741824 ? `${(e / 1048576).toFixed(1)} MB` : `${(e / 1073741824).toFixed(2)} GB`;
597
1546
  }
598
- function $({ kind: s, kindClass: n, tag: o, state: i, metrics: c, age: t, onKill: l }) {
599
- return /* @__PURE__ */ r("div", { className: "flex items-center gap-2 py-0.5 text-[10px]", children: [
600
- /* @__PURE__ */ e("span", { className: `inline-block px-1 rounded text-[9px] font-bold shrink-0 w-14 text-center ${n}`, children: s }),
601
- /* @__PURE__ */ e("span", { className: "text-foreground font-medium truncate flex-1", children: o }),
602
- i && /* @__PURE__ */ e("span", { className: `text-[9px] px-1 rounded shrink-0 ${i.className}`, children: i.text }),
603
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle flex items-center gap-1.5 shrink-0", children: [
604
- c.map((d, u) => /* @__PURE__ */ r("span", { children: [
605
- u > 0 && /* @__PURE__ */ e("span", { className: "mr-1.5 text-foreground-subtle/50", children: "·" }),
606
- typeof d == "string" ? d : /* @__PURE__ */ e("span", { className: d.warn ? "text-amber-400" : "", children: d.text })
607
- ] }, u)),
608
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle/70", children: [
609
- "· ",
610
- g(t)
611
- ] })
612
- ] }),
613
- /* @__PURE__ */ e("div", { className: "w-5 flex-shrink-0 flex items-center justify-end", children: l ? /* @__PURE__ */ e(C, { onClick: l }) : null })
614
- ] });
1547
+ function Se({ clients: e, encodedCount: t, onKill: n }) {
1548
+ let i = e?.decoded ?? [], a = e?.audio ?? [], o = e?.rtsp ?? [], s = e?.encoded ?? [], c = i.length + a.length + o.length + s.length, [l, u] = r(!0);
1549
+ return c === 0 ? /* @__PURE__ */ g("div", {
1550
+ className: "mt-1.5 text-[10px] text-foreground-subtle italic",
1551
+ children: "No active subscribers"
1552
+ }) : /* @__PURE__ */ _("div", {
1553
+ className: "mt-1.5 border-t border-border/30 pt-1.5",
1554
+ children: [/* @__PURE__ */ _("button", {
1555
+ type: "button",
1556
+ onClick: () => u((e) => !e),
1557
+ className: "flex items-center gap-1 text-[10px] text-foreground-subtle hover:text-foreground transition-colors",
1558
+ children: [g(l ? A : j, { className: "h-3 w-3" }), /* @__PURE__ */ _("span", {
1559
+ className: "uppercase tracking-wider",
1560
+ children: [
1561
+ "Subscribers (",
1562
+ c,
1563
+ ")"
1564
+ ]
1565
+ })]
1566
+ }), l && /* @__PURE__ */ _("div", {
1567
+ className: "mt-1 divide-y divide-border/20",
1568
+ children: [
1569
+ i.map((e, t) => /* @__PURE__ */ g(Q, {
1570
+ kind: "DECODED",
1571
+ kindClass: "bg-success/10 text-success",
1572
+ tag: e.tag || "unknown",
1573
+ metrics: [
1574
+ `${e.maxFps.toFixed(0)}fps`,
1575
+ `${e.framesDelivered} del`,
1576
+ ...e.framesDropped > 0 ? [{
1577
+ text: `${e.framesDropped} drop`,
1578
+ warn: !0
1579
+ }] : []
1580
+ ],
1581
+ age: Date.now() - e.subscribedAt,
1582
+ onKill: n && e.tag ? () => n({
1583
+ channel: "decoded",
1584
+ handle: e.tag
1585
+ }) : void 0
1586
+ }, `d-${t}`)),
1587
+ a.map((e, t) => /* @__PURE__ */ g(Q, {
1588
+ kind: "AUDIO",
1589
+ kindClass: "bg-info/10 text-info",
1590
+ tag: e.tag || "unknown",
1591
+ metrics: [`${e.chunksDelivered} chunks`],
1592
+ age: Date.now() - e.subscribedAt,
1593
+ onKill: n && e.tag ? () => n({
1594
+ channel: "audio",
1595
+ handle: e.tag
1596
+ }) : void 0
1597
+ }, `a-${t}`)),
1598
+ o.map((e) => {
1599
+ let t = Date.now() - e.lastRtpAt, r = t > 5e3, i = e.playing ? r ? "stalled" : "playing" : "paused", a = e.playing ? r ? "bg-amber-400/10 text-amber-400" : "bg-success/10 text-success" : "bg-foreground-subtle/10 text-foreground-subtle";
1600
+ return /* @__PURE__ */ g(Q, {
1601
+ kind: "RTSP",
1602
+ kindClass: "bg-warning/10 text-warning",
1603
+ tag: e.remoteAddr,
1604
+ state: {
1605
+ text: i + (e.muted ? " · muted" : ""),
1606
+ className: a
1607
+ },
1608
+ metrics: [Z(e.bytesSent), `last rtp ${X(t)} ago`],
1609
+ age: Date.now() - e.connectedAt,
1610
+ onKill: n ? () => n({
1611
+ channel: "rtsp",
1612
+ handle: e.sessionId
1613
+ }) : void 0
1614
+ }, `r-${e.sessionId}`);
1615
+ }),
1616
+ s.map((e) => {
1617
+ let t = e.attribution, n = me[t.kind] ?? "bg-foreground-subtle/10 text-foreground-subtle", r = t.sessionId ? t.sessionId.slice(0, 8) : null, i = [];
1618
+ t.label && i.push(t.label), r && i.push(`sess ${r}`), t.userId && i.push(`user ${t.userId.slice(0, 8)}`), t.remoteAddr && i.push(`@${t.remoteAddr}`), t.userAgent && i.push(fe(t.userAgent));
1619
+ let a = i.length > 0 ? i.join(" · ") : ge(t.kind), o = [];
1620
+ return t.media && o.push({ text: t.media }), t.targetCodec && o.push(t.targetCodec), t.transport && o.push(t.transport), o.push(`${e.packetsDelivered} pkts`), /* @__PURE__ */ g(Q, {
1621
+ kind: he(t.kind),
1622
+ kindClass: n,
1623
+ tag: a,
1624
+ metrics: o,
1625
+ age: Date.now() - e.subscribedAt
1626
+ }, e.id);
1627
+ }),
1628
+ s.length === 0 && t > 0 && /* @__PURE__ */ _("div", {
1629
+ className: "py-0.5 text-[10px] text-foreground-subtle",
1630
+ children: [
1631
+ /* @__PURE__ */ g("span", {
1632
+ className: "inline-block px-1 rounded text-[9px] font-bold bg-foreground-subtle/10 text-foreground-subtle mr-2",
1633
+ children: "ENCODED"
1634
+ }),
1635
+ t,
1636
+ " callback subscriber(s)"
1637
+ ]
1638
+ })
1639
+ ]
1640
+ })]
1641
+ });
615
1642
  }
616
- function Ne({ count: s, clients: n, onKill: o }) {
617
- const i = n?.decoded ?? [], c = n?.audio ?? [], t = n ? n.encodedSubscribers : 0, l = i.length > 0 || c.length > 0 || t > 0, d = /* @__PURE__ */ e("span", { className: `text-foreground ${l ? "underline decoration-dotted decoration-foreground-subtle/50 underline-offset-2 cursor-help" : ""}`, children: s });
618
- if (!l) return d;
619
- const u = /* @__PURE__ */ r(B, { children: [
620
- i.length > 0 && /* @__PURE__ */ r("div", { className: "mb-2", children: [
621
- /* @__PURE__ */ e("div", { className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1", children: "Decoded subscribers" }),
622
- i.map((a, m) => /* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-2 py-0.5", children: [
623
- /* @__PURE__ */ e("span", { className: "text-foreground font-medium truncate", children: a.tag || "unknown" }),
624
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle text-[9px] flex items-center gap-1.5 shrink-0", children: [
625
- /* @__PURE__ */ r("span", { children: [
626
- a.maxFps.toFixed(0),
627
- "fps"
628
- ] }),
629
- /* @__PURE__ */ e("span", { children: "·" }),
630
- /* @__PURE__ */ r("span", { children: [
631
- a.framesDelivered,
632
- " del"
633
- ] }),
634
- a.framesDropped > 0 && /* @__PURE__ */ r("span", { className: "text-amber-400", children: [
635
- "· ",
636
- a.framesDropped,
637
- " drop"
638
- ] }),
639
- /* @__PURE__ */ e("span", { children: "·" }),
640
- /* @__PURE__ */ e("span", { children: g(Date.now() - a.subscribedAt) }),
641
- o && a.tag && /* @__PURE__ */ e(C, { onClick: () => o({ channel: "decoded", handle: a.tag }) })
642
- ] })
643
- ] }, `d-${m}`))
644
- ] }),
645
- c.length > 0 && /* @__PURE__ */ r("div", { className: "mb-2", children: [
646
- /* @__PURE__ */ e("div", { className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1", children: "Audio subscribers" }),
647
- c.map((a, m) => /* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-2 py-0.5", children: [
648
- /* @__PURE__ */ e("span", { className: "text-foreground font-medium truncate", children: a.tag || "unknown" }),
649
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle text-[9px] flex items-center gap-1.5 shrink-0", children: [
650
- /* @__PURE__ */ r("span", { children: [
651
- a.chunksDelivered,
652
- " chunks"
653
- ] }),
654
- /* @__PURE__ */ e("span", { children: "·" }),
655
- /* @__PURE__ */ e("span", { children: g(Date.now() - a.subscribedAt) }),
656
- o && a.tag && /* @__PURE__ */ e(C, { onClick: () => o({ channel: "audio", handle: a.tag }) })
657
- ] })
658
- ] }, `a-${m}`))
659
- ] }),
660
- t > 0 && /* @__PURE__ */ r("div", { children: [
661
- /* @__PURE__ */ e("div", { className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1", children: "Encoded" }),
662
- /* @__PURE__ */ r("div", { className: "text-foreground", children: [
663
- t,
664
- " callback subscriber(s)"
665
- ] })
666
- ] })
667
- ] });
668
- return /* @__PURE__ */ e(K, { trigger: d, content: u, widthClass: "min-w-[260px] max-w-[360px]" });
1643
+ function Q({ kind: e, kindClass: t, tag: n, state: r, metrics: i, age: a, onKill: o }) {
1644
+ return /* @__PURE__ */ _("div", {
1645
+ className: "flex items-center gap-2 py-0.5 text-[10px]",
1646
+ children: [
1647
+ /* @__PURE__ */ g("span", {
1648
+ className: `inline-block px-1 rounded text-[9px] font-bold shrink-0 w-14 text-center ${t}`,
1649
+ children: e
1650
+ }),
1651
+ /* @__PURE__ */ g("span", {
1652
+ className: "text-foreground font-medium truncate flex-1",
1653
+ children: n
1654
+ }),
1655
+ r && /* @__PURE__ */ g("span", {
1656
+ className: `text-[9px] px-1 rounded shrink-0 ${r.className}`,
1657
+ children: r.text
1658
+ }),
1659
+ /* @__PURE__ */ _("span", {
1660
+ className: "text-foreground-subtle flex items-center gap-1.5 shrink-0",
1661
+ children: [i.map((e, t) => /* @__PURE__ */ _("span", { children: [t > 0 && /* @__PURE__ */ g("span", {
1662
+ className: "mr-1.5 text-foreground-subtle/50",
1663
+ children: "·"
1664
+ }), typeof e == "string" ? e : /* @__PURE__ */ g("span", {
1665
+ className: e.warn ? "text-amber-400" : "",
1666
+ children: e.text
1667
+ })] }, t)), /* @__PURE__ */ _("span", {
1668
+ className: "text-foreground-subtle/70",
1669
+ children: ["· ", X(a)]
1670
+ })]
1671
+ }),
1672
+ /* @__PURE__ */ g("div", {
1673
+ className: "w-5 flex-shrink-0 flex items-center justify-end",
1674
+ children: o ? /* @__PURE__ */ g($, { onClick: o }) : null
1675
+ })
1676
+ ]
1677
+ });
669
1678
  }
670
- function we({
671
- enabled: s,
672
- onToggle: n,
673
- disabled: o
674
- }) {
675
- return /* @__PURE__ */ e(
676
- "button",
677
- {
678
- type: "button",
679
- role: "switch",
680
- "aria-checked": s,
681
- disabled: o,
682
- onClick: () => n(!s),
683
- className: `relative inline-flex h-3 w-6 shrink-0 items-center rounded-full transition-colors ${s ? "bg-success/60" : "bg-foreground-subtle/30"} ${o ? "opacity-50 cursor-wait" : "cursor-pointer"}`,
684
- title: s ? "Pre-buffer enabled — click to disable" : "Pre-buffer disabled — click to enable",
685
- children: /* @__PURE__ */ e(
686
- "span",
687
- {
688
- className: `inline-block h-2.5 w-2.5 rounded-full bg-white shadow transition-transform ${s ? "translate-x-3" : "translate-x-0.5"}`
689
- }
690
- )
691
- }
692
- );
1679
+ function Ce({ count: e, clients: t, onKill: n }) {
1680
+ let r = t?.decoded ?? [], i = t?.audio ?? [], a = t ? t.encodedSubscribers : 0, o = r.length > 0 || i.length > 0 || a > 0, s = /* @__PURE__ */ g("span", {
1681
+ className: `text-foreground ${o ? "underline decoration-dotted decoration-foreground-subtle/50 underline-offset-2 cursor-help" : ""}`,
1682
+ children: e
1683
+ });
1684
+ return o ? /* @__PURE__ */ g(Y, {
1685
+ trigger: s,
1686
+ content: /* @__PURE__ */ _(v, { children: [
1687
+ r.length > 0 && /* @__PURE__ */ _("div", {
1688
+ className: "mb-2",
1689
+ children: [/* @__PURE__ */ g("div", {
1690
+ className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1",
1691
+ children: "Decoded subscribers"
1692
+ }), r.map((e, t) => /* @__PURE__ */ _("div", {
1693
+ className: "flex items-center justify-between gap-2 py-0.5",
1694
+ children: [/* @__PURE__ */ g("span", {
1695
+ className: "text-foreground font-medium truncate",
1696
+ children: e.tag || "unknown"
1697
+ }), /* @__PURE__ */ _("span", {
1698
+ className: "text-foreground-subtle text-[9px] flex items-center gap-1.5 shrink-0",
1699
+ children: [
1700
+ /* @__PURE__ */ _("span", { children: [e.maxFps.toFixed(0), "fps"] }),
1701
+ /* @__PURE__ */ g("span", { children: "·" }),
1702
+ /* @__PURE__ */ _("span", { children: [e.framesDelivered, " del"] }),
1703
+ e.framesDropped > 0 && /* @__PURE__ */ _("span", {
1704
+ className: "text-amber-400",
1705
+ children: [
1706
+ "· ",
1707
+ e.framesDropped,
1708
+ " drop"
1709
+ ]
1710
+ }),
1711
+ /* @__PURE__ */ g("span", { children: "·" }),
1712
+ /* @__PURE__ */ g("span", { children: X(Date.now() - e.subscribedAt) }),
1713
+ n && e.tag && /* @__PURE__ */ g($, { onClick: () => n({
1714
+ channel: "decoded",
1715
+ handle: e.tag
1716
+ }) })
1717
+ ]
1718
+ })]
1719
+ }, `d-${t}`))]
1720
+ }),
1721
+ i.length > 0 && /* @__PURE__ */ _("div", {
1722
+ className: "mb-2",
1723
+ children: [/* @__PURE__ */ g("div", {
1724
+ className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1",
1725
+ children: "Audio subscribers"
1726
+ }), i.map((e, t) => /* @__PURE__ */ _("div", {
1727
+ className: "flex items-center justify-between gap-2 py-0.5",
1728
+ children: [/* @__PURE__ */ g("span", {
1729
+ className: "text-foreground font-medium truncate",
1730
+ children: e.tag || "unknown"
1731
+ }), /* @__PURE__ */ _("span", {
1732
+ className: "text-foreground-subtle text-[9px] flex items-center gap-1.5 shrink-0",
1733
+ children: [
1734
+ /* @__PURE__ */ _("span", { children: [e.chunksDelivered, " chunks"] }),
1735
+ /* @__PURE__ */ g("span", { children: "·" }),
1736
+ /* @__PURE__ */ g("span", { children: X(Date.now() - e.subscribedAt) }),
1737
+ n && e.tag && /* @__PURE__ */ g($, { onClick: () => n({
1738
+ channel: "audio",
1739
+ handle: e.tag
1740
+ }) })
1741
+ ]
1742
+ })]
1743
+ }, `a-${t}`))]
1744
+ }),
1745
+ a > 0 && /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("div", {
1746
+ className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1",
1747
+ children: "Encoded"
1748
+ }), /* @__PURE__ */ _("div", {
1749
+ className: "text-foreground",
1750
+ children: [a, " callback subscriber(s)"]
1751
+ })] })
1752
+ ] }),
1753
+ widthClass: "min-w-[260px] max-w-[360px]"
1754
+ }) : s;
693
1755
  }
694
- function C({ onClick: s }) {
695
- return /* @__PURE__ */ e(
696
- "button",
697
- {
698
- type: "button",
699
- title: "Force-disconnect this client",
700
- onClick: (n) => {
701
- n.stopPropagation(), s();
702
- },
703
- className: "inline-flex items-center justify-center h-4 w-4 rounded-sm border border-border/60 text-foreground-subtle hover:bg-red-500/10 hover:text-red-400 hover:border-red-500/40 transition-colors",
704
- children: /* @__PURE__ */ e(le, { className: "h-2.5 w-2.5" })
705
- }
706
- );
1756
+ function we({ enabled: e, onToggle: t, disabled: n }) {
1757
+ return /* @__PURE__ */ g("button", {
1758
+ type: "button",
1759
+ role: "switch",
1760
+ "aria-checked": e,
1761
+ disabled: n,
1762
+ onClick: () => t(!e),
1763
+ className: `relative inline-flex h-3 w-6 shrink-0 items-center rounded-full transition-colors ${e ? "bg-success/60" : "bg-foreground-subtle/30"} ${n ? "opacity-50 cursor-wait" : "cursor-pointer"}`,
1764
+ title: e ? "Pre-buffer enabled — click to disable" : "Pre-buffer disabled — click to enable",
1765
+ children: /* @__PURE__ */ g("span", { className: `inline-block h-2.5 w-2.5 rounded-full bg-white shadow transition-transform ${e ? "translate-x-3" : "translate-x-0.5"}` })
1766
+ });
707
1767
  }
708
- function ve({ count: s, clients: n, onKill: o }) {
709
- const i = n?.rtsp ?? [], c = i.length > 0, t = /* @__PURE__ */ e("span", { className: `text-foreground ${c ? "underline decoration-dotted decoration-foreground-subtle/50 underline-offset-2 cursor-help" : ""}`, children: s });
710
- if (!c) return t;
711
- const l = /* @__PURE__ */ r(B, { children: [
712
- /* @__PURE__ */ e("div", { className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1", children: "RTSP sessions" }),
713
- i.map((d) => {
714
- const u = Date.now() - d.lastRtpAt, a = u > 5e3;
715
- return /* @__PURE__ */ r("div", { className: "py-1 border-b border-border/40 last:border-b-0", children: [
716
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-2", children: [
717
- /* @__PURE__ */ e("span", { className: "text-foreground font-mono", children: d.remoteAddr }),
718
- /* @__PURE__ */ r("span", { className: "flex items-center gap-1 shrink-0", children: [
719
- /* @__PURE__ */ r("span", { className: `text-[9px] px-1 rounded ${d.playing ? a ? "bg-amber-400/10 text-amber-400" : "bg-success/10 text-success" : "bg-foreground-subtle/10 text-foreground-subtle"}`, children: [
720
- d.playing ? a ? "stalled" : "playing" : "paused",
721
- d.muted && " · muted"
722
- ] }),
723
- o && /* @__PURE__ */ e(C, { onClick: () => o({ channel: "rtsp", handle: d.sessionId }) })
724
- ] })
725
- ] }),
726
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-2 text-foreground-subtle text-[9px] mt-0.5", children: [
727
- /* @__PURE__ */ r("span", { children: [
728
- U(d.bytesSent),
729
- " sent"
730
- ] }),
731
- /* @__PURE__ */ r("span", { children: [
732
- "connected ",
733
- g(Date.now() - d.connectedAt),
734
- " ago"
735
- ] }),
736
- /* @__PURE__ */ r("span", { children: [
737
- "last rtp ",
738
- g(u),
739
- " ago"
740
- ] })
741
- ] })
742
- ] }, d.sessionId);
743
- })
744
- ] });
745
- return /* @__PURE__ */ e(K, { trigger: t, content: l, widthClass: "min-w-[300px] max-w-[420px]" });
1768
+ function $({ onClick: e }) {
1769
+ return /* @__PURE__ */ g("button", {
1770
+ type: "button",
1771
+ title: "Force-disconnect this client",
1772
+ onClick: (t) => {
1773
+ t.stopPropagation(), e();
1774
+ },
1775
+ className: "inline-flex items-center justify-center h-4 w-4 rounded-sm border border-border/60 text-foreground-subtle hover:bg-red-500/10 hover:text-red-400 hover:border-red-500/40 transition-colors",
1776
+ children: /* @__PURE__ */ g(ne, { className: "h-2.5 w-2.5" })
1777
+ });
746
1778
  }
747
- const $e = {
748
- "stream-broker-panel": ue
749
- };
750
- export {
751
- $e as default
1779
+ function Te({ count: e, clients: t, onKill: n }) {
1780
+ let r = t?.rtsp ?? [], i = r.length > 0, a = /* @__PURE__ */ g("span", {
1781
+ className: `text-foreground ${i ? "underline decoration-dotted decoration-foreground-subtle/50 underline-offset-2 cursor-help" : ""}`,
1782
+ children: e
1783
+ });
1784
+ return i ? /* @__PURE__ */ g(Y, {
1785
+ trigger: a,
1786
+ content: /* @__PURE__ */ _(v, { children: [/* @__PURE__ */ g("div", {
1787
+ className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1",
1788
+ children: "RTSP sessions"
1789
+ }), r.map((e) => {
1790
+ let t = Date.now() - e.lastRtpAt, r = t > 5e3;
1791
+ return /* @__PURE__ */ _("div", {
1792
+ className: "py-1 border-b border-border/40 last:border-b-0",
1793
+ children: [/* @__PURE__ */ _("div", {
1794
+ className: "flex items-center justify-between gap-2",
1795
+ children: [/* @__PURE__ */ g("span", {
1796
+ className: "text-foreground font-mono",
1797
+ children: e.remoteAddr
1798
+ }), /* @__PURE__ */ _("span", {
1799
+ className: "flex items-center gap-1 shrink-0",
1800
+ children: [/* @__PURE__ */ _("span", {
1801
+ className: `text-[9px] px-1 rounded ${e.playing ? r ? "bg-amber-400/10 text-amber-400" : "bg-success/10 text-success" : "bg-foreground-subtle/10 text-foreground-subtle"}`,
1802
+ children: [e.playing ? r ? "stalled" : "playing" : "paused", e.muted && " · muted"]
1803
+ }), n && /* @__PURE__ */ g($, { onClick: () => n({
1804
+ channel: "rtsp",
1805
+ handle: e.sessionId
1806
+ }) })]
1807
+ })]
1808
+ }), /* @__PURE__ */ _("div", {
1809
+ className: "flex items-center justify-between gap-2 text-foreground-subtle text-[9px] mt-0.5",
1810
+ children: [
1811
+ /* @__PURE__ */ _("span", { children: [Z(e.bytesSent), " sent"] }),
1812
+ /* @__PURE__ */ _("span", { children: [
1813
+ "connected ",
1814
+ X(Date.now() - e.connectedAt),
1815
+ " ago"
1816
+ ] }),
1817
+ /* @__PURE__ */ _("span", { children: [
1818
+ "last rtp ",
1819
+ X(t),
1820
+ " ago"
1821
+ ] })
1822
+ ]
1823
+ })]
1824
+ }, e.sessionId);
1825
+ })] }),
1826
+ widthClass: "min-w-[300px] max-w-[420px]"
1827
+ }) : a;
1828
+ }
1829
+ //#endregion
1830
+ //#region src/stream-broker/widgets/index.tsx
1831
+ var Ee = {
1832
+ "stream-broker-panel": _e,
1833
+ "ffmpeg-params": ue
752
1834
  };
1835
+ //#endregion
1836
+ export { Ee as default };