@norskvideo/norsk-studio-built-ins 1.11.3 → 1.12.0-2025-01-27-b21c8c91

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 (246) hide show
  1. package/README.md +16 -0
  2. package/client/info.js +1288 -788
  3. package/client/output.whep/styles.css +9 -0
  4. package/client/style.css +501 -863
  5. package/lib/index.js +1 -2
  6. package/lib/index.js.map +1 -1
  7. package/lib/info.js +5 -9
  8. package/lib/info.js.map +1 -1
  9. package/lib/input.rtmp/info.js +3 -2
  10. package/lib/input.rtmp/info.js.map +1 -1
  11. package/lib/input.rtmp/openApi.d.ts +133 -0
  12. package/lib/input.rtmp/openApi.js +3 -0
  13. package/lib/input.rtmp/openApi.js.map +1 -0
  14. package/lib/input.rtmp/runtime.d.ts +24 -5
  15. package/lib/input.rtmp/runtime.js +166 -60
  16. package/lib/input.rtmp/runtime.js.map +1 -1
  17. package/lib/input.rtmp/summary-view.d.ts +3 -5
  18. package/lib/input.rtmp/summary-view.js +26 -6
  19. package/lib/input.rtmp/summary-view.js.map +1 -1
  20. package/lib/input.rtmp/types.yaml +99 -0
  21. package/lib/input.silence/info.js +4 -3
  22. package/lib/input.silence/info.js.map +1 -1
  23. package/lib/input.srt-caller/info.js +7 -6
  24. package/lib/input.srt-caller/info.js.map +1 -1
  25. package/lib/input.srt-caller/runtime.d.ts +1 -1
  26. package/lib/input.srt-listener/info.js +8 -6
  27. package/lib/input.srt-listener/info.js.map +1 -1
  28. package/lib/input.srt-listener/openApi.d.ts +133 -0
  29. package/lib/input.srt-listener/openApi.js +3 -0
  30. package/lib/input.srt-listener/openApi.js.map +1 -0
  31. package/lib/input.srt-listener/runtime.d.ts +26 -6
  32. package/lib/input.srt-listener/runtime.js +168 -57
  33. package/lib/input.srt-listener/runtime.js.map +1 -1
  34. package/lib/input.srt-listener/summary-view.d.ts +3 -5
  35. package/lib/input.srt-listener/summary-view.js +28 -4
  36. package/lib/input.srt-listener/summary-view.js.map +1 -1
  37. package/lib/input.srt-listener/types.yaml +99 -0
  38. package/lib/input.udp-ts/info.d.ts +1 -1
  39. package/lib/input.udp-ts/info.js +6 -5
  40. package/lib/input.udp-ts/info.js.map +1 -1
  41. package/lib/input.udp-ts/runtime.d.ts +1 -1
  42. package/lib/input.videoTestCard/info.d.ts +1 -1
  43. package/lib/input.videoTestCard/info.js +15 -5
  44. package/lib/input.videoTestCard/info.js.map +1 -1
  45. package/lib/output.autoCmaf/form-views.js +2 -3
  46. package/lib/output.autoCmaf/form-views.js.map +1 -1
  47. package/lib/output.autoCmaf/info.d.ts +2 -2
  48. package/lib/output.autoCmaf/info.js +66 -8
  49. package/lib/output.autoCmaf/info.js.map +1 -1
  50. package/lib/output.autoCmaf/runtime.d.ts +29 -9
  51. package/lib/output.autoCmaf/runtime.js +198 -60
  52. package/lib/output.autoCmaf/runtime.js.map +1 -1
  53. package/lib/output.autoCmaf/summary.js +26 -1
  54. package/lib/output.autoCmaf/summary.js.map +1 -1
  55. package/lib/output.autoCmaf/types.d.ts +101 -0
  56. package/lib/output.autoCmaf/types.js +3 -0
  57. package/lib/output.autoCmaf/types.js.map +1 -0
  58. package/lib/output.autoCmaf/types.yaml +28 -0
  59. package/lib/output.preview/info.js +5 -3
  60. package/lib/output.preview/info.js.map +1 -1
  61. package/lib/output.preview/inline-view.d.ts +2 -4
  62. package/lib/output.preview/inline-view.js +8 -4
  63. package/lib/output.preview/inline-view.js.map +1 -1
  64. package/lib/output.preview/runtime.d.ts +4 -3
  65. package/lib/output.preview/runtime.js +29 -18
  66. package/lib/output.preview/runtime.js.map +1 -1
  67. package/lib/output.rtmp/info.js +2 -1
  68. package/lib/output.rtmp/info.js.map +1 -1
  69. package/lib/output.rtmp/inline-view.js +2 -2
  70. package/lib/output.rtmp/runtime.d.ts +2 -2
  71. package/lib/output.rtmp/runtime.js.map +1 -1
  72. package/lib/output.srt/info.d.ts +2 -2
  73. package/lib/output.srt/info.js +27 -6
  74. package/lib/output.srt/info.js.map +1 -1
  75. package/lib/output.srt/runtime.d.ts +30 -5
  76. package/lib/output.srt/runtime.js +139 -5
  77. package/lib/output.srt/runtime.js.map +1 -1
  78. package/lib/output.srt/types.d.ts +101 -0
  79. package/lib/output.srt/types.js +3 -0
  80. package/lib/output.srt/types.js.map +1 -0
  81. package/lib/output.srt/types.yaml +31 -0
  82. package/lib/output.statistics/info.js +3 -3
  83. package/lib/output.statistics/info.js.map +1 -1
  84. package/lib/output.statistics/inline-view.js +3 -2
  85. package/lib/output.statistics/inline-view.js.map +1 -1
  86. package/lib/output.statistics/runtime.d.ts +1 -1
  87. package/lib/output.statistics/runtime.js.map +1 -1
  88. package/lib/output.udpTs/info.d.ts +1 -1
  89. package/lib/output.udpTs/info.js +5 -4
  90. package/lib/output.udpTs/info.js.map +1 -1
  91. package/lib/output.udpTs/runtime.d.ts +1 -1
  92. package/lib/output.whep/info.d.ts +2 -2
  93. package/lib/output.whep/info.js +49 -1
  94. package/lib/output.whep/info.js.map +1 -1
  95. package/lib/output.whep/inline-view.d.ts +4 -0
  96. package/lib/output.whep/inline-view.js +24 -0
  97. package/lib/output.whep/inline-view.js.map +1 -0
  98. package/lib/output.whep/runtime.d.ts +26 -5
  99. package/lib/output.whep/runtime.js +64 -13
  100. package/lib/output.whep/runtime.js.map +1 -1
  101. package/lib/output.whep/types.d.ts +101 -0
  102. package/lib/output.whep/types.js +3 -0
  103. package/lib/output.whep/types.js.map +1 -0
  104. package/lib/output.whep/types.yaml +30 -0
  105. package/lib/processor.browserOverlay/info.d.ts +2 -2
  106. package/lib/processor.browserOverlay/info.js +57 -3
  107. package/lib/processor.browserOverlay/info.js.map +1 -1
  108. package/lib/processor.browserOverlay/inline-view.d.ts +6 -0
  109. package/lib/processor.browserOverlay/inline-view.js +8 -0
  110. package/lib/processor.browserOverlay/inline-view.js.map +1 -0
  111. package/lib/processor.browserOverlay/openApi.d.ts +174 -0
  112. package/lib/processor.browserOverlay/openApi.js +3 -0
  113. package/lib/processor.browserOverlay/openApi.js.map +1 -0
  114. package/lib/processor.browserOverlay/runtime.d.ts +40 -6
  115. package/lib/processor.browserOverlay/runtime.js +151 -23
  116. package/lib/processor.browserOverlay/runtime.js.map +1 -1
  117. package/lib/processor.browserOverlay/summary-view.d.ts +4 -0
  118. package/lib/processor.browserOverlay/summary-view.js +27 -0
  119. package/lib/processor.browserOverlay/summary-view.js.map +1 -0
  120. package/lib/processor.browserOverlay/types.yaml +65 -0
  121. package/lib/processor.cascadingSwitch/info.js +5 -4
  122. package/lib/processor.cascadingSwitch/info.js.map +1 -1
  123. package/lib/processor.cascadingSwitch/inline-view.js +3 -3
  124. package/lib/processor.cascadingSwitch/runtime.d.ts +1 -1
  125. package/lib/processor.cascadingSwitch/runtime.js +2 -2
  126. package/lib/processor.cascadingSwitch/runtime.js.map +1 -1
  127. package/lib/processor.fixedLadder/codec-editor.js +2 -2
  128. package/lib/processor.fixedLadder/codec-editor.js.map +1 -1
  129. package/lib/processor.fixedLadder/codec-view.js +2 -2
  130. package/lib/processor.fixedLadder/codec-view.js.map +1 -1
  131. package/lib/processor.fixedLadder/info.js +11 -9
  132. package/lib/processor.fixedLadder/info.js.map +1 -1
  133. package/lib/processor.fixedLadder/rung-view.js +2 -2
  134. package/lib/processor.fixedLadder/rung-view.js.map +1 -1
  135. package/lib/processor.onscreenGraphic/image-selection.d.ts +9 -0
  136. package/lib/{processor.dynamicBug/bug-selection.js → processor.onscreenGraphic/image-selection.js} +10 -10
  137. package/lib/processor.onscreenGraphic/image-selection.js.map +1 -0
  138. package/lib/processor.onscreenGraphic/info.d.ts +3 -0
  139. package/lib/{processor.dynamicBug → processor.onscreenGraphic}/info.js +24 -17
  140. package/lib/processor.onscreenGraphic/info.js.map +1 -0
  141. package/lib/processor.onscreenGraphic/runtime.d.ts +91 -0
  142. package/lib/processor.onscreenGraphic/runtime.js +503 -0
  143. package/lib/processor.onscreenGraphic/runtime.js.map +1 -0
  144. package/lib/processor.onscreenGraphic/summary-view.d.ts +4 -0
  145. package/lib/processor.onscreenGraphic/summary-view.js +343 -0
  146. package/lib/processor.onscreenGraphic/summary-view.js.map +1 -0
  147. package/lib/processor.onscreenGraphic/types.d.ts +271 -0
  148. package/lib/processor.onscreenGraphic/types.js +3 -0
  149. package/lib/processor.onscreenGraphic/types.js.map +1 -0
  150. package/lib/processor.onscreenGraphic/types.yaml +211 -0
  151. package/lib/processor.streamKeyOverride/info.d.ts +3 -0
  152. package/lib/processor.streamKeyOverride/info.js +150 -0
  153. package/lib/processor.streamKeyOverride/info.js.map +1 -0
  154. package/lib/processor.streamKeyOverride/runtime.d.ts +54 -0
  155. package/lib/processor.streamKeyOverride/runtime.js +226 -0
  156. package/lib/processor.streamKeyOverride/runtime.js.map +1 -0
  157. package/lib/shared/drm/axinom.d.ts +2 -0
  158. package/lib/shared/drm/axinom.js +120 -0
  159. package/lib/shared/drm/axinom.js.map +1 -0
  160. package/lib/shared/drm/cpix.d.ts +24 -0
  161. package/lib/shared/drm/cpix.js +97 -0
  162. package/lib/shared/drm/cpix.js.map +1 -0
  163. package/lib/shared/drm/ezdrm.d.ts +2 -0
  164. package/lib/shared/drm/ezdrm.js +26 -0
  165. package/lib/shared/drm/ezdrm.js.map +1 -0
  166. package/lib/shared/srt-form-views.js +1 -2
  167. package/lib/shared/srt-form-views.js.map +1 -1
  168. package/lib/shared/srt-socket-options.js +6 -6
  169. package/lib/shared/srt-socket-options.js.map +1 -1
  170. package/lib/shared/webrtcSettings.js +1 -2
  171. package/lib/shared/webrtcSettings.js.map +1 -1
  172. package/lib/test/auto-cmaf.js +25 -17
  173. package/lib/test/auto-cmaf.js.map +1 -1
  174. package/lib/test/browser-overlay.js +3 -2
  175. package/lib/test/browser-overlay.js.map +1 -1
  176. package/lib/test/{dynamic-bug.js → onscreen-graphic.js} +146 -114
  177. package/lib/test/onscreen-graphic.js.map +1 -0
  178. package/lib/test/preview.js +3 -3
  179. package/lib/test/preview.js.map +1 -1
  180. package/lib/test/rtmp-input.js +6 -3
  181. package/lib/test/rtmp-input.js.map +1 -1
  182. package/lib/test/srt-input-caller.js +5 -5
  183. package/lib/test/srt-input-caller.js.map +1 -1
  184. package/lib/test/srt-input-listener.js +99 -18
  185. package/lib/test/srt-input-listener.js.map +1 -1
  186. package/lib/test/srt-output.js +13 -5
  187. package/lib/test/srt-output.js.map +1 -1
  188. package/lib/test/udp-output.js +11 -4
  189. package/lib/test/udp-output.js.map +1 -1
  190. package/lib/test/udp-ts-input.js +2 -2
  191. package/lib/test/udp-ts-input.js.map +1 -1
  192. package/lib/test/whep-output.js +11 -5
  193. package/lib/test/whep-output.js.map +1 -1
  194. package/lib/{util.latency → util.stats.latency}/info.js +3 -2
  195. package/lib/util.stats.latency/info.js.map +1 -0
  196. package/lib/util.stats.latency/inline-view.js.map +1 -0
  197. package/lib/{util.latency → util.stats.latency}/runtime.d.ts +1 -1
  198. package/lib/{util.latency → util.stats.latency}/runtime.js +2 -2
  199. package/lib/util.stats.latency/runtime.js.map +1 -0
  200. package/lib/util.stats.latency/source-node-selection.js.map +1 -0
  201. package/package.json +12 -5
  202. package/lib/processor.dynamicBug/bug-selection.d.ts +0 -9
  203. package/lib/processor.dynamicBug/bug-selection.js.map +0 -1
  204. package/lib/processor.dynamicBug/info.d.ts +0 -3
  205. package/lib/processor.dynamicBug/info.js.map +0 -1
  206. package/lib/processor.dynamicBug/runtime.d.ts +0 -64
  207. package/lib/processor.dynamicBug/runtime.js +0 -304
  208. package/lib/processor.dynamicBug/runtime.js.map +0 -1
  209. package/lib/processor.dynamicBug/summary-view.d.ts +0 -4
  210. package/lib/processor.dynamicBug/summary-view.js +0 -60
  211. package/lib/processor.dynamicBug/summary-view.js.map +0 -1
  212. package/lib/processor.whisper-transcribe/info.d.ts +0 -3
  213. package/lib/processor.whisper-transcribe/info.js +0 -43
  214. package/lib/processor.whisper-transcribe/info.js.map +0 -1
  215. package/lib/processor.whisper-transcribe/runtime.d.ts +0 -29
  216. package/lib/processor.whisper-transcribe/runtime.js +0 -83
  217. package/lib/processor.whisper-transcribe/runtime.js.map +0 -1
  218. package/lib/test/dynamic-bug.js.map +0 -1
  219. package/lib/util.latency/info.js.map +0 -1
  220. package/lib/util.latency/inline-view.js.map +0 -1
  221. package/lib/util.latency/runtime.js.map +0 -1
  222. package/lib/util.latency/source-node-selection.js.map +0 -1
  223. package/lib/util.ma35d/info.d.ts +0 -3
  224. package/lib/util.ma35d/info.js +0 -78
  225. package/lib/util.ma35d/info.js.map +0 -1
  226. package/lib/util.ma35d/inline-view.d.ts +0 -6
  227. package/lib/util.ma35d/inline-view.js +0 -76
  228. package/lib/util.ma35d/inline-view.js.map +0 -1
  229. package/lib/util.ma35d/runtime.d.ts +0 -21
  230. package/lib/util.ma35d/runtime.js +0 -49
  231. package/lib/util.ma35d/runtime.js.map +0 -1
  232. package/lib/util.timestamps/info.d.ts +0 -5
  233. package/lib/util.timestamps/info.js +0 -86
  234. package/lib/util.timestamps/info.js.map +0 -1
  235. package/lib/util.timestamps/inline-view.d.ts +0 -6
  236. package/lib/util.timestamps/inline-view.js +0 -94
  237. package/lib/util.timestamps/inline-view.js.map +0 -1
  238. package/lib/util.timestamps/runtime.d.ts +0 -29
  239. package/lib/util.timestamps/runtime.js +0 -40
  240. package/lib/util.timestamps/runtime.js.map +0 -1
  241. /package/lib/test/{dynamic-bug.d.ts → onscreen-graphic.d.ts} +0 -0
  242. /package/lib/{util.latency → util.stats.latency}/info.d.ts +0 -0
  243. /package/lib/{util.latency → util.stats.latency}/inline-view.d.ts +0 -0
  244. /package/lib/{util.latency → util.stats.latency}/inline-view.js +0 -0
  245. /package/lib/{util.latency → util.stats.latency}/source-node-selection.d.ts +0 -0
  246. /package/lib/{util.latency → util.stats.latency}/source-node-selection.js +0 -0
package/client/info.js CHANGED
@@ -34,7 +34,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
34
  // external-global-plugin:react
35
35
  var require_react = __commonJS({
36
36
  "external-global-plugin:react"(exports, module) {
37
- module.exports = window.React;
37
+ module.exports = window.ReactExports;
38
38
  }
39
39
  });
40
40
 
@@ -75,7 +75,7 @@ var summary_view_exports = {};
75
75
  __export(summary_view_exports, {
76
76
  default: () => summary_view_default
77
77
  });
78
- function SummaryView({ state, config }) {
78
+ function SummaryView({ state, config, urls, sendCommand }) {
79
79
  const connectedSources = [];
80
80
  const disconnectedSources = [];
81
81
  config.streamNames.forEach((streamName) => {
@@ -85,11 +85,30 @@ function SummaryView({ state, config }) {
85
85
  disconnectedSources.push(streamName);
86
86
  }
87
87
  });
88
- return (0, import_jsx_runtime2.jsxs)("div", { className: "dark:text-white text-black mb-3 w-60", children: [(0, import_jsx_runtime2.jsxs)("div", { id: "rtmp-sources-connected", children: [(0, import_jsx_runtime2.jsx)("span", { children: "Sources connected" }), (0, import_jsx_runtime2.jsx)("ul", { children: connectedSources.map((streamId) => {
89
- return (0, import_jsx_runtime2.jsx)("li", { className: "text-green-300", children: streamId });
90
- }) })] }), (0, import_jsx_runtime2.jsxs)("div", { id: "rtmp-sources-disconnected", className: "mt-3", children: [(0, import_jsx_runtime2.jsx)("span", { children: "Sources disconnected" }), (0, import_jsx_runtime2.jsx)("ul", { children: disconnectedSources.map((streamId) => {
91
- return (0, import_jsx_runtime2.jsx)("li", { className: "text-orange-300", children: streamId });
92
- }) })] })] });
88
+ const handleDisconnectStream = (streamName) => {
89
+ void disconnectStream(streamName);
90
+ };
91
+ const disconnectStream = async (streamName) => {
92
+ try {
93
+ const response = await fetch(`${urls.componentUrl}/disconnect`, {
94
+ method: "POST",
95
+ headers: {
96
+ "Content-Type": "application/json"
97
+ },
98
+ body: JSON.stringify({ streamName })
99
+ });
100
+ if (!response.ok) {
101
+ console.error("Stream failed to disconnect");
102
+ }
103
+ sendCommand({
104
+ type: "disconnect-source",
105
+ streamName
106
+ });
107
+ } catch (error) {
108
+ console.error("Failed to disconnect stream:", error);
109
+ }
110
+ };
111
+ return (0, import_jsx_runtime2.jsxs)("div", { className: "dark:text-white text-black mb-3 w-60", children: [(0, import_jsx_runtime2.jsxs)("div", { id: "rtmp-sources-connected", children: [(0, import_jsx_runtime2.jsx)("span", { children: "Sources connected" }), (0, import_jsx_runtime2.jsx)("ul", { children: connectedSources.map((streamName) => (0, import_jsx_runtime2.jsxs)("li", { className: "flex items-center justify-between", children: [(0, import_jsx_runtime2.jsx)("span", { className: "text-green-300", children: streamName }), (0, import_jsx_runtime2.jsx)("button", { onClick: () => handleDisconnectStream(streamName), className: "ml-2 px-2 py-1 text-xs bg-red-600 hover:bg-red-700 text-white rounded", children: "Disconnect" })] }, streamName)) })] }), (0, import_jsx_runtime2.jsxs)("div", { id: "rtmp-sources-disconnected", className: "mt-3", children: [(0, import_jsx_runtime2.jsx)("span", { children: "Sources disconnected" }), (0, import_jsx_runtime2.jsx)("ul", { children: disconnectedSources.map((streamName) => (0, import_jsx_runtime2.jsx)("li", { className: "flex items-center justify-between", children: (0, import_jsx_runtime2.jsx)("span", { className: "text-orange-300", children: streamName }) }, streamName)) })] })] });
93
112
  }
94
113
  var import_jsx_runtime2, summary_view_default;
95
114
  var init_summary_view = __esm({
@@ -147,9 +166,32 @@ var summary_view_exports2 = {};
147
166
  __export(summary_view_exports2, {
148
167
  default: () => summary_view_default2
149
168
  });
150
- function SummaryView3({ state, config }) {
169
+ function SummaryView3({ state, config, urls, sendCommand }) {
151
170
  const connectedSources = [];
152
171
  const disconnectedSources = [];
172
+ const disconnectStream = async (streamId) => {
173
+ try {
174
+ const response = await fetch(`${urls.componentUrl}/disconnect`, {
175
+ method: "POST",
176
+ headers: {
177
+ "Content-Type": "application/json"
178
+ },
179
+ body: JSON.stringify({ streamId })
180
+ });
181
+ if (!response.ok) {
182
+ console.error("Stream failed to disconnect");
183
+ }
184
+ sendCommand({
185
+ type: "disconnect-source",
186
+ streamId
187
+ });
188
+ } catch (error) {
189
+ console.error("Failed to disconnect stream:", error);
190
+ }
191
+ };
192
+ const handleDisconnectStream = (streamId) => {
193
+ void disconnectStream(streamId);
194
+ };
153
195
  config.streamIds.forEach((streamId) => {
154
196
  if (state.connectedStreams.includes(streamId)) {
155
197
  connectedSources.push(streamId);
@@ -157,9 +199,9 @@ function SummaryView3({ state, config }) {
157
199
  disconnectedSources.push(streamId);
158
200
  }
159
201
  });
160
- return (0, import_jsx_runtime5.jsxs)("div", { className: "dark:text-white text-black mb-3 w-60", children: [(0, import_jsx_runtime5.jsxs)("div", { id: "srt-sources-connected", children: [(0, import_jsx_runtime5.jsx)("span", { children: "Sources connected" }), (0, import_jsx_runtime5.jsx)("ul", { children: connectedSources.map((streamId) => {
161
- return (0, import_jsx_runtime5.jsx)("li", { className: "text-green-300", children: streamId }, streamId);
162
- }) })] }), (0, import_jsx_runtime5.jsxs)("div", { id: "srt-sources-disconnected", className: "mt-3", children: [(0, import_jsx_runtime5.jsx)("span", { children: "Sources disconnected" }), (0, import_jsx_runtime5.jsx)("ul", { children: disconnectedSources.map((streamId) => {
202
+ return (0, import_jsx_runtime5.jsxs)("div", { className: "dark:text-white text-black mb-3 w-60", children: [(0, import_jsx_runtime5.jsxs)("div", { id: "srt-sources-connected", children: [(0, import_jsx_runtime5.jsx)("span", { children: "Connected Sources" }), (0, import_jsx_runtime5.jsx)("ul", { children: connectedSources.map((streamId) => {
203
+ return (0, import_jsx_runtime5.jsxs)("li", { className: "text-green-300", children: [streamId, (0, import_jsx_runtime5.jsx)("button", { onClick: () => handleDisconnectStream(streamId), className: "ml-2 px-2 py-1 text-xs bg-red-600 hover:bg-red-700 text-white rounded", children: "Disconnect" })] }, streamId);
204
+ }) })] }), (0, import_jsx_runtime5.jsxs)("div", { id: "srt-sources-disconnected", className: "mt-3", children: [(0, import_jsx_runtime5.jsx)("span", { children: "Disconnected Sources" }), (0, import_jsx_runtime5.jsx)("ul", { children: disconnectedSources.map((streamId) => {
163
205
  return (0, import_jsx_runtime5.jsx)("li", { className: "text-orange-300", children: streamId }, streamId);
164
206
  }) })] })] });
165
207
  }
@@ -172,124 +214,30 @@ var init_summary_view2 = __esm({
172
214
  }
173
215
  });
174
216
 
175
- // external-global-plugin:hls.js
176
- var require_hls = __commonJS({
177
- "external-global-plugin:hls.js"(exports, module) {
178
- module.exports = window.HlsJs;
179
- }
180
- });
181
-
182
- // build/output.autoCmaf/summary.js
183
- var summary_exports = {};
184
- __export(summary_exports, {
185
- default: () => summary_default
186
- });
187
- function InlineView5({ state, config }) {
188
- const url = state.url;
189
- const id = config.id;
190
- const previewVideo = (0, import_react4.useRef)(null);
191
- (0, import_react4.useEffect)(() => {
192
- if (!url)
193
- return;
194
- if (!previewVideo.current)
195
- return;
196
- if (import_hls.default.isSupported()) {
197
- const hls = new import_hls.default();
198
- hls.loadSource(url);
199
- hls.attachMedia(previewVideo.current);
200
- } else if (previewVideo.current.canPlayType("application/vnd.apple.mpegurl")) {
201
- previewVideo.current.src = url;
202
- }
203
- }, [state.url]);
204
- if (!url)
205
- return (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: "..." });
206
- return (0, import_jsx_runtime6.jsx)("div", { className: "mb-5", children: (0, import_jsx_runtime6.jsx)("video", { ref: previewVideo, autoPlay: true, muted: true, id: `${id}-video` }) });
207
- }
208
- var import_jsx_runtime6, import_react4, import_hls, summary_default;
209
- var init_summary = __esm({
210
- "build/output.autoCmaf/summary.js"() {
211
- "use strict";
212
- import_jsx_runtime6 = __toESM(require_jsx_runtime());
213
- import_react4 = __toESM(require_react());
214
- import_hls = __toESM(require_hls());
215
- summary_default = InlineView5;
216
- }
217
- });
218
-
219
- // build/output.autoCmaf/fullscreen.js
220
- var fullscreen_exports = {};
221
- __export(fullscreen_exports, {
222
- default: () => fullscreen_default
223
- });
224
- function FullscreenView({ state, config }) {
225
- const url = state.url;
226
- const id = config.id;
227
- (0, import_react5.useEffect)(() => {
228
- if (!url)
229
- return;
230
- const element = document.getElementById(`${id}-video`);
231
- if (import_hls2.default.isSupported()) {
232
- const hls = new import_hls2.default();
233
- hls.loadSource(url);
234
- hls.attachMedia(element);
235
- } else if (element.canPlayType("application/vnd.apple.mpegurl")) {
236
- element.src = url;
237
- }
238
- }, [state.url]);
239
- if (!url)
240
- return (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: "..." });
241
- {
242
- }
243
- return (0, import_jsx_runtime7.jsx)("div", { children: (0, import_jsx_runtime7.jsx)("video", { controls: true, autoPlay: true, muted: true, id: `${id}-video` }) });
244
- }
245
- var import_jsx_runtime7, import_react5, import_hls2, fullscreen_default;
246
- var init_fullscreen = __esm({
247
- "build/output.autoCmaf/fullscreen.js"() {
248
- "use strict";
249
- import_jsx_runtime7 = __toESM(require_jsx_runtime());
250
- import_react5 = __toESM(require_react());
251
- import_hls2 = __toESM(require_hls());
252
- fullscreen_default = FullscreenView;
253
- }
254
- });
255
-
256
- // build/output.autoCmaf/form-views.js
257
- var form_views_exports = {};
258
- __export(form_views_exports, {
259
- S3Destination: () => S3Destination,
260
- SegmentConfiguration: () => SegmentConfiguration
261
- });
262
- function S3Destination(destination) {
263
- return (0, import_jsx_runtime8.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-3 text-sm", children: [(0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Host" }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2", children: destination.host }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Path" }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2", children: destination.prefix }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Include Ads" }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2", children: destination.includeAdInsertions ? "yes" : "no" })] });
264
- }
265
- function SegmentConfiguration(cfg) {
266
- return (0, import_jsx_runtime8.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-3 text-sm", children: [(0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Segments" }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2", children: cfg.defaultSegmentCount == 0 ? "all" : cfg.defaultSegmentCount }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Segment Target" }), (0, import_jsx_runtime8.jsxs)("div", { className: "col-span-2", children: [cfg.targetSegmentDuration, "s"] }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Part Target" }), (0, import_jsx_runtime8.jsxs)("div", { className: "col-span-2", children: [cfg.targetPartDuration, "s"] }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Retention" }), (0, import_jsx_runtime8.jsxs)("div", { className: "col-span-2", children: [cfg.retentionPeriod, "s"] })] });
267
- }
268
- var import_jsx_runtime8;
269
- var init_form_views = __esm({
270
- "build/output.autoCmaf/form-views.js"() {
271
- "use strict";
272
- import_jsx_runtime8 = __toESM(require_jsx_runtime());
273
- }
274
- });
275
-
276
- // ../../../norsk-studio-core/lib/shared/shared-views.js
217
+ // ../../node_modules/@norskvideo/norsk-studio/lib/shared/shared-views.js
277
218
  var require_shared_views = __commonJS({
278
- "../../../norsk-studio-core/lib/shared/shared-views.js"(exports) {
219
+ "../../node_modules/@norskvideo/norsk-studio/lib/shared/shared-views.js"(exports) {
279
220
  "use strict";
280
221
  Object.defineProperty(exports, "__esModule", { value: true });
281
- exports.GlobalIceServerView = void 0;
222
+ exports.GlobalIceServerView = GlobalIceServerView;
223
+ exports.EzDrmConfigView = EzDrmConfigView;
224
+ exports.AxinomConfigView = AxinomConfigView;
282
225
  var jsx_runtime_1 = require_jsx_runtime();
283
226
  function GlobalIceServerView(i) {
284
227
  return (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-3 text-sm", children: [(0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "URL" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-2", children: i.url }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "Reported URL" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-2", children: i.reportedUrl ?? "" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "Username" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-2", children: i.username ?? "" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "Password" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-2", children: i.credential ?? "" })] });
285
228
  }
286
- exports.GlobalIceServerView = GlobalIceServerView;
229
+ function EzDrmConfigView(i) {
230
+ return (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-2 text-sm", children: [(0, jsx_runtime_1.jsx)("div", { className: "col-span-2 node-editor-helper-text", children: "For Encryption (required)" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "Token" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: i.token?.trim() ? "Yes" : "No" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-2 node-editor-helper-text", children: "For Local Preview (optional)" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "pX" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: i.pX?.trim() ? "Yes" : "No" })] });
231
+ }
232
+ function AxinomConfigView(i) {
233
+ return (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-2 text-sm", children: [(0, jsx_runtime_1.jsx)("div", { className: "col-span-2 node-editor-helper-text", children: "For Encryption (required)" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "Tenant ID" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: i.tenantId?.trim() ? "Yes" : "No" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "Management Key" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: i.managementKey?.trim() ? "Yes" : "No" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-2 node-editor-helper-text", children: "For Local Preview (optional)" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "Communication ID" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: i.comKeyId?.trim() ? "Yes" : "No" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: "Communication Key" }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1", children: i.comKey?.trim() ? "Yes" : "No" })] });
234
+ }
287
235
  }
288
236
  });
289
237
 
290
- // ../../../norsk-studio-core/lib/shared/config.js
238
+ // ../../node_modules/@norskvideo/norsk-studio/lib/shared/config.js
291
239
  var require_config = __commonJS({
292
- "../../../norsk-studio-core/lib/shared/config.js"(exports) {
240
+ "../../node_modules/@norskvideo/norsk-studio/lib/shared/config.js"(exports) {
293
241
  "use strict";
294
242
  var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
295
243
  if (k2 === void 0)
@@ -327,7 +275,12 @@ var require_config = __commonJS({
327
275
  return mod && mod.__esModule ? mod : { "default": mod };
328
276
  };
329
277
  Object.defineProperty(exports, "__esModule", { value: true });
330
- exports.RootDataDir = exports.HardwareSelection = exports.contractHardwareAcceleration = exports.GlobalIceServers = void 0;
278
+ exports.GlobalIceServers = GlobalIceServers3;
279
+ exports.GlobalEzDrmConfig = GlobalEzDrmConfig2;
280
+ exports.GlobalAxinomConfig = GlobalAxinomConfig2;
281
+ exports.contractHardwareAcceleration = contractHardwareAcceleration;
282
+ exports.HardwareSelection = HardwareSelection5;
283
+ exports.RootDataDir = RootDataDir;
331
284
  var react_1 = __importDefault(require_react());
332
285
  function GlobalIceServers3(f) {
333
286
  const GlobalIceServerView = react_1.default.lazy(async () => {
@@ -354,7 +307,8 @@ var require_config = __commonJS({
354
307
  help: "Optional URL of the STUN/TURN server as accessed by the client (if different to the above)",
355
308
  hint: {
356
309
  type: "text",
357
- validation: f.validation.IceServer
310
+ validation: Z.union([Z.literal(""), f.validation.IceServer]).optional(),
311
+ optional: true
358
312
  }
359
313
  },
360
314
  username: {
@@ -380,7 +334,90 @@ var require_config = __commonJS({
380
334
  }
381
335
  };
382
336
  }
383
- exports.GlobalIceServers = GlobalIceServers3;
337
+ function GlobalEzDrmConfig2(_f) {
338
+ const EzDrmConfigView = react_1.default.lazy(async () => {
339
+ const views = await Promise.resolve().then(() => __importStar(require_shared_views()));
340
+ return { default: views.EzDrmConfigView };
341
+ });
342
+ return {
343
+ id: "ezdrm-config",
344
+ form: {
345
+ help: "Configuration for EZDRM",
346
+ hint: {
347
+ envOverride: true,
348
+ type: "form-item",
349
+ optional: true,
350
+ form: {
351
+ token: {
352
+ help: "Token for EZDRM",
353
+ hint: {
354
+ envOverride: true,
355
+ type: "text"
356
+ }
357
+ },
358
+ pX: {
359
+ help: "The last six digits of your Widevine Profile ID",
360
+ hint: {
361
+ envOverride: true,
362
+ defaultValue: "",
363
+ type: "text"
364
+ }
365
+ }
366
+ },
367
+ view: EzDrmConfigView
368
+ }
369
+ }
370
+ };
371
+ }
372
+ function GlobalAxinomConfig2(_f) {
373
+ const AxinomConfigView = react_1.default.lazy(async () => {
374
+ const views = await Promise.resolve().then(() => __importStar(require_shared_views()));
375
+ return { default: views.AxinomConfigView };
376
+ });
377
+ return {
378
+ id: "axinom-config",
379
+ form: {
380
+ help: "Configuration for Axinom DRM",
381
+ hint: {
382
+ envOverride: true,
383
+ type: "form-item",
384
+ form: {
385
+ tenantId: {
386
+ help: "Tenant ID from your Axinom DRM account",
387
+ hint: {
388
+ envOverride: true,
389
+ type: "text"
390
+ }
391
+ },
392
+ managementKey: {
393
+ help: "Management Key from your Axinom DRM account",
394
+ hint: {
395
+ envOverride: true,
396
+ type: "text"
397
+ }
398
+ },
399
+ comKeyId: {
400
+ help: "Communication Key ID from your Axinom DRM account",
401
+ hint: {
402
+ envOverride: true,
403
+ defaultValue: "",
404
+ type: "text"
405
+ }
406
+ },
407
+ comKey: {
408
+ help: "Communication Key from your Axinom DRM account",
409
+ hint: {
410
+ envOverride: true,
411
+ defaultValue: "",
412
+ type: "text"
413
+ }
414
+ }
415
+ },
416
+ view: AxinomConfigView
417
+ }
418
+ }
419
+ };
420
+ }
384
421
  function contractHardwareAcceleration(value, accepted) {
385
422
  if (!value)
386
423
  return void 0;
@@ -390,7 +427,6 @@ var require_config = __commonJS({
390
427
  }
391
428
  return void 0;
392
429
  }
393
- exports.contractHardwareAcceleration = contractHardwareAcceleration;
394
430
  function HardwareSelection5() {
395
431
  return {
396
432
  id: "hardware-acceleration",
@@ -409,7 +445,6 @@ var require_config = __commonJS({
409
445
  }
410
446
  };
411
447
  }
412
- exports.HardwareSelection = HardwareSelection5;
413
448
  function RootDataDir() {
414
449
  return {
415
450
  id: "root-data-dir",
@@ -422,7 +457,70 @@ var require_config = __commonJS({
422
457
  }
423
458
  };
424
459
  }
425
- exports.RootDataDir = RootDataDir;
460
+ }
461
+ });
462
+
463
+ // external-global-plugin:hls.js
464
+ var require_hls = __commonJS({
465
+ "external-global-plugin:hls.js"(exports, module) {
466
+ module.exports = window.HlsJs;
467
+ }
468
+ });
469
+
470
+ // build/output.autoCmaf/fullscreen.js
471
+ var fullscreen_exports = {};
472
+ __export(fullscreen_exports, {
473
+ default: () => fullscreen_default
474
+ });
475
+ function FullscreenView({ state, config }) {
476
+ const url = state.url;
477
+ const id = config.id;
478
+ (0, import_react4.useEffect)(() => {
479
+ if (!url)
480
+ return;
481
+ const element = document.getElementById(`${id}-video`);
482
+ if (import_hls.default.isSupported()) {
483
+ const hls = new import_hls.default();
484
+ hls.loadSource(url);
485
+ hls.attachMedia(element);
486
+ } else if (element.canPlayType("application/vnd.apple.mpegurl")) {
487
+ element.src = url;
488
+ }
489
+ }, [state.url]);
490
+ if (!url)
491
+ return (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: "..." });
492
+ {
493
+ }
494
+ return (0, import_jsx_runtime6.jsx)("div", { children: (0, import_jsx_runtime6.jsx)("video", { controls: true, autoPlay: true, muted: true, id: `${id}-video` }) });
495
+ }
496
+ var import_jsx_runtime6, import_react4, import_hls, fullscreen_default;
497
+ var init_fullscreen = __esm({
498
+ "build/output.autoCmaf/fullscreen.js"() {
499
+ "use strict";
500
+ import_jsx_runtime6 = __toESM(require_jsx_runtime());
501
+ import_react4 = __toESM(require_react());
502
+ import_hls = __toESM(require_hls());
503
+ fullscreen_default = FullscreenView;
504
+ }
505
+ });
506
+
507
+ // build/output.autoCmaf/form-views.js
508
+ var form_views_exports = {};
509
+ __export(form_views_exports, {
510
+ S3Destination: () => S3Destination,
511
+ SegmentConfiguration: () => SegmentConfiguration
512
+ });
513
+ function S3Destination(destination) {
514
+ return (0, import_jsx_runtime7.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-3 text-sm", children: [(0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Host" }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-2", children: destination.host }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Path" }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-2", children: destination.prefix }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Include Ads" }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-2", children: destination.includeAdInsertions ? "yes" : "no" })] });
515
+ }
516
+ function SegmentConfiguration(cfg) {
517
+ return (0, import_jsx_runtime7.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-3 text-sm", children: [(0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Segments" }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-2", children: cfg.defaultSegmentCount == 0 ? "all" : cfg.defaultSegmentCount }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Segment Target" }), (0, import_jsx_runtime7.jsxs)("div", { className: "col-span-2", children: [cfg.targetSegmentDuration, "s"] }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Part Target" }), (0, import_jsx_runtime7.jsxs)("div", { className: "col-span-2", children: [cfg.targetPartDuration, "s"] }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Retention" }), (0, import_jsx_runtime7.jsxs)("div", { className: "col-span-2", children: [cfg.retentionPeriod, "s"] })] });
518
+ }
519
+ var import_jsx_runtime7;
520
+ var init_form_views = __esm({
521
+ "build/output.autoCmaf/form-views.js"() {
522
+ "use strict";
523
+ import_jsx_runtime7 = __toESM(require_jsx_runtime());
426
524
  }
427
525
  });
428
526
 
@@ -438,17 +536,21 @@ var inline_view_exports3 = {};
438
536
  __export(inline_view_exports3, {
439
537
  default: () => inline_view_default3
440
538
  });
441
- function InlineView6({ state, config }) {
539
+ function InlineView5({ state, config, raise }) {
442
540
  const url = state.url;
443
541
  const id = config.id;
444
- (0, import_react7.useEffect)(() => {
542
+ (0, import_react6.useEffect)(() => {
445
543
  if (!url)
446
544
  return;
447
- const client = new import_webrtc_client.WhepClient({ url, container: document.getElementById(`preview-${id}`) ?? void 0 });
545
+ const client = new import_webrtc_client.WhepClient({
546
+ url,
547
+ container: document.getElementById(`preview-${id}`) ?? void 0
548
+ });
448
549
  void client.start();
449
550
  }, [state.url]);
551
+ raise && (0, import_react6.useEffect)(raise, []);
450
552
  if (!url)
451
- return (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: "..." });
553
+ return (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: "..." });
452
554
  function percentage(levels) {
453
555
  if (!levels) {
454
556
  return 0;
@@ -458,16 +560,16 @@ function InlineView6({ state, config }) {
458
560
  const snapped = Math.floor(capped * 10) * 10;
459
561
  return Math.max(0, 100 - snapped);
460
562
  }
461
- return (0, import_jsx_runtime9.jsxs)("div", { className: "preview-outer-container", children: [(0, import_jsx_runtime9.jsx)("div", { className: "preview-video", id: `preview-${id}` }), (0, import_jsx_runtime9.jsx)("div", { className: "preview-levels", children: (0, import_jsx_runtime9.jsx)("div", { className: `preview-level clip-${percentage(state.levels)}-preview` }) })] });
563
+ return (0, import_jsx_runtime8.jsxs)("div", { className: "preview-outer-container", children: [(0, import_jsx_runtime8.jsx)("div", { className: "preview-video", id: `preview-${id}` }), (0, import_jsx_runtime8.jsx)("div", { className: "preview-levels", children: (0, import_jsx_runtime8.jsx)("div", { className: `preview-level clip-${percentage(state.levels)}-preview` }) })] });
462
564
  }
463
- var import_jsx_runtime9, import_react7, import_webrtc_client, inline_view_default3;
565
+ var import_jsx_runtime8, import_react6, import_webrtc_client, inline_view_default3;
464
566
  var init_inline_view3 = __esm({
465
567
  "build/output.preview/inline-view.js"() {
466
568
  "use strict";
467
- import_jsx_runtime9 = __toESM(require_jsx_runtime());
468
- import_react7 = __toESM(require_react());
569
+ import_jsx_runtime8 = __toESM(require_jsx_runtime());
570
+ import_react6 = __toESM(require_react());
469
571
  import_webrtc_client = __toESM(require_webrtc_client());
470
- inline_view_default3 = InlineView6;
572
+ inline_view_default3 = InlineView5;
471
573
  }
472
574
  });
473
575
 
@@ -476,17 +578,92 @@ var inline_view_exports4 = {};
476
578
  __export(inline_view_exports4, {
477
579
  default: () => inline_view_default4
478
580
  });
479
- function InlineView7({ state, config }) {
480
- const connected = (0, import_jsx_runtime10.jsx)("div", { className: "active text-green-300 dark:text-green-300", children: "Connected and publishing" });
481
- const disconnected = (0, import_jsx_runtime10.jsxs)("div", { className: "inactive text-orange-300 dark:text-orange-300", children: ["Disconnected ", state.connectRetries > 0 ? `- retrying(${state.connectRetries})` : ""] });
482
- return (0, import_jsx_runtime10.jsx)("div", { className: "rtmp-output", id: `rtmp-output-${config.id}`, children: state.connected ? connected : disconnected });
581
+ function InlineView6({ state, config }) {
582
+ const connected = (0, import_jsx_runtime9.jsx)("div", { className: "active text-green-500 dark:text-green-300", children: "Connected and publishing" });
583
+ const disconnected = (0, import_jsx_runtime9.jsxs)("div", { className: "inactive text-orange-500 dark:text-orange-300", children: ["Disconnected ", state.connectRetries > 0 ? `- retrying(${state.connectRetries})` : ""] });
584
+ return (0, import_jsx_runtime9.jsx)("div", { className: "rtmp-output", id: `rtmp-output-${config.id}`, children: state.connected ? connected : disconnected });
483
585
  }
484
- var import_jsx_runtime10, inline_view_default4;
586
+ var import_jsx_runtime9, inline_view_default4;
485
587
  var init_inline_view4 = __esm({
486
588
  "build/output.rtmp/inline-view.js"() {
487
589
  "use strict";
488
- import_jsx_runtime10 = __toESM(require_jsx_runtime());
489
- inline_view_default4 = InlineView7;
590
+ import_jsx_runtime9 = __toESM(require_jsx_runtime());
591
+ inline_view_default4 = InlineView6;
592
+ }
593
+ });
594
+
595
+ // ../../node_modules/@norskvideo/norsk-studio/lib/shared/util.js
596
+ var require_util = __commonJS({
597
+ "../../node_modules/@norskvideo/norsk-studio/lib/shared/util.js"(exports) {
598
+ "use strict";
599
+ Object.defineProperty(exports, "__esModule", { value: true });
600
+ exports.nodeApiUrl = nodeApiUrl;
601
+ exports.componentApiUrl = componentApiUrl;
602
+ exports.findObjectByType = findObjectByType;
603
+ exports.getObjectByType = getObjectByType;
604
+ exports.getObjectByPath = getObjectByPath;
605
+ exports.displayNodeId = displayNodeId;
606
+ exports.assertUnreachable = assertUnreachable15;
607
+ exports.waitForCondition = waitForCondition;
608
+ function nodeApiUrl(nodeId) {
609
+ return new URL(`${document.location.protocol}//${document.location.host}/live/api/${encodeURIComponent(nodeId)}`);
610
+ }
611
+ function componentApiUrl(indentifier) {
612
+ return new URL(`${document.location.protocol}//${document.location.host}/components/${encodeURIComponent(indentifier)}`);
613
+ }
614
+ function findObjectByType(potentials, t) {
615
+ for (const v of potentials) {
616
+ const potential = getObjectByType(v, t);
617
+ if (potential) {
618
+ return potential;
619
+ }
620
+ }
621
+ return null;
622
+ }
623
+ function getObjectByType(acc, t) {
624
+ const paths = t.split(".");
625
+ return getObjectByPath(acc, paths);
626
+ }
627
+ function getObjectByPath(acc, paths) {
628
+ if (paths.length == 0) {
629
+ return acc;
630
+ }
631
+ if (!acc) {
632
+ return null;
633
+ }
634
+ const head = paths[0];
635
+ const tail = paths.slice(1);
636
+ const result2 = Object.entries(acc).find(([k, _]) => k == head);
637
+ if (!result2) {
638
+ return null;
639
+ }
640
+ return getObjectByPath(result2[1], tail);
641
+ }
642
+ function displayNodeId(id, document2) {
643
+ if (!id) {
644
+ return "";
645
+ }
646
+ return document2.components[id]?.config?.displayName ?? id;
647
+ }
648
+ function assertUnreachable15(_) {
649
+ throw new Error("Didn't expect to get here");
650
+ }
651
+ async function waitForCondition(condition, timeout, interval) {
652
+ return new Promise((r, f) => {
653
+ const i = setInterval(async () => {
654
+ const success = await condition();
655
+ if (success) {
656
+ clearInterval(i);
657
+ clearTimeout(t);
658
+ r();
659
+ }
660
+ }, interval ?? 10);
661
+ const t = setTimeout(() => {
662
+ clearInterval(i);
663
+ f(new Error("Timeout on condition wait"));
664
+ }, timeout ?? 2e3);
665
+ });
666
+ }
490
667
  }
491
668
  });
492
669
 
@@ -495,49 +672,51 @@ var inline_view_exports5 = {};
495
672
  __export(inline_view_exports5, {
496
673
  default: () => inline_view_default5
497
674
  });
498
- function InlineView8({ state }) {
675
+ function InlineView7({ state }) {
499
676
  if (!state.previous)
500
- return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
501
- return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: state.previous.allStreams.map((s, i) => {
677
+ return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
678
+ const format = (stat) => Math.floor(stat).toLocaleString("en-US", { maximumFractionDigits: 0 });
679
+ return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: state.previous.allStreams.map((s, i) => {
502
680
  const metaCase = s.metadata.case;
503
681
  switch (metaCase) {
504
682
  case "audio":
505
- return (0, import_jsx_runtime11.jsxs)("div", { children: [(0, import_jsx_runtime11.jsxs)("div", { children: ["StreamKey: ", streamKey(s.streamKey)] }), (0, import_jsx_runtime11.jsxs)("div", { children: ["Bitrate: ", Math.floor(s.bitrate), "bps"] })] }, i);
683
+ return (0, import_jsx_runtime10.jsxs)("div", { children: [(0, import_jsx_runtime10.jsxs)("div", { children: ["StreamKey: ", streamKey(s.streamKey)] }), (0, import_jsx_runtime10.jsxs)("div", { children: ["Bitrate: ", format(s.bitrate), "bps"] })] }, i);
506
684
  case "video":
507
- return (0, import_jsx_runtime11.jsxs)("div", { children: [(0, import_jsx_runtime11.jsxs)("div", { children: ["StreamKey: ", streamKey(s.streamKey)] }), (0, import_jsx_runtime11.jsxs)("div", { children: ["Bitrate: ", Math.floor(s.bitrate), "bps"] })] }, i);
685
+ return (0, import_jsx_runtime10.jsxs)("div", { children: [(0, import_jsx_runtime10.jsxs)("div", { children: ["StreamKey: ", streamKey(s.streamKey)] }), (0, import_jsx_runtime10.jsxs)("div", { children: ["Bitrate: ", format(s.bitrate), "bps"] })] }, i);
508
686
  case "ancillary":
509
- return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
687
+ return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
510
688
  case "subtitle":
511
- return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
689
+ return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
512
690
  case "playlist":
513
- return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
691
+ return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
514
692
  case void 0:
515
- return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
693
+ return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
516
694
  default:
517
- assertUnreachable6(metaCase);
695
+ assertUnreachable7(metaCase);
518
696
  }
519
697
  }) });
520
698
  }
521
699
  function streamKey(streamKey2) {
522
700
  return streamKey2.streamId.toString();
523
701
  }
524
- var import_jsx_runtime11, inline_view_default5;
702
+ var import_jsx_runtime10, inline_view_default5;
525
703
  var init_inline_view5 = __esm({
526
704
  "build/output.statistics/inline-view.js"() {
527
705
  "use strict";
528
- import_jsx_runtime11 = __toESM(require_jsx_runtime());
706
+ import_jsx_runtime10 = __toESM(require_jsx_runtime());
529
707
  init_info();
530
- inline_view_default5 = InlineView8;
708
+ inline_view_default5 = InlineView7;
531
709
  }
532
710
  });
533
711
 
534
712
  // build/output.statistics/info.js
535
713
  function info_default11({ defineComponent, All }) {
536
- const InlineView13 = import_react11.default.lazy(async () => Promise.resolve().then(() => (init_inline_view5(), inline_view_exports5)));
714
+ const InlineView13 = import_react10.default.lazy(async () => Promise.resolve().then(() => (init_inline_view5(), inline_view_exports5)));
537
715
  return defineComponent({
538
716
  identifier: "output.statistics",
539
717
  category: "output",
540
718
  name: "Statistics",
719
+ description: "This component accepts multiple media streams, captures and reports metrics or statistical data related to the media streams.",
541
720
  subscription: {
542
721
  // No validation required
543
722
  accepts: {
@@ -557,7 +736,7 @@ function info_default11({ defineComponent, All }) {
557
736
  state.previous = ev.summary;
558
737
  break;
559
738
  default:
560
- assertUnreachable6(evType);
739
+ assertUnreachable7(evType);
561
740
  }
562
741
  return { ...state };
563
742
  },
@@ -568,14 +747,99 @@ function info_default11({ defineComponent, All }) {
568
747
  }
569
748
  });
570
749
  }
571
- function assertUnreachable6(_) {
750
+ function assertUnreachable7(_) {
572
751
  throw new Error("Didn't expect to get here");
573
752
  }
574
- var import_react11;
753
+ var import_react10;
575
754
  var init_info = __esm({
576
755
  "build/output.statistics/info.js"() {
577
756
  "use strict";
757
+ import_react10 = __toESM(require_react());
758
+ }
759
+ });
760
+
761
+ // build/output.whep/inline-view.js
762
+ var inline_view_exports6 = {};
763
+ __export(inline_view_exports6, {
764
+ default: () => inline_view_default6
765
+ });
766
+ function InlineView8({ state, config, raise }) {
767
+ const url = state.url;
768
+ const id = config.id;
769
+ (0, import_react11.useEffect)(() => {
770
+ if (!url)
771
+ return;
772
+ const client = new import_webrtc_client2.WhepClient({
773
+ url,
774
+ container: document.getElementById(`whep-${id}`) ?? void 0
775
+ });
776
+ void client.start();
777
+ }, [state.url]);
778
+ raise && (0, import_react11.useEffect)(raise, []);
779
+ if (!url)
780
+ return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: "..." });
781
+ return (0, import_jsx_runtime11.jsx)("div", { className: "whep-container", children: (0, import_jsx_runtime11.jsx)("div", { className: "whep-video", id: `whep-${id}` }) });
782
+ }
783
+ var import_jsx_runtime11, import_react11, import_webrtc_client2, inline_view_default6;
784
+ var init_inline_view6 = __esm({
785
+ "build/output.whep/inline-view.js"() {
786
+ "use strict";
787
+ import_jsx_runtime11 = __toESM(require_jsx_runtime());
578
788
  import_react11 = __toESM(require_react());
789
+ import_webrtc_client2 = __toESM(require_webrtc_client());
790
+ inline_view_default6 = InlineView8;
791
+ }
792
+ });
793
+
794
+ // build/processor.browserOverlay/summary-view.js
795
+ var summary_view_exports3 = {};
796
+ __export(summary_view_exports3, {
797
+ default: () => summary_view_default3
798
+ });
799
+ function SummaryView5({ state, sendCommand }) {
800
+ const [url, setUrl] = (0, import_react13.useState)(state.currentUrl);
801
+ const [enabled, setEnabled] = (0, import_react13.useState)(state.enabled);
802
+ const stateChanged = (0, import_react13.useMemo)(() => {
803
+ return url !== state.currentUrl || enabled !== state.enabled;
804
+ }, [url, enabled]);
805
+ const buttonClass = "mt-2 mb-5 text-white w-full justify-center bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800";
806
+ return (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-3 mb-5", children: [(0, import_jsx_runtime12.jsx)("h2", { className: "text-xl font-bold text-gray-900 dark:text-white", children: "Controls" }), (0, import_jsx_runtime12.jsxs)("div", { className: "mb-5", children: [(0, import_jsx_runtime12.jsx)("label", { htmlFor: "url", className: "mb-2 mr-2 text-sm font-medium text-gray-900 dark:text-white", children: "URL" }), (0, import_jsx_runtime12.jsx)("input", { type: "email", id: "url", className: "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500", value: url, onChange: (e) => setUrl(e.target.value), required: true })] }), (0, import_jsx_runtime12.jsx)("div", { className: "mb-5", children: (0, import_jsx_runtime12.jsxs)("label", { className: "inline-flex items-center cursor-pointer", children: [(0, import_jsx_runtime12.jsx)("span", { className: "me-3 text-sm font-medium text-gray-900 dark:text-gray-300", children: "Enabled" }), (0, import_jsx_runtime12.jsx)("input", { type: "checkbox", checked: enabled, onChange: (e) => setEnabled(e.target.checked), className: "sr-only peer" }), (0, import_jsx_runtime12.jsx)("div", { className: "relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600" })] }) }), (0, import_jsx_runtime12.jsx)("button", { type: "button", className: `${buttonClass} ${!stateChanged ? "opacity-50 cursor-not-allowed" : ""}`, disabled: !stateChanged, onClick: () => {
807
+ if (url !== state.currentUrl) {
808
+ sendCommand({ type: "change-url", url });
809
+ }
810
+ if (enabled !== state.enabled) {
811
+ if (enabled) {
812
+ sendCommand({ type: "enable" });
813
+ } else {
814
+ sendCommand({ type: "disable" });
815
+ }
816
+ }
817
+ }, children: "Commit" })] });
818
+ }
819
+ var import_jsx_runtime12, import_react13, summary_view_default3;
820
+ var init_summary_view3 = __esm({
821
+ "build/processor.browserOverlay/summary-view.js"() {
822
+ "use strict";
823
+ import_jsx_runtime12 = __toESM(require_jsx_runtime());
824
+ import_react13 = __toESM(require_react());
825
+ summary_view_default3 = SummaryView5;
826
+ }
827
+ });
828
+
829
+ // build/processor.browserOverlay/inline-view.js
830
+ var inline_view_exports7 = {};
831
+ __export(inline_view_exports7, {
832
+ default: () => inline_view_default7
833
+ });
834
+ function InlineView9({ state, config }) {
835
+ return (0, import_jsx_runtime13.jsx)("div", { id: `browser-overlay-${config.id}`, children: (0, import_jsx_runtime13.jsxs)("div", { className: "w-64 grid grid-cols-[min-content,1fr] gap-2", children: [(0, import_jsx_runtime13.jsx)("div", { children: "URL:" }), (0, import_jsx_runtime13.jsx)("div", { className: "truncate", children: state.currentUrl }), (0, import_jsx_runtime13.jsx)("div", { children: "Enabled:" }), (0, import_jsx_runtime13.jsx)("div", { children: (0, import_jsx_runtime13.jsxs)("label", { className: "inline-flex items-center cursor-pointer", children: [(0, import_jsx_runtime13.jsx)("input", { type: "checkbox", checked: state.enabled, disabled: true, className: "sr-only peer" }), (0, import_jsx_runtime13.jsx)("div", { className: "relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600" })] }) })] }) });
836
+ }
837
+ var import_jsx_runtime13, inline_view_default7;
838
+ var init_inline_view7 = __esm({
839
+ "build/processor.browserOverlay/inline-view.js"() {
840
+ "use strict";
841
+ import_jsx_runtime13 = __toESM(require_jsx_runtime());
842
+ inline_view_default7 = InlineView9;
579
843
  }
580
844
  });
581
845
 
@@ -585,15 +849,15 @@ __export(source_selection_exports, {
585
849
  default: () => source_selection_default
586
850
  });
587
851
  function OrderInput(props) {
588
- (0, import_react12.useEffect)(() => {
852
+ (0, import_react15.useEffect)(() => {
589
853
  props.onChanged(props.defaultValue ?? []);
590
854
  }, [props.defaultValue]);
591
- const [value, setValue] = (0, import_react12.useState)(props.defaultValue ?? []);
855
+ const [value, setValue] = (0, import_react15.useState)(props.defaultValue ?? []);
592
856
  if (value.length == 0) {
593
- return (0, import_jsx_runtime12.jsx)("p", { className: "node-editor-helper-text", children: "Sources will appear here when subscriptions have been added to this node" });
857
+ return (0, import_jsx_runtime14.jsx)("p", { className: "node-editor-helper-text", children: "Sources will appear here when subscriptions have been added to this node" });
594
858
  } else {
595
- return (0, import_jsx_runtime12.jsx)("div", { id: props.id, children: (0, import_jsx_runtime12.jsx)("ul", { children: value.map((v, ix) => {
596
- return (0, import_jsx_runtime12.jsxs)("li", { className: "flex", children: [(0, import_jsx_runtime12.jsx)("span", { className: "node-editor-label flex-grow", children: v }), ix == 0 ? (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, {}) : (0, import_jsx_runtime12.jsx)("svg", { onClick: moveUp(ix), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, className: "w-4 h-6 shrink cursor-pointer stroke-gray-700 dark:stroke-gray-50", children: (0, import_jsx_runtime12.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 6.75L12 3m0 0l3.75 3.75M12 3v18" }) }), ix == value.length - 1 ? (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, {}) : (0, import_jsx_runtime12.jsx)("svg", { onClick: moveDown(ix), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, className: "w-4 h-6 shrink cursor-pointer stroke-gray-700 dark:stroke-gray-50", children: (0, import_jsx_runtime12.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 17.25L12 21m0 0l-3.75-3.75M12 21V3" }) })] }, v);
859
+ return (0, import_jsx_runtime14.jsx)("div", { id: props.id, children: (0, import_jsx_runtime14.jsx)("ul", { children: value.map((v, ix) => {
860
+ return (0, import_jsx_runtime14.jsxs)("li", { className: "flex", children: [(0, import_jsx_runtime14.jsx)("span", { className: "node-editor-label flex-grow", children: v }), ix == 0 ? (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, {}) : (0, import_jsx_runtime14.jsx)("svg", { onClick: moveUp(ix), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, className: "w-4 h-6 shrink cursor-pointer stroke-gray-700 dark:stroke-gray-50", children: (0, import_jsx_runtime14.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 6.75L12 3m0 0l3.75 3.75M12 3v18" }) }), ix == value.length - 1 ? (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, {}) : (0, import_jsx_runtime14.jsx)("svg", { onClick: moveDown(ix), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, className: "w-4 h-6 shrink cursor-pointer stroke-gray-700 dark:stroke-gray-50", children: (0, import_jsx_runtime14.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 17.25L12 21m0 0l-3.75-3.75M12 21V3" }) })] }, v);
597
861
  }) }) });
598
862
  }
599
863
  function moveUp(ix) {
@@ -615,146 +879,33 @@ function OrderInput(props) {
615
879
  };
616
880
  }
617
881
  }
618
- var import_jsx_runtime12, import_react12, source_selection_default;
882
+ var import_jsx_runtime14, import_react15, source_selection_default;
619
883
  var init_source_selection = __esm({
620
884
  "build/processor.cascadingSwitch/source-selection.js"() {
621
885
  "use strict";
622
- import_jsx_runtime12 = __toESM(require_jsx_runtime());
623
- import_react12 = __toESM(require_react());
886
+ import_jsx_runtime14 = __toESM(require_jsx_runtime());
887
+ import_react15 = __toESM(require_react());
624
888
  source_selection_default = OrderInput;
625
889
  }
626
890
  });
627
891
 
628
892
  // build/processor.cascadingSwitch/inline-view.js
629
- var inline_view_exports6 = {};
630
- __export(inline_view_exports6, {
631
- default: () => inline_view_default6
893
+ var inline_view_exports8 = {};
894
+ __export(inline_view_exports8, {
895
+ default: () => inline_view_default8
632
896
  });
633
- function InlineView9({ state, config }) {
634
- return (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [(0, import_jsx_runtime13.jsx)("h5", { children: "Sources" }), (0, import_jsx_runtime13.jsxs)("ul", { children: [config.sources.map((s, i) => state.activeSource == s ? (0, import_jsx_runtime13.jsxs)("li", { className: activeClasses, children: [s, " <--"] }, i) : state.availableSources.includes(s) ? (0, import_jsx_runtime13.jsxs)("li", { className: availableClasses, children: [s, " (available)"] }, i) : (0, import_jsx_runtime13.jsxs)("li", { className: inactiveClasses, children: [s, " (inactive)"] }, i)), (0, import_jsx_runtime13.jsx)("li", { className: state.activeSource == "fallback" ? activeClasses : availableClasses, children: "fallback" }, "fallback")] })] });
897
+ function InlineView11({ state, config }) {
898
+ return (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [(0, import_jsx_runtime15.jsx)("h5", { children: "Sources" }), (0, import_jsx_runtime15.jsxs)("ul", { children: [config.sources.map((s, i) => state.activeSource == s ? (0, import_jsx_runtime15.jsxs)("li", { className: activeClasses, children: [s, " <--"] }, i) : state.availableSources.includes(s) ? (0, import_jsx_runtime15.jsxs)("li", { className: availableClasses, children: [s, " (available)"] }, i) : (0, import_jsx_runtime15.jsxs)("li", { className: inactiveClasses, children: [s, " (inactive)"] }, i)), (0, import_jsx_runtime15.jsx)("li", { className: state.activeSource == "fallback" ? activeClasses : availableClasses, children: "fallback" }, "fallback")] })] });
635
899
  }
636
- var import_jsx_runtime13, activeClasses, availableClasses, inactiveClasses, inline_view_default6;
637
- var init_inline_view6 = __esm({
900
+ var import_jsx_runtime15, activeClasses, availableClasses, inactiveClasses, inline_view_default8;
901
+ var init_inline_view8 = __esm({
638
902
  "build/processor.cascadingSwitch/inline-view.js"() {
639
- "use strict";
640
- import_jsx_runtime13 = __toESM(require_jsx_runtime());
641
- activeClasses = "active text-green-300 dark:text-green-300";
642
- availableClasses = "available text-green-300 dark:text-green-300";
643
- inactiveClasses = "inactive text-orange-300 dark:text-orange-300";
644
- inline_view_default6 = InlineView9;
645
- }
646
- });
647
-
648
- // build/processor.dynamicBug/bug-selection.js
649
- var bug_selection_exports = {};
650
- __export(bug_selection_exports, {
651
- default: () => bug_selection_default
652
- });
653
- function BugSelection(props) {
654
- const [loading, setLoading] = (0, import_react13.useState)(true);
655
- (0, import_react13.useEffect)(() => {
656
- const fn = async () => {
657
- const result2 = await fetch("components/processor.dynamicBug/bugs");
658
- if (result2.ok && result2.body) {
659
- const bugs2 = await result2.json();
660
- setBugs(bugs2);
661
- setLoading(false);
662
- if (props.defaultValue)
663
- props.onChanged(props.defaultValue);
664
- } else {
665
- const text = await result2.text();
666
- throw new Error(text);
667
- }
668
- };
669
- fn().catch(console.error);
670
- }, []);
671
- const [bugs, setBugs] = (0, import_react13.useState)([]);
672
- if (loading) {
673
- return (0, import_jsx_runtime14.jsx)("div", { children: "Loading.." });
674
- }
675
- if (bugs.length == 0) {
676
- return (0, import_jsx_runtime14.jsx)("div", { children: "No bugs loaded" });
677
- }
678
- return (0, import_jsx_runtime14.jsx)("div", { children: (0, import_jsx_runtime14.jsxs)("select", { defaultValue: props.defaultValue, className: `node-editor-select-input`, id: props.id, onChange: myOnChange, onBlur: myOnChange, children: [(0, import_jsx_runtime14.jsx)("option", { value: "", children: "---" }, "empty"), bugs.map((o, i) => {
679
- return (0, import_jsx_runtime14.jsx)("option", { value: o, children: o }, i);
680
- })] }) });
681
- function myOnChange(e) {
682
- props.onChanged(e.target.value);
683
- }
684
- }
685
- var import_jsx_runtime14, import_react13, bug_selection_default;
686
- var init_bug_selection = __esm({
687
- "build/processor.dynamicBug/bug-selection.js"() {
688
- "use strict";
689
- import_jsx_runtime14 = __toESM(require_jsx_runtime());
690
- import_react13 = __toESM(require_react());
691
- bug_selection_default = BugSelection;
692
- }
693
- });
694
-
695
- // build/processor.dynamicBug/summary-view.js
696
- var summary_view_exports3 = {};
697
- __export(summary_view_exports3, {
698
- default: () => summary_view_default3
699
- });
700
- function SummaryView5({ state, sendCommand, httpApi }) {
701
- const [bug, setBug] = (0, import_react14.useState)(state.activeBug?.file);
702
- const [position, setPosition] = (0, import_react14.useState)(state.activeBug?.position);
703
- const [bugs, setBugs] = (0, import_react14.useState)([]);
704
- const [fileToUpload, setFileToUpload] = (0, import_react14.useState)(void 0);
705
- async function updateBugs() {
706
- const result2 = await fetch("components/processor.dynamicBug/bugs");
707
- if (result2.ok && result2.body) {
708
- const bugs2 = await result2.json();
709
- setBugs(bugs2);
710
- } else {
711
- const text = await result2.text();
712
- throw new Error(text);
713
- }
714
- }
715
- (0, import_react14.useEffect)(() => {
716
- const fn = async () => {
717
- await updateBugs();
718
- };
719
- fn().catch(console.error);
720
- }, []);
721
- function onFileChange(e) {
722
- if (e.target.files?.[0])
723
- setFileToUpload(e.target.files[0]);
724
- }
725
- return (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [(0, import_jsx_runtime15.jsx)("h2", { children: "Controls" }), (0, import_jsx_runtime15.jsx)("label", { htmlFor: "select-preview", className: "mt-2", children: "Source" }), (0, import_jsx_runtime15.jsxs)("select", { id: "select-bug", className: "mt-2 node-editor-select-input", onChange: (e) => {
726
- setBug(e.currentTarget.value === "" ? void 0 : e.currentTarget.value);
727
- }, children: [(0, import_jsx_runtime15.jsx)("option", { value: "", selected: bug === void 0, children: "---" }), (0, import_jsx_runtime15.jsx)("option", { value: "new", selected: bug === "new", children: "New" }), bugs.map((s, i) => (0, import_jsx_runtime15.jsx)("option", { selected: bug == s, value: s, children: s }, i))] }), (0, import_jsx_runtime15.jsx)("form", { style: { display: bug === "new" ? "block" : "none" }, onSubmit: (e) => e.preventDefault(), children: (0, import_jsx_runtime15.jsx)("input", { type: "file", id: "file", name: "filename", onChange: onFileChange }) }), (0, import_jsx_runtime15.jsxs)("select", { style: { display: bug ? "block" : "none" }, id: "select-position", className: "mt-2 node-editor-select-input", onChange: (e) => {
728
- setPosition(e.currentTarget.value);
729
- }, children: [(0, import_jsx_runtime15.jsx)("option", { value: "topleft", selected: position === "topleft", children: "Top Left" }), (0, import_jsx_runtime15.jsx)("option", { value: "topright", selected: position === "topright", children: "Top Right" }), (0, import_jsx_runtime15.jsx)("option", { value: "bottomleft", selected: position === "bottomleft", children: "Bottom Left" }), (0, import_jsx_runtime15.jsx)("option", { value: "bottomright", selected: position === "bottomright", children: "Bottom Right" })] }), bug != state.activeBug?.file || position != state.activeBug?.position || fileToUpload ? (0, import_jsx_runtime15.jsx)("button", { type: "button", className: "mt-2 mb-2 text-white w-full justify-center bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800", onClick: async (e) => {
730
- e.preventDefault();
731
- if (fileToUpload && bug === "new") {
732
- const form = new FormData();
733
- const url = httpApi.toString() + "/bugs";
734
- form.append("file", fileToUpload);
735
- await fetch(url, {
736
- method: "POST",
737
- body: form
738
- });
739
- setTimeout(async () => {
740
- await updateBugs();
741
- sendCommand({ type: "change-bug", file: fileToUpload.name, position });
742
- setBug(fileToUpload.name);
743
- setFileToUpload(void 0);
744
- return;
745
- }, 500);
746
- } else {
747
- sendCommand({ type: "change-bug", file: bug, position });
748
- }
749
- }, children: "Commit" }) : (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, {})] });
750
- }
751
- var import_jsx_runtime15, import_react14, summary_view_default3;
752
- var init_summary_view3 = __esm({
753
- "build/processor.dynamicBug/summary-view.js"() {
754
903
  "use strict";
755
904
  import_jsx_runtime15 = __toESM(require_jsx_runtime());
756
- import_react14 = __toESM(require_react());
757
- summary_view_default3 = SummaryView5;
905
+ activeClasses = "active text-green-500 dark:text-green-300";
906
+ availableClasses = "available text-green-500 dark:text-green-300";
907
+ inactiveClasses = "inactive text-orange-500 dark:text-orange-300";
908
+ inline_view_default8 = InlineView11;
758
909
  }
759
910
  });
760
911
 
@@ -764,7 +915,7 @@ __export(rung_view_exports, {
764
915
  default: () => rung_view_default
765
916
  });
766
917
  function rung_view_default(rung) {
767
- return (0, import_jsx_runtime16.jsx)("div", { className: "", children: rung.name });
918
+ return (0, import_jsx_runtime16.jsx)("div", { className: "text-gray-900 dark:text-white", children: rung.name });
768
919
  }
769
920
  var import_jsx_runtime16;
770
921
  var init_rung_view = __esm({
@@ -793,7 +944,7 @@ function CodecEditor(props) {
793
944
  target.style.height = target.scrollHeight + "px";
794
945
  }
795
946
  }, []);
796
- return (0, import_jsx_runtime17.jsx)("textarea", { ref: textAreaRef, className: "w-full min-h-fit dark:text-white dark:bg-black", onChange: (e) => {
947
+ return (0, import_jsx_runtime17.jsx)("textarea", { ref: textAreaRef, className: "w-full min-h-fit bg-white text-gray-900 dark:text-white dark:bg-black", onChange: (e) => {
797
948
  const target = e.currentTarget;
798
949
  try {
799
950
  const codec = JSON.parse(target.value);
@@ -818,7 +969,7 @@ __export(codec_view_exports, {
818
969
  default: () => CodecEditor2
819
970
  });
820
971
  function CodecEditor2(props) {
821
- return (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [props.width, "x", props.height] });
972
+ return (0, import_jsx_runtime18.jsxs)("div", { className: "text-gray-900 dark:text-white", children: [props.width, "x", props.height] });
822
973
  }
823
974
  var import_jsx_runtime18;
824
975
  var init_codec_view = __esm({
@@ -828,6 +979,384 @@ var init_codec_view = __esm({
828
979
  }
829
980
  });
830
981
 
982
+ // build/processor.onscreenGraphic/image-selection.js
983
+ var image_selection_exports = {};
984
+ __export(image_selection_exports, {
985
+ default: () => image_selection_default
986
+ });
987
+ function GraphicSelection(props) {
988
+ const [loading, setLoading] = (0, import_react18.useState)(true);
989
+ (0, import_react18.useEffect)(() => {
990
+ const fn = async () => {
991
+ const result2 = await fetch("components/processor.onscreenGraphic/graphics");
992
+ if (result2.ok && result2.body) {
993
+ const graphics = await result2.json();
994
+ setGraphics(graphics);
995
+ setLoading(false);
996
+ if (props.defaultValue)
997
+ props.onChanged(props.defaultValue);
998
+ } else {
999
+ const text = await result2.text();
1000
+ throw new Error(text);
1001
+ }
1002
+ };
1003
+ fn().catch(console.error);
1004
+ }, []);
1005
+ const [graphcs, setGraphics] = (0, import_react18.useState)([]);
1006
+ if (loading) {
1007
+ return (0, import_jsx_runtime19.jsx)("div", { children: "Loading.." });
1008
+ }
1009
+ if (graphcs.length == 0) {
1010
+ return (0, import_jsx_runtime19.jsx)("div", { children: "No graphics loaded" });
1011
+ }
1012
+ return (0, import_jsx_runtime19.jsx)("div", { children: (0, import_jsx_runtime19.jsxs)("select", { defaultValue: props.defaultValue, className: `node-editor-select-input`, id: props.id, onChange: myOnChange, onBlur: myOnChange, children: [(0, import_jsx_runtime19.jsx)("option", { value: "", children: "---" }, "empty"), graphcs.map((o, i) => {
1013
+ return (0, import_jsx_runtime19.jsx)("option", { value: o, children: o }, i);
1014
+ })] }) });
1015
+ function myOnChange(e) {
1016
+ props.onChanged(e.target.value);
1017
+ }
1018
+ }
1019
+ var import_jsx_runtime19, import_react18, image_selection_default;
1020
+ var init_image_selection = __esm({
1021
+ "build/processor.onscreenGraphic/image-selection.js"() {
1022
+ "use strict";
1023
+ import_jsx_runtime19 = __toESM(require_jsx_runtime());
1024
+ import_react18 = __toESM(require_react());
1025
+ image_selection_default = GraphicSelection;
1026
+ }
1027
+ });
1028
+
1029
+ // build/processor.onscreenGraphic/summary-view.js
1030
+ var summary_view_exports4 = {};
1031
+ __export(summary_view_exports4, {
1032
+ default: () => summary_view_default4
1033
+ });
1034
+ function SummaryView7({ state, sendCommand, urls }) {
1035
+ const [graphic, setGraphic] = (0, import_react19.useState)(state.activeGraphic?.file);
1036
+ const [position, setPosition] = (0, import_react19.useState)(state.activeGraphic?.position ?? { type: "named", position: "topleft" });
1037
+ const [graphics, setGraphics] = (0, import_react19.useState)([]);
1038
+ const [fileToUpload, setFileToUpload] = (0, import_react19.useState)(void 0);
1039
+ const [showFileInput, setShowFileInput] = (0, import_react19.useState)(false);
1040
+ const [showUploadButton, setShowUploadButton] = (0, import_react19.useState)(false);
1041
+ const [uploadStatus, setUploadStatus] = (0, import_react19.useState)({ success: false, message: null });
1042
+ const [showDeleteDropdown, setShowDeleteDropdown] = (0, import_react19.useState)(false);
1043
+ const [graphicToDelete, setGraphicToDelete] = (0, import_react19.useState)("");
1044
+ const updateGraphics = (0, import_react19.useCallback)(async () => {
1045
+ try {
1046
+ const result2 = await fetch(`${urls.componentUrl}/graphics`);
1047
+ if (result2.ok) {
1048
+ const newGraphics = await result2.json();
1049
+ setGraphics(newGraphics);
1050
+ } else {
1051
+ throw new Error(await result2.text());
1052
+ }
1053
+ } catch (error) {
1054
+ console.error("Failed to update graphics:", error);
1055
+ setUploadStatus({
1056
+ success: false,
1057
+ message: "Failed to update graphic list."
1058
+ });
1059
+ }
1060
+ }, [urls.componentUrl]);
1061
+ (0, import_react19.useEffect)(() => {
1062
+ updateGraphics().catch(console.error);
1063
+ }, [updateGraphics]);
1064
+ const onFileChange = (e) => {
1065
+ const file = e.target.files?.[0];
1066
+ setFileToUpload(file);
1067
+ setShowUploadButton(!!file);
1068
+ setUploadStatus({ success: false, message: null });
1069
+ };
1070
+ const uploadFileHandle = async () => {
1071
+ if (!fileToUpload)
1072
+ return;
1073
+ try {
1074
+ const form = new FormData();
1075
+ form.append("file", fileToUpload);
1076
+ const response = await fetch(`${urls.componentUrl}/graphics`, {
1077
+ method: "POST",
1078
+ body: form
1079
+ });
1080
+ if (response.status === 409) {
1081
+ const errorData = await response.json();
1082
+ setUploadStatus({
1083
+ success: false,
1084
+ message: `${errorData.error}. Delete the existing graphic first if you want to replace it.`
1085
+ });
1086
+ } else if (!response.ok) {
1087
+ throw new Error("Upload failed");
1088
+ } else {
1089
+ setFileToUpload(void 0);
1090
+ setShowFileInput(false);
1091
+ setUploadStatus({
1092
+ success: true,
1093
+ message: "Graphic uploaded successfully!"
1094
+ });
1095
+ await updateGraphics();
1096
+ }
1097
+ } catch (error) {
1098
+ console.error("Failed to upload file:", error);
1099
+ setUploadStatus({ success: false, message: "Failed to upload graphic." });
1100
+ }
1101
+ setTimeout(() => setUploadStatus({ success: false, message: null }), 5e3);
1102
+ };
1103
+ const uploadFile = () => {
1104
+ void uploadFileHandle();
1105
+ };
1106
+ const deleteBugHandle = async () => {
1107
+ if (!graphicToDelete)
1108
+ return;
1109
+ try {
1110
+ console.log(`${urls.componentUrl}`);
1111
+ const response = await fetch(`${urls.componentUrl}/graphic`, {
1112
+ method: "DELETE",
1113
+ headers: {
1114
+ "Content-Type": "application/json"
1115
+ },
1116
+ body: JSON.stringify({ filename: graphicToDelete })
1117
+ });
1118
+ if (response.ok) {
1119
+ setUploadStatus({
1120
+ success: true,
1121
+ message: "Graphic deleted successfully!"
1122
+ });
1123
+ await updateGraphics();
1124
+ if (graphic === graphicToDelete) {
1125
+ setGraphic(void 0);
1126
+ sendCommand({
1127
+ type: "change-graphic",
1128
+ file: void 0,
1129
+ position: void 0
1130
+ });
1131
+ }
1132
+ setGraphicToDelete("");
1133
+ setShowDeleteDropdown(false);
1134
+ } else {
1135
+ const errorData = await response.json();
1136
+ setUploadStatus({
1137
+ success: false,
1138
+ message: errorData.error || "Failed to delete graphic"
1139
+ });
1140
+ }
1141
+ } catch (error) {
1142
+ console.error("Failed to delete graphic:", error);
1143
+ setUploadStatus({ success: false, message: "Failed to delete graphic" });
1144
+ }
1145
+ setTimeout(() => setUploadStatus({ success: false, message: null }), 3e3);
1146
+ };
1147
+ const deleteBug = () => {
1148
+ void deleteBugHandle();
1149
+ };
1150
+ const eqPosition = (l, r) => {
1151
+ if (!r)
1152
+ return false;
1153
+ if (l.type === "named") {
1154
+ if (r.type !== "named")
1155
+ return false;
1156
+ return l.position === r.position;
1157
+ }
1158
+ if (r.type === "named")
1159
+ return false;
1160
+ if (l.type !== r.type)
1161
+ return false;
1162
+ return l.x === r.x && l.y === r.y;
1163
+ };
1164
+ const graphicChanged = graphic !== state.activeGraphic?.file;
1165
+ const stateChanged = graphicChanged || !eqPosition(position, state.activeGraphic?.position);
1166
+ const buttonClass = "mt-2 mb-5 text-white w-full justify-center bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800";
1167
+ const deleteButtonClass = "mt-2 text-white w-full justify-center bg-red-600 hover:bg-red-700 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-red-700 dark:hover:bg-red-800 dark:focus:ring-red-900";
1168
+ const fileInputClass = "block w-full text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400";
1169
+ return (0, import_jsx_runtime20.jsxs)("div", { className: "space-y-3", children: [(0, import_jsx_runtime20.jsx)("h2", { className: "text-xl font-bold text-gray-900 dark:text-white", children: "Controls" }), (0, import_jsx_runtime20.jsxs)("div", { children: [(0, import_jsx_runtime20.jsx)("label", { htmlFor: "select-graphic", className: "block text-gray-900 dark:text-white mb-1", children: "Source" }), (0, import_jsx_runtime20.jsxs)("select", { id: "select-graphic", className: "w-full node-editor-select-input", value: graphic || "", onChange: (e) => setGraphic(e.target.value || void 0), children: [(0, import_jsx_runtime20.jsx)("option", { value: "", children: "---" }), graphics.map((s) => (0, import_jsx_runtime20.jsx)("option", { value: s, children: s }, s))] })] }), graphic && (0, import_jsx_runtime20.jsxs)("div", { children: [(0, import_jsx_runtime20.jsx)("label", { htmlFor: "select-position", className: "block text-gray-900 dark:text-white mb-1", children: "Graphic position" }), (0, import_jsx_runtime20.jsx)(PositionSelector, { initialPosition: position, onChange: setPosition, graphicChanged, ...state })] }), (0, import_jsx_runtime20.jsx)("button", { type: "button", className: `${buttonClass} ${!stateChanged ? "opacity-50 cursor-not-allowed" : ""}`, onClick: () => sendCommand({ type: "change-graphic", file: graphic, position }), disabled: !stateChanged, children: "Commit" }), !showFileInput && !uploadStatus.success && (0, import_jsx_runtime20.jsx)("button", { type: "button", className: buttonClass, onClick: () => setShowFileInput(true), style: { marginBottom: "1rem" }, children: "Upload Graphic" }), showFileInput && (0, import_jsx_runtime20.jsxs)("form", { style: { display: "block", marginBottom: "1rem" }, children: [(0, import_jsx_runtime20.jsx)("input", { type: "file", id: "file", name: "filename", onChange: onFileChange, className: fileInputClass }), showUploadButton && (0, import_jsx_runtime20.jsx)("button", { type: "button", className: buttonClass, onClick: uploadFile, children: "Upload" })] }), (0, import_jsx_runtime20.jsx)("button", { type: "button", className: deleteButtonClass, onClick: () => setShowDeleteDropdown(!showDeleteDropdown), style: { marginBottom: "1rem" }, children: showDeleteDropdown ? "Hide Delete Options" : "Delete Graphics" }), showDeleteDropdown && (0, import_jsx_runtime20.jsxs)("div", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded-lg", children: [(0, import_jsx_runtime20.jsx)("h3", { className: "text-lg font-semibold mb-2 text-gray-900 dark:text-white", children: "Select Graphic to Delete" }), (0, import_jsx_runtime20.jsxs)("select", { className: "w-full mb-2 node-editor-select-input", value: graphicToDelete, onChange: (e) => setGraphicToDelete(e.target.value), children: [(0, import_jsx_runtime20.jsx)("option", { value: "", children: " Select a graphic" }), graphics.map((graphicName) => (0, import_jsx_runtime20.jsx)("option", { value: graphicName, children: graphicName }, graphicName))] }), (0, import_jsx_runtime20.jsx)("button", { onClick: deleteBug, disabled: !graphicToDelete, className: `${deleteButtonClass} ${!graphicToDelete ? "opacity-50 cursor-not-allowed" : ""}`, children: "Delete Selected Graphic" })] }), uploadStatus.message && (0, import_jsx_runtime20.jsx)("div", { className: `mt-2 text-center ${uploadStatus.success ? "text-green-600" : "text-red-600"}`, children: uploadStatus.message })] });
1170
+ }
1171
+ function convertPosition(givenPosition, currentVideo, currentGraphic) {
1172
+ if (!givenPosition)
1173
+ givenPosition = { type: "named", position: "topleft" };
1174
+ if (givenPosition.type === "named") {
1175
+ let xy;
1176
+ if (givenPosition.position === "topleft") {
1177
+ xy = { x: 0, y: 0 };
1178
+ } else if (givenPosition.position === "topright") {
1179
+ xy = { x: 100, y: 0 };
1180
+ } else if (givenPosition.position === "bottomleft") {
1181
+ xy = { x: 0, y: 100 };
1182
+ } else if (givenPosition.position === "bottomright") {
1183
+ xy = { x: 100, y: 100 };
1184
+ } else if (givenPosition.position === "center") {
1185
+ xy = { x: 50, y: 50 };
1186
+ } else {
1187
+ assertUnreachable12(givenPosition.position);
1188
+ }
1189
+ return { ...givenPosition, ...xy, xPct: xy.x, yPct: xy.y };
1190
+ }
1191
+ if (givenPosition.type === "coordinate") {
1192
+ if (!currentVideo || !currentGraphic) {
1193
+ return { ...givenPosition, xPct: 0, yPct: 0 };
1194
+ }
1195
+ const { width: videoWidth, height: videoHeight } = currentVideo;
1196
+ const { width: graphicWidth, height: graphicHeight } = currentGraphic;
1197
+ const maxX = videoWidth - graphicWidth;
1198
+ const maxY = videoHeight - graphicHeight;
1199
+ return {
1200
+ ...givenPosition,
1201
+ x: clamp(0, givenPosition.x, maxX),
1202
+ xPct: clamp(0, givenPosition.x * 100 / maxX, 100),
1203
+ y: clamp(0, givenPosition.y, maxY),
1204
+ yPct: clamp(0, givenPosition.y * 100 / maxY, 100)
1205
+ };
1206
+ }
1207
+ return { ...givenPosition, xPct: givenPosition.x, yPct: givenPosition.y };
1208
+ }
1209
+ function clamp(min, num, max) {
1210
+ return num < min ? min : num > max ? max : num;
1211
+ }
1212
+ function assertUnreachable12(_) {
1213
+ throw new Error("Didn't expect to get here");
1214
+ }
1215
+ var import_jsx_runtime20, import_react19, PositionSelector, summary_view_default4;
1216
+ var init_summary_view4 = __esm({
1217
+ "build/processor.onscreenGraphic/summary-view.js"() {
1218
+ "use strict";
1219
+ import_jsx_runtime20 = __toESM(require_jsx_runtime());
1220
+ import_react19 = __toESM(require_react());
1221
+ PositionSelector = ({ initialPosition: givenPosition = { type: "named", position: "topleft" }, onChange, currentVideo, currentGraphic, graphicChanged }) => {
1222
+ const convertPos = (pos) => convertPosition(pos, currentVideo, currentGraphic);
1223
+ const initialPosition = convertPos(givenPosition);
1224
+ const [position, setLocalPosition] = (0, import_react19.useState)(initialPosition);
1225
+ const setPosition = (v) => {
1226
+ setLocalPosition(v);
1227
+ onChange(v);
1228
+ };
1229
+ const [positionUnit, setPositionUnit] = (0, import_react19.useState)(position.type === "coordinate" ? "px" : "%");
1230
+ const [isDragging, setIsDragging] = (0, import_react19.useState)(false);
1231
+ const [dragStart, setDragStart] = (0, import_react19.useState)({ xPct: 0, yPct: 0, cx: 0, cy: 0 });
1232
+ const previewAreaRef = (0, import_react19.useRef)(null);
1233
+ const previewTargetRef = (0, import_react19.useRef)(null);
1234
+ const handleMouseDown = (e) => {
1235
+ setIsDragging(true);
1236
+ setDragStart({
1237
+ ...position,
1238
+ cx: e.clientX,
1239
+ cy: e.clientY
1240
+ });
1241
+ handleMouseMove(e);
1242
+ };
1243
+ const handleMouseMove = (e) => {
1244
+ if (!isDragging)
1245
+ return;
1246
+ const boundingBox = previewAreaRef.current?.getBoundingClientRect() ?? { width: 0, height: 0 };
1247
+ const bbTarget = previewTargetRef.current?.getBoundingClientRect() ?? { width: 0, height: 0 };
1248
+ const clientWidth = boundingBox.width - bbTarget.width;
1249
+ const clientHeight = boundingBox.height - bbTarget.height;
1250
+ const newX = clamp(0, dragStart.xPct + (e.clientX - dragStart.cx) * (100 / clientWidth), 100);
1251
+ const newY = clamp(0, dragStart.yPct + (e.clientY - dragStart.cy) * (100 / clientHeight), 100);
1252
+ if (positionUnit === "px" && currentVideo && currentGraphic) {
1253
+ const { width: videoWidth, height: videoHeight } = currentVideo;
1254
+ const { width: graphicWidth, height: graphicHeight } = currentGraphic;
1255
+ const maxX = videoWidth - graphicWidth;
1256
+ const maxY = videoHeight - graphicHeight;
1257
+ setPosition({
1258
+ type: "coordinate",
1259
+ x: newX * maxX / 100,
1260
+ y: newY * maxY / 100,
1261
+ xPct: newX,
1262
+ yPct: newY
1263
+ });
1264
+ } else {
1265
+ setPosition({
1266
+ type: "percentage",
1267
+ x: newX,
1268
+ y: newY,
1269
+ xPct: newX,
1270
+ yPct: newY
1271
+ });
1272
+ }
1273
+ };
1274
+ const handleMouseUp = () => {
1275
+ setIsDragging(false);
1276
+ };
1277
+ (0, import_react19.useEffect)(() => {
1278
+ if (isDragging) {
1279
+ window.addEventListener("mousemove", handleMouseMove);
1280
+ window.addEventListener("mouseup", handleMouseUp);
1281
+ }
1282
+ return () => {
1283
+ window.removeEventListener("mousemove", handleMouseMove);
1284
+ window.removeEventListener("mouseup", handleMouseUp);
1285
+ };
1286
+ }, [isDragging]);
1287
+ return (0, import_jsx_runtime20.jsxs)("div", { className: "relative w-full max-w-lg mx-auto mt-4 mb-8", children: [(0, import_jsx_runtime20.jsxs)("div", { className: "mb-4 flex items-center gap-2", children: [(0, import_jsx_runtime20.jsx)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: "Position Type:" }), (0, import_jsx_runtime20.jsxs)("select", { value: position.type, onChange: (e) => {
1288
+ const newType = e.target.value;
1289
+ if (newType === "named") {
1290
+ setPosition(convertPos({ type: "named", position: "topleft" }));
1291
+ } else {
1292
+ setPositionUnit("%");
1293
+ setPosition({ ...convertPos(position), type: "percentage" });
1294
+ }
1295
+ }, className: "node-editor-select-input", children: [(0, import_jsx_runtime20.jsx)("option", { value: "coordinate", children: "Custom Position" }), (0, import_jsx_runtime20.jsx)("option", { value: "named", children: "Preset Position" })] })] }), position.type === "named" ? (0, import_jsx_runtime20.jsx)("div", { className: "mb-4", children: (0, import_jsx_runtime20.jsxs)("select", { value: position.position, onChange: (e) => {
1296
+ setPosition(convertPos({
1297
+ type: "named",
1298
+ position: e.target.value
1299
+ }));
1300
+ }, className: "w-full node-editor-select-input", children: [(0, import_jsx_runtime20.jsx)("option", { value: "topleft", children: "Top Left" }), (0, import_jsx_runtime20.jsx)("option", { value: "topright", children: "Top Right" }), (0, import_jsx_runtime20.jsx)("option", { value: "bottomleft", children: "Bottom Left" }), (0, import_jsx_runtime20.jsx)("option", { value: "bottomright", children: "Bottom Right" }), (0, import_jsx_runtime20.jsx)("option", { value: "center", children: "Centered" })] }) }) : (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [(0, import_jsx_runtime20.jsxs)("div", { className: "mb-4 flex items-center gap-2", children: [(0, import_jsx_runtime20.jsx)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: "Position Unit:" }), (0, import_jsx_runtime20.jsxs)("select", { value: positionUnit, onChange: (e) => {
1301
+ setPositionUnit(e.target.value);
1302
+ if (e.target.value === "px" && position.type !== "coordinate" && currentVideo && currentGraphic) {
1303
+ const { width: videoWidth, height: videoHeight } = currentVideo;
1304
+ const { width: graphicWidth, height: graphicHeight } = currentGraphic;
1305
+ const maxX = videoWidth - graphicWidth;
1306
+ const maxY = videoHeight - graphicHeight;
1307
+ setPosition({
1308
+ ...position,
1309
+ type: "coordinate",
1310
+ x: position.xPct * maxX / 100,
1311
+ y: position.yPct * maxY / 100,
1312
+ xStr: void 0,
1313
+ yStr: void 0
1314
+ });
1315
+ } else if (e.target.value === "%") {
1316
+ setPosition({
1317
+ ...position,
1318
+ type: "percentage",
1319
+ x: position.xPct,
1320
+ y: position.yPct,
1321
+ xStr: void 0,
1322
+ yStr: void 0
1323
+ });
1324
+ }
1325
+ }, className: "node-editor-select-input", children: [(0, import_jsx_runtime20.jsx)("option", { value: "px", children: "Pixels" }), (0, import_jsx_runtime20.jsx)("option", { value: "%", children: "Percentage" })] })] }), (0, import_jsx_runtime20.jsxs)("div", { className: "relative bg-gray-200 dark:bg-gray-700 rounded-lg", style: {
1326
+ width: "100%",
1327
+ userSelect: "none",
1328
+ aspectRatio: currentVideo ? `${currentVideo.width} / ${currentVideo.height}` : `3 / 2`
1329
+ }, ref: previewAreaRef, children: [(0, import_jsx_runtime20.jsxs)("div", { className: "absolute inset-0 flex flex-col items-center justify-center text-gray-500 dark:text-gray-400", children: [(0, import_jsx_runtime20.jsx)("span", { children: currentVideo ? "Video Preview Area" : "Video Dimensions Unknown" }), " ", currentVideo ? (0, import_jsx_runtime20.jsxs)("span", { children: [currentVideo.width, "x", currentVideo.height, "px"] }) : ""] }), (0, import_jsx_runtime20.jsx)("div", { className: `absolute cursor-move ${currentGraphic && !graphicChanged ? "" : "p-2"} rounded-lg bg-primary-500 bg-opacity-50 hover:bg-opacity-75 transition-colors
1330
+ ${isDragging ? "bg-opacity-75" : ""}`, style: {
1331
+ left: `${position.xPct}%`,
1332
+ top: `${position.yPct}%`,
1333
+ transform: `translate(-${position.xPct}%, -${position.yPct}%)`,
1334
+ aspectRatio: currentGraphic && !graphicChanged ? `${currentGraphic.width} / ${currentGraphic.height}` : `1`,
1335
+ width: currentGraphic && currentVideo && !graphicChanged ? currentGraphic.width / currentVideo.width * 100 + "%" : void 0
1336
+ }, onMouseDown: handleMouseDown, ref: previewTargetRef, children: (0, import_jsx_runtime20.jsx)("svg", { className: `${currentGraphic && !graphicChanged ? "w-full h-full" : "w-6 h-6"} text-white`, "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: (0, import_jsx_runtime20.jsx)("path", { stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 6v12m-6-6h12m-6-6 1.5 1.5M12 6l-1.5 1.5m1.5 10.5L10.5 16.5M12 18l1.5-1.5M6 12l1.5-1.5M7.5 13.5 6 12m12 0-1.5-1.5M16.5 13.5 18 12" }) }) })] }), (0, import_jsx_runtime20.jsxs)("div", { className: "mt-2 text-sm text-gray-600 dark:text-gray-300 text-center", children: ["Position:", " ", position.type === "percentage" ? `${position.xPct.toFixed(1)}%, ${position.yPct.toFixed(1)}%` : `${Math.round(position.x)}px, ${Math.round(position.y)}px`] }), (0, import_jsx_runtime20.jsxs)("div", { className: "mt-2 flex gap-4", children: [(0, import_jsx_runtime20.jsxs)("div", { children: [(0, import_jsx_runtime20.jsxs)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: ["X Position ", positionUnit] }), (0, import_jsx_runtime20.jsx)("input", { type: "number", step: positionUnit === "%" ? "0.1" : "1", value: position.xStr ?? (positionUnit === "%" ? position.xPct.toFixed(1) : Math.round(position.x)), onChange: (e) => {
1337
+ const newX = Number(e.target.value);
1338
+ setPosition(convertPos({
1339
+ type: positionUnit === "%" ? "percentage" : "coordinate",
1340
+ x: newX,
1341
+ xStr: e.target.value,
1342
+ y: position.y,
1343
+ yStr: position.yStr
1344
+ }));
1345
+ }, className: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600" })] }), (0, import_jsx_runtime20.jsxs)("div", { children: [(0, import_jsx_runtime20.jsxs)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: ["Y Position ", positionUnit] }), (0, import_jsx_runtime20.jsx)("input", { type: "number", step: positionUnit === "%" ? "0.1" : "1", value: position.yStr ?? (positionUnit === "%" ? position.yPct.toFixed(1) : Math.round(position.y)), onChange: (e) => {
1346
+ const newY = Number(e.target.value);
1347
+ setPosition(convertPos({
1348
+ type: positionUnit === "%" ? "percentage" : "coordinate",
1349
+ x: position.x,
1350
+ xStr: position.xStr,
1351
+ y: newY,
1352
+ yStr: e.target.value
1353
+ }));
1354
+ }, className: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600" })] })] })] })] });
1355
+ };
1356
+ summary_view_default4 = SummaryView7;
1357
+ }
1358
+ });
1359
+
831
1360
  // ../../node_modules/@kurkle/color/dist/color.esm.js
832
1361
  function round(v) {
833
1362
  return v + 0.5 | 0;
@@ -15146,14 +15675,14 @@ var init_auto = __esm({
15146
15675
  }
15147
15676
  });
15148
15677
 
15149
- // build/util.latency/inline-view.js
15150
- var inline_view_exports7 = {};
15151
- __export(inline_view_exports7, {
15152
- default: () => inline_view_default7
15678
+ // build/util.stats.latency/inline-view.js
15679
+ var inline_view_exports9 = {};
15680
+ __export(inline_view_exports9, {
15681
+ default: () => inline_view_default9
15153
15682
  });
15154
- function InlineView10({ state, config: _2 }) {
15155
- const chartContainer = (0, import_react18.useRef)(null);
15156
- const [chartControl, setChartControl] = (0, import_react18.useState)(void 0);
15683
+ function InlineView12({ state, config: _2 }) {
15684
+ const chartContainer = (0, import_react21.useRef)(null);
15685
+ const [chartControl, setChartControl] = (0, import_react21.useState)(void 0);
15157
15686
  function makeDataSet(key, color2, values) {
15158
15687
  return {
15159
15688
  label: key,
@@ -15170,7 +15699,7 @@ function InlineView10({ state, config: _2 }) {
15170
15699
  datasets: [makeDataSet("latency", "rgba(255, 0, 0, 255)", state2.values)]
15171
15700
  };
15172
15701
  }
15173
- (0, import_react18.useEffect)(() => {
15702
+ (0, import_react21.useEffect)(() => {
15174
15703
  if (!chartContainer.current)
15175
15704
  return;
15176
15705
  auto_default.defaults.color = "#FFF";
@@ -15208,237 +15737,47 @@ function InlineView10({ state, config: _2 }) {
15208
15737
  chart.update();
15209
15738
  }, 100);
15210
15739
  }, [chartContainer]);
15211
- (0, import_react18.useEffect)(() => {
15740
+ (0, import_react21.useEffect)(() => {
15212
15741
  if (!chartControl)
15213
15742
  return;
15214
15743
  chartControl.data = makeData(state);
15215
15744
  }, [state]);
15216
- return (0, import_jsx_runtime19.jsx)("div", { className: "bg-gray-50 dark:bg-gray-700 rounded", style: { width: "360px", height: "200px", padding: "10px" }, children: (0, import_jsx_runtime19.jsx)("canvas", { className: "bg-gray-50 dark:bg-gray-700 rounded", ref: chartContainer }) });
15745
+ return (0, import_jsx_runtime21.jsx)("div", { className: "bg-gray-50 dark:bg-gray-700 rounded", style: { width: "360px", height: "200px", padding: "10px" }, children: (0, import_jsx_runtime21.jsx)("canvas", { className: "bg-gray-50 dark:bg-gray-700 rounded", ref: chartContainer }) });
15217
15746
  }
15218
- var import_jsx_runtime19, import_react18, inline_view_default7;
15219
- var init_inline_view7 = __esm({
15220
- "build/util.latency/inline-view.js"() {
15747
+ var import_jsx_runtime21, import_react21, inline_view_default9;
15748
+ var init_inline_view9 = __esm({
15749
+ "build/util.stats.latency/inline-view.js"() {
15221
15750
  "use strict";
15222
- import_jsx_runtime19 = __toESM(require_jsx_runtime());
15223
- import_react18 = __toESM(require_react());
15751
+ import_jsx_runtime21 = __toESM(require_jsx_runtime());
15752
+ import_react21 = __toESM(require_react());
15224
15753
  init_auto();
15225
- inline_view_default7 = InlineView10;
15754
+ inline_view_default9 = InlineView12;
15226
15755
  }
15227
15756
  });
15228
15757
 
15229
- // build/util.latency/source-node-selection.js
15758
+ // build/util.stats.latency/source-node-selection.js
15230
15759
  var source_node_selection_exports = {};
15231
15760
  __export(source_node_selection_exports, {
15232
15761
  default: () => source_node_selection_default
15233
15762
  });
15234
15763
  function SourceNodeSelection(props) {
15235
- return (0, import_jsx_runtime20.jsx)("div", { children: (0, import_jsx_runtime20.jsxs)("select", { defaultValue: props.defaultValue, className: `node-editor-select-input`, id: props.id, onChange: myOnChange, onBlur: myOnChange, children: [(0, import_jsx_runtime20.jsx)("option", { value: "", children: "---" }, "empty"), Object.values(props.latestDocument.components).map((o, i) => {
15764
+ return (0, import_jsx_runtime22.jsx)("div", { children: (0, import_jsx_runtime22.jsxs)("select", { defaultValue: props.defaultValue, className: `node-editor-select-input`, id: props.id, onChange: myOnChange, onBlur: myOnChange, children: [(0, import_jsx_runtime22.jsx)("option", { value: "", children: "---" }, "empty"), Object.values(props.latestDocument.components).map((o, i) => {
15236
15765
  if (o.id == props.id)
15237
- return (0, import_jsx_runtime20.jsx)(import_jsx_runtime20.Fragment, {});
15766
+ return (0, import_jsx_runtime22.jsx)(import_jsx_runtime22.Fragment, {});
15238
15767
  if (o.info.category === "output")
15239
15768
  return;
15240
- return (0, import_jsx_runtime20.jsx)("option", { value: o.id, children: o.config.displayName }, i);
15769
+ return (0, import_jsx_runtime22.jsx)("option", { value: o.id, children: o.config.displayName }, i);
15241
15770
  })] }) });
15242
15771
  function myOnChange(e) {
15243
15772
  props.onChanged(e.target.value);
15244
15773
  }
15245
15774
  }
15246
- var import_jsx_runtime20, source_node_selection_default;
15775
+ var import_jsx_runtime22, source_node_selection_default;
15247
15776
  var init_source_node_selection = __esm({
15248
- "build/util.latency/source-node-selection.js"() {
15249
- "use strict";
15250
- import_jsx_runtime20 = __toESM(require_jsx_runtime());
15251
- source_node_selection_default = SourceNodeSelection;
15252
- }
15253
- });
15254
-
15255
- // build/util.ma35d/inline-view.js
15256
- var inline_view_exports8 = {};
15257
- __export(inline_view_exports8, {
15258
- default: () => inline_view_default8
15259
- });
15260
- function InlineView11({ state, config: _2 }) {
15261
- const chartContainer = (0, import_react20.useRef)(null);
15262
- const [chartControl, setChartControl] = (0, import_react20.useState)(void 0);
15263
- function makeDataSet(key, color2, values) {
15264
- return {
15265
- label: key,
15266
- fill: false,
15267
- borderColor: color2,
15268
- borderWidth: 1,
15269
- pointStyle: "dash",
15270
- data: values
15271
- };
15272
- }
15273
- function makeData(state2) {
15274
- return {
15275
- labels: new Array(state2.decoder.length).fill(0).map((_, i) => i).map((_) => ""),
15276
- datasets: [
15277
- makeDataSet("decoder", "rgba(255, 0, 0, 255)", state2.decoder),
15278
- makeDataSet("scaler", "rgba(0, 255, 0, 255)", state2.scaler),
15279
- makeDataSet("encoder", "rgba(0, 0, 255, 255)", state2.encoder)
15280
- ]
15281
- };
15282
- }
15283
- (0, import_react20.useEffect)(() => {
15284
- if (!chartContainer.current)
15285
- return;
15286
- auto_default.defaults.color = "#FFF";
15287
- const chart = new auto_default(chartContainer.current, {
15288
- type: "line",
15289
- options: {
15290
- plugins: {
15291
- legend: {
15292
- display: true
15293
- }
15294
- },
15295
- animation: false,
15296
- color: "#FFF",
15297
- scales: {
15298
- x: {
15299
- min: 0,
15300
- max: 200,
15301
- grid: {
15302
- display: false
15303
- }
15304
- },
15305
- y: {
15306
- min: 0,
15307
- max: 100,
15308
- grid: {
15309
- display: false
15310
- }
15311
- }
15312
- }
15313
- },
15314
- data: makeData(state)
15315
- });
15316
- setChartControl(chart);
15317
- setInterval(() => {
15318
- chart.update();
15319
- }, 100);
15320
- }, [chartContainer]);
15321
- (0, import_react20.useEffect)(() => {
15322
- if (!chartControl)
15323
- return;
15324
- chartControl.data = makeData(state);
15325
- }, [state]);
15326
- return (0, import_jsx_runtime21.jsx)("div", { className: "bg-gray-50 dark:bg-gray-700 rounded", style: { width: "360px", height: "200px", padding: "10px" }, children: (0, import_jsx_runtime21.jsx)("canvas", { className: "bg-gray-50 dark:bg-gray-700 rounded", ref: chartContainer }) });
15327
- }
15328
- var import_jsx_runtime21, import_react20, inline_view_default8;
15329
- var init_inline_view8 = __esm({
15330
- "build/util.ma35d/inline-view.js"() {
15331
- "use strict";
15332
- import_jsx_runtime21 = __toESM(require_jsx_runtime());
15333
- import_react20 = __toESM(require_react());
15334
- init_auto();
15335
- inline_view_default8 = InlineView11;
15336
- }
15337
- });
15338
-
15339
- // build/util.timestamps/inline-view.js
15340
- var inline_view_exports9 = {};
15341
- __export(inline_view_exports9, {
15342
- default: () => inline_view_default9
15343
- });
15344
- function InlineView12({ state, config: _2 }) {
15345
- const chartContainer = (0, import_react22.useRef)(null);
15346
- const [chartControl, setChartControl] = (0, import_react22.useState)(void 0);
15347
- (0, import_react22.useEffect)(() => {
15348
- if (!chartContainer.current)
15349
- return;
15350
- if (state.timestamps.length < 2)
15351
- return;
15352
- auto_default.defaults.color = "#FFF";
15353
- const chart = new auto_default(chartContainer.current, {
15354
- type: "line",
15355
- options: {
15356
- plugins: {
15357
- legend: {
15358
- display: false
15359
- }
15360
- },
15361
- // spanGaps: true,
15362
- animation: false,
15363
- // backgroundColor: 'rgba(0,0,0, 255)',
15364
- color: "#FFF",
15365
- // borderColor: '#FFF',
15366
- // aspectRatio: 1,
15367
- scales: {
15368
- x: {
15369
- min: 0,
15370
- max: 200,
15371
- grid: {
15372
- display: false
15373
- }
15374
- },
15375
- y: {
15376
- min: 0,
15377
- max: 5e3,
15378
- grid: {
15379
- display: false
15380
- }
15381
- }
15382
- }
15383
- },
15384
- data: {
15385
- labels: new Array(200).fill(0).map((_, i) => i).map((_) => ""),
15386
- datasets: state.timestamps.map((t) => {
15387
- const mapped = t.timestamps.map((f) => {
15388
- const elapsedWall = f.wall - t.startTimeMs;
15389
- const elapsedTime = (f.ts - t.startTimestamp) * 1e3;
15390
- return Math.abs(elapsedTime - elapsedWall);
15391
- });
15392
- return {
15393
- label: t.key,
15394
- fill: false,
15395
- borderColor: "rgba(255, 0, 0, 255)",
15396
- borderWidth: 1,
15397
- pointStyle: "dash",
15398
- // backgroundColor: 'rgba(255, 128, 128, 255)',
15399
- data: mapped
15400
- };
15401
- })
15402
- }
15403
- });
15404
- setChartControl(chart);
15405
- setInterval(() => {
15406
- chart.update();
15407
- }, 100);
15408
- }, [chartContainer]);
15409
- (0, import_react22.useEffect)(() => {
15410
- if (!chartControl)
15411
- return;
15412
- chartControl.data = {
15413
- labels: new Array(200).fill(0).map((_, i) => i).map((_) => ""),
15414
- datasets: state.timestamps.map((t) => {
15415
- const mapped = t.timestamps.map((f) => {
15416
- const elapsedWall = f.wall - t.startTimeMs;
15417
- const elapsedTime = (f.ts - t.startTimestamp) * 1e3;
15418
- return Math.abs(elapsedTime - elapsedWall);
15419
- });
15420
- return {
15421
- label: t.key,
15422
- fill: false,
15423
- borderColor: "rgba(255, 0, 0, 255)",
15424
- borderWidth: 1,
15425
- pointStyle: "dash",
15426
- // backgroundColor: 'rgba(255, 128, 128, 255)',
15427
- data: mapped
15428
- };
15429
- })
15430
- };
15431
- }, [state]);
15432
- return (0, import_jsx_runtime22.jsx)("div", { className: "bg-gray-50 dark:bg-gray-700 rounded", style: { width: "360px", height: "200px", padding: "10px" }, children: (0, import_jsx_runtime22.jsx)("canvas", { className: "bg-gray-50 dark:bg-gray-700 rounded", ref: chartContainer }) });
15433
- }
15434
- var import_jsx_runtime22, import_react22, inline_view_default9;
15435
- var init_inline_view9 = __esm({
15436
- "build/util.timestamps/inline-view.js"() {
15777
+ "build/util.stats.latency/source-node-selection.js"() {
15437
15778
  "use strict";
15438
15779
  import_jsx_runtime22 = __toESM(require_jsx_runtime());
15439
- import_react22 = __toESM(require_react());
15440
- init_auto();
15441
- inline_view_default9 = InlineView12;
15780
+ source_node_selection_default = SourceNodeSelection;
15442
15781
  }
15443
15782
  });
15444
15783
 
@@ -15452,6 +15791,7 @@ function info_default({ defineComponent, Av, validation: { Z, Port, SourceName,
15452
15791
  identifier: "input.rtmp",
15453
15792
  category: "input",
15454
15793
  name: "RTMP Ingest",
15794
+ description: "A component that listens for RTMP input on the address specified.",
15455
15795
  subscription: {
15456
15796
  accepts: void 0,
15457
15797
  produces: {
@@ -15496,7 +15836,7 @@ function info_default({ defineComponent, Av, validation: { Z, Port, SourceName,
15496
15836
  configForm: {
15497
15837
  form: {
15498
15838
  port: { help: "The port this RTMP input will listen on", hint: { type: "numeric", validation: Port, defaultValue: defaultPort, global: unique("port") } },
15499
- ssl: { help: "Optional: SSL", hint: { type: "boolean" } },
15839
+ ssl: { help: "Optional: SSL", hint: { type: "boolean", optional: true } },
15500
15840
  appName: { help: "Name of the app", hint: { type: "text", validation: Z.string().min(1), defaultValue: "norsk" } },
15501
15841
  streamNames: {
15502
15842
  help: "List of stream names to assign to the accepted streams",
@@ -15521,6 +15861,7 @@ function info_default2({ defineComponent, Audio }) {
15521
15861
  identifier: "input.silence",
15522
15862
  category: "input",
15523
15863
  name: "Silence Generator",
15864
+ description: "A component that produces silent audio streams with configurable sample rate and channel layout.",
15524
15865
  subscription: {
15525
15866
  produces: {
15526
15867
  type: "single-stream",
@@ -15529,14 +15870,14 @@ function info_default2({ defineComponent, Audio }) {
15529
15870
  },
15530
15871
  display: (desc) => {
15531
15872
  return {
15532
- sampleRate: desc.config.sampleRate.toString() + "khz",
15873
+ sampleRate: desc.config.sampleRate.toString() + "Hz",
15533
15874
  channelLayout: desc.config.channelLayout.toString()
15534
15875
  };
15535
15876
  },
15536
15877
  configForm: {
15537
15878
  form: {
15538
15879
  sampleRate: {
15539
- help: "Samplerate in khz of the generated audio",
15880
+ help: "Samplerate in Hz of the generated audio",
15540
15881
  hint: {
15541
15882
  type: "select",
15542
15883
  options: [
@@ -15568,6 +15909,7 @@ var result = ({ Z }) => ({
15568
15909
  help: "The latency value in the receiving direction of the socket (SRTO_RCVLATENCY)",
15569
15910
  hint: {
15570
15911
  type: "numeric",
15912
+ optional: true,
15571
15913
  validation: Z.optional(Z.number())
15572
15914
  }
15573
15915
  },
@@ -15575,13 +15917,15 @@ var result = ({ Z }) => ({
15575
15917
  help: "The latency value provided by the sender side as a minimum value for the receiver (SRTO_PEERLATENCY)",
15576
15918
  hint: {
15577
15919
  type: "numeric",
15920
+ optional: true,
15578
15921
  validation: Z.optional(Z.number())
15579
15922
  }
15580
15923
  },
15581
15924
  inputBandwidth: {
15582
- help: "Input bandwidth (SRTO_INPUTBW xxx",
15925
+ help: "Input bandwidth (SRTO_INPUTBW)",
15583
15926
  hint: {
15584
15927
  type: "numeric",
15928
+ optional: true,
15585
15929
  validation: Z.optional(Z.number())
15586
15930
  }
15587
15931
  },
@@ -15589,6 +15933,7 @@ var result = ({ Z }) => ({
15589
15933
  help: "Overhead bandwidth (SRTO_OHEADBW)",
15590
15934
  hint: {
15591
15935
  type: "numeric",
15936
+ optional: true,
15592
15937
  validation: Z.optional(Z.number())
15593
15938
  }
15594
15939
  },
@@ -15596,6 +15941,7 @@ var result = ({ Z }) => ({
15596
15941
  help: "Max bandwidth (SRTO_MAXBW)",
15597
15942
  hint: {
15598
15943
  type: "numeric",
15944
+ optional: true,
15599
15945
  validation: Z.optional(Z.number())
15600
15946
  }
15601
15947
  }
@@ -15605,7 +15951,7 @@ var srt_socket_options_default = result;
15605
15951
  // build/input.srt-caller/info.js
15606
15952
  var import_react2 = __toESM(require_react());
15607
15953
  function info_default3({ defineComponent, Av, validation }) {
15608
- const { Port, IpAddress, SourceName, SrtPassphrase, SrtStreamId } = validation;
15954
+ const { Port, Hostname, SourceName, SrtPassphrase, SrtStreamId } = validation;
15609
15955
  const SocketConfiguration2 = import_react2.default.lazy(async () => {
15610
15956
  const views = await Promise.resolve().then(() => (init_srt_form_views(), srt_form_views_exports));
15611
15957
  return { default: views.SocketConfiguration };
@@ -15614,6 +15960,7 @@ function info_default3({ defineComponent, Av, validation }) {
15614
15960
  identifier: "input.srt-caller",
15615
15961
  category: "input",
15616
15962
  name: "SRT Ingest (Caller)",
15963
+ description: "This component allows you to receive Secure Reliable Transport (SRT) streams by calling a remote SRT listener.",
15617
15964
  subscription: {
15618
15965
  accepts: void 0,
15619
15966
  produces: {
@@ -15624,16 +15971,16 @@ function info_default3({ defineComponent, Av, validation }) {
15624
15971
  display: (desc) => {
15625
15972
  return {
15626
15973
  port: desc.config.port.toString(),
15627
- ip: desc.config.ip
15974
+ ip: desc.config.host
15628
15975
  };
15629
15976
  },
15630
15977
  configForm: {
15631
15978
  form: {
15632
15979
  port: { help: "The port this SRT input will connect to", hint: { type: "numeric", validation: Port, defaultValue: 5001 } },
15633
- ip: { help: "The IP address this SRT input will connect to", hint: { type: "text", validation: IpAddress, defaultValue: "0.0.0.0" } },
15980
+ host: { help: "The IP address/hostname this SRT input will connect to", hint: { type: "text", validation: Hostname, defaultValue: "0.0.0.0" } },
15634
15981
  sourceName: { help: "Source name to identify this by", hint: { type: "text", validation: SourceName, defaultValue: "camera1" } },
15635
- passphrase: { help: "Optional: Authentication for this SRT input", hint: { type: "text", validation: SrtPassphrase } },
15636
- streamId: { help: "Optional: StreamId to use when calling the remote listener", hint: { type: "text", validation: SrtStreamId } },
15982
+ passphrase: { help: "Optional: Authentication for this SRT input", hint: { type: "text", optional: true, validation: SrtPassphrase } },
15983
+ streamId: { help: "Optional: StreamId to use when calling the remote listener", hint: { type: "text", optional: true, validation: SrtStreamId } },
15637
15984
  socketOptions: {
15638
15985
  help: "Socket Options",
15639
15986
  hint: {
@@ -15652,7 +15999,7 @@ var import_react3 = __toESM(require_react());
15652
15999
  var InlineView4 = import_react3.default.lazy(async () => Promise.resolve().then(() => (init_inline_view2(), inline_view_exports2)));
15653
16000
  var SummaryView4 = import_react3.default.lazy(async () => Promise.resolve().then(() => (init_summary_view2(), summary_view_exports2)));
15654
16001
  function info_default4({ defineComponent, Av, validation }) {
15655
- const { Z, Port, IpAddress, SourceName, SrtPassphrase, unique } = validation;
16002
+ const { Z, Port, Hostname, SourceName, SrtPassphrase, unique } = validation;
15656
16003
  const SocketConfiguration2 = import_react3.default.lazy(async () => {
15657
16004
  const views = await Promise.resolve().then(() => (init_srt_form_views(), srt_form_views_exports));
15658
16005
  return { default: views.SocketConfiguration };
@@ -15661,6 +16008,7 @@ function info_default4({ defineComponent, Av, validation }) {
15661
16008
  identifier: "input.srt-listener",
15662
16009
  category: "input",
15663
16010
  name: "SRT Ingest (Listener)",
16011
+ description: "This component handles media ingest via the SRT(Secure Reliable Transport) protocol. It acts as a listener, receiving media streams from remote SRT sources and is highly configurable, allowing for custom IP addresses, ports, and stream handling behaviours.",
15664
16012
  subscription: {
15665
16013
  accepts: void 0,
15666
16014
  produces: {
@@ -15681,7 +16029,7 @@ function info_default4({ defineComponent, Av, validation }) {
15681
16029
  display: (desc) => {
15682
16030
  return {
15683
16031
  port: desc.config.port.toString(),
15684
- ip: desc.config.ip
16032
+ ip: desc.config.host
15685
16033
  };
15686
16034
  },
15687
16035
  runtime: {
@@ -15715,11 +16063,11 @@ function info_default4({ defineComponent, Av, validation }) {
15715
16063
  envOverride: true
15716
16064
  }
15717
16065
  },
15718
- ip: {
15719
- help: "The IP address this SRT input will listen on",
16066
+ host: {
16067
+ help: "The IP address/hostname this SRT input will listen on",
15720
16068
  hint: {
15721
16069
  type: "text",
15722
- validation: IpAddress,
16070
+ validation: Hostname,
15723
16071
  defaultValue: "0.0.0.0",
15724
16072
  envOverride: true
15725
16073
  }
@@ -15728,6 +16076,7 @@ function info_default4({ defineComponent, Av, validation }) {
15728
16076
  help: "Optional: Authentication for this SRT input",
15729
16077
  hint: {
15730
16078
  type: "text",
16079
+ optional: true,
15731
16080
  validation: SrtPassphrase,
15732
16081
  envOverride: true
15733
16082
  }
@@ -15769,11 +16118,12 @@ function assertUnreachable2(_) {
15769
16118
  }
15770
16119
 
15771
16120
  // build/input.udp-ts/info.js
15772
- function info_default5({ defineComponent, Av, validation: { Z, Port, IpAddress, SourceName, unique } }) {
16121
+ function info_default5({ defineComponent, Av, validation: { Z, Port, Hostname, SourceName, unique } }) {
15773
16122
  return defineComponent({
15774
16123
  identifier: "input.udp-ts",
15775
16124
  category: "input",
15776
16125
  name: "UDP TS ingest",
16126
+ description: "This component receives and processes MPEG Transport Streams (TS) over UDP.",
15777
16127
  subscription: {
15778
16128
  accepts: void 0,
15779
16129
  produces: {
@@ -15784,15 +16134,15 @@ function info_default5({ defineComponent, Av, validation: { Z, Port, IpAddress,
15784
16134
  display: (desc) => {
15785
16135
  return {
15786
16136
  port: desc.config.port.toString(),
15787
- ip: desc.config.ip
16137
+ ip: desc.config.host
15788
16138
  };
15789
16139
  },
15790
16140
  configForm: {
15791
16141
  form: {
15792
16142
  port: { help: "The receiving port", hint: { type: "numeric", validation: Port, defaultValue: 5001, global: unique("port") } },
15793
- ip: { help: "The receiving IP address", hint: { type: "text", validation: IpAddress, defaultValue: "127.0.0.1" } },
16143
+ host: { help: "The receiving IP address/hostname", hint: { type: "text", validation: Hostname, defaultValue: "127.0.0.1" } },
15794
16144
  sourceName: { help: "Source name to identify this by", hint: { type: "text", validation: SourceName, defaultValue: "udp-ts", global: unique("sourceName") } },
15795
- interface: { help: "Optional interface to bind to", hint: { type: "text", validation: Z.union([Z.string().min(2).max(32), Z.string().length(0)]).optional() } },
16145
+ interface: { help: "Optional interface to bind to", hint: { type: "text", optional: true, validation: Z.union([Z.string().min(2).max(32), Z.string().length(0)]).optional() } },
15796
16146
  timeout: { help: "Timeout in milliseconds before determining the input is closed", hint: { type: "numeric", validation: Z.number().refine((value) => value > 0 && value < 6e5, "Timeout must be less than 10 minutes"), defaultValue: 1e3 } },
15797
16147
  rtpDecapsulate: { help: "Whether to expect the input TS to be encapsulated in RTP via RFC 2250 (default: false)", hint: { type: "boolean" } }
15798
16148
  }
@@ -15801,11 +16151,12 @@ function info_default5({ defineComponent, Av, validation: { Z, Port, IpAddress,
15801
16151
  }
15802
16152
 
15803
16153
  // build/input.videoTestCard/info.js
15804
- function info_default6({ defineComponent, Video, validation: { SourceName }, common: { Resolutions, FrameRates } }) {
16154
+ function info_default6({ defineComponent, Video, validation: { SourceName, unique }, common: { Resolutions, FrameRates } }) {
15805
16155
  return defineComponent({
15806
16156
  identifier: "input.videoTestCard",
15807
16157
  category: "input",
15808
16158
  name: "Video Test Card",
16159
+ description: "The Video Test Card component generates a test card video stream with customizable settings.",
15809
16160
  subscription: {
15810
16161
  accepts: void 0,
15811
16162
  produces: {
@@ -15822,9 +16173,18 @@ function info_default6({ defineComponent, Video, validation: { SourceName }, com
15822
16173
  },
15823
16174
  configForm: {
15824
16175
  form: {
15825
- resolution: { help: "The resolution of the test card stream", hint: { type: "select", options: Resolutions, defaultValue: { width: 1280, height: 720 } } },
15826
- frameRate: { help: "The frame rate of the test card stream", hint: { type: "select", options: FrameRates, defaultValue: { frames: 25, seconds: 1 } } },
15827
- sourceName: { help: "Source name to use for this test card stream", hint: { type: "text", validation: SourceName, defaultValue: "video" } },
16176
+ resolution: {
16177
+ help: "The resolution of the test card stream",
16178
+ hint: { type: "select", options: Resolutions, defaultValue: { width: 1280, height: 720 } }
16179
+ },
16180
+ frameRate: {
16181
+ help: "The frame rate of the test card stream",
16182
+ hint: { type: "select", options: FrameRates, defaultValue: { frames: 25, seconds: 1 } }
16183
+ },
16184
+ sourceName: {
16185
+ help: "Source name to use for this test card stream",
16186
+ hint: { type: "text", validation: SourceName, defaultValue: "video", global: unique("sourceName") }
16187
+ },
15828
16188
  pattern: {
15829
16189
  help: "The pattern on the test card stream",
15830
16190
  hint: {
@@ -15843,15 +16203,16 @@ function info_default6({ defineComponent, Video, validation: { SourceName }, com
15843
16203
  }
15844
16204
 
15845
16205
  // build/output.autoCmaf/info.js
15846
- var import_react6 = __toESM(require_react());
15847
- function info_default7({ defineComponent, All, validation: { Z, Hostname } }) {
15848
- const SummaryView6 = import_react6.default.lazy(async () => Promise.resolve().then(() => (init_summary(), summary_exports)));
15849
- const FullscreenView2 = import_react6.default.lazy(async () => Promise.resolve().then(() => (init_fullscreen(), fullscreen_exports)));
15850
- const SegmentConfiguration2 = import_react6.default.lazy(async () => {
16206
+ var import_config = __toESM(require_config());
16207
+ var import_react5 = __toESM(require_react());
16208
+ function info_default7(R) {
16209
+ const { defineComponent, All, validation: { Z, Hostname } } = R;
16210
+ const FullscreenView2 = import_react5.default.lazy(async () => Promise.resolve().then(() => (init_fullscreen(), fullscreen_exports)));
16211
+ const SegmentConfiguration2 = import_react5.default.lazy(async () => {
15851
16212
  const views = await Promise.resolve().then(() => (init_form_views(), form_views_exports));
15852
16213
  return { default: views.SegmentConfiguration };
15853
16214
  });
15854
- const S3Destination2 = import_react6.default.lazy(async () => {
16215
+ const S3Destination2 = import_react5.default.lazy(async () => {
15855
16216
  const views = await Promise.resolve().then(() => (init_form_views(), form_views_exports));
15856
16217
  return { default: views.S3Destination };
15857
16218
  });
@@ -15859,6 +16220,7 @@ function info_default7({ defineComponent, All, validation: { Z, Hostname } }) {
15859
16220
  identifier: "output.autoCmaf",
15860
16221
  category: "output",
15861
16222
  name: "Auto CMAF",
16223
+ description: "This component handles the creation of CMAF outputs from multiple video and audio streams.",
15862
16224
  subscription: {
15863
16225
  // Again, accept anything
15864
16226
  // but reject the same stream twice
@@ -15869,10 +16231,36 @@ function info_default7({ defineComponent, All, validation: { Z, Hostname } }) {
15869
16231
  }
15870
16232
  },
15871
16233
  extraValidation: (ctx) => {
15872
- const audioStreams = ctx.subscriptions.filter((s) => s.streams.select.includes("audio"));
16234
+ const audioStreams = ctx.subscriptions.filter((s) => s.validatedStreams.select.includes("audio"));
15873
16235
  if (audioStreams.length == 0) {
15874
16236
  ctx.addError("AutoCMAF requires at least one audio stream");
15875
16237
  }
16238
+ const uniqueVideoStreamNodes = ctx.subscriptions.reduce((acc, s) => {
16239
+ if (s.validatedStreams.select.includes("video")) {
16240
+ if (!acc.includes(s.source)) {
16241
+ acc.push(s.source);
16242
+ }
16243
+ }
16244
+ return acc;
16245
+ }, []);
16246
+ if (uniqueVideoStreamNodes.length > 1) {
16247
+ ctx.addWarning("More than one video source detected, did you mean to do this? (For example: Did you subscribe to both a source *and* a ladder?)");
16248
+ }
16249
+ if (ctx.config.drmProvider && ctx.config.__global) {
16250
+ if (ctx.config.drmProvider === "ezdrm") {
16251
+ if (!ctx.config.__global.ezdrmConfig?.token) {
16252
+ ctx.addError("Provide EZDRM token in global configuration");
16253
+ }
16254
+ }
16255
+ if (ctx.config.drmProvider === "axinom") {
16256
+ if (!ctx.config.__global.axinomConfig?.tenantId) {
16257
+ ctx.addError("Provide Axinom DRM Tenant ID in global configuration");
16258
+ }
16259
+ if (!ctx.config.__global.axinomConfig?.managementKey) {
16260
+ ctx.addError("Provide Axinom DRM Management Key in global configuration");
16261
+ }
16262
+ }
16263
+ }
15876
16264
  },
15877
16265
  display: (desc) => {
15878
16266
  return {
@@ -15880,22 +16268,35 @@ function info_default7({ defineComponent, All, validation: { Z, Hostname } }) {
15880
16268
  };
15881
16269
  },
15882
16270
  runtime: {
15883
- initialState: () => ({}),
16271
+ initialState: () => ({
16272
+ enabled: true
16273
+ }),
15884
16274
  handleEvent(ev, state) {
15885
16275
  const evType = ev.type;
15886
16276
  switch (evType) {
15887
16277
  case "url-published":
15888
16278
  state.url = ev.url;
16279
+ state.drmToken = ev.drmToken;
16280
+ break;
16281
+ case "output-enabled":
16282
+ state.enabled = true;
16283
+ break;
16284
+ case "output-disabled":
16285
+ state.enabled = false;
15889
16286
  break;
15890
16287
  default:
15891
16288
  assertUnreachable3(evType);
15892
16289
  }
15893
16290
  return { ...state };
15894
16291
  },
15895
- summary: SummaryView6,
16292
+ //summary: SummaryView,
15896
16293
  fullscreen: FullscreenView2
15897
16294
  },
15898
16295
  configForm: {
16296
+ global: {
16297
+ ezdrmConfig: (0, import_config.GlobalEzDrmConfig)(R),
16298
+ axinomConfig: (0, import_config.GlobalAxinomConfig)(R)
16299
+ },
15899
16300
  form: {
15900
16301
  name: {
15901
16302
  help: "The name of the multivariant/dash playlist",
@@ -15963,6 +16364,7 @@ function info_default7({ defineComponent, All, validation: { Z, Hostname } }) {
15963
16364
  help: "How many segments back should a player start",
15964
16365
  hint: {
15965
16366
  type: "numeric",
16367
+ optional: true,
15966
16368
  validation: Z.number().min(3).max(10).int().optional()
15967
16369
  }
15968
16370
  },
@@ -15970,6 +16372,7 @@ function info_default7({ defineComponent, All, validation: { Z, Hostname } }) {
15970
16372
  help: "How many parts back should a player start",
15971
16373
  hint: {
15972
16374
  type: "numeric",
16375
+ optional: true,
15973
16376
  validation: Z.number().min(3).max(10).int().optional()
15974
16377
  }
15975
16378
  }
@@ -15987,12 +16390,11 @@ function info_default7({ defineComponent, All, validation: { Z, Hostname } }) {
15987
16390
  help: "The hostname of the s3 bucket to push to",
15988
16391
  hint: {
15989
16392
  type: "text",
15990
- defaultValue: "",
15991
16393
  validation: Hostname
15992
16394
  }
15993
16395
  },
15994
16396
  prefix: {
15995
- help: "The sub directory of the bucket to place playlists + segments into",
16397
+ help: "The sub directory of the bucket to place playlists and segments into",
15996
16398
  hint: {
15997
16399
  type: "text",
15998
16400
  defaultValue: ""
@@ -16007,6 +16409,23 @@ function info_default7({ defineComponent, All, validation: { Z, Hostname } }) {
16007
16409
  }
16008
16410
  }
16009
16411
  }
16412
+ },
16413
+ drmProvider: {
16414
+ help: "Encrypt with a DRM provider (if configured globally)",
16415
+ hint: {
16416
+ type: "select",
16417
+ optional: true,
16418
+ options: [
16419
+ {
16420
+ display: "EZDRM",
16421
+ value: "ezdrm"
16422
+ },
16423
+ {
16424
+ display: "Axinom DRM",
16425
+ value: "axinom"
16426
+ }
16427
+ ]
16428
+ }
16010
16429
  }
16011
16430
  }
16012
16431
  }
@@ -16017,15 +16436,16 @@ function assertUnreachable3(_) {
16017
16436
  }
16018
16437
 
16019
16438
  // build/output.preview/info.js
16020
- var import_react8 = __toESM(require_react());
16021
- var import_config = __toESM(require_config());
16439
+ var import_react7 = __toESM(require_react());
16440
+ var import_config2 = __toESM(require_config());
16022
16441
  function info_default8(R) {
16023
16442
  const { defineComponent, Av, validation: { JitterBuffer } } = R;
16024
- const InlineView13 = import_react8.default.lazy(async () => Promise.resolve().then(() => (init_inline_view3(), inline_view_exports3)));
16443
+ const InlineView13 = import_react7.default.lazy(async () => Promise.resolve().then(() => (init_inline_view3(), inline_view_exports3)));
16025
16444
  return defineComponent({
16026
16445
  identifier: "output.preview",
16027
16446
  category: "output",
16028
16447
  name: "Preview",
16448
+ description: "Preview allows for the real-time preview of media streams. It provides a way to visualize and monitor the output from various media sources before final processing or distribution.",
16029
16449
  subscription: {
16030
16450
  accepts: {
16031
16451
  type: "single-stream",
@@ -16034,8 +16454,8 @@ function info_default8(R) {
16034
16454
  produces: void 0
16035
16455
  },
16036
16456
  extraValidation: (ctx) => {
16037
- const video = ctx.subscriptions.filter((s) => s.streams.select.includes("video"));
16038
- const audio = ctx.subscriptions.filter((s) => s.streams.select.includes("audio"));
16457
+ const video = ctx.subscriptions.filter((s) => s.validatedStreams.select.includes("video"));
16458
+ const audio = ctx.subscriptions.filter((s) => s.validatedStreams.select.includes("audio"));
16039
16459
  if (video.length == 1 && audio.length == 1)
16040
16460
  return;
16041
16461
  if (video.length == 0) {
@@ -16075,11 +16495,12 @@ function info_default8(R) {
16075
16495
  },
16076
16496
  configForm: {
16077
16497
  global: {
16078
- iceServers: (0, import_config.GlobalIceServers)(R),
16079
- hardware: (0, import_config.HardwareSelection)()
16498
+ iceServers: (0, import_config2.GlobalIceServers)(R),
16499
+ hardware: (0, import_config2.HardwareSelection)()
16080
16500
  },
16081
16501
  form: {
16082
- bufferDelayMs: { help: "How many milliseconds in the jitter buffer", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 500 } }
16502
+ bufferDelayMs: { help: "How many milliseconds in the jitter buffer", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 500 } },
16503
+ skipTranscode: { help: "Skip transcoding for WebRTC-ready streams", hint: { type: "boolean", defaultValue: false } }
16083
16504
  }
16084
16505
  }
16085
16506
  });
@@ -16089,13 +16510,14 @@ function assertUnreachable4(_) {
16089
16510
  }
16090
16511
 
16091
16512
  // build/output.rtmp/info.js
16092
- var import_react9 = __toESM(require_react());
16513
+ var import_react8 = __toESM(require_react());
16093
16514
  function info_default9({ defineComponent, Av, validation: { Z, JitterBuffer } }) {
16094
- const InlineView13 = import_react9.default.lazy(async () => Promise.resolve().then(() => (init_inline_view4(), inline_view_exports4)));
16515
+ const InlineView13 = import_react8.default.lazy(async () => Promise.resolve().then(() => (init_inline_view4(), inline_view_exports4)));
16095
16516
  return defineComponent({
16096
16517
  identifier: "output.rtmp",
16097
16518
  category: "output",
16098
16519
  name: "RTMP Egest",
16520
+ description: "This component handles the output of RTMP (Real-Time Messaging Protocol) streams. It is used to connect to a remote RTMP server and manage the streaming of media. ",
16099
16521
  subscription: {
16100
16522
  // No validation?
16101
16523
  // Accept either *just* audio, or *just* video, or audio *and* video
@@ -16146,11 +16568,12 @@ function assertUnreachable5(_) {
16146
16568
  }
16147
16569
 
16148
16570
  // build/output.srt/info.js
16149
- var import_react10 = __toESM(require_react());
16571
+ var import_react9 = __toESM(require_react());
16572
+ var import_util = __toESM(require_util());
16150
16573
  function info_default10(registration) {
16151
16574
  const { defineComponent, All, validation } = registration;
16152
- const { Port, IpAddress, JitterBuffer, SrtPassphrase, SrtStreamId } = validation;
16153
- const SocketConfiguration2 = import_react10.default.lazy(async () => {
16575
+ const { Port, Hostname, JitterBuffer, SrtPassphrase, SrtStreamId } = validation;
16576
+ const SocketConfiguration2 = import_react9.default.lazy(async () => {
16154
16577
  const views = await Promise.resolve().then(() => (init_srt_form_views(), srt_form_views_exports));
16155
16578
  return { default: views.SocketConfiguration };
16156
16579
  });
@@ -16158,6 +16581,7 @@ function info_default10(registration) {
16158
16581
  identifier: "output.srt",
16159
16582
  category: "output",
16160
16583
  name: "SRT Egest",
16584
+ description: "This component manages the sending of SRT (Secure Reliable Transport) streams. It allows you to configure various settings to control how the SRT output is handled, including connection details, buffer settings, and delay options.",
16161
16585
  subscription: {
16162
16586
  // No validation?
16163
16587
  // Streams have to be unique? That's a stretch goal
@@ -16169,11 +16593,30 @@ function info_default10(registration) {
16169
16593
  display: (desc) => {
16170
16594
  return {
16171
16595
  port: desc.config.port?.toString() ?? "",
16172
- ip: desc.config.ip,
16596
+ host: desc.config.host,
16173
16597
  mode: desc.config.mode,
16174
16598
  bufferDelayMs: desc.config.bufferDelayMs?.toString() ?? "none"
16175
16599
  };
16176
16600
  },
16601
+ runtime: {
16602
+ initialState: () => ({
16603
+ enabled: true
16604
+ }),
16605
+ handleEvent(ev, state) {
16606
+ const evType = ev.type;
16607
+ switch (evType) {
16608
+ case "output-enabled":
16609
+ state.enabled = true;
16610
+ break;
16611
+ case "output-disabled":
16612
+ state.enabled = false;
16613
+ break;
16614
+ default:
16615
+ (0, import_util.assertUnreachable)(evType);
16616
+ }
16617
+ return { ...state };
16618
+ }
16619
+ },
16177
16620
  configForm: {
16178
16621
  form: {
16179
16622
  port: {
@@ -16189,7 +16632,7 @@ function info_default10(registration) {
16189
16632
  }
16190
16633
  }
16191
16634
  },
16192
- ip: { help: "The IP address this SRT output will connect to or listen on", hint: { type: "text", validation: IpAddress, defaultValue: "0.0.0.0" } },
16635
+ host: { help: "The IP address/Hostname this SRT output will connect to or listen on", hint: { type: "text", validation: Hostname, defaultValue: "0.0.0.0" } },
16193
16636
  bufferDelayMs: { help: "How many milliseconds in the jitter buffer", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 500 } },
16194
16637
  avDelayMs: { help: "How many milliseconds to delay A/V to account for subtitles/ancillary data", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 50 } },
16195
16638
  mode: {
@@ -16209,8 +16652,8 @@ function info_default10(registration) {
16209
16652
  ]
16210
16653
  }
16211
16654
  },
16212
- passphrase: { help: "Optional: Authentication for this SRT output", hint: { type: "text", validation: SrtPassphrase } },
16213
- streamId: { help: "Optional: StreamId to use when calling a remote listener", hint: { type: "text", validation: SrtStreamId } },
16655
+ passphrase: { help: "Optional: Authentication for this SRT output", hint: { type: "text", optional: true, validation: SrtPassphrase } },
16656
+ streamId: { help: "Optional: StreamId to use when calling a remote listener", hint: { type: "text", optional: true, validation: SrtStreamId } },
16214
16657
  socketOptions: {
16215
16658
  help: "Socket Options",
16216
16659
  hint: {
@@ -16228,11 +16671,12 @@ function info_default10(registration) {
16228
16671
  init_info();
16229
16672
 
16230
16673
  // build/output.udpTs/info.js
16231
- function info_default12({ defineComponent, All, validation: { Port, IpAddress, JitterBuffer, Iface, Z } }) {
16674
+ function info_default12({ defineComponent, All, validation: { Port, Hostname, JitterBuffer, Iface, Z } }) {
16232
16675
  return defineComponent({
16233
16676
  identifier: "output.udpTs",
16234
16677
  category: "output",
16235
16678
  name: "UDP TS Egest",
16679
+ description: "This component outputs multiple media streams over UDP in TS (Transport Stream) format. It accepts multiple input streams and sends them to a specified IP address and port.",
16236
16680
  subscription: {
16237
16681
  // Just works with no validation
16238
16682
  // although uniqueness again, stretch goal
@@ -16244,7 +16688,7 @@ function info_default12({ defineComponent, All, validation: { Port, IpAddress, J
16244
16688
  display: (desc) => {
16245
16689
  return {
16246
16690
  port: desc.config.port.toString(),
16247
- destinationIp: desc.config.destinationIp,
16691
+ destinationIp: desc.config.destinationHost,
16248
16692
  interface: desc.config.interface,
16249
16693
  bufferDelayMs: desc.config.bufferDelayMs?.toString() ?? "none"
16250
16694
  };
@@ -16252,7 +16696,7 @@ function info_default12({ defineComponent, All, validation: { Port, IpAddress, J
16252
16696
  configForm: {
16253
16697
  form: {
16254
16698
  port: { help: "The port this UDP TS output will send to", hint: { type: "numeric", validation: Port, defaultValue: 8001 } },
16255
- destinationIp: { help: "The IP address this UDP TS output will send to", hint: { type: "text", validation: IpAddress, defaultValue: "127.0.0.1" } },
16699
+ destinationHost: { help: "The IP address/Hostname this UDP TS output will send to", hint: { type: "text", validation: Hostname, defaultValue: "127.0.0.1" } },
16256
16700
  bufferDelayMs: { help: "How many milliseconds in the jitter buffer", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 500 } },
16257
16701
  interface: { help: "Which interface to bind to for publishing", hint: { type: "text", validation: Z.union([Z.string().length(0), Iface]), defaultValue: "any" } }
16258
16702
  }
@@ -16261,13 +16705,16 @@ function info_default12({ defineComponent, All, validation: { Port, IpAddress, J
16261
16705
  }
16262
16706
 
16263
16707
  // build/output.whep/info.js
16264
- var import_config2 = __toESM(require_config());
16708
+ var import_config3 = __toESM(require_config());
16709
+ var import_react12 = __toESM(require_react());
16265
16710
  function info_default13(R) {
16266
16711
  const { defineComponent, Av, validation: { JitterBuffer } } = R;
16712
+ const InlineView13 = import_react12.default.lazy(async () => Promise.resolve().then(() => (init_inline_view6(), inline_view_exports6)));
16267
16713
  return defineComponent({
16268
16714
  identifier: "output.whep",
16269
16715
  category: "output",
16270
16716
  name: "WHEP Egest",
16717
+ description: "This component allows us to use WebRTC egress for outputs.",
16271
16718
  subscription: {
16272
16719
  // No validation?
16273
16720
  // Accept either *just* audio, or *just* video, or audio *and* video
@@ -16282,9 +16729,25 @@ function info_default13(R) {
16282
16729
  display: (_desc) => {
16283
16730
  return {};
16284
16731
  },
16732
+ css: ["styles.css"],
16733
+ runtime: {
16734
+ initialState: () => ({}),
16735
+ handleEvent(ev, state) {
16736
+ const evType = ev.type;
16737
+ switch (evType) {
16738
+ case "url-published":
16739
+ state.url = ev.url;
16740
+ break;
16741
+ default:
16742
+ assertUnreachable8(evType);
16743
+ }
16744
+ return { ...state };
16745
+ },
16746
+ inline: InlineView13
16747
+ },
16285
16748
  configForm: {
16286
16749
  global: {
16287
- iceServers: (0, import_config2.GlobalIceServers)(R)
16750
+ iceServers: (0, import_config3.GlobalIceServers)(R)
16288
16751
  },
16289
16752
  form: {
16290
16753
  bufferDelayMs: { help: "How many milliseconds in the jitter buffer", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 500 } }
@@ -16292,14 +16755,21 @@ function info_default13(R) {
16292
16755
  }
16293
16756
  });
16294
16757
  }
16758
+ function assertUnreachable8(_) {
16759
+ throw new Error("Didn't expect to get here");
16760
+ }
16295
16761
 
16296
16762
  // build/processor.browserOverlay/info.js
16297
- var import_config3 = __toESM(require_config());
16763
+ var import_config4 = __toESM(require_config());
16764
+ var import_react14 = __toESM(require_react());
16765
+ var SummaryView6 = import_react14.default.lazy(async () => Promise.resolve().then(() => (init_summary_view3(), summary_view_exports3)));
16766
+ var InlineView10 = import_react14.default.lazy(async () => Promise.resolve().then(() => (init_inline_view7(), inline_view_exports7)));
16298
16767
  function info_default14({ defineComponent, Video, validation: { Z } }) {
16299
16768
  return defineComponent({
16300
- identifier: "processor.transform.browserOverlay",
16769
+ identifier: "processor.browserOverlay",
16301
16770
  category: "processor",
16302
16771
  name: "Browser Overlay",
16772
+ description: "Capture a live URL and overlay onto a video",
16303
16773
  subscription: {
16304
16774
  // Only accept a single video stream
16305
16775
  accepts: {
@@ -16316,12 +16786,33 @@ function info_default14({ defineComponent, Video, validation: { Z } }) {
16316
16786
  },
16317
16787
  display: (desc) => {
16318
16788
  return {
16319
- url: desc.config?.url
16789
+ url: desc.config.url
16320
16790
  };
16321
16791
  },
16792
+ runtime: {
16793
+ summary: SummaryView6,
16794
+ inline: InlineView10,
16795
+ initialState: () => ({
16796
+ currentUrl: "",
16797
+ enabled: true
16798
+ }),
16799
+ handleEvent: (ev, state) => {
16800
+ const evType = ev.type;
16801
+ switch (evType) {
16802
+ case "url-changed":
16803
+ return { ...state, currentUrl: ev.url };
16804
+ case "enabled":
16805
+ return { ...state, enabled: true };
16806
+ case "disabled":
16807
+ return { ...state, enabled: false };
16808
+ default:
16809
+ assertUnreachable9(evType);
16810
+ }
16811
+ }
16812
+ },
16322
16813
  configForm: {
16323
16814
  global: {
16324
- hardware: (0, import_config3.HardwareSelection)()
16815
+ hardware: (0, import_config4.HardwareSelection)()
16325
16816
  },
16326
16817
  form: {
16327
16818
  url: { help: "URL to render on top of the video", hint: { type: "text", validation: Z.string().url(), defaultValue: "" } }
@@ -16329,15 +16820,19 @@ function info_default14({ defineComponent, Video, validation: { Z } }) {
16329
16820
  }
16330
16821
  });
16331
16822
  }
16823
+ function assertUnreachable9(_) {
16824
+ throw new Error("Didn't expect to get here");
16825
+ }
16332
16826
 
16333
16827
  // build/processor.cascadingSwitch/info.js
16334
16828
  function info_default15({ defineComponent, Av, React: React14, common: { Resolutions, FrameRates } }) {
16335
16829
  const SourceSelection = React14.lazy(async () => Promise.resolve().then(() => (init_source_selection(), source_selection_exports)));
16336
- const InlineView13 = React14.lazy(async () => Promise.resolve().then(() => (init_inline_view6(), inline_view_exports6)));
16830
+ const InlineView13 = React14.lazy(async () => Promise.resolve().then(() => (init_inline_view8(), inline_view_exports8)));
16337
16831
  return defineComponent({
16338
- identifier: "processor.control.cascadingSwitch",
16832
+ identifier: "processor.cascadingSwitch",
16339
16833
  category: "processor",
16340
16834
  name: "Cascading Switch",
16835
+ description: "This component manages multiple A/V (audio and video) sources based on priority, allowing for the configuration of settings such as resolution, frame rate, sample rate, and channel layout.",
16341
16836
  subscription: {
16342
16837
  // This needs to change anyway
16343
16838
  // but it'll be the same as MCS
@@ -16352,10 +16847,10 @@ function info_default15({ defineComponent, Av, React: React14, common: { Resolut
16352
16847
  },
16353
16848
  extraValidation: function(ctx) {
16354
16849
  ctx.subscriptions.forEach((s) => {
16355
- if (!s.streams.select.includes("video")) {
16850
+ if (!s.validatedStreams.select.includes("video")) {
16356
16851
  ctx.addError(`Subscription to ${s.source} is missing video`);
16357
16852
  }
16358
- if (!s.streams.select.includes("audio")) {
16853
+ if (!s.validatedStreams.select.includes("audio")) {
16359
16854
  ctx.addError(`Subscription to ${s.source} is missing audio`);
16360
16855
  }
16361
16856
  if (s.streams.type == "take-all-streams") {
@@ -16411,7 +16906,7 @@ function info_default15({ defineComponent, Av, React: React14, common: { Resolut
16411
16906
  state.availableSources.splice(state.availableSources.indexOf(ev.source), 1);
16412
16907
  return { ...state };
16413
16908
  default:
16414
- assertUnreachable7(evType);
16909
+ assertUnreachable10(evType);
16415
16910
  }
16416
16911
  },
16417
16912
  inline: InlineView13,
@@ -16462,96 +16957,22 @@ function info_default15({ defineComponent, Av, React: React14, common: { Resolut
16462
16957
  }
16463
16958
  });
16464
16959
  }
16465
- function assertUnreachable7(_) {
16466
- throw new Error("Didn't expect to get here");
16467
- }
16468
-
16469
- // build/processor.dynamicBug/info.js
16470
- var import_config4 = __toESM(require_config());
16471
- var import_react15 = __toESM(require_react());
16472
- function info_default16({ defineComponent, Video }) {
16473
- const BugSelection2 = import_react15.default.lazy(async () => Promise.resolve().then(() => (init_bug_selection(), bug_selection_exports)));
16474
- const SummaryView6 = import_react15.default.lazy(async () => Promise.resolve().then(() => (init_summary_view3(), summary_view_exports3)));
16475
- return defineComponent({
16476
- identifier: "processor.dynamicBug",
16477
- category: "processor",
16478
- name: "Dynamic Bug",
16479
- subscription: {
16480
- // Only accept a single video stream
16481
- accepts: {
16482
- type: "single-stream",
16483
- media: Video
16484
- },
16485
- produces: {
16486
- type: "single-stream",
16487
- media: Video
16488
- }
16489
- },
16490
- extraValidation: function(ctx) {
16491
- ctx.requireVideo(1);
16492
- },
16493
- display: (desc) => {
16494
- return {
16495
- default: desc.config.defaultBug ?? "none"
16496
- };
16497
- },
16498
- runtime: {
16499
- summary: SummaryView6,
16500
- initialState: () => ({}),
16501
- handleEvent: (ev, state) => {
16502
- const evType = ev.type;
16503
- switch (evType) {
16504
- case "bug-changed":
16505
- return { ...state, activeBug: { file: ev.file, position: ev.position } };
16506
- default:
16507
- assertUnreachable8(evType);
16508
- }
16509
- }
16510
- },
16511
- configForm: {
16512
- global: {
16513
- hardware: (0, import_config4.HardwareSelection)()
16514
- },
16515
- form: {
16516
- defaultBug: {
16517
- help: "The default bug to render on the video (if any)",
16518
- hint: {
16519
- type: "custom",
16520
- component: BugSelection2
16521
- }
16522
- },
16523
- defaultPosition: {
16524
- help: "The default location to render the bug in",
16525
- hint: {
16526
- type: "select",
16527
- optional: true,
16528
- options: [
16529
- { value: "topleft", display: "Top Left" },
16530
- { value: "topright", display: "Top Right" },
16531
- { value: "bottomleft", display: "Bottom Left" },
16532
- { value: "bottomright", display: "Bottom Right" }
16533
- ]
16534
- }
16535
- }
16536
- }
16537
- }
16538
- });
16539
- }
16540
- function assertUnreachable8(_) {
16960
+ function assertUnreachable10(_) {
16541
16961
  throw new Error("Didn't expect to get here");
16542
16962
  }
16543
16963
 
16544
16964
  // build/processor.fixedLadder/info.js
16545
16965
  var import_react17 = __toESM(require_react());
16546
16966
  var import_config5 = __toESM(require_config());
16547
- function info_default17({ defineComponent, Video }) {
16967
+ function info_default16({ defineComponent, Video }) {
16548
16968
  const RungView = import_react17.default.lazy(async () => Promise.resolve().then(() => (init_rung_view(), rung_view_exports)));
16549
16969
  const CodecEditor3 = import_react17.default.lazy(async () => Promise.resolve().then(() => (init_codec_editor(), codec_editor_exports)));
16550
16970
  const CodecView = import_react17.default.lazy(async () => Promise.resolve().then(() => (init_codec_view(), codec_view_exports)));
16551
16971
  return defineComponent({
16552
- identifier: "processor.transform.fixedLadder",
16972
+ identifier: "processor.fixedLadder",
16553
16973
  category: "processor",
16554
16974
  name: "Encode Ladder",
16975
+ description: "The Fixed Ladder Encoder is a processor component for encoding a single input video stream into multiple encoded renditions. It creates an encoding ladder, where each `rung` represents a different quality level or rendition of the original video, typically varying in resolution and bitrate.",
16555
16976
  subscription: {
16556
16977
  // Only accept a single video stream
16557
16978
  accepts: {
@@ -16667,6 +17088,7 @@ function info_default17({ defineComponent, Video }) {
16667
17088
  help: `Settings to use when encoding using ${mode} mode`,
16668
17089
  hint: {
16669
17090
  type: "form-item",
17091
+ optional: true,
16670
17092
  view: CodecView,
16671
17093
  form: {
16672
17094
  width: {
@@ -16709,7 +17131,7 @@ function createSoftwareRung(rung) {
16709
17131
  case "h264_320x180":
16710
17132
  return createRungImpl({ name: rung, threads: 1, bitrate: 800 });
16711
17133
  default:
16712
- return assertUnreachable9(rung);
17134
+ return assertUnreachable11(rung);
16713
17135
  }
16714
17136
  }
16715
17137
  function createMa35dRung(rung) {
@@ -16723,7 +17145,7 @@ function createMa35dRung(rung) {
16723
17145
  case "h264_320x180":
16724
17146
  return createMa35DH264RungImpl({ name: rung, bitrate: 1e3 });
16725
17147
  default:
16726
- return assertUnreachable9(rung);
17148
+ return assertUnreachable11(rung);
16727
17149
  }
16728
17150
  }
16729
17151
  function createNvidiaRung(rung) {
@@ -16737,7 +17159,7 @@ function createNvidiaRung(rung) {
16737
17159
  case "h264_320x180":
16738
17160
  return createNvidiaRungImpl({ name: rung, bitrate: 8e5 });
16739
17161
  default:
16740
- return assertUnreachable9(rung);
17162
+ return assertUnreachable11(rung);
16741
17163
  }
16742
17164
  }
16743
17165
  function createQuadraRung(rung) {
@@ -16751,7 +17173,7 @@ function createQuadraRung(rung) {
16751
17173
  case "h264_320x180":
16752
17174
  return createQuadraRungImpl({ name: rung, bitrate: 8e5 });
16753
17175
  default:
16754
- return assertUnreachable9(rung);
17176
+ return assertUnreachable11(rung);
16755
17177
  }
16756
17178
  }
16757
17179
  function createLoganRung(rung) {
@@ -16765,7 +17187,7 @@ function createLoganRung(rung) {
16765
17187
  case "h264_320x180":
16766
17188
  return createLoganRungImpl({ name: rung, bitrate: 8e5 });
16767
17189
  default:
16768
- return assertUnreachable9(rung);
17190
+ return assertUnreachable11(rung);
16769
17191
  }
16770
17192
  }
16771
17193
  function createRungImpl({ name, threads, bitrate }) {
@@ -16863,62 +17285,248 @@ function rungWidth(rungName) {
16863
17285
  function rungHeight(rungName) {
16864
17286
  return parseInt(rungName.split("_")[1].split(`x`)[1]);
16865
17287
  }
16866
- function assertUnreachable9(_) {
17288
+ function assertUnreachable11(_) {
16867
17289
  throw new Error("Didn't expect to get here");
16868
17290
  }
16869
17291
 
16870
- // build/processor.whisper-transcribe/info.js
16871
- function info_default18({ defineComponent, Av, Subtitle, validation: { Z } }) {
17292
+ // build/processor.onscreenGraphic/info.js
17293
+ var import_config6 = __toESM(require_config());
17294
+ var import_react20 = __toESM(require_react());
17295
+ function info_default17({ defineComponent, Video }) {
17296
+ const GraphicSelection2 = import_react20.default.lazy(async () => Promise.resolve().then(() => (init_image_selection(), image_selection_exports)));
17297
+ const SummaryView8 = import_react20.default.lazy(async () => Promise.resolve().then(() => (init_summary_view4(), summary_view_exports4)));
16872
17298
  return defineComponent({
16873
- identifier: "processor.whisper-transcribe",
17299
+ identifier: "processor.onscreenGraphic",
16874
17300
  category: "processor",
16875
- name: "Whisper Transcribe",
17301
+ name: "Onscreen Graphic",
17302
+ description: "Overlay graphics onto a video",
16876
17303
  subscription: {
17304
+ // Only accept a single video stream
16877
17305
  accepts: {
16878
17306
  type: "single-stream",
16879
- media: Av
16880
- // video because we'll use the id of it..
17307
+ media: Video
16881
17308
  },
16882
17309
  produces: {
16883
- media: Subtitle,
16884
- type: "single-stream"
17310
+ type: "single-stream",
17311
+ media: Video
16885
17312
  }
16886
17313
  },
16887
17314
  extraValidation: function(ctx) {
16888
- const video = ctx.videoInputs();
16889
- const audio = ctx.audioInputs();
16890
- if (video.length !== 1) {
16891
- ctx.addError("Whisper Transcribe requires a single video stream to use as a reference");
16892
- }
16893
- if (audio.length !== 1) {
16894
- ctx.addError("Whisper Transcribe requires a single audio stream to transcribe");
16895
- }
17315
+ ctx.requireVideo(1);
16896
17316
  },
16897
17317
  display: (desc) => {
16898
17318
  return {
16899
- model: desc.config.model
17319
+ default: desc.config.initialGraphic ?? "none"
16900
17320
  };
16901
17321
  },
17322
+ runtime: {
17323
+ summary: SummaryView8,
17324
+ initialState: () => ({}),
17325
+ handleEvent: (ev, state) => {
17326
+ const evType = ev.type;
17327
+ switch (evType) {
17328
+ case "graphic-changed":
17329
+ return { ...state, activeGraphic: { file: ev.file, position: ev.position } };
17330
+ case "video-changed":
17331
+ return { ...state, currentVideo: ev.currentVideo };
17332
+ case "graphic-loaded":
17333
+ return { ...state, currentGraphic: ev.currentGraphic };
17334
+ default:
17335
+ assertUnreachable13(evType);
17336
+ }
17337
+ }
17338
+ },
17339
+ configForm: {
17340
+ global: {
17341
+ hardware: (0, import_config6.HardwareSelection)()
17342
+ },
17343
+ form: {
17344
+ initialGraphic: {
17345
+ help: "The initial graphic to render on the video (if any)",
17346
+ hint: {
17347
+ type: "custom",
17348
+ optional: true,
17349
+ component: GraphicSelection2
17350
+ }
17351
+ },
17352
+ initialPosition: {
17353
+ help: "The initial location at which to render the graphic",
17354
+ hint: {
17355
+ type: "select",
17356
+ optional: true,
17357
+ options: [
17358
+ { value: { type: "named", position: "topleft" }, display: "Top Left" },
17359
+ { value: { type: "named", position: "topright" }, display: "Top Right" },
17360
+ { value: { type: "named", position: "bottomleft" }, display: "Bottom Left" },
17361
+ { value: { type: "named", position: "bottomright" }, display: "Bottom Right" },
17362
+ { value: { type: "named", position: "center" }, display: "Centered" }
17363
+ ]
17364
+ }
17365
+ }
17366
+ }
17367
+ }
17368
+ });
17369
+ }
17370
+ function assertUnreachable13(_) {
17371
+ throw new Error("Didn't expect to get here");
17372
+ }
17373
+
17374
+ // build/processor.streamKeyOverride/info.js
17375
+ function info_default18({ defineComponent, All, validation: { Z } }) {
17376
+ return defineComponent({
17377
+ identifier: "processor.StreamKeyOverride",
17378
+ category: "processor",
17379
+ name: "Stream Key Override",
17380
+ description: "Override stream keys for several streams at once, setting some components of the keys and optionally incrementing stream ID.",
17381
+ subscription: {
17382
+ accepts: {
17383
+ type: "multi-stream",
17384
+ media: All
17385
+ },
17386
+ produces: {
17387
+ type: "fixed-list",
17388
+ possibleMedia: All,
17389
+ keys: (cfg, subs) => {
17390
+ const outputs = subs.flatMap((sub) => {
17391
+ const sourceNode = sub.document.components[sub.source];
17392
+ if (!sourceNode)
17393
+ return [];
17394
+ const produces = sourceNode.info.subscription.produces;
17395
+ if (produces?.type === "fixed-list") {
17396
+ return produces.keys(sourceNode.config, sourceNode.subscriptions).map((sel) => ({ ...sel, key: `${sourceNode.id}-${sel.key}`, display: `${sourceNode.config.displayName}: ${sel.display}` }));
17397
+ } else {
17398
+ return [{ key: `${sourceNode.id}`, display: `${sourceNode.config.displayName}`, media: produces ? produces.media : All }];
17399
+ }
17400
+ });
17401
+ if (cfg.output === "merged") {
17402
+ const media = Array.from(new Set(outputs.flatMap((x) => x.media)));
17403
+ return [{ key: `merged`, display: "Merged", media }];
17404
+ }
17405
+ return outputs;
17406
+ },
17407
+ selector: () => {
17408
+ console.error("Use selectOutputs from process.streamKeyOverride/runtime.ts, not selector from info.ts");
17409
+ return [];
17410
+ }
17411
+ }
17412
+ },
17413
+ display: ({ config }) => {
17414
+ const disp = {};
17415
+ disp.mode = config.mode || "simple";
17416
+ disp.output = config.output || "individually-selectable";
17417
+ if (config.sourceName) {
17418
+ disp.sourceName = config.sourceName;
17419
+ }
17420
+ if (config.programNumber !== void 0) {
17421
+ disp.programNumber = String(config.programNumber);
17422
+ }
17423
+ if (config.streamId !== void 0) {
17424
+ disp.streamId = String(config.streamId);
17425
+ }
17426
+ if (config.renditionName) {
17427
+ disp.renditionName = config.renditionName;
17428
+ }
17429
+ return disp;
17430
+ },
17431
+ extraValidation: (ctx) => {
17432
+ const { config, subscriptions } = ctx;
17433
+ if ((config.mode || "simple") == "simple" && config.sourceName && config.programNumber !== void 0 && config.streamId !== void 0 && config.renditionName) {
17434
+ if (subscriptions.length > 1)
17435
+ ctx.addError("A fully specified stream key override must only subscribe to one stream, or use a mode other than simple");
17436
+ }
17437
+ if (config.mode === "by-media-type" && config.streamId === void 0) {
17438
+ ctx.addError("You must specify the starting streamId for a by-media-type stream key override");
17439
+ }
17440
+ if (config.output === "merged" && !config.sourceName) {
17441
+ ctx.addError("You must specify a sourceName for a single merged output");
17442
+ }
17443
+ },
16902
17444
  configForm: {
16903
17445
  form: {
16904
- model: { help: "The ggml model path", hint: { type: "text", validation: Z.string().min(1, "Choosing a model is mandatory") } },
16905
- translate: { help: "Whether to translate the output to English", hint: { type: "boolean", defaultValue: false } },
16906
- language: { help: "Source language (otherwise automatic)", hint: { type: "text", validation: Z.union([Z.string().length(0), Z.string().min(1)]) } }
17446
+ mode: {
17447
+ help: "Multi-stream behavior",
17448
+ hint: {
17449
+ type: "select",
17450
+ defaultValue: "simple",
17451
+ options: [
17452
+ {
17453
+ display: "Override values directly",
17454
+ value: "simple"
17455
+ },
17456
+ {
17457
+ display: "Increment stream ID by media type (video, audio, ...)",
17458
+ value: "by-media-type"
17459
+ },
17460
+ {
17461
+ display: "Increment stream ID per program in order of subscription",
17462
+ value: "in-order"
17463
+ }
17464
+ ]
17465
+ }
17466
+ },
17467
+ output: {
17468
+ help: "Output individual streams or a single merged stream",
17469
+ hint: {
17470
+ type: "select",
17471
+ defaultValue: "individually-selectable",
17472
+ options: [
17473
+ {
17474
+ display: "Individual inputs can be selected in the output",
17475
+ value: "individually-selectable"
17476
+ },
17477
+ {
17478
+ display: "The outputs are merged into a single stream",
17479
+ value: "merged"
17480
+ }
17481
+ ]
17482
+ }
17483
+ },
17484
+ sourceName: {
17485
+ help: "Override source name",
17486
+ hint: {
17487
+ type: "text",
17488
+ optional: true
17489
+ }
17490
+ },
17491
+ programNumber: {
17492
+ help: "Override program number",
17493
+ hint: {
17494
+ type: "numeric",
17495
+ optional: true,
17496
+ validation: Z.number().min(0).int().optional()
17497
+ }
17498
+ },
17499
+ streamId: {
17500
+ help: "Override stream ID",
17501
+ hint: {
17502
+ type: "numeric",
17503
+ optional: true,
17504
+ validation: Z.number().min(0).int().optional()
17505
+ }
17506
+ },
17507
+ renditionName: {
17508
+ help: "Override rendition name",
17509
+ hint: {
17510
+ type: "text",
17511
+ optional: true
17512
+ }
17513
+ }
16907
17514
  }
16908
17515
  }
16909
17516
  });
16910
17517
  }
16911
17518
 
16912
- // build/util.latency/info.js
16913
- var import_react19 = __toESM(require_react());
17519
+ // build/util.stats.latency/info.js
17520
+ var import_react22 = __toESM(require_react());
16914
17521
  function info_default19(R) {
16915
17522
  const { defineComponent } = R;
16916
- const InlineView13 = import_react19.default.lazy(async () => Promise.resolve().then(() => (init_inline_view7(), inline_view_exports7)));
16917
- const SourceNodeSelection2 = import_react19.default.lazy(async () => Promise.resolve().then(() => (init_source_node_selection(), source_node_selection_exports)));
17523
+ const InlineView13 = import_react22.default.lazy(async () => Promise.resolve().then(() => (init_inline_view9(), inline_view_exports9)));
17524
+ const SourceNodeSelection2 = import_react22.default.lazy(async () => Promise.resolve().then(() => (init_source_node_selection(), source_node_selection_exports)));
16918
17525
  return defineComponent({
16919
- identifier: "util.latency-stats",
17526
+ identifier: "util.stats.latency",
16920
17527
  category: "output",
16921
17528
  name: "Latency Probe",
17529
+ description: "This component tracks and processes latency statistics within a media processing pipeline.",
16922
17530
  subscription: {
16923
17531
  accepts: void 0,
16924
17532
  produces: void 0
@@ -16941,7 +17549,7 @@ function info_default19(R) {
16941
17549
  break;
16942
17550
  }
16943
17551
  default:
16944
- assertUnreachable10(evType);
17552
+ assertUnreachable14(evType);
16945
17553
  }
16946
17554
  return { ...state };
16947
17555
  },
@@ -16995,113 +17603,7 @@ function info_default19(R) {
16995
17603
  }
16996
17604
  });
16997
17605
  }
16998
- function assertUnreachable10(_) {
16999
- throw new Error("Didn't expect to get here");
17000
- }
17001
-
17002
- // build/util.ma35d/info.js
17003
- var import_react21 = __toESM(require_react());
17004
- function info_default20(R) {
17005
- const { defineComponent } = R;
17006
- const InlineView13 = import_react21.default.lazy(async () => Promise.resolve().then(() => (init_inline_view8(), inline_view_exports8)));
17007
- return defineComponent({
17008
- identifier: "util.ma35d-stats",
17009
- category: "output",
17010
- name: "MA35D Stats",
17011
- subscription: {
17012
- accepts: void 0,
17013
- produces: void 0
17014
- },
17015
- display: (_desc) => {
17016
- return {};
17017
- },
17018
- runtime: {
17019
- initialState: () => ({
17020
- decoder: new Array(200).fill(0),
17021
- scaler: new Array(200).fill(0),
17022
- encoder: new Array(200).fill(0)
17023
- }),
17024
- handleEvent(ev, state) {
17025
- const evType = ev.type;
17026
- switch (evType) {
17027
- case "new-stats": {
17028
- state.decoder.push(ev.decoder);
17029
- state.scaler.push(ev.scaler);
17030
- state.encoder.push(ev.encoder);
17031
- while (state.decoder.length > 200) {
17032
- state.decoder.splice(0, 1);
17033
- state.scaler.splice(0, 1);
17034
- state.encoder.splice(0, 1);
17035
- }
17036
- break;
17037
- }
17038
- default:
17039
- assertUnreachable11(evType);
17040
- }
17041
- return { ...state };
17042
- },
17043
- inline: InlineView13
17044
- },
17045
- configForm: {
17046
- form: {}
17047
- }
17048
- });
17049
- }
17050
- function assertUnreachable11(_) {
17051
- throw new Error("Didn't expect to get here");
17052
- }
17053
-
17054
- // build/util.timestamps/info.js
17055
- var import_react23 = __toESM(require_react());
17056
- function info_default21(R) {
17057
- const { defineComponent, All } = R;
17058
- const InlineView13 = import_react23.default.lazy(async () => Promise.resolve().then(() => (init_inline_view9(), inline_view_exports9)));
17059
- return defineComponent({
17060
- identifier: "util.timestamps",
17061
- category: "output",
17062
- name: "Jitter",
17063
- subscription: {
17064
- accepts: {
17065
- type: "multi-stream",
17066
- media: All
17067
- },
17068
- produces: void 0
17069
- },
17070
- display: (_desc) => {
17071
- return {};
17072
- },
17073
- runtime: {
17074
- initialState: () => ({
17075
- timestamps: new Array(200).fill(0)
17076
- }),
17077
- handleEvent(ev, state) {
17078
- const evType = ev.type;
17079
- switch (evType) {
17080
- case "new-timestamp": {
17081
- const target = state.timestamps.find((e) => e.key === ev.key) ?? (() => {
17082
- const start = { key: ev.key, startTimeMs: (/* @__PURE__ */ new Date()).valueOf(), startTimestamp: ev.value, timestamps: [] };
17083
- state.timestamps.push(start);
17084
- return start;
17085
- })();
17086
- target.timestamps.push({ ts: ev.value, wall: ev.wallMs });
17087
- while (target.timestamps.length > 200) {
17088
- target.timestamps.splice(0, 1);
17089
- }
17090
- break;
17091
- }
17092
- default:
17093
- assertUnreachable12(evType);
17094
- }
17095
- return { ...state };
17096
- },
17097
- inline: InlineView13
17098
- },
17099
- configForm: {
17100
- form: {}
17101
- }
17102
- });
17103
- }
17104
- function assertUnreachable12(_) {
17606
+ function assertUnreachable14(_) {
17105
17607
  throw new Error("Didn't expect to get here");
17106
17608
  }
17107
17609
 
@@ -17138,8 +17640,6 @@ AllComponents.push((r) => info_default16(r));
17138
17640
  AllComponents.push((r) => info_default17(r));
17139
17641
  AllComponents.push((r) => info_default18(r));
17140
17642
  AllComponents.push((r) => info_default19(r));
17141
- AllComponents.push((r) => info_default20(r));
17142
- AllComponents.push((r) => info_default21(r));
17143
17643
  export {
17144
17644
  getNodeInfo as default
17145
17645
  };