@ceralive/cerastream 2026.7.6 → 2026.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/messages.js CHANGED
@@ -1,7 +1,7 @@
1
- import { z } from "zod";
2
- import { AUDIO_DELAY_MAX_MS } from "./constants.js";
3
- import { helloParamsSchema, helloResultSchema, } from "./envelope.js";
4
- import { balancerAlgorithmSchema, bitrateControlSchema, captureDeviceKindSchema, captureDeviceSchema, cerastreamConfigSchema, configChangePhaseSchema, inputModeSchema, mediaClassSchema, previewEncodeModeSchema, previewTierSchema, streamStateSchema, videoCodecSchema, } from "./types.js";
1
+ import { z } from 'zod';
2
+ import { AUDIO_DELAY_MAX_MS } from './constants.js';
3
+ import { helloParamsSchema, helloResultSchema } from './envelope.js';
4
+ import { balancerAlgorithmSchema, bitrateControlSchema, captureDeviceKindSchema, captureDeviceSchema, cerastreamConfigSchema, configChangePhaseSchema, inputModeSchema, mediaClassSchema, previewEncodeModeSchema, previewTierSchema, streamStateSchema, videoCodecSchema, } from './types.js';
5
5
  // The eight v1 control methods (schema.md "v1 messages"). Each is matched
6
6
  // byte-for-byte to schema.md: the JSON shape on the wire is the contract.
7
7
  // ---- 1. start ----
@@ -73,7 +73,7 @@ export const setBitrateResultSchema = z.object({
73
73
  // ---- 5. switch-input ----
74
74
  export const switchInputParamsSchema = z.object({
75
75
  input_id: z.string(), // device/input identifier from list-devices
76
- mode: inputModeSchema.default("manual"),
76
+ mode: inputModeSchema.default('manual'),
77
77
  });
78
78
  export const switchInputResultSchema = z.object({
79
79
  active_input: z.string(),
@@ -102,15 +102,15 @@ export const listDevicesResultSchema = z.object({
102
102
  });
103
103
  // ---- 7. subscribe-events ----
104
104
  export const eventTopicSchema = z.enum([
105
- "status",
106
- "switch",
107
- "device",
108
- "bitrate",
109
- "srt-stats",
110
- "error",
111
- "preview",
112
- "audio-level",
113
- "config-change",
105
+ 'status',
106
+ 'switch',
107
+ 'device',
108
+ 'bitrate',
109
+ 'srt-stats',
110
+ 'error',
111
+ 'preview',
112
+ 'audio-level',
113
+ 'config-change',
114
114
  ]);
115
115
  export const subscribeEventsParamsSchema = z.object({
116
116
  topics: z.array(eventTopicSchema).optional(), // default: all topics
@@ -119,14 +119,14 @@ export const subscribeEventsResultSchema = z.object({
119
119
  subscribed: z.array(eventTopicSchema),
120
120
  });
121
121
  // ---- 8. preview-session ----
122
- export const previewSessionParamsSchema = z.discriminatedUnion("action", [
122
+ export const previewSessionParamsSchema = z.discriminatedUnion('action', [
123
123
  z.object({
124
- action: z.literal("start"),
124
+ action: z.literal('start'),
125
125
  tier: previewTierSchema,
126
126
  }),
127
- z.object({ action: z.literal("stop"), session_id: z.string() }),
127
+ z.object({ action: z.literal('stop'), session_id: z.string() }),
128
128
  z.object({
129
- action: z.literal("signal"), // webrtc only
129
+ action: z.literal('signal'), // webrtc only
130
130
  session_id: z.string(),
131
131
  sdp: z.string().optional(),
132
132
  ice: z.unknown().optional(),
@@ -135,12 +135,12 @@ export const previewSessionParamsSchema = z.discriminatedUnion("action", [
135
135
  export const previewSessionResultSchema = z.object({
136
136
  session_id: z.string(),
137
137
  tier: previewTierSchema,
138
- transport: z.discriminatedUnion("kind", [
138
+ transport: z.discriminatedUnion('kind', [
139
139
  z.object({
140
- kind: z.literal("uds-binary"),
141
- socket: z.literal("/run/cerastream/preview.sock"),
140
+ kind: z.literal('uds-binary'),
141
+ socket: z.literal('/run/cerastream/preview.sock'),
142
142
  }),
143
- z.object({ kind: z.literal("webrtc"), sdp: z.string().optional() }),
143
+ z.object({ kind: z.literal('webrtc'), sdp: z.string().optional() }),
144
144
  ]),
145
145
  });
146
146
  // ---- 9. get-capabilities ----
@@ -176,8 +176,8 @@ export const platformCapsSchema = z.object({
176
176
  max_resolution: z.string(),
177
177
  // additive: the engine's resolved hardware kind and how it was resolved.
178
178
  // Optional so a pre-field engine (which omits both) still parses.
179
- hardware_kind: z.enum(["rk3588", "jetson", "n100", "generic"]).optional(),
180
- source: z.enum(["detected", "override"]).optional(),
179
+ hardware_kind: z.enum(['rk3588', 'jetson', 'n100', 'generic']).optional(),
180
+ source: z.enum(['detected', 'override']).optional(),
181
181
  });
182
182
  // Preview-server availability (0.4.0, additive). Lets the UI tell an unbound /
183
183
  // port-conflicted preview (enabled:true, bound:false) from a down engine.
@@ -231,7 +231,7 @@ export const changeConfigParamsSchema = z
231
231
  input_mode: captureDeviceKindSchema.optional(),
232
232
  })
233
233
  .refine((delta) => Object.keys(delta).length > 0, {
234
- message: "change-config delta must carry at least one field",
234
+ message: 'change-config delta must carry at least one field',
235
235
  });
236
236
  // `Ok` for every phase the transaction actually reached — INCLUDING
237
237
  // `rollback_failed`, an honest terminal outcome rather than an RPC fault. A
@@ -250,18 +250,18 @@ export const changeConfigResultSchema = z.object({
250
250
  * refuses to build a second session that would race it. Mirrors the Rust
251
251
  * `REASON_TEARDOWN_TIMEOUT`; consumers render it distinctly.
252
252
  */
253
- export const REASON_TEARDOWN_TIMEOUT = "teardown_timeout";
253
+ export const REASON_TEARDOWN_TIMEOUT = 'teardown_timeout';
254
254
  // ---- method registry (count-assertion source of truth) ----
255
255
  /** The eight v1 control methods (the literal JSON-RPC `method` strings). */
256
256
  export const V1_METHODS = [
257
- "start",
258
- "stop",
259
- "reload-config",
260
- "set-bitrate",
261
- "switch-input",
262
- "list-devices",
263
- "subscribe-events",
264
- "preview-session",
257
+ 'start',
258
+ 'stop',
259
+ 'reload-config',
260
+ 'set-bitrate',
261
+ 'switch-input',
262
+ 'list-devices',
263
+ 'subscribe-events',
264
+ 'preview-session',
265
265
  ];
266
266
  /**
267
267
  * method → { params, result } Zod schema pair. `hello` is the handshake; the
@@ -272,27 +272,27 @@ export const requestSchemas = {
272
272
  hello: { params: helloParamsSchema, result: helloResultSchema },
273
273
  start: { params: startParamsSchema, result: startResultSchema },
274
274
  stop: { params: stopParamsSchema, result: stopResultSchema },
275
- "reload-config": {
275
+ 'reload-config': {
276
276
  params: reloadConfigParamsSchema,
277
277
  result: reloadConfigResultSchema,
278
278
  },
279
- "set-bitrate": {
279
+ 'set-bitrate': {
280
280
  params: setBitrateParamsSchema,
281
281
  result: setBitrateResultSchema,
282
282
  },
283
- "switch-input": {
283
+ 'switch-input': {
284
284
  params: switchInputParamsSchema,
285
285
  result: switchInputResultSchema,
286
286
  },
287
- "list-devices": {
287
+ 'list-devices': {
288
288
  params: listDevicesParamsSchema,
289
289
  result: listDevicesResultSchema,
290
290
  },
291
- "subscribe-events": {
291
+ 'subscribe-events': {
292
292
  params: subscribeEventsParamsSchema,
293
293
  result: subscribeEventsResultSchema,
294
294
  },
295
- "preview-session": {
295
+ 'preview-session': {
296
296
  params: previewSessionParamsSchema,
297
297
  result: previewSessionResultSchema,
298
298
  },
package/dist/paths.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CONTROL_SOCKET_NAME, DEFAULT_IPC_DIR, PREVIEW_SOCKET_NAME } from "./constants.js";
1
+ import { CONTROL_SOCKET_NAME, DEFAULT_IPC_DIR, PREVIEW_SOCKET_NAME } from './constants.js';
2
2
  /** Resolve the IPC runtime dir: explicit override → {@link IPC_DIR_ENV} → default. */
3
3
  export declare function resolveIpcDir(override?: string): string;
4
4
  /** Resolve the control-plane socket path within the (possibly overridden) IPC dir. */
@@ -11,4 +11,4 @@ export declare function previewSocketPath(dir?: string): string;
11
11
  * `/usr/bin/cerastream` → the bare name (let PATH decide).
12
12
  */
13
13
  export declare function getCerastreamExec(execPath?: string): string;
14
- export { DEFAULT_IPC_DIR, CONTROL_SOCKET_NAME, PREVIEW_SOCKET_NAME };
14
+ export { CONTROL_SOCKET_NAME, DEFAULT_IPC_DIR, PREVIEW_SOCKET_NAME };
package/dist/paths.js CHANGED
@@ -1,7 +1,7 @@
1
- import { execSync } from "node:child_process";
2
- import { existsSync, statSync } from "node:fs";
3
- import { join } from "node:path";
4
- import { CERASTREAM_BIN, CONTROL_SOCKET_NAME, DEFAULT_IPC_DIR, IPC_DIR_ENV, PREVIEW_SOCKET_NAME, } from "./constants.js";
1
+ import { execSync } from 'node:child_process';
2
+ import { existsSync, statSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { CERASTREAM_BIN, CONTROL_SOCKET_NAME, DEFAULT_IPC_DIR, IPC_DIR_ENV, PREVIEW_SOCKET_NAME, } from './constants.js';
5
5
  // Socket-path + engine-exec helpers (ADR-0002 §3). They resolve the runtime IPC
6
6
  // dir from the CERASTREAM_IPC_DIR override (then the explicit arg), defaulting to
7
7
  // /run/cerastream. cerastream is a systemd-owned service (ADR-0005) — CeraUI
@@ -34,9 +34,7 @@ export function getCerastreamExec(execPath) {
34
34
  const inDir = join(execPath, CERASTREAM_BIN);
35
35
  if (isFile(inDir))
36
36
  return inDir;
37
- return execPath.endsWith(CERASTREAM_BIN)
38
- ? execPath
39
- : join(execPath, CERASTREAM_BIN);
37
+ return execPath.endsWith(CERASTREAM_BIN) ? execPath : join(execPath, CERASTREAM_BIN);
40
38
  }
41
39
  const onPath = findInPath(CERASTREAM_BIN);
42
40
  if (onPath)
@@ -57,10 +55,10 @@ function isFile(p) {
57
55
  function findInPath(name) {
58
56
  try {
59
57
  const out = execSync(`command -v ${name}`, {
60
- encoding: "utf-8",
61
- stdio: ["pipe", "pipe", "pipe"],
58
+ encoding: 'utf-8',
59
+ stdio: ['pipe', 'pipe', 'pipe'],
62
60
  }).trim();
63
- const first = out.split("\n")[0]?.trim();
61
+ const first = out.split('\n')[0]?.trim();
64
62
  if (first && existsSync(first))
65
63
  return first;
66
64
  }
@@ -69,4 +67,4 @@ function findInPath(name) {
69
67
  }
70
68
  return undefined;
71
69
  }
72
- export { DEFAULT_IPC_DIR, CONTROL_SOCKET_NAME, PREVIEW_SOCKET_NAME };
70
+ export { CONTROL_SOCKET_NAME, DEFAULT_IPC_DIR, PREVIEW_SOCKET_NAME };
package/dist/transport.js CHANGED
@@ -1,4 +1,4 @@
1
- import { MAX_LINE_BYTES } from "./constants.js";
1
+ import { MAX_LINE_BYTES } from './constants.js';
2
2
  /**
3
3
  * A single Unix-socket connection that frames bytes into NDJSON lines. Construct,
4
4
  * `open()` (rejects if the socket can't be reached), `send()` lines, `close()`
@@ -7,7 +7,7 @@ import { MAX_LINE_BYTES } from "./constants.js";
7
7
  export class LineSocket {
8
8
  socketPath;
9
9
  socket;
10
- buffer = "";
10
+ buffer = '';
11
11
  bufferedBytes = 0;
12
12
  handlers;
13
13
  closed = false;
@@ -39,7 +39,7 @@ export class LineSocket {
39
39
  */
40
40
  send(line) {
41
41
  if (this.closed || !this.socket) {
42
- throw new Error("LineSocket.send: socket is not open");
42
+ throw new Error('LineSocket.send: socket is not open');
43
43
  }
44
44
  this.socket.write(`${line}\n`);
45
45
  this.socket.flush();
@@ -61,9 +61,9 @@ export class LineSocket {
61
61
  onData(chunk) {
62
62
  if (this.closed)
63
63
  return;
64
- this.buffer += chunk.toString("utf8");
64
+ this.buffer += chunk.toString('utf8');
65
65
  this.bufferedBytes += chunk.byteLength;
66
- let nl = this.buffer.indexOf("\n");
66
+ let nl = this.buffer.indexOf('\n');
67
67
  if (nl === -1) {
68
68
  // No complete line yet — guard the unbounded-line case (fatal framing error).
69
69
  if (this.bufferedBytes > MAX_LINE_BYTES) {
@@ -80,9 +80,9 @@ export class LineSocket {
80
80
  }
81
81
  if (line.length > 0)
82
82
  this.handlers?.onLine(line);
83
- nl = this.buffer.indexOf("\n");
83
+ nl = this.buffer.indexOf('\n');
84
84
  }
85
- this.bufferedBytes = Buffer.byteLength(this.buffer, "utf8");
85
+ this.bufferedBytes = Buffer.byteLength(this.buffer, 'utf8');
86
86
  }
87
87
  fail(err) {
88
88
  this.fireClose(err);
package/dist/types.d.ts CHANGED
@@ -1,25 +1,25 @@
1
- import { z } from "zod";
1
+ import { z } from 'zod';
2
2
  export declare const streamStateSchema: z.ZodEnum<{
3
3
  idle: "idle";
4
4
  starting: "starting";
5
- streaming: "streaming";
6
5
  stopping: "stopping";
6
+ streaming: "streaming";
7
7
  }>;
8
8
  export type StreamState = z.infer<typeof streamStateSchema>;
9
9
  export declare const inputModeSchema: z.ZodEnum<{
10
- manual: "manual";
11
10
  auto: "auto";
11
+ manual: "manual";
12
12
  }>;
13
13
  export type InputMode = z.infer<typeof inputModeSchema>;
14
14
  export declare const balancerAlgorithmSchema: z.ZodEnum<{
15
15
  adaptive: "adaptive";
16
- fixed: "fixed";
17
16
  aimd: "aimd";
17
+ fixed: "fixed";
18
18
  }>;
19
19
  export type BalancerAlgorithm = z.infer<typeof balancerAlgorithmSchema>;
20
20
  export declare const mediaClassSchema: z.ZodEnum<{
21
- video: "video";
22
21
  audio: "audio";
22
+ video: "video";
23
23
  }>;
24
24
  export type MediaClass = z.infer<typeof mediaClassSchema>;
25
25
  export declare const previewTierSchema: z.ZodEnum<{
@@ -28,8 +28,8 @@ export declare const previewTierSchema: z.ZodEnum<{
28
28
  }>;
29
29
  export type PreviewTier = z.infer<typeof previewTierSchema>;
30
30
  export declare const previewEncodeModeSchema: z.ZodEnum<{
31
- software: "software";
32
31
  hardware: "hardware";
32
+ software: "software";
33
33
  }>;
34
34
  export type PreviewEncodeMode = z.infer<typeof previewEncodeModeSchema>;
35
35
  export declare const previewEncodeFallbackSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -57,25 +57,25 @@ export declare const bitrateControlSchema: z.ZodEnum<{
57
57
  export type BitrateControl = z.infer<typeof bitrateControlSchema>;
58
58
  export declare const captureDeviceKindSchema: z.ZodEnum<{
59
59
  audio: "audio";
60
+ camlink: "camlink";
60
61
  hdmi: "hdmi";
61
- uvc_h264: "uvc_h264";
62
- uvc_h265: "uvc_h265";
63
62
  mjpeg: "mjpeg";
64
- camlink: "camlink";
65
- test: "test";
66
63
  network: "network";
64
+ test: "test";
65
+ uvc_h264: "uvc_h264";
66
+ uvc_h265: "uvc_h265";
67
67
  }>;
68
68
  export type CaptureDeviceKind = z.infer<typeof captureDeviceKindSchema>;
69
69
  export declare const deviceTransportSchema: z.ZodEnum<{
70
- hdmi: "hdmi";
71
- usb: "usb";
72
70
  bluetooth: "bluetooth";
71
+ hdmi: "hdmi";
73
72
  onboard: "onboard";
73
+ usb: "usb";
74
74
  }>;
75
75
  export type DeviceTransport = z.infer<typeof deviceTransportSchema>;
76
76
  export declare const configChangePhaseSchema: z.ZodEnum<{
77
- applying: "applying";
78
77
  applied: "applied";
78
+ applying: "applying";
79
79
  reverted: "reverted";
80
80
  rollback_failed: "rollback_failed";
81
81
  }>;
@@ -98,8 +98,8 @@ export declare const bitrateConfigSchema: z.ZodObject<{
98
98
  max_bitrate: z.ZodNumber;
99
99
  balancer: z.ZodDefault<z.ZodEnum<{
100
100
  adaptive: "adaptive";
101
- fixed: "fixed";
102
101
  aimd: "aimd";
102
+ fixed: "fixed";
103
103
  }>>;
104
104
  }, z.core.$strip>;
105
105
  export type BitrateConfig = z.infer<typeof bitrateConfigSchema>;
@@ -112,15 +112,15 @@ export type BitrateConfig = z.infer<typeof bitrateConfigSchema>;
112
112
  */
113
113
  export declare const audioModeSchema: z.ZodEnum<{
114
114
  default: "default";
115
- none: "none";
116
115
  device: "device";
116
+ none: "none";
117
117
  }>;
118
118
  export type AudioMode = z.infer<typeof audioModeSchema>;
119
119
  export declare const audioConfigSchema: z.ZodObject<{
120
120
  mode: z.ZodOptional<z.ZodEnum<{
121
121
  default: "default";
122
- none: "none";
123
122
  device: "device";
123
+ none: "none";
124
124
  }>>;
125
125
  device: z.ZodOptional<z.ZodString>;
126
126
  codec: z.ZodOptional<z.ZodString>;
@@ -150,8 +150,8 @@ export declare const cerastreamConfigSchema: z.ZodObject<{
150
150
  max_bitrate: z.ZodNumber;
151
151
  balancer: z.ZodDefault<z.ZodEnum<{
152
152
  adaptive: "adaptive";
153
- fixed: "fixed";
154
153
  aimd: "aimd";
154
+ fixed: "fixed";
155
155
  }>>;
156
156
  }, z.core.$strip>;
157
157
  input_id: z.ZodOptional<z.ZodString>;
@@ -164,8 +164,8 @@ export declare const cerastreamConfigSchema: z.ZodObject<{
164
164
  audio: z.ZodOptional<z.ZodObject<{
165
165
  mode: z.ZodOptional<z.ZodEnum<{
166
166
  default: "default";
167
- none: "none";
168
167
  device: "device";
168
+ none: "none";
169
169
  }>>;
170
170
  device: z.ZodOptional<z.ZodString>;
171
171
  codec: z.ZodOptional<z.ZodString>;
@@ -178,13 +178,13 @@ export declare const cerastreamConfigSchema: z.ZodObject<{
178
178
  }>>;
179
179
  input_mode: z.ZodOptional<z.ZodEnum<{
180
180
  audio: "audio";
181
+ camlink: "camlink";
181
182
  hdmi: "hdmi";
182
- uvc_h264: "uvc_h264";
183
- uvc_h265: "uvc_h265";
184
183
  mjpeg: "mjpeg";
185
- camlink: "camlink";
186
- test: "test";
187
184
  network: "network";
185
+ test: "test";
186
+ uvc_h264: "uvc_h264";
187
+ uvc_h265: "uvc_h265";
188
188
  }>>;
189
189
  }, z.core.$strip>;
190
190
  export type CerastreamConfig = z.infer<typeof cerastreamConfigSchema>;
@@ -206,13 +206,13 @@ export declare const captureModeSchema: z.ZodObject<{
206
206
  media_type: z.ZodString;
207
207
  pipeline_kind: z.ZodEnum<{
208
208
  audio: "audio";
209
+ camlink: "camlink";
209
210
  hdmi: "hdmi";
210
- uvc_h264: "uvc_h264";
211
- uvc_h265: "uvc_h265";
212
211
  mjpeg: "mjpeg";
213
- camlink: "camlink";
214
- test: "test";
215
212
  network: "network";
213
+ test: "test";
214
+ uvc_h264: "uvc_h264";
215
+ uvc_h265: "uvc_h265";
216
216
  }>;
217
217
  caps: z.ZodArray<z.ZodObject<{
218
218
  width: z.ZodOptional<z.ZodNumber>;
@@ -227,8 +227,8 @@ export declare const captureDeviceSchema: z.ZodObject<{
227
227
  device_path: z.ZodString;
228
228
  display_name: z.ZodString;
229
229
  media_class: z.ZodEnum<{
230
- video: "video";
231
230
  audio: "audio";
231
+ video: "video";
232
232
  }>;
233
233
  caps: z.ZodOptional<z.ZodArray<z.ZodObject<{
234
234
  width: z.ZodOptional<z.ZodNumber>;
@@ -238,25 +238,25 @@ export declare const captureDeviceSchema: z.ZodObject<{
238
238
  }, z.core.$strip>>>;
239
239
  kind: z.ZodOptional<z.ZodEnum<{
240
240
  audio: "audio";
241
+ camlink: "camlink";
241
242
  hdmi: "hdmi";
242
- uvc_h264: "uvc_h264";
243
- uvc_h265: "uvc_h265";
244
243
  mjpeg: "mjpeg";
245
- camlink: "camlink";
246
- test: "test";
247
244
  network: "network";
245
+ test: "test";
246
+ uvc_h264: "uvc_h264";
247
+ uvc_h265: "uvc_h265";
248
248
  }>>;
249
249
  modes: z.ZodOptional<z.ZodArray<z.ZodObject<{
250
250
  media_type: z.ZodString;
251
251
  pipeline_kind: z.ZodEnum<{
252
252
  audio: "audio";
253
+ camlink: "camlink";
253
254
  hdmi: "hdmi";
254
- uvc_h264: "uvc_h264";
255
- uvc_h265: "uvc_h265";
256
255
  mjpeg: "mjpeg";
257
- camlink: "camlink";
258
- test: "test";
259
256
  network: "network";
257
+ test: "test";
258
+ uvc_h264: "uvc_h264";
259
+ uvc_h265: "uvc_h265";
260
260
  }>;
261
261
  caps: z.ZodArray<z.ZodObject<{
262
262
  width: z.ZodOptional<z.ZodNumber>;
@@ -268,10 +268,10 @@ export declare const captureDeviceSchema: z.ZodObject<{
268
268
  alsa_card_id: z.ZodOptional<z.ZodString>;
269
269
  product_name: z.ZodOptional<z.ZodString>;
270
270
  transport: z.ZodOptional<z.ZodEnum<{
271
- hdmi: "hdmi";
272
- usb: "usb";
273
271
  bluetooth: "bluetooth";
272
+ hdmi: "hdmi";
274
273
  onboard: "onboard";
274
+ usb: "usb";
275
275
  }>>;
276
276
  stable_id: z.ZodOptional<z.ZodString>;
277
277
  physical_group_id: z.ZodOptional<z.ZodString>;
package/dist/types.js CHANGED
@@ -1,24 +1,19 @@
1
- import { z } from "zod";
2
- import { DEFAULT_BALANCER, DEFAULT_MAX_BITRATE, DEFAULT_MIN_BITRATE, DEFAULT_SRT_LATENCY, } from "./constants.js";
1
+ import { z } from 'zod';
2
+ import { DEFAULT_BALANCER, DEFAULT_MAX_BITRATE, DEFAULT_MIN_BITRATE, DEFAULT_SRT_LATENCY, } from './constants.js';
3
3
  // Shared domain enums + the unified engine config. Field names are domain-level
4
4
  // (snake_case, matching the ceracoder config convention) — never engine
5
5
  // internals (schema.md "Conventions").
6
- export const streamStateSchema = z.enum([
7
- "idle",
8
- "starting",
9
- "streaming",
10
- "stopping",
11
- ]);
12
- export const inputModeSchema = z.enum(["manual", "auto"]);
6
+ export const streamStateSchema = z.enum(['idle', 'starting', 'streaming', 'stopping']);
7
+ export const inputModeSchema = z.enum(['manual', 'auto']);
13
8
  // re-used from ceracoder (schema.md §"v1 messages" shared fragments)
14
- export const balancerAlgorithmSchema = z.enum(["adaptive", "fixed", "aimd"]);
15
- export const mediaClassSchema = z.enum(["video", "audio"]);
16
- export const previewTierSchema = z.enum(["webcodecs", "webrtc"]);
9
+ export const balancerAlgorithmSchema = z.enum(['adaptive', 'fixed', 'aimd']);
10
+ export const mediaClassSchema = z.enum(['video', 'audio']);
11
+ export const previewTierSchema = z.enum(['webcodecs', 'webrtc']);
17
12
  // Which encoder the LIVE preview branch uses. Set through `reload-config`
18
13
  // (additive) and reported back as the ACTIVE mode on stream status. Applies to
19
14
  // the NEXT stream session: the preview encoder is fixed when a session graph is
20
15
  // built, so this never swaps an encoder mid-stream.
21
- export const previewEncodeModeSchema = z.enum(["software", "hardware"]);
16
+ export const previewEncodeModeSchema = z.enum(['software', 'hardware']);
22
17
  // Why a `hardware` preview request is encoding in software anyway — a tagged
23
18
  // union so a consumer branches on `code` and still receives the detail a code
24
19
  // carries. `property-failure` names the property the element refused, which is
@@ -26,48 +21,43 @@ export const previewEncodeModeSchema = z.enum(["software", "hardware"]);
26
21
  // plugin does not take `rc-mode`". ABSENT is the normal case (software was
27
22
  // chosen, hardware was delivered, or the board never offered the toggle) — there
28
23
  // is deliberately no `{code:"none"}` sentinel.
29
- export const previewEncodeFallbackSchema = z.discriminatedUnion("code", [
30
- z.object({ code: z.literal("factory-missing") }),
31
- z.object({ code: z.literal("property-failure"), property: z.string() }),
24
+ export const previewEncodeFallbackSchema = z.discriminatedUnion('code', [
25
+ z.object({ code: z.literal('factory-missing') }),
26
+ z.object({ code: z.literal('property-failure'), property: z.string() }),
32
27
  ]);
33
28
  // Requested egress video codec (0.4.0, additive). Absent ⇒ the engine picks its
34
29
  // platform default. Wire values are the codec id strings the encoder caps also
35
30
  // advertise ("h264"/"h265") — never an encoder element name.
36
- export const videoCodecSchema = z.enum(["h264", "h265"]);
31
+ export const videoCodecSchema = z.enum(['h264', 'h265']);
37
32
  // Same-codec passthrough policy (0.5.0, additive). Absent ⇒ "auto". "auto" =
38
33
  // passthrough only when adaptive bitrate is inactive and eligibility holds;
39
34
  // "force" = passthrough whenever eligible (typed start failure otherwise);
40
35
  // "off" = always transcode. See schema.md and the engine's layer-C matrix.
41
- export const videoPassthroughSchema = z.enum(["auto", "force", "off"]);
36
+ export const videoPassthroughSchema = z.enum(['auto', 'force', 'off']);
42
37
  // Which surface owns the running bitrate, reported additively on a set-bitrate /
43
38
  // reload-config response (0.5.0). "encoder" = applied; "source-fixed" = a
44
39
  // passthrough graph fixes the bitrate at the source, so the request was NOT
45
40
  // applied (paired with reason "passthrough").
46
- export const bitrateControlSchema = z.enum(["encoder", "source-fixed"]);
41
+ export const bitrateControlSchema = z.enum(['encoder', 'source-fixed']);
47
42
  // Engine-typed capture-device family (0.4.0, additive). CeraUI groups a device
48
43
  // by the engine's resolved kind (a UVC/USB dongle is uvc_h264/mjpeg, never
49
44
  // mislabeled HDMI). Absent ⇒ CeraUI falls back to a bus/name heuristic.
50
45
  export const captureDeviceKindSchema = z.enum([
51
- "hdmi",
52
- "uvc_h264",
53
- "uvc_h265",
54
- "mjpeg",
55
- "camlink",
56
- "audio",
57
- "test",
58
- "network",
46
+ 'hdmi',
47
+ 'uvc_h264',
48
+ 'uvc_h265',
49
+ 'mjpeg',
50
+ 'camlink',
51
+ 'audio',
52
+ 'test',
53
+ 'network',
59
54
  ]);
60
55
  // How a capture device is physically attached (Todo 20, additive). The transport
61
56
  // tag CeraUI renders beside the product name (e.g. "RØDE NT-USB · USB"). Distinct
62
57
  // from captureDeviceKind: an HDMI-to-USB dongle is kind:uvc_h264 but transport:usb,
63
58
  // while the SoC's dedicated HDMI-RX port is transport:hdmi. Absent on a legacy
64
59
  // producer or when no hint identifies a transport.
65
- export const deviceTransportSchema = z.enum([
66
- "usb",
67
- "hdmi",
68
- "bluetooth",
69
- "onboard",
70
- ]);
60
+ export const deviceTransportSchema = z.enum(['usb', 'hdmi', 'bluetooth', 'onboard']);
71
61
  // Phase of one `change-config` transaction (0.10.0, additive). `applying` is
72
62
  // published once at entry, then exactly ONE terminal phase for the same
73
63
  // attempt_id: `applied` (the new config satisfied the outcome gate),
@@ -75,10 +65,10 @@ export const deviceTransportSchema = z.enum([
75
65
  // `rollback_failed` (no rollback was possible, or the one attempt also failed —
76
66
  // the engine is idle, which is the truthful terminal state).
77
67
  export const configChangePhaseSchema = z.enum([
78
- "applying",
79
- "applied",
80
- "reverted",
81
- "rollback_failed",
68
+ 'applying',
69
+ 'applied',
70
+ 'reverted',
71
+ 'rollback_failed',
82
72
  ]);
83
73
  // ---- config sub-schemas (canonical; reused by `start` + the unified config) ----
84
74
  /** SRT transport config. Mirrors schema.md `start.srt` exactly. */
@@ -106,8 +96,8 @@ export const bitrateConfigSchema = z
106
96
  })
107
97
  // Mirrors the Rust dispatch guard: an inverted range can't drive the balancer.
108
98
  .refine((b) => b.min_bitrate <= b.max_bitrate, {
109
- message: "min_bitrate must not exceed max_bitrate",
110
- path: ["min_bitrate"],
99
+ message: 'min_bitrate must not exceed max_bitrate',
100
+ path: ['min_bitrate'],
111
101
  });
112
102
  /**
113
103
  * Audio config section of the unified engine config (0.4.0, additive). Every
@@ -122,7 +112,7 @@ export const bitrateConfigSchema = z
122
112
  // leg (requires `device`). Absent ⇒ legacy inference from `device`/source kind,
123
113
  // so a pre-0.6.0 caller keeps working. Replaces leaking pseudo-source strings
124
114
  // (e.g. "No audio") into `device`.
125
- export const audioModeSchema = z.enum(["none", "default", "device"]);
115
+ export const audioModeSchema = z.enum(['none', 'default', 'device']);
126
116
  export const audioConfigSchema = z.object({
127
117
  mode: audioModeSchema.optional(),
128
118
  device: z.string().optional(), // ALSA capture device id; absent ⇒ test-tone fallback