@camstack/addon-pipeline 0.1.20 → 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 (101) hide show
  1. package/dist/audio-analyzer/index.js +736 -719
  2. package/dist/audio-analyzer/index.mjs +726 -679
  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-CMcx_k6Y.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 +2029 -1827
  20. package/dist/pipeline-runner/index.mjs +2025 -1811
  21. package/dist/recorder/index.js +2045 -2157
  22. package/dist/recorder/index.mjs +2042 -2156
  23. package/dist/stream-broker/_stub.js +1806 -1352
  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 +17778 -15470
  33. package/dist/stream-broker/index.mjs +17769 -15465
  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 +25 -7
  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-5aYef068.mjs +0 -17514
  52. package/dist/index-5aYef068.mjs.map +0 -1
  53. package/dist/index-B36NMAdu.js +0 -17513
  54. package/dist/index-B36NMAdu.js.map +0 -1
  55. package/dist/index-CMcx_k6Y.js.map +0 -1
  56. package/dist/index-CYb7cFrv.mjs +0 -5790
  57. package/dist/index-CYb7cFrv.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/recorder/index.js.map +0 -1
  63. package/dist/recorder/index.mjs.map +0 -1
  64. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/FfmpegParamsField.d.ts +0 -41
  65. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/GeometryBuilder.d.ts +0 -54
  66. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/StreamBrokerPanel.d.ts +0 -21
  67. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/format-ua.d.ts +0 -13
  68. package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/index.d.ts +0 -15
  69. package/dist/stream-broker/@mf-types/widgets.d.ts +0 -2
  70. package/dist/stream-broker/@mf-types.d.ts +0 -3
  71. package/dist/stream-broker/@mf-types.zip +0 -0
  72. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-lantnv8e.mjs +0 -12
  73. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-DJ3UNg7O.mjs +0 -30
  74. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-CYXy_bhS.mjs +0 -21
  75. 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
  76. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_trpc_mf_1_client__loadShare__.mjs-DeouEaSs.mjs +0 -85
  77. 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
  78. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs-CaDEYBIU.mjs +0 -89
  79. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-D6EROtlA.mjs +0 -29
  80. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-x6pP3Ghk.mjs +0 -36
  81. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs-DYEKzzY-.mjs +0 -45
  82. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-CcnN6sbA.mjs +0 -6
  83. package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom_mf_1_client__loadShare__.mjs-DICOtMTl.mjs +0 -34
  84. package/dist/stream-broker/_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CL9DR49k.mjs +0 -156
  85. package/dist/stream-broker/client-BvTmMOQu.mjs +0 -9836
  86. package/dist/stream-broker/getErrorShape-BPSzUA7W-TlK8ipWe.mjs +0 -211
  87. package/dist/stream-broker/hostInit-ChmiMPS0.mjs +0 -168
  88. package/dist/stream-broker/index-BxsFuFmE.mjs +0 -2603
  89. package/dist/stream-broker/index-C-248uOU.mjs +0 -725
  90. package/dist/stream-broker/index-C05B6jqp.mjs +0 -185
  91. package/dist/stream-broker/index-CWkKuNLr.mjs +0 -232
  92. package/dist/stream-broker/index-DOJoSShD.mjs +0 -67784
  93. package/dist/stream-broker/index-DtOI1aTU.mjs +0 -18504
  94. package/dist/stream-broker/index-oMq6ilgR.mjs +0 -1641
  95. package/dist/stream-broker/index-vIWZQBIL.mjs +0 -435
  96. package/dist/stream-broker/index-xncRG7-x.mjs +0 -2713
  97. package/dist/stream-broker/index.js.map +0 -1
  98. package/dist/stream-broker/index.mjs.map +0 -1
  99. package/dist/stream-broker/jsx-runtime-BRT_HL0A.mjs +0 -55
  100. package/dist/stream-broker/schemas-B7L0qZtq.mjs +0 -3599
  101. package/dist/stream-broker/virtualExposes-pCd777Rp.mjs +0 -42
@@ -1,1382 +1,1836 @@
1
- import { _ as r, a as e, b as $ } from "./__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-x6pP3Ghk.mjs";
2
- import { a as oe, b as V, c as x, d as R, e as W, f as me } from "./__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs-CaDEYBIU.mjs";
3
- import { _ as he, a as ie, b as fe, c as ge, d as be, e as le, f as xe, g as ve, h as Ne, i as we } from "./__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-CYXy_bhS.mjs";
4
- import { _ as ye, a as ke } from "./__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.mjs-U1EUeEPs.mjs";
5
- import { _ as Ce } from "./__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-DJ3UNg7O.mjs";
6
- /**
7
- * @license lucide-react v0.511.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */
12
- const _e = (t) => t.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), $e = (t) => t.replace(
13
- /^([A-Z])|[\s-_]+(\w)/g,
14
- (a, n, o) => o ? o.toUpperCase() : n.toLowerCase()
15
- ), Y = (t) => {
16
- const a = $e(t);
17
- return a.charAt(0).toUpperCase() + a.slice(1);
18
- }, ce = (...t) => t.filter((a, n, o) => !!a && a.trim() !== "" && o.indexOf(a) === n).join(" ").trim(), Ae = (t) => {
19
- for (const a in t)
20
- if (a.startsWith("aria-") || a === "role" || a === "title")
21
- return !0;
22
- };
23
- /**
24
- * @license lucide-react v0.511.0 - ISC
25
- *
26
- * This source code is licensed under the ISC license.
27
- * See the LICENSE file in the root directory of this source tree.
28
- */
29
- var Se = {
30
- xmlns: "http://www.w3.org/2000/svg",
31
- width: 24,
32
- height: 24,
33
- viewBox: "0 0 24 24",
34
- fill: "none",
35
- stroke: "currentColor",
36
- strokeWidth: 2,
37
- strokeLinecap: "round",
38
- strokeLinejoin: "round"
39
- };
40
- /**
41
- * @license lucide-react v0.511.0 - ISC
42
- *
43
- * This source code is licensed under the ISC license.
44
- * See the LICENSE file in the root directory of this source tree.
45
- */
46
- const Ie = oe(
47
- ({
48
- color: t = "currentColor",
49
- size: a = 24,
50
- strokeWidth: n = 2,
51
- absoluteStrokeWidth: o,
52
- className: c = "",
53
- children: s,
54
- iconNode: m,
55
- ...l
56
- }, f) => V(
57
- "svg",
58
- {
59
- ref: f,
60
- ...Se,
61
- width: a,
62
- height: a,
63
- stroke: t,
64
- strokeWidth: o ? Number(n) * 24 / Number(a) : n,
65
- className: ce("lucide", c),
66
- ...!s && !Ae(l) && { "aria-hidden": "true" },
67
- ...l
68
- },
69
- [
70
- ...m.map(([u, d]) => V(u, d)),
71
- ...Array.isArray(s) ? s : [s]
72
- ]
73
- )
74
- );
75
- /**
76
- * @license lucide-react v0.511.0 - ISC
77
- *
78
- * This source code is licensed under the ISC license.
79
- * See the LICENSE file in the root directory of this source tree.
80
- */
81
- const T = (t, a) => {
82
- const n = oe(
83
- ({ className: o, ...c }, s) => V(Ie, {
84
- ref: s,
85
- iconNode: a,
86
- className: ce(
87
- `lucide-${_e(Y(t))}`,
88
- `lucide-${t}`,
89
- o
90
- ),
91
- ...c
92
- })
93
- );
94
- return n.displayName = Y(t), n;
95
- };
96
- /**
97
- * @license lucide-react v0.511.0 - ISC
98
- *
99
- * This source code is licensed under the ISC license.
100
- * See the LICENSE file in the root directory of this source tree.
101
- */
102
- const Fe = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]], X = T("chevron-down", Fe);
103
- /**
104
- * @license lucide-react v0.511.0 - ISC
105
- *
106
- * This source code is licensed under the ISC license.
107
- * See the LICENSE file in the root directory of this source tree.
108
- */
109
- const Pe = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]], Q = T("chevron-right", Pe);
110
- /**
111
- * @license lucide-react v0.511.0 - ISC
112
- *
113
- * This source code is licensed under the ISC license.
114
- * See the LICENSE file in the root directory of this source tree.
115
- */
116
- const Be = [
117
- ["path", { d: "M5 12h14", key: "1ays0h" }],
118
- ["path", { d: "M12 5v14", key: "s699le" }]
119
- ], Oe = T("plus", Be);
120
- /**
121
- * @license lucide-react v0.511.0 - ISC
122
- *
123
- * This source code is licensed under the ISC license.
124
- * See the LICENSE file in the root directory of this source tree.
125
- */
126
- const De = [
127
- ["path", { d: "M4.9 19.1C1 15.2 1 8.8 4.9 4.9", key: "1vaf9d" }],
128
- ["path", { d: "M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5", key: "u1ii0m" }],
129
- ["circle", { cx: "12", cy: "12", r: "2", key: "1c9p78" }],
130
- ["path", { d: "M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5", key: "1j5fej" }],
131
- ["path", { d: "M19.1 4.9C23 8.8 23 15.1 19.1 19", key: "10b0cb" }]
132
- ], Me = T("radio", De);
133
- /**
134
- * @license lucide-react v0.511.0 - ISC
135
- *
136
- * This source code is licensed under the ISC license.
137
- * See the LICENSE file in the root directory of this source tree.
138
- */
139
- const Ee = [
140
- ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
141
- ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
142
- ], Ke = T("x", Ee);
143
- function Re(t) {
144
- const a = [];
145
- if (t.crop && a.push(`crop=${t.crop.w}:${t.crop.h}:${t.crop.x}:${t.crop.y}`), t.targetAspect && t.width !== void 0 && t.height !== void 0) {
146
- const n = t.targetAspect.replace(":", "/");
147
- t.mode === "pad" ? (a.push(`scale=${t.width}:${t.height}:force_original_aspect_ratio=decrease`), a.push(`pad=${t.width}:${t.height}:(ow-iw)/2:(oh-ih)/2`)) : (a.push(`scale=${t.width}:${t.height}:force_original_aspect_ratio=increase`), a.push(`crop=${t.width}:${t.height}`)), a.push(`setdar=${n}`);
148
- }
149
- return t.rotate === 90 ? a.push("transpose=1") : t.rotate === 270 ? a.push("transpose=2") : t.rotate === 180 && a.push("hflip", "vflip"), t.hflip && t.rotate !== 180 && a.push("hflip"), t.vflip && t.rotate !== 180 && a.push("vflip"), a.join(",");
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(",");
150
91
  }
151
- function Te(t, a) {
152
- const n = [];
153
- for (let o = 0; o < t.length; o++) {
154
- if (t[o] === "-vf") {
155
- o++;
156
- continue;
157
- }
158
- const c = t[o];
159
- c !== void 0 && n.push(c);
160
- }
161
- return a.length > 0 && n.push("-vf", a), n;
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;
162
103
  }
163
- const F = "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", q = F + " appearance-none pr-6", B = "text-[11px] uppercase tracking-wider text-foreground-subtle font-medium";
164
- function je({ outputArgs: t, onChange: a }) {
165
- const [n, o] = x(""), [c, s] = x("pad"), [m, l] = x("1920"), [f, u] = x("1080"), [d, p] = x(!1), [v, N] = x("0"), [h, C] = x("0"), [w, A] = x("0"), [S, M] = x("0"), [k, E] = x(0), [K, i] = x(!1), [g, y] = x(!1), z = Re((() => {
166
- const b = { rotate: k, hflip: K, vflip: g };
167
- return n !== "" && (b.targetAspect = n, b.mode = c, b.width = Number(m), b.height = Number(f)), d && (b.crop = { x: Number(v), y: Number(h), w: Number(w), h: Number(S) }), b;
168
- })());
169
- return /* @__PURE__ */ r("div", { className: "space-y-2 rounded border border-border/50 bg-surface-2/30 px-3 py-2", children: [
170
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between", children: [
171
- /* @__PURE__ */ r("span", { className: B, children: [
172
- "Geometry / zoom",
173
- /* @__PURE__ */ e("span", { className: "ml-2 text-[10px] normal-case text-foreground-subtle italic", children: "composes a single -vf into output args" })
174
- ] }),
175
- /* @__PURE__ */ e(
176
- "button",
177
- {
178
- type: "button",
179
- onClick: () => a(Te(t, z)),
180
- 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",
181
- children: "Apply geometry"
182
- }
183
- )
184
- ] }),
185
- /* @__PURE__ */ r("div", { className: "flex flex-wrap items-center gap-2", children: [
186
- /* @__PURE__ */ e("label", { className: B, htmlFor: "geom-aspect", children: "Aspect" }),
187
- /* @__PURE__ */ r(
188
- "select",
189
- {
190
- id: "geom-aspect",
191
- value: n,
192
- onChange: (b) => o(b.target.value),
193
- className: q + " min-w-[90px]",
194
- children: [
195
- /* @__PURE__ */ e("option", { value: "", children: "none" }),
196
- /* @__PURE__ */ e("option", { value: "16:9", children: "16:9" }),
197
- /* @__PURE__ */ e("option", { value: "4:3", children: "4:3" }),
198
- /* @__PURE__ */ e("option", { value: "1:1", children: "1:1" })
199
- ]
200
- }
201
- ),
202
- n !== "" && /* @__PURE__ */ r($, { children: [
203
- /* @__PURE__ */ r(
204
- "select",
205
- {
206
- "aria-label": "Aspect mode",
207
- value: c,
208
- onChange: (b) => s(b.target.value),
209
- className: q + " min-w-[80px]",
210
- children: [
211
- /* @__PURE__ */ e("option", { value: "pad", children: "pad" }),
212
- /* @__PURE__ */ e("option", { value: "crop", children: "crop" })
213
- ]
214
- }
215
- ),
216
- /* @__PURE__ */ e(
217
- "input",
218
- {
219
- type: "number",
220
- "aria-label": "Aspect width",
221
- value: m,
222
- onChange: (b) => l(b.target.value),
223
- className: F + " w-20 text-right"
224
- }
225
- ),
226
- /* @__PURE__ */ e("span", { className: "text-[11px] text-foreground-subtle", children: "×" }),
227
- /* @__PURE__ */ e(
228
- "input",
229
- {
230
- type: "number",
231
- "aria-label": "Aspect height",
232
- value: f,
233
- onChange: (b) => u(b.target.value),
234
- className: F + " w-20 text-right"
235
- }
236
- )
237
- ] })
238
- ] }),
239
- /* @__PURE__ */ r("div", { className: "flex flex-wrap items-center gap-2", children: [
240
- /* @__PURE__ */ r("label", { className: B + " inline-flex items-center gap-1", children: [
241
- /* @__PURE__ */ e("input", { type: "checkbox", checked: d, onChange: (b) => p(b.target.checked) }),
242
- "Crop / zoom"
243
- ] }),
244
- d && /* @__PURE__ */ r($, { children: [
245
- /* @__PURE__ */ e("input", { type: "number", "aria-label": "Crop x", value: v, onChange: (b) => N(b.target.value), className: F + " w-16 text-right", placeholder: "x" }),
246
- /* @__PURE__ */ e("input", { type: "number", "aria-label": "Crop y", value: h, onChange: (b) => C(b.target.value), className: F + " w-16 text-right", placeholder: "y" }),
247
- /* @__PURE__ */ e("input", { type: "number", "aria-label": "Crop width", value: w, onChange: (b) => A(b.target.value), className: F + " w-20 text-right", placeholder: "w" }),
248
- /* @__PURE__ */ e("input", { type: "number", "aria-label": "Crop height", value: S, onChange: (b) => M(b.target.value), className: F + " w-20 text-right", placeholder: "h" })
249
- ] })
250
- ] }),
251
- /* @__PURE__ */ r("div", { className: "flex flex-wrap items-center gap-2", children: [
252
- /* @__PURE__ */ e("label", { className: B, htmlFor: "geom-rotate", children: "Rotate" }),
253
- /* @__PURE__ */ r(
254
- "select",
255
- {
256
- id: "geom-rotate",
257
- value: String(k),
258
- onChange: (b) => E(Number(b.target.value)),
259
- className: q + " min-w-[80px]",
260
- children: [
261
- /* @__PURE__ */ e("option", { value: "0", children: "0°" }),
262
- /* @__PURE__ */ e("option", { value: "90", children: "90°" }),
263
- /* @__PURE__ */ e("option", { value: "180", children: "180°" }),
264
- /* @__PURE__ */ e("option", { value: "270", children: "270°" })
265
- ]
266
- }
267
- ),
268
- /* @__PURE__ */ r("label", { className: B + " inline-flex items-center gap-1", children: [
269
- /* @__PURE__ */ e("input", { type: "checkbox", checked: K, onChange: (b) => i(b.target.checked) }),
270
- "hflip"
271
- ] }),
272
- /* @__PURE__ */ r("label", { className: B + " inline-flex items-center gap-1", children: [
273
- /* @__PURE__ */ e("input", { type: "checkbox", checked: g, onChange: (b) => y(b.target.checked) }),
274
- "vflip"
275
- ] })
276
- ] }),
277
- /* @__PURE__ */ r("div", { className: "font-mono text-[10px] text-foreground-subtle break-all", children: [
278
- "-vf ",
279
- z.length > 0 ? z : /* @__PURE__ */ e("span", { className: "italic", children: "(empty)" })
280
- ] })
281
- ] });
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
+ });
282
307
  }
283
- const Le = [
284
- { group: "Demuxer", label: "-thread_queue_size 1024", args: ["-thread_queue_size", "1024"], description: "Larger input packet queue (helps with high-bitrate sources)" },
285
- { group: "Demuxer", label: "-fflags +genpts", args: ["-fflags", "+genpts"], description: "Generate PTS when the source lacks them" },
286
- { group: "Demuxer", label: "-re", args: ["-re"], description: "Read input at native frame rate (file replay)" },
287
- { group: "Demuxer", label: "-probesize 32", args: ["-probesize", "32"], description: "Minimal probe size — faster start" },
288
- { group: "Demuxer", label: "-analyzeduration 0", args: ["-analyzeduration", "0"], description: "Skip stream analysis — faster start" },
289
- { group: "RTSP", label: "-rtsp_transport tcp", args: ["-rtsp_transport", "tcp"], description: "Force TCP transport for RTSP source" },
290
- { group: "RTSP", label: "-stimeout 5000000", args: ["-stimeout", "5000000"], description: "Socket I/O timeout (microseconds, 5s)" }
291
- ], He = [
292
- { group: "Muxer", label: "-flush_packets 1", args: ["-flush_packets", "1"], description: "Flush each packet immediately" },
293
- { group: "Muxer", label: "-movflags +faststart", args: ["-movflags", "+faststart"], description: "Move MOOV atom to front (MP4)" },
294
- { group: "Bitstream", label: "-bsf:v h264_mp4toannexb", args: ["-bsf:v", "h264_mp4toannexb"], description: "Convert MP4-format H.264 to Annex-B" },
295
- { group: "Bitstream", label: "-bsf:v hevc_mp4toannexb", args: ["-bsf:v", "hevc_mp4toannexb"], description: "Convert MP4-format HEVC to Annex-B" },
296
- { group: "x264", label: "-x264-params keyint_min=15", args: ["-x264-params", "keyint_min=15"], description: "Force minimum keyframe interval to 15 frames" },
297
- { group: "x264", label: "-x264-params scenecut=0", args: ["-x264-params", "scenecut=0"], description: "Disable scene-change keyframes (predictable GOP)" },
298
- { group: "x264", label: "-x264-params nal-hrd=cbr", args: ["-x264-params", "nal-hrd=cbr"], description: "Force CBR HRD signalling (HomeKit-friendly)" },
299
- { group: "x264", label: "-aq-mode 3", args: ["-aq-mode", "3"], description: "Auto-variance adaptive quantisation (mode 3)" },
300
- { group: "x265", label: "-x265-params keyint=30", args: ["-x265-params", "keyint=30"], description: "Force maximum keyframe interval to 30 frames" },
301
- { group: "x265", label: "-x265-params no-scenecut=1", args: ["-x265-params", "no-scenecut=1"], description: "Disable scene-change keyframes" },
302
- { group: "Global", label: "-fps_mode passthrough", args: ["-fps_mode", "passthrough"], description: "Preserve source framerate exactly" },
303
- { group: "Global", label: "-copyts", args: ["-copyts"], description: "Preserve source timestamps" }
304
- ], Ue = { video: { codec: "copy" }, audio: "passthrough" }, O = "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", Z = O + " appearance-none pr-6", J = "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", I = "flex items-center justify-between gap-3 py-1.5", _ = "text-[11px] uppercase tracking-wider text-foreground-subtle font-medium", j = "rounded-lg border border-border bg-surface overflow-hidden", G = "border-b border-border px-3 py-1.5 flex items-center justify-between bg-surface-hover/30", L = "text-[11px] font-semibold text-foreground uppercase tracking-wider";
305
- function ze({ config: t, value: a, onSave: n }) {
306
- const [o, c] = x(!1), s = a ?? Ue, [m, l] = x(() => (s.inputArgs ?? []).join(`
307
- `)), [f, u] = x(() => (s.outputArgs ?? []).join(`
308
- `)), d = W(s);
309
- d.current !== s && (d.current = s, l((s.inputArgs ?? []).join(`
310
- `)), u((s.outputArgs ?? []).join(`
311
- `)));
312
- const p = (i) => {
313
- n(i(s));
314
- }, v = (i) => p((g) => ({ ...g, video: { ...g.video, codec: i } })), N = (i) => p((g) => ({ ...g, video: { ...g.video, width: i } })), h = (i) => p((g) => ({ ...g, video: { ...g.video, height: i } })), C = (i) => p((g) => ({ ...g, video: { ...g.video, fps: i } })), w = (i) => p((g) => ({ ...g, video: { ...g.video, bitrateKbps: i } })), A = () => p((i) => ({ ...i, audio: "passthrough" })), S = (i) => p((g) => ({
315
- ...g,
316
- audio: typeof g.audio == "object" ? { ...g.audio, codec: i } : { codec: i }
317
- })), M = (i) => p((g) => ({
318
- ...g,
319
- audio: typeof g.audio == "object" ? { ...g.audio, bitrateKbps: i } : { codec: "opus", bitrateKbps: i }
320
- })), k = (i) => p((g) => ({ ...g, inputArgs: i.split(`
321
- `).map((y) => y.trim()).filter((y) => y.length > 0) })), E = (i) => p((g) => ({ ...g, outputArgs: i.split(`
322
- `).map((y) => y.trim()).filter((y) => y.length > 0) })), K = (i, g) => {
323
- const y = g.args.join(" ");
324
- if (i === "input") {
325
- const P = m.length === 0 ? y : `${m}
326
- ${y}`;
327
- l(P), k(P);
328
- } else {
329
- const P = f.length === 0 ? y : `${f}
330
- ${y}`;
331
- u(P), E(P);
332
- }
333
- };
334
- return /* @__PURE__ */ r("div", { className: "space-y-3", children: [
335
- t.sourceParams !== void 0 && /* @__PURE__ */ r("div", { className: j, children: [
336
- /* @__PURE__ */ r("div", { className: G, children: [
337
- /* @__PURE__ */ e("h3", { className: L, children: "Source (probed)" }),
338
- /* @__PURE__ */ e("span", { className: "text-[10px] text-foreground-subtle italic", children: "From the publisher" })
339
- ] }),
340
- /* @__PURE__ */ e("div", { className: "px-3 py-2 flex flex-wrap gap-1.5", children: /* @__PURE__ */ e(qe, { profile: t.sourceParams }) })
341
- ] }),
342
- /* @__PURE__ */ e("div", { className: "@container", children: /* @__PURE__ */ r("div", { className: "grid grid-cols-1 @[480px]:grid-cols-2 gap-3", children: [
343
- /* @__PURE__ */ r("div", { className: j, children: [
344
- /* @__PURE__ */ e("div", { className: G, children: /* @__PURE__ */ e("h3", { className: L, children: "Video" }) }),
345
- /* @__PURE__ */ r("div", { className: "px-3 py-2 divide-y divide-border/30", children: [
346
- /* @__PURE__ */ r("div", { className: I, children: [
347
- /* @__PURE__ */ e("label", { htmlFor: `${t.fieldKey}-video-codec`, className: _, children: "Codec" }),
348
- /* @__PURE__ */ r(
349
- "select",
350
- {
351
- id: `${t.fieldKey}-video-codec`,
352
- value: s.video.codec,
353
- onChange: (i) => v(i.target.value),
354
- className: Z + " min-w-[120px]",
355
- children: [
356
- /* @__PURE__ */ e("option", { value: "h264", children: "h264" }),
357
- /* @__PURE__ */ e("option", { value: "h265", children: "h265" }),
358
- /* @__PURE__ */ e("option", { value: "copy", children: "copy (passthrough)" })
359
- ]
360
- }
361
- )
362
- ] }),
363
- s.video.codec !== "copy" && /* @__PURE__ */ r($, { children: [
364
- /* @__PURE__ */ r("div", { className: I, children: [
365
- /* @__PURE__ */ e("label", { htmlFor: `${t.fieldKey}-video-width`, className: _, children: "Width" }),
366
- /* @__PURE__ */ e(
367
- "input",
368
- {
369
- id: `${t.fieldKey}-video-width`,
370
- type: "number",
371
- "aria-label": "Width",
372
- value: s.video.width ?? "",
373
- onChange: (i) => N(Number(i.target.value)),
374
- className: O + " w-24 text-right"
375
- }
376
- )
377
- ] }),
378
- /* @__PURE__ */ r("div", { className: I, children: [
379
- /* @__PURE__ */ e("label", { htmlFor: `${t.fieldKey}-video-height`, className: _, children: "Height" }),
380
- /* @__PURE__ */ e(
381
- "input",
382
- {
383
- id: `${t.fieldKey}-video-height`,
384
- type: "number",
385
- value: s.video.height ?? "",
386
- onChange: (i) => h(Number(i.target.value)),
387
- className: O + " w-24 text-right"
388
- }
389
- )
390
- ] }),
391
- /* @__PURE__ */ r("div", { className: I, children: [
392
- /* @__PURE__ */ e("label", { htmlFor: `${t.fieldKey}-video-fps`, className: _, children: "FPS" }),
393
- /* @__PURE__ */ e(
394
- "input",
395
- {
396
- id: `${t.fieldKey}-video-fps`,
397
- type: "number",
398
- value: s.video.fps ?? "",
399
- onChange: (i) => C(Number(i.target.value)),
400
- className: O + " w-24 text-right"
401
- }
402
- )
403
- ] }),
404
- /* @__PURE__ */ r("div", { className: I, children: [
405
- /* @__PURE__ */ e("label", { htmlFor: `${t.fieldKey}-video-bitrate`, className: _, children: "Bitrate (kbps)" }),
406
- /* @__PURE__ */ e(
407
- "input",
408
- {
409
- id: `${t.fieldKey}-video-bitrate`,
410
- type: "number",
411
- value: s.video.bitrateKbps ?? "",
412
- onChange: (i) => w(Number(i.target.value)),
413
- className: O + " w-24 text-right"
414
- }
415
- )
416
- ] })
417
- ] })
418
- ] })
419
- ] }),
420
- /* @__PURE__ */ r("div", { className: j, children: [
421
- /* @__PURE__ */ e("div", { className: G, children: /* @__PURE__ */ e("h3", { className: L, children: "Audio" }) }),
422
- /* @__PURE__ */ e("div", { className: "px-3 py-2", children: s.audio === "passthrough" ? /* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-3", children: [
423
- /* @__PURE__ */ e("span", { className: "text-[11px] text-foreground-subtle italic", children: "Source audio forwarded without re-encode." }),
424
- /* @__PURE__ */ e(
425
- "button",
426
- {
427
- type: "button",
428
- onClick: () => S("opus"),
429
- className: "rounded-md border border-border bg-surface-hover px-2 py-1 text-[11px] text-foreground hover:bg-surface-hover/70 transition-colors",
430
- children: "Switch to custom encode"
431
- }
432
- )
433
- ] }) : /* @__PURE__ */ r("div", { className: "divide-y divide-border/30", children: [
434
- /* @__PURE__ */ r("div", { className: I, children: [
435
- /* @__PURE__ */ e("label", { htmlFor: `${t.fieldKey}-audio-codec`, className: _, children: "Codec" }),
436
- /* @__PURE__ */ r(
437
- "select",
438
- {
439
- id: `${t.fieldKey}-audio-codec`,
440
- value: s.audio.codec,
441
- onChange: (i) => S(i.target.value),
442
- className: Z + " min-w-[120px]",
443
- children: [
444
- /* @__PURE__ */ e("option", { value: "opus", children: "opus" }),
445
- /* @__PURE__ */ e("option", { value: "aac", children: "aac" }),
446
- /* @__PURE__ */ e("option", { value: "pcmu", children: "pcmu" }),
447
- /* @__PURE__ */ e("option", { value: "pcma", children: "pcma" }),
448
- /* @__PURE__ */ e("option", { value: "copy", children: "copy (passthrough)" })
449
- ]
450
- }
451
- )
452
- ] }),
453
- /* @__PURE__ */ r("div", { className: I, children: [
454
- /* @__PURE__ */ e("label", { htmlFor: `${t.fieldKey}-audio-bitrate`, className: _, children: "Bitrate (kbps)" }),
455
- /* @__PURE__ */ e(
456
- "input",
457
- {
458
- id: `${t.fieldKey}-audio-bitrate`,
459
- type: "number",
460
- value: s.audio.bitrateKbps ?? "",
461
- onChange: (i) => M(Number(i.target.value)),
462
- className: O + " w-24 text-right"
463
- }
464
- )
465
- ] }),
466
- /* @__PURE__ */ e("div", { className: "pt-2", children: /* @__PURE__ */ e(
467
- "button",
468
- {
469
- type: "button",
470
- onClick: A,
471
- className: "text-[11px] text-foreground-subtle hover:text-foreground underline-offset-2 hover:underline",
472
- children: "Switch back to passthrough"
473
- }
474
- ) })
475
- ] }) })
476
- ] })
477
- ] }) }),
478
- /* @__PURE__ */ r("div", { className: j, children: [
479
- /* @__PURE__ */ r(
480
- "button",
481
- {
482
- type: "button",
483
- onClick: () => c((i) => !i),
484
- className: "w-full px-3 py-1.5 flex items-center justify-between bg-surface-hover/30 hover:bg-surface-hover transition-colors",
485
- children: [
486
- /* @__PURE__ */ r("span", { className: "inline-flex items-center gap-1.5 " + L, children: [
487
- o ? /* @__PURE__ */ e(X, { className: "h-3 w-3" }) : /* @__PURE__ */ e(Q, { className: "h-3 w-3" }),
488
- "Advanced raw ffmpeg args"
489
- ] }),
490
- /* @__PURE__ */ r("span", { className: "text-[10px] text-foreground-subtle italic", children: [
491
- (s.inputArgs?.length ?? 0) + (s.outputArgs?.length ?? 0),
492
- " args"
493
- ] })
494
- ]
495
- }
496
- ),
497
- o && /* @__PURE__ */ r("div", { className: "px-3 py-2 space-y-3 border-t border-border/50", children: [
498
- /* @__PURE__ */ r("div", { className: "space-y-1.5", children: [
499
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between", children: [
500
- /* @__PURE__ */ r("label", { htmlFor: `${t.fieldKey}-input-args`, className: _, children: [
501
- "Input args",
502
- /* @__PURE__ */ e("span", { className: "ml-2 text-[10px] normal-case text-foreground-subtle italic", children: "one per line · inserted between globals and -i" })
503
- ] }),
504
- /* @__PURE__ */ e(
505
- ee,
506
- {
507
- id: `${t.fieldKey}-input-picker`,
508
- disabled: !1,
509
- catalogue: Le,
510
- onPick: (i) => K("input", i)
511
- }
512
- )
513
- ] }),
514
- /* @__PURE__ */ e(
515
- "textarea",
516
- {
517
- id: `${t.fieldKey}-input-args`,
518
- value: m,
519
- onChange: (i) => l(i.target.value),
520
- onBlur: (i) => k(i.target.value),
521
- placeholder: "-thread_queue_size 1024",
522
- className: J
523
- }
524
- )
525
- ] }),
526
- /* @__PURE__ */ e(
527
- je,
528
- {
529
- outputArgs: s.outputArgs ?? [],
530
- onChange: (i) => {
531
- u(i.join(`
532
- `)), E(i.join(`
533
- `));
534
- }
535
- }
536
- ),
537
- /* @__PURE__ */ r("div", { className: "space-y-1.5", children: [
538
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between", children: [
539
- /* @__PURE__ */ r("label", { htmlFor: `${t.fieldKey}-output-args`, className: _, children: [
540
- "Output args",
541
- /* @__PURE__ */ e("span", { className: "ml-2 text-[10px] normal-case text-foreground-subtle italic", children: "one per line · inserted before the final muxer" })
542
- ] }),
543
- /* @__PURE__ */ e(
544
- ee,
545
- {
546
- id: `${t.fieldKey}-output-picker`,
547
- disabled: !1,
548
- catalogue: He,
549
- onPick: (i) => K("output", i)
550
- }
551
- )
552
- ] }),
553
- /* @__PURE__ */ e(
554
- "textarea",
555
- {
556
- id: `${t.fieldKey}-output-args`,
557
- value: f,
558
- onChange: (i) => u(i.target.value),
559
- onBlur: (i) => E(i.target.value),
560
- placeholder: "-bsf:v h264_mp4toannexb",
561
- className: J
562
- }
563
- )
564
- ] })
565
- ] })
566
- ] })
567
- ] });
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
+ });
568
785
  }
569
- function qe({ profile: t }) {
570
- const a = "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: o } = t, c = n.width !== void 0 && n.height !== void 0 ? `${n.width}×${n.height}` : void 0;
571
- return /* @__PURE__ */ r($, { children: [
572
- /* @__PURE__ */ r("span", { className: a, children: [
573
- /* @__PURE__ */ e("span", { className: "opacity-60", children: "codec" }),
574
- n.codec
575
- ] }),
576
- c !== void 0 && /* @__PURE__ */ r("span", { className: a, children: [
577
- /* @__PURE__ */ e("span", { className: "opacity-60", children: "res" }),
578
- c
579
- ] }),
580
- n.fps !== void 0 && /* @__PURE__ */ r("span", { className: a, children: [
581
- /* @__PURE__ */ e("span", { className: "opacity-60", children: "fps" }),
582
- n.fps
583
- ] }),
584
- n.bitrateKbps !== void 0 && /* @__PURE__ */ r("span", { className: a, children: [
585
- /* @__PURE__ */ e("span", { className: "opacity-60", children: "bitrate" }),
586
- n.bitrateKbps,
587
- "k"
588
- ] }),
589
- o === "passthrough" ? /* @__PURE__ */ r("span", { className: a, children: [
590
- /* @__PURE__ */ e("span", { className: "opacity-60", children: "audio" }),
591
- "passthrough"
592
- ] }) : /* @__PURE__ */ r($, { children: [
593
- /* @__PURE__ */ r("span", { className: a, children: [
594
- /* @__PURE__ */ e("span", { className: "opacity-60", children: "audio" }),
595
- o.codec
596
- ] }),
597
- o.bitrateKbps !== void 0 && /* @__PURE__ */ r("span", { className: a, children: [
598
- /* @__PURE__ */ e("span", { className: "opacity-60", children: "a-bitrate" }),
599
- o.bitrateKbps,
600
- "k"
601
- ] }),
602
- o.sampleRateHz !== void 0 && /* @__PURE__ */ r("span", { className: a, children: [
603
- /* @__PURE__ */ e("span", { className: "opacity-60", children: "a-sr" }),
604
- o.sampleRateHz,
605
- "Hz"
606
- ] }),
607
- o.channels !== void 0 && /* @__PURE__ */ r("span", { className: a, children: [
608
- /* @__PURE__ */ e("span", { className: "opacity-60", children: "a-ch" }),
609
- o.channels
610
- ] })
611
- ] })
612
- ] });
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
+ ] });
613
866
  }
614
- function Ge(t) {
615
- const a = t.config ?? {}, n = he(), [o, c] = x(() => a.initialValue), s = R((f) => {
616
- if (c(f), t.deviceId === void 0) return;
617
- const u = a.writerCapName, d = a.writerAddonId, p = a.fieldKey;
618
- if (u === void 0 || d === void 0 || p === void 0) {
619
- console.warn(
620
- `[ffmpeg-params] widgetConfig is missing writerCapName/writerAddonId/fieldKey — field ${p ?? "(unknown)"} cannot be saved. Fix the contribution builder.`
621
- );
622
- return;
623
- }
624
- n.mutate({
625
- deviceId: t.deviceId,
626
- writerCapName: u,
627
- writerAddonId: d,
628
- key: p,
629
- value: f ?? null
630
- });
631
- }, [
632
- t.deviceId,
633
- a.fieldKey,
634
- a.writerCapName,
635
- a.writerAddonId,
636
- n
637
- ]);
638
- if (t.deviceId === void 0)
639
- return /* @__PURE__ */ e("div", { className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning", children: "ffmpeg-params: no deviceId in widget context — this widget only renders inside a device tab." });
640
- const m = a.fieldKey;
641
- if (m === void 0 || m.length === 0)
642
- return /* @__PURE__ */ e("div", { className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning", children: "ffmpeg-params: widgetConfig.fieldKey is required — fix the contribution builder." });
643
- const l = { ...a, fieldKey: m };
644
- return /* @__PURE__ */ e(ze, { config: l, value: o, onSave: s });
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
+ });
645
905
  }
646
- function ee({ id: t, disabled: a, catalogue: n, onPick: o }) {
647
- const [c, s] = x(!1), m = me(() => {
648
- const l = /* @__PURE__ */ new Map();
649
- for (const f of n) {
650
- const u = l.get(f.group) ?? [];
651
- u.push(f), l.set(f.group, u);
652
- }
653
- return l;
654
- }, [n]);
655
- return /* @__PURE__ */ r("div", { className: "relative", children: [
656
- /* @__PURE__ */ r(
657
- "button",
658
- {
659
- id: t,
660
- type: "button",
661
- disabled: a,
662
- onClick: () => s((l) => !l),
663
- 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",
664
- children: [
665
- /* @__PURE__ */ e(Oe, { className: "h-3 w-3" }),
666
- "Add flag…"
667
- ]
668
- }
669
- ),
670
- c && !a && /* @__PURE__ */ r($, { children: [
671
- /* @__PURE__ */ e("div", { className: "fixed inset-0 z-40", onClick: () => s(!1), "aria-hidden": "true" }),
672
- /* @__PURE__ */ e(
673
- "div",
674
- {
675
- 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",
676
- role: "menu",
677
- children: Array.from(m.entries()).map(([l, f]) => /* @__PURE__ */ r("div", { className: "border-b border-border/30 last:border-b-0", children: [
678
- /* @__PURE__ */ e("div", { className: "sticky top-0 bg-surface-hover/80 backdrop-blur px-2 py-1 text-[9px] font-semibold uppercase tracking-wider text-foreground-subtle", children: l }),
679
- f.map((u) => /* @__PURE__ */ r(
680
- "button",
681
- {
682
- type: "button",
683
- onClick: () => {
684
- o(u), s(!1);
685
- },
686
- className: "w-full text-left px-2 py-1.5 hover:bg-surface-hover transition-colors group",
687
- children: [
688
- /* @__PURE__ */ e("div", { className: "font-mono text-[11px] text-foreground", children: u.label }),
689
- u.description !== void 0 && /* @__PURE__ */ e("div", { className: "text-[10px] text-foreground-subtle leading-snug mt-0.5", children: u.description })
690
- ]
691
- },
692
- u.label
693
- ))
694
- ] }, l))
695
- }
696
- )
697
- ] })
698
- ] });
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
+ });
699
953
  }
700
- const te = 24;
701
- function Ve(t) {
702
- return /\bEdg\b|\bEdgA\b|\bEdgiOS\b|Edge\//.test(t) ? "Edge" : /\bOPR\b|Opera/.test(t) ? "Opera" : /Firefox\/|\bFxiOS\b/.test(t) ? "Firefox" : /Chrome\/|\bCriOS\b/.test(t) ? "Chrome" : /Safari\//.test(t) ? "Safari" : null;
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;
703
959
  }
704
- function We(t) {
705
- return /iPhone|iPad|iPod|\biOS\b|CriOS|FxiOS/.test(t) ? "iOS" : /Mac OS X|Macintosh/.test(t) ? "macOS" : /Windows/.test(t) ? "Windows" : /Android/.test(t) ? "Android" : /Linux/.test(t) ? "Linux" : null;
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;
706
962
  }
707
- function Xe(t) {
708
- const a = t.trim();
709
- if (a.length === 0) return "";
710
- const n = Ve(a), o = We(a);
711
- return n && o ? `${n}/${o}` : n || o || (a.length > te ? `${a.slice(0, te)}…` : a);
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);
712
968
  }
713
- function Qe(t) {
714
- const a = Math.floor(t / 1e3);
715
- if (a < 60) return `${a}s`;
716
- const n = Math.floor(a / 60);
717
- return n < 60 ? `${n}m` : `${Math.floor(n / 60)}h ${n % 60}m`;
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`;
718
976
  }
719
- const re = {
720
- high: "High",
721
- mid: "Mid",
722
- low: "Low"
723
- }, se = ["high", "mid", "low"], Ye = {
724
- alexa: "bg-blue-500/15 text-blue-400",
725
- homekit: "bg-purple-500/15 text-purple-400",
726
- "webrtc-browser": "bg-emerald-500/15 text-emerald-400",
727
- "webrtc-mobile": "bg-emerald-500/15 text-emerald-400",
728
- "webrtc-whep": "bg-emerald-500/15 text-emerald-400",
729
- "rtsp-listen": "bg-warning/15 text-warning",
730
- "derived-broker": "bg-amber-500/15 text-amber-400",
731
- recording: "bg-rose-500/15 text-rose-400",
732
- pipeline: "bg-cyan-500/15 text-cyan-400",
733
- snapshot: "bg-cyan-500/15 text-cyan-400",
734
- warmup: "bg-foreground-subtle/10 text-foreground-subtle",
735
- unknown: "bg-foreground-subtle/10 text-foreground-subtle"
736
- }, de = {
737
- alexa: "ALEXA",
738
- homekit: "HOMEKIT",
739
- "webrtc-browser": "BROWSER",
740
- "webrtc-mobile": "MOBILE",
741
- "webrtc-whep": "WHEP",
742
- "rtsp-listen": "RTSP",
743
- "derived-broker": "DERIVED",
744
- recording: "RECORD",
745
- pipeline: "PIPELINE",
746
- snapshot: "SNAP",
747
- warmup: "WARMUP",
748
- unknown: ""
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: "—"
749
1011
  };
750
- function Ze(t) {
751
- return de[t] ?? t.toUpperCase().slice(0, 8);
1012
+ function he(e) {
1013
+ return G[e] ?? e.toUpperCase().slice(0, 8);
752
1014
  }
753
- function Je(t) {
754
- return de[t] ?? t;
1015
+ function ge(e) {
1016
+ return G[e] ?? e;
755
1017
  }
756
- function et(t) {
757
- const a = t.config ?? {};
758
- return t.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(
759
- tt,
760
- {
761
- deviceId: t.deviceId,
762
- title: a.title,
763
- variant: a.variant,
764
- hideEmpty: a.hideEmpty
765
- }
766
- );
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
+ });
767
1029
  }
768
- function tt({
769
- deviceId: t,
770
- title: a = "Stream Brokers",
771
- variant: n = "full",
772
- hideEmpty: o = !1
773
- }) {
774
- ie(
775
- ["streamBroker", "listAllProfileSlots"],
776
- [
777
- "device.streams-registered",
778
- "device.streams-unregistered",
779
- "device.registered",
780
- "device.unregistered"
781
- ]
782
- );
783
- const { data: c } = fe(
784
- void 0,
785
- { staleTime: 3e4 }
786
- ), s = (c ?? []).filter((h) => h.deviceId === t && h.sourceCamStreamId !== null).slice().sort((h, C) => se.indexOf(h.profile) - se.indexOf(C.profile)), m = ge(), l = be(m.trpcClient, t), { data: f } = ye({
787
- queryKey: ["device", t, "cameraStreams.getCameraStreams"],
788
- queryFn: () => l?.cameraStreams?.getCameraStreams({}) ?? [],
789
- enabled: !!l,
790
- staleTime: 3e4
791
- }), u = /* @__PURE__ */ new Map();
792
- for (const h of f ?? []) u.set(h.camStreamId, h);
793
- const d = new Set(
794
- s.map((h) => h.sourceCamStreamId).filter((h) => h !== null)
795
- ), p = (f ?? []).filter(
796
- (h) => !d.has(h.camStreamId)
797
- ), v = s.length > 0, N = p.length > 0;
798
- return o && !v && !N ? null : n === "compact" ? v ? /* @__PURE__ */ e("div", { className: "divide-y divide-border/30", children: s.map((h) => /* @__PURE__ */ e(
799
- ne,
800
- {
801
- slot: h,
802
- camStreams: u,
803
- compact: !0
804
- },
805
- h.brokerId
806
- )) }) : /* @__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: [
807
- /* @__PURE__ */ r("div", { className: "border-b border-border px-4 py-2 flex items-center justify-between", children: [
808
- /* @__PURE__ */ e("h2", { className: "text-xs font-semibold text-foreground uppercase tracking-wider", children: a }),
809
- v && /* @__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: [
810
- s.length,
811
- " assigned"
812
- ] })
813
- ] }),
814
- v ? /* @__PURE__ */ e("div", { className: "divide-y divide-border/30", children: s.map((h) => /* @__PURE__ */ e(
815
- ne,
816
- {
817
- slot: h,
818
- camStreams: u,
819
- compact: !1
820
- },
821
- h.brokerId
822
- )) }) : /* @__PURE__ */ r("div", { className: "px-4 py-6 flex flex-col items-center text-center text-foreground-subtle", children: [
823
- /* @__PURE__ */ e(Me, { className: "h-5 w-5 mb-2 opacity-30" }),
824
- /* @__PURE__ */ e("p", { className: "text-xs", children: "No profile slots assigned for this device" })
825
- ] }),
826
- N && /* @__PURE__ */ e(
827
- rt,
828
- {
829
- deviceId: t,
830
- camStreamIds: p.map((h) => h.camStreamId),
831
- camStreams: u
832
- }
833
- )
834
- ] });
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
+ });
835
1093
  }
836
- function rt({
837
- deviceId: t,
838
- camStreamIds: a,
839
- camStreams: n
840
- }) {
841
- const [o, c] = x(!1);
842
- return /* @__PURE__ */ r("div", { className: "border-t border-border/50", children: [
843
- /* @__PURE__ */ r(
844
- "button",
845
- {
846
- type: "button",
847
- onClick: () => c((s) => !s),
848
- className: "w-full px-4 py-1.5 flex items-center justify-between bg-surface-hover/30 hover:bg-surface-hover transition-colors",
849
- children: [
850
- /* @__PURE__ */ r("span", { className: "inline-flex items-center gap-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle", children: [
851
- o ? /* @__PURE__ */ e(X, { className: "h-3 w-3" }) : /* @__PURE__ */ e(Q, { className: "h-3 w-3" }),
852
- "Other active streams"
853
- ] }),
854
- /* @__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: a.length })
855
- ]
856
- }
857
- ),
858
- o && /* @__PURE__ */ e("div", { className: "divide-y divide-border/30", children: a.map((s) => /* @__PURE__ */ e(
859
- st,
860
- {
861
- deviceId: t,
862
- camStreamId: s,
863
- camStreams: n
864
- },
865
- s
866
- )) })
867
- ] });
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
+ });
868
1118
  }
869
- function st({ deviceId: t, camStreamId: a, camStreams: n }) {
870
- const o = Ce(t, a), s = le("stream-broker.metrics-snapshot", (f) => f.brokerId === o)?.stats, m = n.get(a), l = s?.status === "streaming";
871
- return /* @__PURE__ */ r("div", { className: "px-4 py-2", children: [
872
- /* @__PURE__ */ e("div", { className: "flex items-center justify-between mb-1", children: /* @__PURE__ */ r("div", { className: "flex items-center gap-1.5", children: [
873
- /* @__PURE__ */ e(
874
- "span",
875
- {
876
- className: `h-1.5 w-1.5 rounded-full ${l ? "bg-success" : "bg-foreground-subtle/40"}`
877
- }
878
- ),
879
- /* @__PURE__ */ e("span", { className: "text-[11px] font-medium text-foreground", children: m?.label ?? a }),
880
- m?.resolution && /* @__PURE__ */ r("span", { className: "text-[10px] text-foreground-subtle", children: [
881
- m.resolution.width,
882
- "×",
883
- m.resolution.height
884
- ] }),
885
- /* @__PURE__ */ e("span", { className: `text-[10px] ${l ? "text-success" : "text-foreground-subtle"}`, children: s?.status ?? "idle" })
886
- ] }) }),
887
- s && l && /* @__PURE__ */ r("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-[10px]", children: [
888
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
889
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "FPS:" }),
890
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.inputFps.toFixed(1) })
891
- ] }),
892
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
893
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Bitrate:" }),
894
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.bitrateKbps >= 1e3 ? `${(s.bitrateKbps / 1e3).toFixed(1)} Mbps` : `${s.bitrateKbps} kbps` })
895
- ] }),
896
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
897
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Codec:" }),
898
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.codec?.toUpperCase() ?? "—" })
899
- ] }),
900
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
901
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Pkts:" }),
902
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.packetCount > 1e3 ? `${(s.packetCount / 1e3).toFixed(1)}k` : s.packetCount })
903
- ] })
904
- ] })
905
- ] });
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
+ });
906
1193
  }
907
- function ae(t, a) {
908
- const n = (o) => {
909
- if (!o || typeof o != "object") return;
910
- const c = o;
911
- if (typeof c.key == "string" && c.key === a && "value" in c) return c.value;
912
- if (c.type === "group" && Array.isArray(c.fields))
913
- for (const s of c.fields) {
914
- const m = n(s);
915
- if (m !== void 0) return m;
916
- }
917
- else if (c.type === "sub-tabs" && Array.isArray(c.tabs)) {
918
- for (const s of c.tabs)
919
- if (Array.isArray(s.fields))
920
- for (const m of s.fields) {
921
- const l = n(m);
922
- if (l !== void 0) return l;
923
- }
924
- }
925
- };
926
- for (const o of t?.sections ?? [])
927
- if (Array.isArray(o.fields))
928
- for (const c of o.fields) {
929
- const s = n(c);
930
- if (s !== void 0) return s;
931
- }
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
+ }
932
1214
  }
933
- function ne({ slot: t, camStreams: a, compact: n }) {
934
- const o = ke(), s = le("stream-broker.metrics-snapshot", (k) => k.brokerId === t.brokerId)?.stats;
935
- ie(["streamBroker", "listClients"], ["stream-broker.metrics-snapshot"]);
936
- const { data: m } = xe(
937
- { brokerId: t.brokerId },
938
- { enabled: s?.status === "streaming", staleTime: 2e3 }
939
- ), { data: l } = ve(
940
- { deviceId: t.deviceId },
941
- { staleTime: 15e3 }
942
- ), f = t.sourceCamStreamId ?? t.profile, u = !!(ae(l, `preBufferEnabled:${f}`) ?? !0), d = ae(l, `preBufferSec:${f}`), p = Ne({
943
- onSuccess: () => {
944
- o.invalidateQueries({ queryKey: [["streamBroker", "getDeviceSettingsContribution"]] });
945
- }
946
- }), v = (k) => {
947
- p.mutate({
948
- deviceId: t.deviceId,
949
- patch: { [`preBufferEnabled:${f}`]: k }
950
- });
951
- }, N = we({
952
- onSuccess: () => {
953
- o.invalidateQueries({ queryKey: [["streamBroker", "listClients"]] });
954
- }
955
- }), h = R(
956
- (k) => {
957
- N.mutate({ brokerId: t.brokerId, ...k });
958
- },
959
- [N, t.brokerId]
960
- ), w = (t.sourceCamStreamId ? a.get(t.sourceCamStreamId) : void 0)?.resolution ?? t.resolution, A = s?.status === "streaming", S = w ? `${re[t.profile]} (${w.width}×${w.height})` : re[t.profile], M = s ? s.encodedSubscribers + s.decodedSubscribers + (s.rtspClients ?? 0) + (s.pipeClients ?? 0) : 0;
961
- return /* @__PURE__ */ r(
962
- "div",
963
- {
964
- className: `@container ${n ? "px-3 py-1.5" : "px-4 py-2"}`,
965
- style: { containerType: "inline-size" },
966
- children: [
967
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between mb-1.5", children: [
968
- /* @__PURE__ */ r("div", { className: "flex items-center gap-1.5", children: [
969
- /* @__PURE__ */ e(
970
- "span",
971
- {
972
- className: `h-1.5 w-1.5 rounded-full ${A ? t.profile === "high" ? "bg-success" : t.profile === "mid" ? "bg-warning" : "bg-foreground-subtle" : "bg-foreground-subtle/40"}`
973
- }
974
- ),
975
- /* @__PURE__ */ e("span", { className: "text-[11px] font-medium text-foreground", children: S }),
976
- /* @__PURE__ */ e("span", { className: `text-[10px] ${A ? "text-success" : "text-foreground-subtle"}`, children: s?.status ?? "loading" }),
977
- t.sourceCamStreamId && /* @__PURE__ */ r("span", { className: "text-[10px] text-foreground-subtle", children: [
978
- " ",
979
- t.sourceCamStreamId
980
- ] })
981
- ] }),
982
- /* @__PURE__ */ e("span", { className: "text-[10px] text-foreground-subtle", children: s && s.uptimeMs > 0 ? Qe(s.uptimeMs) : "—" })
983
- ] }),
984
- s && A ? n ? /* @__PURE__ */ r("div", { className: "flex flex-wrap gap-x-3 gap-y-0.5 text-[10px]", children: [
985
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
986
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "FPS:" }),
987
- /* @__PURE__ */ r("span", { className: "text-foreground", children: [
988
- s.inputFps.toFixed(1),
989
- "/",
990
- s.decodeFps.toFixed(1)
991
- ] })
992
- ] }),
993
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
994
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Bitrate:" }),
995
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.bitrateKbps >= 1e3 ? `${(s.bitrateKbps / 1e3).toFixed(1)} Mbps` : `${s.bitrateKbps} kbps` })
996
- ] }),
997
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
998
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Codec:" }),
999
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.codec?.toUpperCase() ?? "—" })
1000
- ] }),
1001
- /* @__PURE__ */ r("span", { className: "inline-flex items-center whitespace-nowrap gap-1", children: [
1002
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Clients:" }),
1003
- /* @__PURE__ */ e("span", { className: "text-foreground font-semibold", children: M }),
1004
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle/70", children: "(" }),
1005
- /* @__PURE__ */ e(it, { count: s.encodedSubscribers + s.decodedSubscribers, clients: m, onKill: h }),
1006
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle/70", children: "·" }),
1007
- /* @__PURE__ */ e(ct, { count: s.rtspClients ?? 0, clients: m, onKill: h }),
1008
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle/70", children: [
1009
- pipe ",
1010
- s.pipeClients ?? 0,
1011
- ")"
1012
- ] })
1013
- ] })
1014
- ] }) : /* @__PURE__ */ r($, { children: [
1015
- /* @__PURE__ */ r("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-[10px]", children: [
1016
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
1017
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "In:" }),
1018
- /* @__PURE__ */ r("span", { className: "text-foreground", children: [
1019
- s.inputFps.toFixed(1),
1020
- " fps"
1021
- ] })
1022
- ] }),
1023
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
1024
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Dec:" }),
1025
- /* @__PURE__ */ r("span", { className: "text-foreground", children: [
1026
- s.decodeFps.toFixed(1),
1027
- " fps"
1028
- ] })
1029
- ] }),
1030
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
1031
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Bitrate:" }),
1032
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.bitrateKbps >= 1e3 ? `${(s.bitrateKbps / 1e3).toFixed(1)} Mbps` : `${s.bitrateKbps} kbps` })
1033
- ] }),
1034
- /* @__PURE__ */ r("span", { className: "hidden @[480px]:inline-flex whitespace-nowrap gap-1", children: [
1035
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "IDR:" }),
1036
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.idrIntervalMs > 0 ? `${(s.idrIntervalMs / 1e3).toFixed(1)}s` : "—" })
1037
- ] }),
1038
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap gap-1", children: [
1039
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Codec:" }),
1040
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.codec?.toUpperCase() ?? "—" })
1041
- ] }),
1042
- /* @__PURE__ */ r("span", { className: "hidden @[480px]:inline-flex whitespace-nowrap gap-1 max-w-full overflow-hidden", children: [
1043
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Decoder:" }),
1044
- /* @__PURE__ */ e("span", { className: "text-foreground font-mono truncate", children: s.decoderNodeId ?? /* @__PURE__ */ e("span", { className: "text-foreground-subtle italic", children: "deferred" }) })
1045
- ] }),
1046
- /* @__PURE__ */ r("span", { className: "hidden @[640px]:inline-flex whitespace-nowrap gap-1", children: [
1047
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Pipe:" }),
1048
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.pipeClients ?? 0 })
1049
- ] }),
1050
- /* @__PURE__ */ r("span", { className: "hidden @[640px]:inline-flex whitespace-nowrap gap-1", children: [
1051
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Packets:" }),
1052
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.packetCount > 1e3 ? `${(s.packetCount / 1e3).toFixed(1)}k` : s.packetCount })
1053
- ] }),
1054
- /* @__PURE__ */ r("span", { className: "hidden @[640px]:inline-flex whitespace-nowrap gap-1", children: [
1055
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Data:" }),
1056
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.totalBytes > 1048576 ? `${(s.totalBytes / 1048576).toFixed(1)} MB` : `${(s.totalBytes / 1024).toFixed(0)} KB` })
1057
- ] }),
1058
- s.audio && /* @__PURE__ */ r("div", { className: "basis-full flex flex-wrap items-center gap-x-1.5 gap-y-0.5", children: [
1059
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle whitespace-nowrap", children: "Audio:" }),
1060
- /* @__PURE__ */ r("span", { className: "inline-flex whitespace-nowrap items-center gap-1.5", children: [
1061
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.audio.codec.toUpperCase() }),
1062
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "·" }),
1063
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.audio.sampleRate >= 1e3 ? `${(s.audio.sampleRate / 1e3).toFixed(s.audio.sampleRate % 1e3 === 0 ? 0 : 1)}kHz` : `${s.audio.sampleRate}Hz` }),
1064
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "·" }),
1065
- /* @__PURE__ */ e("span", { className: "text-foreground", children: s.audio.channels === 1 ? "mono" : s.audio.channels === 2 ? "stereo" : `${s.audio.channels}ch` })
1066
- ] }),
1067
- /* @__PURE__ */ e("span", { className: `px-1 py-px rounded text-[8px] font-medium whitespace-nowrap ${s.audio.supported ? "bg-success/15 text-success" : "bg-amber-500/15 text-amber-500"}`, children: s.audio.supported ? "decoded" : "no decoder" })
1068
- ] })
1069
- ] }),
1070
- /* @__PURE__ */ e(ot, { clients: m, encodedCount: s.encodedSubscribers, onKill: h })
1071
- ] }) : /* @__PURE__ */ e("p", { className: "text-[10px] text-foreground-subtle italic", children: "No demand — stream suspended" }),
1072
- /* @__PURE__ */ r("div", { className: "mt-1.5 flex items-center gap-1.5 text-[10px]", children: [
1073
- /* @__PURE__ */ e("span", { className: "text-foreground-subtle", children: "Buffer:" }),
1074
- /* @__PURE__ */ e(
1075
- lt,
1076
- {
1077
- enabled: u,
1078
- onToggle: (k) => v(k),
1079
- disabled: p.isPending
1080
- }
1081
- ),
1082
- /* @__PURE__ */ r("span", { className: "text-foreground", children: [
1083
- d ?? s?.preBufferSec ?? 0,
1084
- "s",
1085
- s && A ? ` (${s.preBufferPackets}p)` : ""
1086
- ] })
1087
- ] })
1088
- ]
1089
- }
1090
- );
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
+ });
1091
1508
  }
1092
- const at = 280, nt = 120;
1093
- function ue({ trigger: t, content: a, widthClass: n }) {
1094
- const o = W(null), c = W(null), [s, m] = x(!1), [l, f] = x(!1), u = R(() => {
1095
- c.current && (clearTimeout(c.current), c.current = null);
1096
- }, []), d = R(() => {
1097
- u(), c.current = setTimeout(() => m(!1), nt);
1098
- }, [u]), p = R(() => {
1099
- u();
1100
- const N = o.current;
1101
- if (N) {
1102
- const h = N.getBoundingClientRect(), C = window.innerHeight - h.bottom, w = h.top;
1103
- f(C < at && w > C);
1104
- }
1105
- m(!0);
1106
- }, [u]);
1107
- return /* @__PURE__ */ r(
1108
- "span",
1109
- {
1110
- ref: o,
1111
- className: "relative inline-block",
1112
- onMouseEnter: p,
1113
- onMouseLeave: d,
1114
- children: [
1115
- t,
1116
- s && /* @__PURE__ */ e(
1117
- "div",
1118
- {
1119
- className: `absolute left-0 ${l ? "bottom-full mb-1" : "top-full mt-1"} z-50 ${n} rounded-md border border-border bg-surface shadow-xl p-2 text-[10px] normal-case`,
1120
- onMouseEnter: u,
1121
- onMouseLeave: d,
1122
- children: a
1123
- }
1124
- )
1125
- ]
1126
- }
1127
- );
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
+ });
1128
1536
  }
1129
- function D(t) {
1130
- if (t < 1e3) return `${t}ms`;
1131
- const a = Math.floor(t / 1e3);
1132
- if (a < 60) return `${a}s`;
1133
- const n = Math.floor(a / 60);
1134
- return n < 60 ? `${n}m ${a % 60}s` : `${Math.floor(n / 60)}h ${n % 60}m`;
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`;
1135
1543
  }
1136
- function pe(t) {
1137
- return t < 1024 ? `${t} B` : t < 1048576 ? `${(t / 1024).toFixed(1)} KB` : t < 1073741824 ? `${(t / 1048576).toFixed(1)} MB` : `${(t / 1073741824).toFixed(2)} GB`;
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`;
1138
1546
  }
1139
- function ot({ clients: t, encodedCount: a, onKill: n }) {
1140
- const o = t?.decoded ?? [], c = t?.audio ?? [], s = t?.rtsp ?? [], m = t?.encoded ?? [], l = o.length + c.length + s.length + m.length, [f, u] = x(!0);
1141
- 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: [
1142
- /* @__PURE__ */ r(
1143
- "button",
1144
- {
1145
- type: "button",
1146
- onClick: () => u((d) => !d),
1147
- className: "flex items-center gap-1 text-[10px] text-foreground-subtle hover:text-foreground transition-colors",
1148
- children: [
1149
- f ? /* @__PURE__ */ e(X, { className: "h-3 w-3" }) : /* @__PURE__ */ e(Q, { className: "h-3 w-3" }),
1150
- /* @__PURE__ */ r("span", { className: "uppercase tracking-wider", children: [
1151
- "Subscribers (",
1152
- l,
1153
- ")"
1154
- ] })
1155
- ]
1156
- }
1157
- ),
1158
- f && /* @__PURE__ */ r("div", { className: "mt-1 divide-y divide-border/20", children: [
1159
- o.map((d, p) => /* @__PURE__ */ e(
1160
- H,
1161
- {
1162
- kind: "DECODED",
1163
- kindClass: "bg-success/10 text-success",
1164
- tag: d.tag || "unknown",
1165
- metrics: [
1166
- `${d.maxFps.toFixed(0)}fps`,
1167
- `${d.framesDelivered} del`,
1168
- ...d.framesDropped > 0 ? [{ text: `${d.framesDropped} drop`, warn: !0 }] : []
1169
- ],
1170
- age: Date.now() - d.subscribedAt,
1171
- onKill: n && d.tag ? () => n({ channel: "decoded", handle: d.tag }) : void 0
1172
- },
1173
- `d-${p}`
1174
- )),
1175
- c.map((d, p) => /* @__PURE__ */ e(
1176
- H,
1177
- {
1178
- kind: "AUDIO",
1179
- kindClass: "bg-info/10 text-info",
1180
- tag: d.tag || "unknown",
1181
- metrics: [`${d.chunksDelivered} chunks`],
1182
- age: Date.now() - d.subscribedAt,
1183
- onKill: n && d.tag ? () => n({ channel: "audio", handle: d.tag }) : void 0
1184
- },
1185
- `a-${p}`
1186
- )),
1187
- s.map((d) => {
1188
- const p = Date.now() - d.lastRtpAt, v = p > 5e3, N = d.playing ? v ? "stalled" : "playing" : "paused", h = d.playing ? v ? "bg-amber-400/10 text-amber-400" : "bg-success/10 text-success" : "bg-foreground-subtle/10 text-foreground-subtle";
1189
- return /* @__PURE__ */ e(
1190
- H,
1191
- {
1192
- kind: "RTSP",
1193
- kindClass: "bg-warning/10 text-warning",
1194
- tag: d.remoteAddr,
1195
- state: { text: N + (d.muted ? " · muted" : ""), className: h },
1196
- metrics: [pe(d.bytesSent), `last rtp ${D(p)} ago`],
1197
- age: Date.now() - d.connectedAt,
1198
- onKill: n ? () => n({ channel: "rtsp", handle: d.sessionId }) : void 0
1199
- },
1200
- `r-${d.sessionId}`
1201
- );
1202
- }),
1203
- m.map((d) => {
1204
- const p = d.attribution, v = Ye[p.kind] ?? "bg-foreground-subtle/10 text-foreground-subtle", N = p.sessionId ? p.sessionId.slice(0, 8) : null, h = [];
1205
- p.label && h.push(p.label), N && h.push(`sess ${N}`), p.userId && h.push(`user ${p.userId.slice(0, 8)}`), p.remoteAddr && h.push(`@${p.remoteAddr}`), p.userAgent && h.push(Xe(p.userAgent));
1206
- const C = h.length > 0 ? h.join(" · ") : Je(p.kind), w = [];
1207
- return p.media && w.push({ text: p.media }), p.targetCodec && w.push(p.targetCodec), p.transport && w.push(p.transport), w.push(`${d.packetsDelivered} pkts`), /* @__PURE__ */ e(
1208
- H,
1209
- {
1210
- kind: Ze(p.kind),
1211
- kindClass: v,
1212
- tag: C,
1213
- metrics: w,
1214
- age: Date.now() - d.subscribedAt
1215
- },
1216
- d.id
1217
- );
1218
- }),
1219
- m.length === 0 && a > 0 && /* @__PURE__ */ r("div", { className: "py-0.5 text-[10px] text-foreground-subtle", children: [
1220
- /* @__PURE__ */ e("span", { className: "inline-block px-1 rounded text-[9px] font-bold bg-foreground-subtle/10 text-foreground-subtle mr-2", children: "ENCODED" }),
1221
- a,
1222
- " callback subscriber(s)"
1223
- ] })
1224
- ] })
1225
- ] });
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
+ });
1226
1642
  }
1227
- function H({ kind: t, kindClass: a, tag: n, state: o, metrics: c, age: s, onKill: m }) {
1228
- return /* @__PURE__ */ r("div", { className: "flex items-center gap-2 py-0.5 text-[10px]", children: [
1229
- /* @__PURE__ */ e("span", { className: `inline-block px-1 rounded text-[9px] font-bold shrink-0 w-14 text-center ${a}`, children: t }),
1230
- /* @__PURE__ */ e("span", { className: "text-foreground font-medium truncate flex-1", children: n }),
1231
- o && /* @__PURE__ */ e("span", { className: `text-[9px] px-1 rounded shrink-0 ${o.className}`, children: o.text }),
1232
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle flex items-center gap-1.5 shrink-0", children: [
1233
- c.map((l, f) => /* @__PURE__ */ r("span", { children: [
1234
- f > 0 && /* @__PURE__ */ e("span", { className: "mr-1.5 text-foreground-subtle/50", children: "·" }),
1235
- typeof l == "string" ? l : /* @__PURE__ */ e("span", { className: l.warn ? "text-amber-400" : "", children: l.text })
1236
- ] }, f)),
1237
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle/70", children: [
1238
- "· ",
1239
- D(s)
1240
- ] })
1241
- ] }),
1242
- /* @__PURE__ */ e("div", { className: "w-5 flex-shrink-0 flex items-center justify-end", children: m ? /* @__PURE__ */ e(U, { onClick: m }) : null })
1243
- ] });
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
+ });
1244
1678
  }
1245
- function it({ count: t, clients: a, onKill: n }) {
1246
- const o = a?.decoded ?? [], c = a?.audio ?? [], s = a ? a.encodedSubscribers : 0, m = o.length > 0 || c.length > 0 || s > 0, l = /* @__PURE__ */ e("span", { className: `text-foreground ${m ? "underline decoration-dotted decoration-foreground-subtle/50 underline-offset-2 cursor-help" : ""}`, children: t });
1247
- if (!m) return l;
1248
- const f = /* @__PURE__ */ r($, { children: [
1249
- o.length > 0 && /* @__PURE__ */ r("div", { className: "mb-2", children: [
1250
- /* @__PURE__ */ e("div", { className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1", children: "Decoded subscribers" }),
1251
- o.map((u, d) => /* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-2 py-0.5", children: [
1252
- /* @__PURE__ */ e("span", { className: "text-foreground font-medium truncate", children: u.tag || "unknown" }),
1253
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle text-[9px] flex items-center gap-1.5 shrink-0", children: [
1254
- /* @__PURE__ */ r("span", { children: [
1255
- u.maxFps.toFixed(0),
1256
- "fps"
1257
- ] }),
1258
- /* @__PURE__ */ e("span", { children: "·" }),
1259
- /* @__PURE__ */ r("span", { children: [
1260
- u.framesDelivered,
1261
- " del"
1262
- ] }),
1263
- u.framesDropped > 0 && /* @__PURE__ */ r("span", { className: "text-amber-400", children: [
1264
- "· ",
1265
- u.framesDropped,
1266
- " drop"
1267
- ] }),
1268
- /* @__PURE__ */ e("span", { children: "·" }),
1269
- /* @__PURE__ */ e("span", { children: D(Date.now() - u.subscribedAt) }),
1270
- n && u.tag && /* @__PURE__ */ e(U, { onClick: () => n({ channel: "decoded", handle: u.tag }) })
1271
- ] })
1272
- ] }, `d-${d}`))
1273
- ] }),
1274
- c.length > 0 && /* @__PURE__ */ r("div", { className: "mb-2", children: [
1275
- /* @__PURE__ */ e("div", { className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1", children: "Audio subscribers" }),
1276
- c.map((u, d) => /* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-2 py-0.5", children: [
1277
- /* @__PURE__ */ e("span", { className: "text-foreground font-medium truncate", children: u.tag || "unknown" }),
1278
- /* @__PURE__ */ r("span", { className: "text-foreground-subtle text-[9px] flex items-center gap-1.5 shrink-0", children: [
1279
- /* @__PURE__ */ r("span", { children: [
1280
- u.chunksDelivered,
1281
- " chunks"
1282
- ] }),
1283
- /* @__PURE__ */ e("span", { children: "·" }),
1284
- /* @__PURE__ */ e("span", { children: D(Date.now() - u.subscribedAt) }),
1285
- n && u.tag && /* @__PURE__ */ e(U, { onClick: () => n({ channel: "audio", handle: u.tag }) })
1286
- ] })
1287
- ] }, `a-${d}`))
1288
- ] }),
1289
- s > 0 && /* @__PURE__ */ r("div", { children: [
1290
- /* @__PURE__ */ e("div", { className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1", children: "Encoded" }),
1291
- /* @__PURE__ */ r("div", { className: "text-foreground", children: [
1292
- s,
1293
- " callback subscriber(s)"
1294
- ] })
1295
- ] })
1296
- ] });
1297
- return /* @__PURE__ */ e(ue, { trigger: l, content: f, widthClass: "min-w-[260px] max-w-[360px]" });
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;
1298
1755
  }
1299
- function lt({
1300
- enabled: t,
1301
- onToggle: a,
1302
- disabled: n
1303
- }) {
1304
- return /* @__PURE__ */ e(
1305
- "button",
1306
- {
1307
- type: "button",
1308
- role: "switch",
1309
- "aria-checked": t,
1310
- disabled: n,
1311
- onClick: () => a(!t),
1312
- className: `relative inline-flex h-3 w-6 shrink-0 items-center rounded-full transition-colors ${t ? "bg-success/60" : "bg-foreground-subtle/30"} ${n ? "opacity-50 cursor-wait" : "cursor-pointer"}`,
1313
- title: t ? "Pre-buffer enabled — click to disable" : "Pre-buffer disabled — click to enable",
1314
- children: /* @__PURE__ */ e(
1315
- "span",
1316
- {
1317
- className: `inline-block h-2.5 w-2.5 rounded-full bg-white shadow transition-transform ${t ? "translate-x-3" : "translate-x-0.5"}`
1318
- }
1319
- )
1320
- }
1321
- );
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
+ });
1322
1767
  }
1323
- function U({ onClick: t }) {
1324
- return /* @__PURE__ */ e(
1325
- "button",
1326
- {
1327
- type: "button",
1328
- title: "Force-disconnect this client",
1329
- onClick: (a) => {
1330
- a.stopPropagation(), t();
1331
- },
1332
- 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",
1333
- children: /* @__PURE__ */ e(Ke, { className: "h-2.5 w-2.5" })
1334
- }
1335
- );
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
+ });
1336
1778
  }
1337
- function ct({ count: t, clients: a, onKill: n }) {
1338
- const o = a?.rtsp ?? [], c = o.length > 0, s = /* @__PURE__ */ e("span", { className: `text-foreground ${c ? "underline decoration-dotted decoration-foreground-subtle/50 underline-offset-2 cursor-help" : ""}`, children: t });
1339
- if (!c) return s;
1340
- const m = /* @__PURE__ */ r($, { children: [
1341
- /* @__PURE__ */ e("div", { className: "text-foreground-subtle uppercase text-[9px] tracking-wider mb-1", children: "RTSP sessions" }),
1342
- o.map((l) => {
1343
- const f = Date.now() - l.lastRtpAt, u = f > 5e3;
1344
- return /* @__PURE__ */ r("div", { className: "py-1 border-b border-border/40 last:border-b-0", children: [
1345
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-2", children: [
1346
- /* @__PURE__ */ e("span", { className: "text-foreground font-mono", children: l.remoteAddr }),
1347
- /* @__PURE__ */ r("span", { className: "flex items-center gap-1 shrink-0", children: [
1348
- /* @__PURE__ */ r("span", { className: `text-[9px] px-1 rounded ${l.playing ? u ? "bg-amber-400/10 text-amber-400" : "bg-success/10 text-success" : "bg-foreground-subtle/10 text-foreground-subtle"}`, children: [
1349
- l.playing ? u ? "stalled" : "playing" : "paused",
1350
- l.muted && " · muted"
1351
- ] }),
1352
- n && /* @__PURE__ */ e(U, { onClick: () => n({ channel: "rtsp", handle: l.sessionId }) })
1353
- ] })
1354
- ] }),
1355
- /* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-2 text-foreground-subtle text-[9px] mt-0.5", children: [
1356
- /* @__PURE__ */ r("span", { children: [
1357
- pe(l.bytesSent),
1358
- " sent"
1359
- ] }),
1360
- /* @__PURE__ */ r("span", { children: [
1361
- "connected ",
1362
- D(Date.now() - l.connectedAt),
1363
- " ago"
1364
- ] }),
1365
- /* @__PURE__ */ r("span", { children: [
1366
- "last rtp ",
1367
- D(f),
1368
- " ago"
1369
- ] })
1370
- ] })
1371
- ] }, l.sessionId);
1372
- })
1373
- ] });
1374
- return /* @__PURE__ */ e(ue, { trigger: s, content: m, widthClass: "min-w-[300px] max-w-[420px]" });
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;
1375
1828
  }
1376
- const gt = {
1377
- "stream-broker-panel": et,
1378
- "ffmpeg-params": Ge
1379
- };
1380
- export {
1381
- gt as default
1829
+ //#endregion
1830
+ //#region src/stream-broker/widgets/index.tsx
1831
+ var Ee = {
1832
+ "stream-broker-panel": _e,
1833
+ "ffmpeg-params": ue
1382
1834
  };
1835
+ //#endregion
1836
+ export { Ee as default };