@ceralive/cerastream 2026.7.3 → 2026.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/client.d.ts +15 -1
- package/dist/client.js +4 -1
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +2 -2
- package/dist/errors.d.ts +13 -0
- package/dist/errors.js +15 -0
- package/dist/events.d.ts +152 -3
- package/dist/events.js +23 -3
- package/dist/messages.d.ts +117 -0
- package/dist/messages.js +49 -1
- package/dist/types.d.ts +58 -0
- package/dist/types.js +36 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,12 +6,14 @@ engine's JSON-RPC 2.0 / NDJSON control plane over a Unix domain socket.
|
|
|
6
6
|
|
|
7
7
|
- JSON-RPC 2.0 envelope + `hello` handshake schemas
|
|
8
8
|
- The eight v1 control methods (Zod params + result schemas + inferred types)
|
|
9
|
-
- The
|
|
9
|
+
- The nine server-push event payloads (discriminated union)
|
|
10
10
|
- Two-tier error codes (RPC + runtime)
|
|
11
11
|
- A unified engine config schema (= `start` params)
|
|
12
12
|
- A `CerastreamClient` interface + `connect()` factory (UDS transport)
|
|
13
13
|
- Additive `client.getCapabilities()` discovery for platform, source, encoder, and
|
|
14
14
|
local preview availability
|
|
15
|
+
- Additive `client.changeConfig()` — reconfigure the live session (resolution,
|
|
16
|
+
framerate, codec, pipeline, source) as one transaction with typed rollback
|
|
15
17
|
|
|
16
18
|
The Zod schemas, types, and constants are the frozen wire contract; `connect()`
|
|
17
19
|
drives that contract over an NDJSON/UDS transport with no native dependencies.
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type HelloResult } from "./envelope.js";
|
|
2
2
|
import { type EventParams } from "./events.js";
|
|
3
|
-
import { type GetCapabilitiesResult, type ListDevicesParams, type ListDevicesResult, type PreviewSessionParams, type PreviewSessionResult, type ReloadConfigParams, type ReloadConfigResult, type SetBitrateParams, type SetBitrateResult, type StartParams, type StartResult, type StopParams, type StopResult, type SubscribeEventsParams, type SubscribeEventsResult, type SwitchInputParams, type SwitchInputResult } from "./messages.js";
|
|
3
|
+
import { type ChangeConfigParams, type ChangeConfigResult, type GetCapabilitiesResult, type ListDevicesParams, type ListDevicesResult, type PreviewSessionParams, type PreviewSessionResult, type ReloadConfigParams, type ReloadConfigResult, type SetBitrateParams, type SetBitrateResult, type StartParams, type StartResult, type StopParams, type StopResult, type SubscribeEventsParams, type SubscribeEventsResult, type SwitchInputParams, type SwitchInputResult } from "./messages.js";
|
|
4
4
|
/** Options for {@link connect}. All optional — `connect({})` is valid. */
|
|
5
5
|
export interface ConnectOptions {
|
|
6
6
|
/** Control socket path override. Defaults to the resolved /run/cerastream/control.sock. */
|
|
@@ -82,6 +82,20 @@ export interface CerastreamClient {
|
|
|
82
82
|
* availability. This request intentionally sits outside the frozen v1 map.
|
|
83
83
|
*/
|
|
84
84
|
getCapabilities(): Promise<GetCapabilitiesResult>;
|
|
85
|
+
/**
|
|
86
|
+
* Reconfigure the LIVE session as one transaction (resolution, framerate,
|
|
87
|
+
* codec, pipeline, source). Also sits outside the frozen v1 map.
|
|
88
|
+
*
|
|
89
|
+
* Resolves for every phase the transaction reached — including
|
|
90
|
+
* `rollback_failed`, an honest terminal outcome. Callers must branch on
|
|
91
|
+
* `result.phase`, not on whether the promise settled. The engine's declared
|
|
92
|
+
* worst-case transaction bound is 65 000 ms, so size any caller-side deadline
|
|
93
|
+
* from that, not from the default per-request timeout.
|
|
94
|
+
* @param params A delta of the live config; absent field ⇒ keep live value.
|
|
95
|
+
* @throws {CerastreamRpcError} ONLY when the transaction never started (not
|
|
96
|
+
* streaming, a concurrent change, or an empty/invalid delta).
|
|
97
|
+
*/
|
|
98
|
+
changeConfig(params: ChangeConfigParams): Promise<ChangeConfigResult>;
|
|
85
99
|
/**
|
|
86
100
|
* Subscribe to the live event stream; `handler` fires for each pushed event.
|
|
87
101
|
* @param params The topics to subscribe to (absent ⇒ all topics).
|
package/dist/client.js
CHANGED
|
@@ -4,7 +4,7 @@ import { existsSync } from "node:fs";
|
|
|
4
4
|
import { CerastreamConnectionError, CerastreamRpcError, CerastreamTimeoutError, } from "./errors.js";
|
|
5
5
|
import { eventParamsSchema } from "./events.js";
|
|
6
6
|
import { controlSocketPath } from "./paths.js";
|
|
7
|
-
import { getCapabilitiesResultSchema, requestSchemas, } from "./messages.js";
|
|
7
|
+
import { changeConfigParamsSchema, changeConfigResultSchema, getCapabilitiesResultSchema, requestSchemas, } from "./messages.js";
|
|
8
8
|
import { LineSocket } from "./transport.js";
|
|
9
9
|
const DEFAULTS = {
|
|
10
10
|
requestTimeoutMs: 10_000,
|
|
@@ -82,6 +82,9 @@ class ClientImpl {
|
|
|
82
82
|
async getCapabilities() {
|
|
83
83
|
return getCapabilitiesResultSchema.parse(await this.rawRequest("get-capabilities", undefined));
|
|
84
84
|
}
|
|
85
|
+
async changeConfig(params) {
|
|
86
|
+
return changeConfigResultSchema.parse(await this.rawRequest("change-config", changeConfigParamsSchema.parse(params)));
|
|
87
|
+
}
|
|
85
88
|
previewSession(params) {
|
|
86
89
|
return this.call("preview-session", params);
|
|
87
90
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export declare const PROTOCOL_VERSION: "cerastream-ipc/1";
|
|
|
8
8
|
* additive-only within protocol major `cerastream-ipc/1` (ADR-0002 §4); this value
|
|
9
9
|
* only moves when the wire schema itself does, in lockstep across both languages.
|
|
10
10
|
*/
|
|
11
|
-
export declare const SCHEMA_VERSION: "0.
|
|
11
|
+
export declare const SCHEMA_VERSION: "0.11.0";
|
|
12
12
|
/** Runtime dir holding both control + preview sockets. systemd `RuntimeDirectory=cerastream`. */
|
|
13
13
|
export declare const DEFAULT_IPC_DIR: "/run/cerastream";
|
|
14
14
|
/** Env override for the IPC dir (tests/dev). Defaults to {@link DEFAULT_IPC_DIR}. */
|
|
@@ -63,7 +63,7 @@ export declare const PROFILE_CATALOG_VERSION: "1.0.0";
|
|
|
63
63
|
* ignores the field) never applies a semantic the caller assumed. Mirrors the
|
|
64
64
|
* Rust `ENGINE_FEATURES`.
|
|
65
65
|
*/
|
|
66
|
-
export declare const ENGINE_FEATURES: readonly ["video-passthrough"];
|
|
66
|
+
export declare const ENGINE_FEATURES: readonly ["video-passthrough", "input-mode"];
|
|
67
67
|
/** Engine binary name (systemd-owned; CeraUI never spawns it — ADR-0005). */
|
|
68
68
|
export declare const CERASTREAM_BIN: "cerastream";
|
|
69
69
|
export declare const DEFAULT_MIN_BITRATE = 300;
|
package/dist/constants.js
CHANGED
|
@@ -11,7 +11,7 @@ export const PROTOCOL_VERSION = "cerastream-ipc/1";
|
|
|
11
11
|
* additive-only within protocol major `cerastream-ipc/1` (ADR-0002 §4); this value
|
|
12
12
|
* only moves when the wire schema itself does, in lockstep across both languages.
|
|
13
13
|
*/
|
|
14
|
-
export const SCHEMA_VERSION = "0.
|
|
14
|
+
export const SCHEMA_VERSION = "0.11.0";
|
|
15
15
|
/** Runtime dir holding both control + preview sockets. systemd `RuntimeDirectory=cerastream`. */
|
|
16
16
|
export const DEFAULT_IPC_DIR = "/run/cerastream";
|
|
17
17
|
/** Env override for the IPC dir (tests/dev). Defaults to {@link DEFAULT_IPC_DIR}. */
|
|
@@ -72,7 +72,7 @@ export const PROFILE_CATALOG_VERSION = "1.0.0";
|
|
|
72
72
|
* ignores the field) never applies a semantic the caller assumed. Mirrors the
|
|
73
73
|
* Rust `ENGINE_FEATURES`.
|
|
74
74
|
*/
|
|
75
|
-
export const ENGINE_FEATURES = ["video-passthrough"];
|
|
75
|
+
export const ENGINE_FEATURES = ["video-passthrough", "input-mode"];
|
|
76
76
|
/** Engine binary name (systemd-owned; CeraUI never spawns it — ADR-0005). */
|
|
77
77
|
export const CERASTREAM_BIN = "cerastream";
|
|
78
78
|
// ---- config defaults (mirror ceracoder, the engine being replaced) ----
|
package/dist/errors.d.ts
CHANGED
|
@@ -88,8 +88,21 @@ export declare const processErrorCodeSchema: z.ZodEnum<{
|
|
|
88
88
|
pipeline_stall: "pipeline_stall";
|
|
89
89
|
srt_connect_failed: "srt_connect_failed";
|
|
90
90
|
srt_connection_lost: "srt_connection_lost";
|
|
91
|
+
capture_unrecoverable: "capture_unrecoverable";
|
|
91
92
|
}>;
|
|
92
93
|
export type ProcessErrorCode = z.infer<typeof processErrorCodeSchema>;
|
|
94
|
+
/**
|
|
95
|
+
* Why a capture device became `capture_unrecoverable` — the `reason` field of the
|
|
96
|
+
* `error` event. Mirrors the Rust `CaptureUnrecoverableReason`.
|
|
97
|
+
*/
|
|
98
|
+
export declare const captureUnrecoverableReasonSchema: z.ZodEnum<{
|
|
99
|
+
node_absent_reprobe_disabled: "node_absent_reprobe_disabled";
|
|
100
|
+
reprobe_no_reenumeration: "reprobe_no_reenumeration";
|
|
101
|
+
reprobe_identity_changed: "reprobe_identity_changed";
|
|
102
|
+
reprobe_node_still_absent: "reprobe_node_still_absent";
|
|
103
|
+
reprobe_unavailable: "reprobe_unavailable";
|
|
104
|
+
}>;
|
|
105
|
+
export type CaptureUnrecoverableReason = z.infer<typeof captureUnrecoverableReasonSchema>;
|
|
93
106
|
/** Origin of a Tier 2 runtime error (the notification channel CeraUI routes on). */
|
|
94
107
|
export declare const processErrorSourceSchema: z.ZodEnum<{
|
|
95
108
|
srtla: "srtla";
|
package/dist/errors.js
CHANGED
|
@@ -124,6 +124,21 @@ export const processErrorCodeSchema = z.enum([
|
|
|
124
124
|
"pipeline_stall",
|
|
125
125
|
"srt_connect_failed",
|
|
126
126
|
"srt_connection_lost",
|
|
127
|
+
// TERMINAL, unlike capture_video_error: the device is still on the bus but the
|
|
128
|
+
// engine has exhausted recovery, so a UI that keeps showing "reconnecting"
|
|
129
|
+
// would be lying. Always carries a captureUnrecoverableReasonSchema `reason`.
|
|
130
|
+
"capture_unrecoverable",
|
|
131
|
+
]);
|
|
132
|
+
/**
|
|
133
|
+
* Why a capture device became `capture_unrecoverable` — the `reason` field of the
|
|
134
|
+
* `error` event. Mirrors the Rust `CaptureUnrecoverableReason`.
|
|
135
|
+
*/
|
|
136
|
+
export const captureUnrecoverableReasonSchema = z.enum([
|
|
137
|
+
"node_absent_reprobe_disabled",
|
|
138
|
+
"reprobe_no_reenumeration",
|
|
139
|
+
"reprobe_identity_changed",
|
|
140
|
+
"reprobe_node_still_absent",
|
|
141
|
+
"reprobe_unavailable",
|
|
127
142
|
]);
|
|
128
143
|
/** Origin of a Tier 2 runtime error (the notification channel CeraUI routes on). */
|
|
129
144
|
export const processErrorSourceSchema = z.enum(["srtla", "engine"]);
|
package/dist/events.d.ts
CHANGED
|
@@ -115,6 +115,25 @@ export declare const deviceEventSchema: z.ZodObject<{
|
|
|
115
115
|
test: "test";
|
|
116
116
|
network: "network";
|
|
117
117
|
}>>;
|
|
118
|
+
modes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
119
|
+
media_type: z.ZodString;
|
|
120
|
+
pipeline_kind: z.ZodEnum<{
|
|
121
|
+
audio: "audio";
|
|
122
|
+
hdmi: "hdmi";
|
|
123
|
+
uvc_h264: "uvc_h264";
|
|
124
|
+
uvc_h265: "uvc_h265";
|
|
125
|
+
mjpeg: "mjpeg";
|
|
126
|
+
camlink: "camlink";
|
|
127
|
+
test: "test";
|
|
128
|
+
network: "network";
|
|
129
|
+
}>;
|
|
130
|
+
caps: z.ZodArray<z.ZodObject<{
|
|
131
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
132
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
133
|
+
framerate: z.ZodOptional<z.ZodString>;
|
|
134
|
+
media_type: z.ZodOptional<z.ZodString>;
|
|
135
|
+
}, z.core.$strip>>;
|
|
136
|
+
}, z.core.$strip>>>;
|
|
118
137
|
alsa_card_id: z.ZodOptional<z.ZodString>;
|
|
119
138
|
product_name: z.ZodOptional<z.ZodString>;
|
|
120
139
|
transport: z.ZodOptional<z.ZodEnum<{
|
|
@@ -124,6 +143,8 @@ export declare const deviceEventSchema: z.ZodObject<{
|
|
|
124
143
|
onboard: "onboard";
|
|
125
144
|
}>>;
|
|
126
145
|
stable_id: z.ZodOptional<z.ZodString>;
|
|
146
|
+
physical_group_id: z.ZodOptional<z.ZodString>;
|
|
147
|
+
hardware_serial: z.ZodOptional<z.ZodString>;
|
|
127
148
|
}, z.core.$strip>;
|
|
128
149
|
}, z.core.$strip>;
|
|
129
150
|
/** Payload of a {@link deviceEventSchema} event. */
|
|
@@ -162,12 +183,14 @@ export declare const runtimeErrorEventSchema: z.ZodObject<{
|
|
|
162
183
|
pipeline_stall: "pipeline_stall";
|
|
163
184
|
srt_connect_failed: "srt_connect_failed";
|
|
164
185
|
srt_connection_lost: "srt_connection_lost";
|
|
186
|
+
capture_unrecoverable: "capture_unrecoverable";
|
|
165
187
|
}>;
|
|
166
188
|
source: z.ZodEnum<{
|
|
167
189
|
srtla: "srtla";
|
|
168
190
|
engine: "engine";
|
|
169
191
|
}>;
|
|
170
192
|
reason: z.ZodOptional<z.ZodString>;
|
|
193
|
+
selected: z.ZodOptional<z.ZodBoolean>;
|
|
171
194
|
}, z.core.$strip>;
|
|
172
195
|
/** Payload of a {@link runtimeErrorEventSchema} event. */
|
|
173
196
|
export type RuntimeErrorEvent = z.infer<typeof runtimeErrorEventSchema>;
|
|
@@ -214,6 +237,28 @@ export declare const audioLevelEventSchema: z.ZodObject<{
|
|
|
214
237
|
}, z.core.$strip>;
|
|
215
238
|
/** Payload of a {@link audioLevelEventSchema} event. */
|
|
216
239
|
export type AudioLevelEvent = z.infer<typeof audioLevelEventSchema>;
|
|
240
|
+
/**
|
|
241
|
+
* `config-change` event — one phase of a `change-config` transaction (0.10.0,
|
|
242
|
+
* additive Todo 9). Exactly one `applying` at entry, then exactly ONE terminal
|
|
243
|
+
* phase for the same `attempt_id` (which the RPC result also echoes, so a caller
|
|
244
|
+
* that missed an event can still correlate). A terminal phase is published only
|
|
245
|
+
* after the outcome gate resolved, so `applied` means "PLAYING **and** frames
|
|
246
|
+
* actually advancing", never merely "PLAYING".
|
|
247
|
+
*/
|
|
248
|
+
export declare const configChangeEventSchema: z.ZodObject<{
|
|
249
|
+
type: z.ZodLiteral<"config-change">;
|
|
250
|
+
seq: z.ZodNumber;
|
|
251
|
+
attempt_id: z.ZodString;
|
|
252
|
+
phase: z.ZodEnum<{
|
|
253
|
+
applying: "applying";
|
|
254
|
+
applied: "applied";
|
|
255
|
+
reverted: "reverted";
|
|
256
|
+
rollback_failed: "rollback_failed";
|
|
257
|
+
}>;
|
|
258
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
259
|
+
}, z.core.$strip>;
|
|
260
|
+
/** Payload of a {@link configChangeEventSchema} event. */
|
|
261
|
+
export type ConfigChangeEvent = z.infer<typeof configChangeEventSchema>;
|
|
217
262
|
/** Discriminated union of every v1 event payload (the inner `params`). */
|
|
218
263
|
export declare const eventParamsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
219
264
|
type: z.ZodLiteral<"status">;
|
|
@@ -288,6 +333,25 @@ export declare const eventParamsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
288
333
|
test: "test";
|
|
289
334
|
network: "network";
|
|
290
335
|
}>>;
|
|
336
|
+
modes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
337
|
+
media_type: z.ZodString;
|
|
338
|
+
pipeline_kind: z.ZodEnum<{
|
|
339
|
+
audio: "audio";
|
|
340
|
+
hdmi: "hdmi";
|
|
341
|
+
uvc_h264: "uvc_h264";
|
|
342
|
+
uvc_h265: "uvc_h265";
|
|
343
|
+
mjpeg: "mjpeg";
|
|
344
|
+
camlink: "camlink";
|
|
345
|
+
test: "test";
|
|
346
|
+
network: "network";
|
|
347
|
+
}>;
|
|
348
|
+
caps: z.ZodArray<z.ZodObject<{
|
|
349
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
350
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
351
|
+
framerate: z.ZodOptional<z.ZodString>;
|
|
352
|
+
media_type: z.ZodOptional<z.ZodString>;
|
|
353
|
+
}, z.core.$strip>>;
|
|
354
|
+
}, z.core.$strip>>>;
|
|
291
355
|
alsa_card_id: z.ZodOptional<z.ZodString>;
|
|
292
356
|
product_name: z.ZodOptional<z.ZodString>;
|
|
293
357
|
transport: z.ZodOptional<z.ZodEnum<{
|
|
@@ -297,6 +361,8 @@ export declare const eventParamsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
297
361
|
onboard: "onboard";
|
|
298
362
|
}>>;
|
|
299
363
|
stable_id: z.ZodOptional<z.ZodString>;
|
|
364
|
+
physical_group_id: z.ZodOptional<z.ZodString>;
|
|
365
|
+
hardware_serial: z.ZodOptional<z.ZodString>;
|
|
300
366
|
}, z.core.$strip>;
|
|
301
367
|
}, z.core.$strip>, z.ZodObject<{
|
|
302
368
|
type: z.ZodLiteral<"bitrate">;
|
|
@@ -320,12 +386,14 @@ export declare const eventParamsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
320
386
|
pipeline_stall: "pipeline_stall";
|
|
321
387
|
srt_connect_failed: "srt_connect_failed";
|
|
322
388
|
srt_connection_lost: "srt_connection_lost";
|
|
389
|
+
capture_unrecoverable: "capture_unrecoverable";
|
|
323
390
|
}>;
|
|
324
391
|
source: z.ZodEnum<{
|
|
325
392
|
srtla: "srtla";
|
|
326
393
|
engine: "engine";
|
|
327
394
|
}>;
|
|
328
395
|
reason: z.ZodOptional<z.ZodString>;
|
|
396
|
+
selected: z.ZodOptional<z.ZodBoolean>;
|
|
329
397
|
}, z.core.$strip>, z.ZodObject<{
|
|
330
398
|
type: z.ZodLiteral<"preview">;
|
|
331
399
|
seq: z.ZodNumber;
|
|
@@ -352,6 +420,17 @@ export declare const eventParamsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
352
420
|
mode_none: "mode_none";
|
|
353
421
|
handoff: "handoff";
|
|
354
422
|
}>>;
|
|
423
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
424
|
+
type: z.ZodLiteral<"config-change">;
|
|
425
|
+
seq: z.ZodNumber;
|
|
426
|
+
attempt_id: z.ZodString;
|
|
427
|
+
phase: z.ZodEnum<{
|
|
428
|
+
applying: "applying";
|
|
429
|
+
applied: "applied";
|
|
430
|
+
reverted: "reverted";
|
|
431
|
+
rollback_failed: "rollback_failed";
|
|
432
|
+
}>;
|
|
433
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
355
434
|
}, z.core.$strip>], "type">;
|
|
356
435
|
export type EventParams = z.infer<typeof eventParamsSchema>;
|
|
357
436
|
/** Full event envelope: { jsonrpc, method:"event", params } with typed params. */
|
|
@@ -431,6 +510,25 @@ export declare const cerastreamEventSchema: z.ZodObject<{
|
|
|
431
510
|
test: "test";
|
|
432
511
|
network: "network";
|
|
433
512
|
}>>;
|
|
513
|
+
modes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
514
|
+
media_type: z.ZodString;
|
|
515
|
+
pipeline_kind: z.ZodEnum<{
|
|
516
|
+
audio: "audio";
|
|
517
|
+
hdmi: "hdmi";
|
|
518
|
+
uvc_h264: "uvc_h264";
|
|
519
|
+
uvc_h265: "uvc_h265";
|
|
520
|
+
mjpeg: "mjpeg";
|
|
521
|
+
camlink: "camlink";
|
|
522
|
+
test: "test";
|
|
523
|
+
network: "network";
|
|
524
|
+
}>;
|
|
525
|
+
caps: z.ZodArray<z.ZodObject<{
|
|
526
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
527
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
528
|
+
framerate: z.ZodOptional<z.ZodString>;
|
|
529
|
+
media_type: z.ZodOptional<z.ZodString>;
|
|
530
|
+
}, z.core.$strip>>;
|
|
531
|
+
}, z.core.$strip>>>;
|
|
434
532
|
alsa_card_id: z.ZodOptional<z.ZodString>;
|
|
435
533
|
product_name: z.ZodOptional<z.ZodString>;
|
|
436
534
|
transport: z.ZodOptional<z.ZodEnum<{
|
|
@@ -440,6 +538,8 @@ export declare const cerastreamEventSchema: z.ZodObject<{
|
|
|
440
538
|
onboard: "onboard";
|
|
441
539
|
}>>;
|
|
442
540
|
stable_id: z.ZodOptional<z.ZodString>;
|
|
541
|
+
physical_group_id: z.ZodOptional<z.ZodString>;
|
|
542
|
+
hardware_serial: z.ZodOptional<z.ZodString>;
|
|
443
543
|
}, z.core.$strip>;
|
|
444
544
|
}, z.core.$strip>, z.ZodObject<{
|
|
445
545
|
type: z.ZodLiteral<"bitrate">;
|
|
@@ -463,12 +563,14 @@ export declare const cerastreamEventSchema: z.ZodObject<{
|
|
|
463
563
|
pipeline_stall: "pipeline_stall";
|
|
464
564
|
srt_connect_failed: "srt_connect_failed";
|
|
465
565
|
srt_connection_lost: "srt_connection_lost";
|
|
566
|
+
capture_unrecoverable: "capture_unrecoverable";
|
|
466
567
|
}>;
|
|
467
568
|
source: z.ZodEnum<{
|
|
468
569
|
srtla: "srtla";
|
|
469
570
|
engine: "engine";
|
|
470
571
|
}>;
|
|
471
572
|
reason: z.ZodOptional<z.ZodString>;
|
|
573
|
+
selected: z.ZodOptional<z.ZodBoolean>;
|
|
472
574
|
}, z.core.$strip>, z.ZodObject<{
|
|
473
575
|
type: z.ZodLiteral<"preview">;
|
|
474
576
|
seq: z.ZodNumber;
|
|
@@ -495,12 +597,24 @@ export declare const cerastreamEventSchema: z.ZodObject<{
|
|
|
495
597
|
mode_none: "mode_none";
|
|
496
598
|
handoff: "handoff";
|
|
497
599
|
}>>;
|
|
600
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
601
|
+
type: z.ZodLiteral<"config-change">;
|
|
602
|
+
seq: z.ZodNumber;
|
|
603
|
+
attempt_id: z.ZodString;
|
|
604
|
+
phase: z.ZodEnum<{
|
|
605
|
+
applying: "applying";
|
|
606
|
+
applied: "applied";
|
|
607
|
+
reverted: "reverted";
|
|
608
|
+
rollback_failed: "rollback_failed";
|
|
609
|
+
}>;
|
|
610
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
498
611
|
}, z.core.$strip>], "type">;
|
|
499
612
|
}, z.core.$strip>;
|
|
500
613
|
export type CerastreamEvent = z.infer<typeof cerastreamEventSchema>;
|
|
501
|
-
/** The
|
|
502
|
-
* `audio-level`
|
|
503
|
-
|
|
614
|
+
/** The nine event topics (schema.md "Events" table) — count-assertion source.
|
|
615
|
+
* `audio-level` (Todo 21) and `config-change` (Todo 9) are additive and appended
|
|
616
|
+
* last, preserving the order of every prior topic. */
|
|
617
|
+
export declare const EVENT_TOPICS: readonly ["status", "switch", "device", "bitrate", "srt-stats", "error", "preview", "audio-level", "config-change"];
|
|
504
618
|
export type EventTopicName = (typeof EVENT_TOPICS)[number];
|
|
505
619
|
/** topic → payload Zod schema. Tests assert every topic is represented here. */
|
|
506
620
|
export declare const eventSchemas: {
|
|
@@ -579,6 +693,25 @@ export declare const eventSchemas: {
|
|
|
579
693
|
test: "test";
|
|
580
694
|
network: "network";
|
|
581
695
|
}>>;
|
|
696
|
+
modes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
697
|
+
media_type: z.ZodString;
|
|
698
|
+
pipeline_kind: z.ZodEnum<{
|
|
699
|
+
audio: "audio";
|
|
700
|
+
hdmi: "hdmi";
|
|
701
|
+
uvc_h264: "uvc_h264";
|
|
702
|
+
uvc_h265: "uvc_h265";
|
|
703
|
+
mjpeg: "mjpeg";
|
|
704
|
+
camlink: "camlink";
|
|
705
|
+
test: "test";
|
|
706
|
+
network: "network";
|
|
707
|
+
}>;
|
|
708
|
+
caps: z.ZodArray<z.ZodObject<{
|
|
709
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
710
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
711
|
+
framerate: z.ZodOptional<z.ZodString>;
|
|
712
|
+
media_type: z.ZodOptional<z.ZodString>;
|
|
713
|
+
}, z.core.$strip>>;
|
|
714
|
+
}, z.core.$strip>>>;
|
|
582
715
|
alsa_card_id: z.ZodOptional<z.ZodString>;
|
|
583
716
|
product_name: z.ZodOptional<z.ZodString>;
|
|
584
717
|
transport: z.ZodOptional<z.ZodEnum<{
|
|
@@ -588,6 +721,8 @@ export declare const eventSchemas: {
|
|
|
588
721
|
onboard: "onboard";
|
|
589
722
|
}>>;
|
|
590
723
|
stable_id: z.ZodOptional<z.ZodString>;
|
|
724
|
+
physical_group_id: z.ZodOptional<z.ZodString>;
|
|
725
|
+
hardware_serial: z.ZodOptional<z.ZodString>;
|
|
591
726
|
}, z.core.$strip>;
|
|
592
727
|
}, z.core.$strip>;
|
|
593
728
|
readonly bitrate: z.ZodObject<{
|
|
@@ -614,12 +749,14 @@ export declare const eventSchemas: {
|
|
|
614
749
|
pipeline_stall: "pipeline_stall";
|
|
615
750
|
srt_connect_failed: "srt_connect_failed";
|
|
616
751
|
srt_connection_lost: "srt_connection_lost";
|
|
752
|
+
capture_unrecoverable: "capture_unrecoverable";
|
|
617
753
|
}>;
|
|
618
754
|
source: z.ZodEnum<{
|
|
619
755
|
srtla: "srtla";
|
|
620
756
|
engine: "engine";
|
|
621
757
|
}>;
|
|
622
758
|
reason: z.ZodOptional<z.ZodString>;
|
|
759
|
+
selected: z.ZodOptional<z.ZodBoolean>;
|
|
623
760
|
}, z.core.$strip>;
|
|
624
761
|
readonly preview: z.ZodObject<{
|
|
625
762
|
type: z.ZodLiteral<"preview">;
|
|
@@ -649,4 +786,16 @@ export declare const eventSchemas: {
|
|
|
649
786
|
handoff: "handoff";
|
|
650
787
|
}>>;
|
|
651
788
|
}, z.core.$strip>;
|
|
789
|
+
readonly "config-change": z.ZodObject<{
|
|
790
|
+
type: z.ZodLiteral<"config-change">;
|
|
791
|
+
seq: z.ZodNumber;
|
|
792
|
+
attempt_id: z.ZodString;
|
|
793
|
+
phase: z.ZodEnum<{
|
|
794
|
+
applying: "applying";
|
|
795
|
+
applied: "applied";
|
|
796
|
+
reverted: "reverted";
|
|
797
|
+
rollback_failed: "rollback_failed";
|
|
798
|
+
}>;
|
|
799
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
800
|
+
}, z.core.$strip>;
|
|
652
801
|
};
|
package/dist/events.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { processErrorCodeSchema, processErrorSourceSchema, } from "./errors.js";
|
|
3
|
-
import { captureDeviceSchema, inputModeSchema, mediaClassSchema, streamStateSchema, } from "./types.js";
|
|
3
|
+
import { captureDeviceSchema, configChangePhaseSchema, inputModeSchema, mediaClassSchema, streamStateSchema, } from "./types.js";
|
|
4
4
|
// Server → client `event` notifications, delivered after `subscribe-events`
|
|
5
5
|
// (schema.md "Events"). Each event is the inner `params` of an rpcEventSchema:
|
|
6
6
|
// { type, seq, … }. `type` discriminates; `seq` is a per-type monotonic counter.
|
|
@@ -93,6 +93,7 @@ export const runtimeErrorEventSchema = z.object({
|
|
|
93
93
|
code: processErrorCodeSchema, // Tier 2 (errors.ts)
|
|
94
94
|
source: processErrorSourceSchema,
|
|
95
95
|
reason: z.string().optional(), // structured replacement for the stderr <reason>
|
|
96
|
+
selected: z.boolean().optional(), // additive (0.11.0): the degraded input is the operator's OWN selection, so the stream will not move itself and only they can pick another — a materially different operator response than a degraded non-selected input, and one to branch on rather than string-match. Absent ⇒ false
|
|
96
97
|
});
|
|
97
98
|
/** `preview` event — a preview-session lifecycle/phase change. */
|
|
98
99
|
export const previewEventSchema = z.object({
|
|
@@ -127,6 +128,21 @@ export const audioLevelEventSchema = z.object({
|
|
|
127
128
|
unavailable: z.literal(true).optional(),
|
|
128
129
|
reason: z.enum(["device_busy", "no_device", "mode_none", "handoff"]).optional(),
|
|
129
130
|
});
|
|
131
|
+
/**
|
|
132
|
+
* `config-change` event — one phase of a `change-config` transaction (0.10.0,
|
|
133
|
+
* additive Todo 9). Exactly one `applying` at entry, then exactly ONE terminal
|
|
134
|
+
* phase for the same `attempt_id` (which the RPC result also echoes, so a caller
|
|
135
|
+
* that missed an event can still correlate). A terminal phase is published only
|
|
136
|
+
* after the outcome gate resolved, so `applied` means "PLAYING **and** frames
|
|
137
|
+
* actually advancing", never merely "PLAYING".
|
|
138
|
+
*/
|
|
139
|
+
export const configChangeEventSchema = z.object({
|
|
140
|
+
type: z.literal("config-change"),
|
|
141
|
+
seq,
|
|
142
|
+
attempt_id: z.string(),
|
|
143
|
+
phase: configChangePhaseSchema,
|
|
144
|
+
reason: z.string().optional(), // absent on applying/applied; "teardown_timeout" marks the supervisor escalation
|
|
145
|
+
});
|
|
130
146
|
/** Discriminated union of every v1 event payload (the inner `params`). */
|
|
131
147
|
export const eventParamsSchema = z.discriminatedUnion("type", [
|
|
132
148
|
statusEventSchema,
|
|
@@ -137,6 +153,7 @@ export const eventParamsSchema = z.discriminatedUnion("type", [
|
|
|
137
153
|
runtimeErrorEventSchema,
|
|
138
154
|
previewEventSchema,
|
|
139
155
|
audioLevelEventSchema,
|
|
156
|
+
configChangeEventSchema,
|
|
140
157
|
]);
|
|
141
158
|
/** Full event envelope: { jsonrpc, method:"event", params } with typed params. */
|
|
142
159
|
export const cerastreamEventSchema = z.object({
|
|
@@ -144,8 +161,9 @@ export const cerastreamEventSchema = z.object({
|
|
|
144
161
|
method: z.literal("event"),
|
|
145
162
|
params: eventParamsSchema,
|
|
146
163
|
});
|
|
147
|
-
/** The
|
|
148
|
-
* `audio-level`
|
|
164
|
+
/** The nine event topics (schema.md "Events" table) — count-assertion source.
|
|
165
|
+
* `audio-level` (Todo 21) and `config-change` (Todo 9) are additive and appended
|
|
166
|
+
* last, preserving the order of every prior topic. */
|
|
149
167
|
export const EVENT_TOPICS = [
|
|
150
168
|
"status",
|
|
151
169
|
"switch",
|
|
@@ -155,6 +173,7 @@ export const EVENT_TOPICS = [
|
|
|
155
173
|
"error",
|
|
156
174
|
"preview",
|
|
157
175
|
"audio-level",
|
|
176
|
+
"config-change",
|
|
158
177
|
];
|
|
159
178
|
/** topic → payload Zod schema. Tests assert every topic is represented here. */
|
|
160
179
|
export const eventSchemas = {
|
|
@@ -166,4 +185,5 @@ export const eventSchemas = {
|
|
|
166
185
|
error: runtimeErrorEventSchema,
|
|
167
186
|
preview: previewEventSchema,
|
|
168
187
|
"audio-level": audioLevelEventSchema,
|
|
188
|
+
"config-change": configChangeEventSchema,
|
|
169
189
|
};
|
package/dist/messages.d.ts
CHANGED
|
@@ -42,6 +42,16 @@ export declare const startParamsSchema: z.ZodObject<{
|
|
|
42
42
|
force: "force";
|
|
43
43
|
off: "off";
|
|
44
44
|
}>>;
|
|
45
|
+
input_mode: z.ZodOptional<z.ZodEnum<{
|
|
46
|
+
audio: "audio";
|
|
47
|
+
hdmi: "hdmi";
|
|
48
|
+
uvc_h264: "uvc_h264";
|
|
49
|
+
uvc_h265: "uvc_h265";
|
|
50
|
+
mjpeg: "mjpeg";
|
|
51
|
+
camlink: "camlink";
|
|
52
|
+
test: "test";
|
|
53
|
+
network: "network";
|
|
54
|
+
}>>;
|
|
45
55
|
}, z.core.$strip>;
|
|
46
56
|
export type StartParams = z.infer<typeof startParamsSchema>;
|
|
47
57
|
export declare const startResultSchema: z.ZodObject<{
|
|
@@ -83,6 +93,7 @@ export declare const reloadConfigParamsSchema: z.ZodObject<{
|
|
|
83
93
|
audio: z.ZodOptional<z.ZodObject<{
|
|
84
94
|
delay_ms: z.ZodOptional<z.ZodNumber>;
|
|
85
95
|
delay_ms_signed: z.ZodOptional<z.ZodNumber>;
|
|
96
|
+
meter_device: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
86
97
|
}, z.core.$strip>>;
|
|
87
98
|
}, z.core.$strip>;
|
|
88
99
|
export type ReloadConfigParams = z.infer<typeof reloadConfigParamsSchema>;
|
|
@@ -103,6 +114,7 @@ export declare const reloadConfigResultSchema: z.ZodObject<{
|
|
|
103
114
|
audio: z.ZodOptional<z.ZodObject<{
|
|
104
115
|
delay_ms: z.ZodOptional<z.ZodNumber>;
|
|
105
116
|
delay_ms_signed: z.ZodOptional<z.ZodNumber>;
|
|
117
|
+
meter_device: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
106
118
|
}, z.core.$strip>>;
|
|
107
119
|
}, z.core.$strip>;
|
|
108
120
|
bitrate_control: z.ZodOptional<z.ZodEnum<{
|
|
@@ -191,6 +203,25 @@ export declare const listDevicesResultSchema: z.ZodObject<{
|
|
|
191
203
|
test: "test";
|
|
192
204
|
network: "network";
|
|
193
205
|
}>>;
|
|
206
|
+
modes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
207
|
+
media_type: z.ZodString;
|
|
208
|
+
pipeline_kind: z.ZodEnum<{
|
|
209
|
+
audio: "audio";
|
|
210
|
+
hdmi: "hdmi";
|
|
211
|
+
uvc_h264: "uvc_h264";
|
|
212
|
+
uvc_h265: "uvc_h265";
|
|
213
|
+
mjpeg: "mjpeg";
|
|
214
|
+
camlink: "camlink";
|
|
215
|
+
test: "test";
|
|
216
|
+
network: "network";
|
|
217
|
+
}>;
|
|
218
|
+
caps: z.ZodArray<z.ZodObject<{
|
|
219
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
220
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
221
|
+
framerate: z.ZodOptional<z.ZodString>;
|
|
222
|
+
media_type: z.ZodOptional<z.ZodString>;
|
|
223
|
+
}, z.core.$strip>>;
|
|
224
|
+
}, z.core.$strip>>>;
|
|
194
225
|
alsa_card_id: z.ZodOptional<z.ZodString>;
|
|
195
226
|
product_name: z.ZodOptional<z.ZodString>;
|
|
196
227
|
transport: z.ZodOptional<z.ZodEnum<{
|
|
@@ -200,6 +231,8 @@ export declare const listDevicesResultSchema: z.ZodObject<{
|
|
|
200
231
|
onboard: "onboard";
|
|
201
232
|
}>>;
|
|
202
233
|
stable_id: z.ZodOptional<z.ZodString>;
|
|
234
|
+
physical_group_id: z.ZodOptional<z.ZodString>;
|
|
235
|
+
hardware_serial: z.ZodOptional<z.ZodString>;
|
|
203
236
|
}, z.core.$strip>>;
|
|
204
237
|
}, z.core.$strip>;
|
|
205
238
|
export type ListDevicesResult = z.infer<typeof listDevicesResultSchema>;
|
|
@@ -212,6 +245,7 @@ export declare const eventTopicSchema: z.ZodEnum<{
|
|
|
212
245
|
"srt-stats": "srt-stats";
|
|
213
246
|
preview: "preview";
|
|
214
247
|
"audio-level": "audio-level";
|
|
248
|
+
"config-change": "config-change";
|
|
215
249
|
}>;
|
|
216
250
|
export type EventTopic = z.infer<typeof eventTopicSchema>;
|
|
217
251
|
export declare const subscribeEventsParamsSchema: z.ZodObject<{
|
|
@@ -224,6 +258,7 @@ export declare const subscribeEventsParamsSchema: z.ZodObject<{
|
|
|
224
258
|
"srt-stats": "srt-stats";
|
|
225
259
|
preview: "preview";
|
|
226
260
|
"audio-level": "audio-level";
|
|
261
|
+
"config-change": "config-change";
|
|
227
262
|
}>>>;
|
|
228
263
|
}, z.core.$strip>;
|
|
229
264
|
export type SubscribeEventsParams = z.infer<typeof subscribeEventsParamsSchema>;
|
|
@@ -237,6 +272,7 @@ export declare const subscribeEventsResultSchema: z.ZodObject<{
|
|
|
237
272
|
"srt-stats": "srt-stats";
|
|
238
273
|
preview: "preview";
|
|
239
274
|
"audio-level": "audio-level";
|
|
275
|
+
"config-change": "config-change";
|
|
240
276
|
}>>;
|
|
241
277
|
}, z.core.$strip>;
|
|
242
278
|
export type SubscribeEventsResult = z.infer<typeof subscribeEventsResultSchema>;
|
|
@@ -373,6 +409,52 @@ export declare const getCapabilitiesResultSchema: z.ZodObject<{
|
|
|
373
409
|
features: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
374
410
|
}, z.core.$strip>;
|
|
375
411
|
export type GetCapabilitiesResult = z.infer<typeof getCapabilitiesResultSchema>;
|
|
412
|
+
export declare const changeConfigParamsSchema: z.ZodObject<{
|
|
413
|
+
pipeline: z.ZodOptional<z.ZodString>;
|
|
414
|
+
resolution: z.ZodOptional<z.ZodString>;
|
|
415
|
+
framerate: z.ZodOptional<z.ZodNumber>;
|
|
416
|
+
codec: z.ZodOptional<z.ZodEnum<{
|
|
417
|
+
h264: "h264";
|
|
418
|
+
h265: "h265";
|
|
419
|
+
}>>;
|
|
420
|
+
input_id: z.ZodOptional<z.ZodString>;
|
|
421
|
+
input_mode: z.ZodOptional<z.ZodEnum<{
|
|
422
|
+
audio: "audio";
|
|
423
|
+
hdmi: "hdmi";
|
|
424
|
+
uvc_h264: "uvc_h264";
|
|
425
|
+
uvc_h265: "uvc_h265";
|
|
426
|
+
mjpeg: "mjpeg";
|
|
427
|
+
camlink: "camlink";
|
|
428
|
+
test: "test";
|
|
429
|
+
network: "network";
|
|
430
|
+
}>>;
|
|
431
|
+
}, z.core.$strip>;
|
|
432
|
+
export type ChangeConfigParams = z.infer<typeof changeConfigParamsSchema>;
|
|
433
|
+
export declare const changeConfigResultSchema: z.ZodObject<{
|
|
434
|
+
attempt_id: z.ZodString;
|
|
435
|
+
phase: z.ZodEnum<{
|
|
436
|
+
applying: "applying";
|
|
437
|
+
applied: "applied";
|
|
438
|
+
reverted: "reverted";
|
|
439
|
+
rollback_failed: "rollback_failed";
|
|
440
|
+
}>;
|
|
441
|
+
state: z.ZodEnum<{
|
|
442
|
+
idle: "idle";
|
|
443
|
+
starting: "starting";
|
|
444
|
+
streaming: "streaming";
|
|
445
|
+
stopping: "stopping";
|
|
446
|
+
}>;
|
|
447
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
448
|
+
}, z.core.$strip>;
|
|
449
|
+
export type ChangeConfigResult = z.infer<typeof changeConfigResultSchema>;
|
|
450
|
+
/**
|
|
451
|
+
* The `reason` a `rollback_failed` carries when a teardown deadline overran.
|
|
452
|
+
* A TERMINAL supervisor escalation, not an ordinary failure: the engine could not
|
|
453
|
+
* prove the old session released its capture devices within the bound, so it
|
|
454
|
+
* refuses to build a second session that would race it. Mirrors the Rust
|
|
455
|
+
* `REASON_TEARDOWN_TIMEOUT`; consumers render it distinctly.
|
|
456
|
+
*/
|
|
457
|
+
export declare const REASON_TEARDOWN_TIMEOUT: "teardown_timeout";
|
|
376
458
|
/** The eight v1 control methods (the literal JSON-RPC `method` strings). */
|
|
377
459
|
export declare const V1_METHODS: readonly ["start", "stop", "reload-config", "set-bitrate", "switch-input", "list-devices", "subscribe-events", "preview-session"];
|
|
378
460
|
export type V1Method = (typeof V1_METHODS)[number];
|
|
@@ -437,6 +519,16 @@ export declare const requestSchemas: {
|
|
|
437
519
|
force: "force";
|
|
438
520
|
off: "off";
|
|
439
521
|
}>>;
|
|
522
|
+
input_mode: z.ZodOptional<z.ZodEnum<{
|
|
523
|
+
audio: "audio";
|
|
524
|
+
hdmi: "hdmi";
|
|
525
|
+
uvc_h264: "uvc_h264";
|
|
526
|
+
uvc_h265: "uvc_h265";
|
|
527
|
+
mjpeg: "mjpeg";
|
|
528
|
+
camlink: "camlink";
|
|
529
|
+
test: "test";
|
|
530
|
+
network: "network";
|
|
531
|
+
}>>;
|
|
440
532
|
}, z.core.$strip>;
|
|
441
533
|
readonly result: z.ZodObject<{
|
|
442
534
|
session_id: z.ZodString;
|
|
@@ -478,6 +570,7 @@ export declare const requestSchemas: {
|
|
|
478
570
|
audio: z.ZodOptional<z.ZodObject<{
|
|
479
571
|
delay_ms: z.ZodOptional<z.ZodNumber>;
|
|
480
572
|
delay_ms_signed: z.ZodOptional<z.ZodNumber>;
|
|
573
|
+
meter_device: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
481
574
|
}, z.core.$strip>>;
|
|
482
575
|
}, z.core.$strip>;
|
|
483
576
|
readonly result: z.ZodObject<{
|
|
@@ -497,6 +590,7 @@ export declare const requestSchemas: {
|
|
|
497
590
|
audio: z.ZodOptional<z.ZodObject<{
|
|
498
591
|
delay_ms: z.ZodOptional<z.ZodNumber>;
|
|
499
592
|
delay_ms_signed: z.ZodOptional<z.ZodNumber>;
|
|
593
|
+
meter_device: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
500
594
|
}, z.core.$strip>>;
|
|
501
595
|
}, z.core.$strip>;
|
|
502
596
|
bitrate_control: z.ZodOptional<z.ZodEnum<{
|
|
@@ -569,6 +663,25 @@ export declare const requestSchemas: {
|
|
|
569
663
|
test: "test";
|
|
570
664
|
network: "network";
|
|
571
665
|
}>>;
|
|
666
|
+
modes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
667
|
+
media_type: z.ZodString;
|
|
668
|
+
pipeline_kind: z.ZodEnum<{
|
|
669
|
+
audio: "audio";
|
|
670
|
+
hdmi: "hdmi";
|
|
671
|
+
uvc_h264: "uvc_h264";
|
|
672
|
+
uvc_h265: "uvc_h265";
|
|
673
|
+
mjpeg: "mjpeg";
|
|
674
|
+
camlink: "camlink";
|
|
675
|
+
test: "test";
|
|
676
|
+
network: "network";
|
|
677
|
+
}>;
|
|
678
|
+
caps: z.ZodArray<z.ZodObject<{
|
|
679
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
680
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
681
|
+
framerate: z.ZodOptional<z.ZodString>;
|
|
682
|
+
media_type: z.ZodOptional<z.ZodString>;
|
|
683
|
+
}, z.core.$strip>>;
|
|
684
|
+
}, z.core.$strip>>>;
|
|
572
685
|
alsa_card_id: z.ZodOptional<z.ZodString>;
|
|
573
686
|
product_name: z.ZodOptional<z.ZodString>;
|
|
574
687
|
transport: z.ZodOptional<z.ZodEnum<{
|
|
@@ -578,6 +691,8 @@ export declare const requestSchemas: {
|
|
|
578
691
|
onboard: "onboard";
|
|
579
692
|
}>>;
|
|
580
693
|
stable_id: z.ZodOptional<z.ZodString>;
|
|
694
|
+
physical_group_id: z.ZodOptional<z.ZodString>;
|
|
695
|
+
hardware_serial: z.ZodOptional<z.ZodString>;
|
|
581
696
|
}, z.core.$strip>>;
|
|
582
697
|
}, z.core.$strip>;
|
|
583
698
|
};
|
|
@@ -592,6 +707,7 @@ export declare const requestSchemas: {
|
|
|
592
707
|
"srt-stats": "srt-stats";
|
|
593
708
|
preview: "preview";
|
|
594
709
|
"audio-level": "audio-level";
|
|
710
|
+
"config-change": "config-change";
|
|
595
711
|
}>>>;
|
|
596
712
|
}, z.core.$strip>;
|
|
597
713
|
readonly result: z.ZodObject<{
|
|
@@ -604,6 +720,7 @@ export declare const requestSchemas: {
|
|
|
604
720
|
"srt-stats": "srt-stats";
|
|
605
721
|
preview: "preview";
|
|
606
722
|
"audio-level": "audio-level";
|
|
723
|
+
"config-change": "config-change";
|
|
607
724
|
}>>;
|
|
608
725
|
}, z.core.$strip>;
|
|
609
726
|
};
|
package/dist/messages.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AUDIO_DELAY_MAX_MS } from "./constants.js";
|
|
3
3
|
import { helloParamsSchema, helloResultSchema, } from "./envelope.js";
|
|
4
|
-
import { balancerAlgorithmSchema, bitrateControlSchema, captureDeviceSchema, cerastreamConfigSchema, inputModeSchema, mediaClassSchema, previewTierSchema, streamStateSchema, } from "./types.js";
|
|
4
|
+
import { balancerAlgorithmSchema, bitrateControlSchema, captureDeviceKindSchema, captureDeviceSchema, cerastreamConfigSchema, configChangePhaseSchema, inputModeSchema, mediaClassSchema, 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 ----
|
|
@@ -39,6 +39,10 @@ export const reloadConfigParamsSchema = z.object({
|
|
|
39
39
|
.object({
|
|
40
40
|
delay_ms: z.number().int().min(0).max(AUDIO_DELAY_MAX_MS).optional(), // legacy unsigned; kept for 0.3.0 callers
|
|
41
41
|
delay_ms_signed: z.number().int().optional(), // signed sibling; clamped at apply, so unbounded
|
|
42
|
+
// additive (0.9.0): idle-meter card preference — absent leaves it unchanged,
|
|
43
|
+
// `null` restores the engine's auto-pick, `hw:CARD=…` prefers that card
|
|
44
|
+
// (a preference, not a pin: a card that never delivers is still demoted)
|
|
45
|
+
meter_device: z.string().nullable().optional(),
|
|
42
46
|
})
|
|
43
47
|
.optional(),
|
|
44
48
|
});
|
|
@@ -100,6 +104,7 @@ export const eventTopicSchema = z.enum([
|
|
|
100
104
|
"error",
|
|
101
105
|
"preview",
|
|
102
106
|
"audio-level",
|
|
107
|
+
"config-change",
|
|
103
108
|
]);
|
|
104
109
|
export const subscribeEventsParamsSchema = z.object({
|
|
105
110
|
topics: z.array(eventTopicSchema).optional(), // default: all topics
|
|
@@ -188,6 +193,49 @@ export const getCapabilitiesResultSchema = z.object({
|
|
|
188
193
|
network_embedded_audio: z.boolean().optional(), // engine routes network-ingest embedded audio to the mux
|
|
189
194
|
features: z.array(z.string()).optional(), // named engine features (e.g. "video-passthrough") for fail-closed negotiation
|
|
190
195
|
});
|
|
196
|
+
// ---- 10. change-config (0.10.0, additive) ----
|
|
197
|
+
// Deliberately absent from V1_METHODS / requestSchemas, like get-capabilities and
|
|
198
|
+
// switch-audio, so the frozen eight-method contract count stays eight. Params are
|
|
199
|
+
// a DELTA of startParamsSchema: absent ⇒ keep the live value. An empty delta is
|
|
200
|
+
// refused with `cerastream.params.invalid` — a no-op that restarted the pipeline
|
|
201
|
+
// would be the worst possible outcome. `input_id` rides the transaction, so a
|
|
202
|
+
// source change renegotiates caps instead of going through `switch-input`.
|
|
203
|
+
export const changeConfigParamsSchema = z
|
|
204
|
+
.object({
|
|
205
|
+
pipeline: z.string().optional(),
|
|
206
|
+
resolution: z.string().optional(), // "WxH" pixels, e.g. "3840x2160"
|
|
207
|
+
framerate: z.number().optional(),
|
|
208
|
+
codec: videoCodecSchema.optional(),
|
|
209
|
+
input_id: z.string().optional(),
|
|
210
|
+
// Switching a LIVE device between a libuvc family (uvc_h264/uvc_h265) and
|
|
211
|
+
// the v4l2 mjpeg family is NOT a plain rebuild: libuvc detaches uvcvideo, so
|
|
212
|
+
// the /dev/videoN node the mjpeg leg needs does not exist until the hold is
|
|
213
|
+
// released — and it then returns asynchronously, possibly renumbered. The
|
|
214
|
+
// engine runs a release → re-enumeration-barrier → open transaction and
|
|
215
|
+
// rolls back honestly (reason: mode_barrier_timeout) if the barrier expires.
|
|
216
|
+
input_mode: captureDeviceKindSchema.optional(),
|
|
217
|
+
})
|
|
218
|
+
.refine((delta) => Object.keys(delta).length > 0, {
|
|
219
|
+
message: "change-config delta must carry at least one field",
|
|
220
|
+
});
|
|
221
|
+
// `Ok` for every phase the transaction actually reached — INCLUDING
|
|
222
|
+
// `rollback_failed`, an honest terminal outcome rather than an RPC fault. A
|
|
223
|
+
// Tier-1 error means the transaction never started, so a caller can tell
|
|
224
|
+
// "nothing happened" from "something happened and here is what".
|
|
225
|
+
export const changeConfigResultSchema = z.object({
|
|
226
|
+
attempt_id: z.string(), // correlates with every config-change event of the attempt
|
|
227
|
+
phase: configChangePhaseSchema, // the TERMINAL phase reached
|
|
228
|
+
state: streamStateSchema, // streaming for applied/reverted, idle for rollback_failed
|
|
229
|
+
reason: z.string().optional(), // machine-stable cause on a non-applied phase
|
|
230
|
+
});
|
|
231
|
+
/**
|
|
232
|
+
* The `reason` a `rollback_failed` carries when a teardown deadline overran.
|
|
233
|
+
* A TERMINAL supervisor escalation, not an ordinary failure: the engine could not
|
|
234
|
+
* prove the old session released its capture devices within the bound, so it
|
|
235
|
+
* refuses to build a second session that would race it. Mirrors the Rust
|
|
236
|
+
* `REASON_TEARDOWN_TIMEOUT`; consumers render it distinctly.
|
|
237
|
+
*/
|
|
238
|
+
export const REASON_TEARDOWN_TIMEOUT = "teardown_timeout";
|
|
191
239
|
// ---- method registry (count-assertion source of truth) ----
|
|
192
240
|
/** The eight v1 control methods (the literal JSON-RPC `method` strings). */
|
|
193
241
|
export const V1_METHODS = [
|
package/dist/types.d.ts
CHANGED
|
@@ -61,6 +61,13 @@ export declare const deviceTransportSchema: z.ZodEnum<{
|
|
|
61
61
|
onboard: "onboard";
|
|
62
62
|
}>;
|
|
63
63
|
export type DeviceTransport = z.infer<typeof deviceTransportSchema>;
|
|
64
|
+
export declare const configChangePhaseSchema: z.ZodEnum<{
|
|
65
|
+
applying: "applying";
|
|
66
|
+
applied: "applied";
|
|
67
|
+
reverted: "reverted";
|
|
68
|
+
rollback_failed: "rollback_failed";
|
|
69
|
+
}>;
|
|
70
|
+
export type ConfigChangePhase = z.infer<typeof configChangePhaseSchema>;
|
|
64
71
|
/** SRT transport config. Mirrors schema.md `start.srt` exactly. */
|
|
65
72
|
export declare const srtConfigSchema: z.ZodObject<{
|
|
66
73
|
host: z.ZodString;
|
|
@@ -157,6 +164,16 @@ export declare const cerastreamConfigSchema: z.ZodObject<{
|
|
|
157
164
|
force: "force";
|
|
158
165
|
off: "off";
|
|
159
166
|
}>>;
|
|
167
|
+
input_mode: z.ZodOptional<z.ZodEnum<{
|
|
168
|
+
audio: "audio";
|
|
169
|
+
hdmi: "hdmi";
|
|
170
|
+
uvc_h264: "uvc_h264";
|
|
171
|
+
uvc_h265: "uvc_h265";
|
|
172
|
+
mjpeg: "mjpeg";
|
|
173
|
+
camlink: "camlink";
|
|
174
|
+
test: "test";
|
|
175
|
+
network: "network";
|
|
176
|
+
}>>;
|
|
160
177
|
}, z.core.$strip>;
|
|
161
178
|
export type CerastreamConfig = z.infer<typeof cerastreamConfigSchema>;
|
|
162
179
|
export type PartialCerastreamConfig = z.input<typeof cerastreamConfigSchema>;
|
|
@@ -173,6 +190,26 @@ export declare const captureCapSchema: z.ZodObject<{
|
|
|
173
190
|
media_type: z.ZodOptional<z.ZodString>;
|
|
174
191
|
}, z.core.$strip>;
|
|
175
192
|
export type CaptureCap = z.infer<typeof captureCapSchema>;
|
|
193
|
+
export declare const captureModeSchema: z.ZodObject<{
|
|
194
|
+
media_type: z.ZodString;
|
|
195
|
+
pipeline_kind: z.ZodEnum<{
|
|
196
|
+
audio: "audio";
|
|
197
|
+
hdmi: "hdmi";
|
|
198
|
+
uvc_h264: "uvc_h264";
|
|
199
|
+
uvc_h265: "uvc_h265";
|
|
200
|
+
mjpeg: "mjpeg";
|
|
201
|
+
camlink: "camlink";
|
|
202
|
+
test: "test";
|
|
203
|
+
network: "network";
|
|
204
|
+
}>;
|
|
205
|
+
caps: z.ZodArray<z.ZodObject<{
|
|
206
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
207
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
208
|
+
framerate: z.ZodOptional<z.ZodString>;
|
|
209
|
+
media_type: z.ZodOptional<z.ZodString>;
|
|
210
|
+
}, z.core.$strip>>;
|
|
211
|
+
}, z.core.$strip>;
|
|
212
|
+
export type CaptureMode = z.infer<typeof captureModeSchema>;
|
|
176
213
|
export declare const captureDeviceSchema: z.ZodObject<{
|
|
177
214
|
input_id: z.ZodString;
|
|
178
215
|
device_path: z.ZodString;
|
|
@@ -197,6 +234,25 @@ export declare const captureDeviceSchema: z.ZodObject<{
|
|
|
197
234
|
test: "test";
|
|
198
235
|
network: "network";
|
|
199
236
|
}>>;
|
|
237
|
+
modes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
238
|
+
media_type: z.ZodString;
|
|
239
|
+
pipeline_kind: z.ZodEnum<{
|
|
240
|
+
audio: "audio";
|
|
241
|
+
hdmi: "hdmi";
|
|
242
|
+
uvc_h264: "uvc_h264";
|
|
243
|
+
uvc_h265: "uvc_h265";
|
|
244
|
+
mjpeg: "mjpeg";
|
|
245
|
+
camlink: "camlink";
|
|
246
|
+
test: "test";
|
|
247
|
+
network: "network";
|
|
248
|
+
}>;
|
|
249
|
+
caps: z.ZodArray<z.ZodObject<{
|
|
250
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
251
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
252
|
+
framerate: z.ZodOptional<z.ZodString>;
|
|
253
|
+
media_type: z.ZodOptional<z.ZodString>;
|
|
254
|
+
}, z.core.$strip>>;
|
|
255
|
+
}, z.core.$strip>>>;
|
|
200
256
|
alsa_card_id: z.ZodOptional<z.ZodString>;
|
|
201
257
|
product_name: z.ZodOptional<z.ZodString>;
|
|
202
258
|
transport: z.ZodOptional<z.ZodEnum<{
|
|
@@ -206,6 +262,8 @@ export declare const captureDeviceSchema: z.ZodObject<{
|
|
|
206
262
|
onboard: "onboard";
|
|
207
263
|
}>>;
|
|
208
264
|
stable_id: z.ZodOptional<z.ZodString>;
|
|
265
|
+
physical_group_id: z.ZodOptional<z.ZodString>;
|
|
266
|
+
hardware_serial: z.ZodOptional<z.ZodString>;
|
|
209
267
|
}, z.core.$strip>;
|
|
210
268
|
export type CaptureDevice = z.infer<typeof captureDeviceSchema>;
|
|
211
269
|
export declare const srtStatsSchema: z.ZodObject<{
|
package/dist/types.js
CHANGED
|
@@ -52,6 +52,18 @@ export const deviceTransportSchema = z.enum([
|
|
|
52
52
|
"bluetooth",
|
|
53
53
|
"onboard",
|
|
54
54
|
]);
|
|
55
|
+
// Phase of one `change-config` transaction (0.10.0, additive). `applying` is
|
|
56
|
+
// published once at entry, then exactly ONE terminal phase for the same
|
|
57
|
+
// attempt_id: `applied` (the new config satisfied the outcome gate),
|
|
58
|
+
// `reverted` (it did not and the single known-good rollback attempt did), or
|
|
59
|
+
// `rollback_failed` (no rollback was possible, or the one attempt also failed —
|
|
60
|
+
// the engine is idle, which is the truthful terminal state).
|
|
61
|
+
export const configChangePhaseSchema = z.enum([
|
|
62
|
+
"applying",
|
|
63
|
+
"applied",
|
|
64
|
+
"reverted",
|
|
65
|
+
"rollback_failed",
|
|
66
|
+
]);
|
|
55
67
|
// ---- config sub-schemas (canonical; reused by `start` + the unified config) ----
|
|
56
68
|
/** SRT transport config. Mirrors schema.md `start.srt` exactly. */
|
|
57
69
|
export const srtConfigSchema = z.object({
|
|
@@ -117,6 +129,7 @@ export const cerastreamConfigSchema = z.object({
|
|
|
117
129
|
framerate: z.number().optional(), // additive (0.4.0): fps as a number, e.g. 29.97
|
|
118
130
|
audio: audioConfigSchema.optional(), // additive (0.4.0): audio device/codec/signed delay
|
|
119
131
|
video_passthrough: videoPassthroughSchema.optional(), // additive (0.5.0): auto|force|off; absent ⇒ auto
|
|
132
|
+
input_mode: captureDeviceKindSchema.optional(), // additive (0.11.0): which MODE family of the selected device to capture in, naming a list-devices modes[].pipeline_kind. Absent ⇒ the engine's precedence pick (h265 → h264 → mjpeg → raw). The ONLY way to reach the non-precedence family of a dual-format camera; a family the device does not expose is a typed cerastream.params.invalid, never a silent fallback
|
|
120
133
|
});
|
|
121
134
|
// convenience defaults for building a config client-side
|
|
122
135
|
export const DEFAULT_BITRATE_CONFIG = {
|
|
@@ -132,17 +145,39 @@ export const captureCapSchema = z.object({
|
|
|
132
145
|
framerate: z.string().optional(), // e.g. "30/1"
|
|
133
146
|
media_type: z.string().optional(), // e.g. "video/x-h265"; additive, absent on legacy producers
|
|
134
147
|
});
|
|
148
|
+
// One startable capture MODE family of a device (0.11.0, additive).
|
|
149
|
+
//
|
|
150
|
+
// A capture device is not necessarily one format family: the DJI Osmo Pocket 3
|
|
151
|
+
// exposes H.264 AND MJPEG on the SAME /dev/video1 node (selection is a
|
|
152
|
+
// VIDIOC_S_FMT pixelformat choice, not a different node). The scalar
|
|
153
|
+
// captureDevice.kind can only name ONE family, so before this contract a
|
|
154
|
+
// dual-format camera was classified uvc_h264 by precedence and its MJPEG ladder
|
|
155
|
+
// was unreachable — visible, but impossible to start.
|
|
156
|
+
//
|
|
157
|
+
// pipeline_kind is exactly what a caller echoes back as start.input_mode to drive
|
|
158
|
+
// the device in this family. caps is the ladder for THIS family ALONE, never the
|
|
159
|
+
// device-wide union: on the Osmo, H.264 offers 4K at 60/50/48 fps while MJPEG
|
|
160
|
+
// tops out at 30, so a merged list would advertise 4K60 MJPEG — a mode the device
|
|
161
|
+
// cannot deliver.
|
|
162
|
+
export const captureModeSchema = z.object({
|
|
163
|
+
media_type: z.string(), // e.g. "image/jpeg"
|
|
164
|
+
pipeline_kind: captureDeviceKindSchema, // the value start.input_mode takes to select this mode
|
|
165
|
+
caps: z.array(captureCapSchema), // the {w × h × framerate} ladder for THIS media type only
|
|
166
|
+
});
|
|
135
167
|
export const captureDeviceSchema = z.object({
|
|
136
168
|
input_id: z.string(), // stable id used by switch-input
|
|
137
169
|
device_path: z.string(), // e.g. /dev/video0 (dedup key)
|
|
138
170
|
display_name: z.string(),
|
|
139
171
|
media_class: mediaClassSchema,
|
|
140
172
|
caps: z.array(captureCapSchema).optional(),
|
|
141
|
-
kind: captureDeviceKindSchema.optional(), // additive (0.4.0): engine-typed device family; absent on legacy producers
|
|
173
|
+
kind: captureDeviceKindSchema.optional(), // additive (0.4.0): engine-typed device family; absent on legacy producers. A dual-format device reports its HIGHEST-PRECEDENCE family here; the full set is `modes`
|
|
174
|
+
modes: z.array(captureModeSchema).optional(), // additive (0.11.0): every startable mode family, each with its OWN caps ladder; absent on legacy producers, on audio rows, and on a device with no probed caps. When present it ALWAYS contains the family named by `kind`, first
|
|
142
175
|
alsa_card_id: z.string().optional(), // additive: ALSA card id for media_class:audio devices only; absent on video + legacy producers
|
|
143
176
|
product_name: z.string().optional(), // additive (Todo 20): real product name, deduped with a #N suffix when shared; absent ⇒ use display_name
|
|
144
177
|
transport: deviceTransportSchema.optional(), // additive (Todo 20): how the device is attached; absent on legacy producers
|
|
145
178
|
stable_id: z.string().optional(), // additive (Todo 20): reboot-stable hardware identity, distinct from input_id/device_path
|
|
179
|
+
physical_group_id: z.string().optional(), // additive (0.10.0, ADR-0008): `usb:<topology-token>` shared by one physical device's rows; absent on non-USB + legacy producers, and an absent group NEVER matches
|
|
180
|
+
hardware_serial: z.string().optional(), // additive (0.10.0, ADR-0008): USB serial, DIAGNOSTIC ONLY — vendors ship placeholder serials, so never match/group/select on it
|
|
146
181
|
});
|
|
147
182
|
// ---- transport telemetry (srt-stats event payload) ----
|
|
148
183
|
export const srtStatsSchema = z.object({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ceralive/cerastream",
|
|
3
|
-
"version": "2026.7.
|
|
3
|
+
"version": "2026.7.5",
|
|
4
4
|
"description": "Type-safe TypeScript schema + IPC client for the cerastream streaming engine (JSON-RPC 2.0 / NDJSON over a Unix domain socket).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|