@camstack/addon-provider-reolink 1.1.17 → 1.1.18
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/addon.js +91 -5
- package/dist/addon.mjs +91 -5
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -18071,7 +18071,17 @@ var AgentAddonConfigSchema = object({
|
|
|
18071
18071
|
});
|
|
18072
18072
|
var AgentPipelineSettingsSchema = object({
|
|
18073
18073
|
addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
|
|
18074
|
-
maxCameras: number().int().nonnegative().nullable().default(null)
|
|
18074
|
+
maxCameras: number().int().nonnegative().nullable().default(null),
|
|
18075
|
+
/** Per-node detection weight (relative share for the quota balancer). */
|
|
18076
|
+
detectWeight: number().positive().optional(),
|
|
18077
|
+
/** Node is eligible to run the detection pipeline (decode + inference). */
|
|
18078
|
+
detect: boolean().optional(),
|
|
18079
|
+
/** Node is eligible to host decoder sessions. */
|
|
18080
|
+
decode: boolean().optional(),
|
|
18081
|
+
/** Node is eligible to run audio-analyzer sessions. */
|
|
18082
|
+
audio: boolean().optional(),
|
|
18083
|
+
/** Node is eligible to be the ingest / source-owner (serve the restream). */
|
|
18084
|
+
ingest: boolean().optional()
|
|
18075
18085
|
});
|
|
18076
18086
|
var CameraPipelineForAgentSchema = object({
|
|
18077
18087
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -18377,6 +18387,21 @@ method(object({
|
|
|
18377
18387
|
}), object({ success: literal(true) }), {
|
|
18378
18388
|
kind: "mutation",
|
|
18379
18389
|
auth: "admin"
|
|
18390
|
+
}), method(object({
|
|
18391
|
+
agentNodeId: string(),
|
|
18392
|
+
detectWeight: number().positive().nullable()
|
|
18393
|
+
}), object({ success: literal(true) }), {
|
|
18394
|
+
kind: "mutation",
|
|
18395
|
+
auth: "admin"
|
|
18396
|
+
}), method(object({
|
|
18397
|
+
agentNodeId: string(),
|
|
18398
|
+
detect: boolean().nullable().optional(),
|
|
18399
|
+
decode: boolean().nullable().optional(),
|
|
18400
|
+
audio: boolean().nullable().optional(),
|
|
18401
|
+
ingest: boolean().nullable().optional()
|
|
18402
|
+
}), object({ success: literal(true) }), {
|
|
18403
|
+
kind: "mutation",
|
|
18404
|
+
auth: "admin"
|
|
18380
18405
|
}), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
|
|
18381
18406
|
deviceId: number(),
|
|
18382
18407
|
addonId: string(),
|
|
@@ -24608,6 +24633,18 @@ Object.freeze({
|
|
|
24608
24633
|
addonId: null,
|
|
24609
24634
|
access: "create"
|
|
24610
24635
|
},
|
|
24636
|
+
"pipelineOrchestrator.setAgentCapabilities": {
|
|
24637
|
+
capName: "pipeline-orchestrator",
|
|
24638
|
+
capScope: "system",
|
|
24639
|
+
addonId: null,
|
|
24640
|
+
access: "create"
|
|
24641
|
+
},
|
|
24642
|
+
"pipelineOrchestrator.setAgentDetectWeight": {
|
|
24643
|
+
capName: "pipeline-orchestrator",
|
|
24644
|
+
capScope: "system",
|
|
24645
|
+
addonId: null,
|
|
24646
|
+
access: "create"
|
|
24647
|
+
},
|
|
24611
24648
|
"pipelineOrchestrator.setAgentMaxCameras": {
|
|
24612
24649
|
capName: "pipeline-orchestrator",
|
|
24613
24650
|
capScope: "system",
|
|
@@ -214519,6 +214556,30 @@ function buildRawState(reader) {
|
|
|
214519
214556
|
};
|
|
214520
214557
|
}
|
|
214521
214558
|
//#endregion
|
|
214559
|
+
//#region src/native-sdp-overlay.ts
|
|
214560
|
+
/**
|
|
214561
|
+
* Return a new descriptor list in which every native `pull-rfc4571` entry with
|
|
214562
|
+
* a live upstream server carries that server's real `tcp://` URL + real SDP.
|
|
214563
|
+
* Pure + immutable: non-native or cold entries pass through unchanged;
|
|
214564
|
+
* upgraded entries are fresh objects and sibling metadata keys are preserved.
|
|
214565
|
+
*/
|
|
214566
|
+
function overlayLiveNativeRfc4571Sdp(descriptors, liveServerFor) {
|
|
214567
|
+
return descriptors.map((descriptor) => {
|
|
214568
|
+
if (descriptor.kind !== "pull-rfc4571") return descriptor;
|
|
214569
|
+
const live = liveServerFor(descriptor.camStreamId);
|
|
214570
|
+
if (!live) return descriptor;
|
|
214571
|
+
const auth = `${encodeURIComponent(live.username)}:${encodeURIComponent(live.password)}`;
|
|
214572
|
+
return {
|
|
214573
|
+
...descriptor,
|
|
214574
|
+
url: `tcp://${auth}@${live.host}:${live.port}`,
|
|
214575
|
+
metadata: {
|
|
214576
|
+
...descriptor.metadata,
|
|
214577
|
+
sdp: live.sdp
|
|
214578
|
+
}
|
|
214579
|
+
};
|
|
214580
|
+
});
|
|
214581
|
+
}
|
|
214582
|
+
//#endregion
|
|
214522
214583
|
//#region src/accessory-probe-flags.ts
|
|
214523
214584
|
var FLAG_KEYS = [
|
|
214524
214585
|
"hasBattery",
|
|
@@ -220529,17 +220590,39 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
220529
220590
|
* session or touches the broker.
|
|
220530
220591
|
*/
|
|
220531
220592
|
async buildStreamCatalog() {
|
|
220532
|
-
if (this.cachedStreamDescriptors?.length) return this.cachedStreamDescriptors;
|
|
220533
|
-
if (this.buildStreamCatalogInFlight) return this.buildStreamCatalogInFlight;
|
|
220593
|
+
if (this.cachedStreamDescriptors?.length) return this.withLiveNativeSdp(this.cachedStreamDescriptors);
|
|
220594
|
+
if (this.buildStreamCatalogInFlight) return this.withLiveNativeSdp(await this.buildStreamCatalogInFlight);
|
|
220534
220595
|
const build = this.buildStreamCatalogUncached();
|
|
220535
220596
|
this.buildStreamCatalogInFlight = build;
|
|
220536
220597
|
try {
|
|
220537
|
-
return await build;
|
|
220598
|
+
return this.withLiveNativeSdp(await build);
|
|
220538
220599
|
} finally {
|
|
220539
220600
|
this.buildStreamCatalogInFlight = null;
|
|
220540
220601
|
}
|
|
220541
220602
|
}
|
|
220542
220603
|
/**
|
|
220604
|
+
* Upgrade native `pull-rfc4571` descriptors to the live upstream server's
|
|
220605
|
+
* real `tcp://` URL + real (sprop-bearing) SDP whenever a server is
|
|
220606
|
+
* currently listening in `this.active`. The synthetic catalog SDP omits
|
|
220607
|
+
* `sprop-parameter-sets`, which the raw ffmpeg decode reader cannot recover
|
|
220608
|
+
* (it has no in-band SPS/PPS merge) — so a decode-path consumer that pulls
|
|
220609
|
+
* the catalog after `materializeStreamSocket` must still see the real SDP.
|
|
220610
|
+
* See `native-sdp-overlay.ts`.
|
|
220611
|
+
*/
|
|
220612
|
+
withLiveNativeSdp(descriptors) {
|
|
220613
|
+
return overlayLiveNativeRfc4571Sdp(descriptors, (camStreamId) => {
|
|
220614
|
+
const server = this.active.get(camStreamId)?.server;
|
|
220615
|
+
if (!server?.server?.listening) return null;
|
|
220616
|
+
return {
|
|
220617
|
+
host: server.host,
|
|
220618
|
+
port: server.port,
|
|
220619
|
+
username: server.username,
|
|
220620
|
+
password: server.password,
|
|
220621
|
+
sdp: server.sdp
|
|
220622
|
+
};
|
|
220623
|
+
});
|
|
220624
|
+
}
|
|
220625
|
+
/**
|
|
220543
220626
|
* Synthesize the HTTP-FLV pull URL for a (channel, profile) pair. FLV is
|
|
220544
220627
|
* served off the Reolink Baichuan media port (default 1935, app `bcs`) as
|
|
220545
220628
|
* `channel<channel>_<profile>.bcs` — the same shape Frigate/go2rtc use. The
|
|
@@ -220763,13 +220846,16 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
220763
220846
|
}
|
|
220764
220847
|
const url = `tcp://${`${encodeURIComponent(server.username)}:${encodeURIComponent(server.password)}`}@${server.host}:${server.port}`;
|
|
220765
220848
|
const codec = server.videoType === "H265" ? "h265" : "h264";
|
|
220849
|
+
const descriptor = this.cachedStreamDescriptors?.find((d) => d.camStreamId === camStreamId);
|
|
220766
220850
|
await this.publishOne({
|
|
220767
220851
|
camStreamId,
|
|
220768
220852
|
kind: "pull-rfc4571",
|
|
220769
|
-
label: camStreamId,
|
|
220853
|
+
label: descriptor?.label ?? camStreamId,
|
|
220770
220854
|
url,
|
|
220771
220855
|
codec,
|
|
220772
220856
|
autoEligible: true,
|
|
220857
|
+
...descriptor?.resolution ? { resolution: descriptor.resolution } : {},
|
|
220858
|
+
...descriptor?.fps !== void 0 ? { fps: descriptor.fps } : {},
|
|
220773
220859
|
metadata: { sdp: server.sdp }
|
|
220774
220860
|
});
|
|
220775
220861
|
this.ctx.logger.info("materialized rfc4571 stream socket on broker demand", {
|
package/dist/addon.mjs
CHANGED
|
@@ -18066,7 +18066,17 @@ var AgentAddonConfigSchema = object({
|
|
|
18066
18066
|
});
|
|
18067
18067
|
var AgentPipelineSettingsSchema = object({
|
|
18068
18068
|
addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
|
|
18069
|
-
maxCameras: number().int().nonnegative().nullable().default(null)
|
|
18069
|
+
maxCameras: number().int().nonnegative().nullable().default(null),
|
|
18070
|
+
/** Per-node detection weight (relative share for the quota balancer). */
|
|
18071
|
+
detectWeight: number().positive().optional(),
|
|
18072
|
+
/** Node is eligible to run the detection pipeline (decode + inference). */
|
|
18073
|
+
detect: boolean().optional(),
|
|
18074
|
+
/** Node is eligible to host decoder sessions. */
|
|
18075
|
+
decode: boolean().optional(),
|
|
18076
|
+
/** Node is eligible to run audio-analyzer sessions. */
|
|
18077
|
+
audio: boolean().optional(),
|
|
18078
|
+
/** Node is eligible to be the ingest / source-owner (serve the restream). */
|
|
18079
|
+
ingest: boolean().optional()
|
|
18070
18080
|
});
|
|
18071
18081
|
var CameraPipelineForAgentSchema = object({
|
|
18072
18082
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -18372,6 +18382,21 @@ method(object({
|
|
|
18372
18382
|
}), object({ success: literal(true) }), {
|
|
18373
18383
|
kind: "mutation",
|
|
18374
18384
|
auth: "admin"
|
|
18385
|
+
}), method(object({
|
|
18386
|
+
agentNodeId: string(),
|
|
18387
|
+
detectWeight: number().positive().nullable()
|
|
18388
|
+
}), object({ success: literal(true) }), {
|
|
18389
|
+
kind: "mutation",
|
|
18390
|
+
auth: "admin"
|
|
18391
|
+
}), method(object({
|
|
18392
|
+
agentNodeId: string(),
|
|
18393
|
+
detect: boolean().nullable().optional(),
|
|
18394
|
+
decode: boolean().nullable().optional(),
|
|
18395
|
+
audio: boolean().nullable().optional(),
|
|
18396
|
+
ingest: boolean().nullable().optional()
|
|
18397
|
+
}), object({ success: literal(true) }), {
|
|
18398
|
+
kind: "mutation",
|
|
18399
|
+
auth: "admin"
|
|
18375
18400
|
}), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
|
|
18376
18401
|
deviceId: number(),
|
|
18377
18402
|
addonId: string(),
|
|
@@ -24603,6 +24628,18 @@ Object.freeze({
|
|
|
24603
24628
|
addonId: null,
|
|
24604
24629
|
access: "create"
|
|
24605
24630
|
},
|
|
24631
|
+
"pipelineOrchestrator.setAgentCapabilities": {
|
|
24632
|
+
capName: "pipeline-orchestrator",
|
|
24633
|
+
capScope: "system",
|
|
24634
|
+
addonId: null,
|
|
24635
|
+
access: "create"
|
|
24636
|
+
},
|
|
24637
|
+
"pipelineOrchestrator.setAgentDetectWeight": {
|
|
24638
|
+
capName: "pipeline-orchestrator",
|
|
24639
|
+
capScope: "system",
|
|
24640
|
+
addonId: null,
|
|
24641
|
+
access: "create"
|
|
24642
|
+
},
|
|
24606
24643
|
"pipelineOrchestrator.setAgentMaxCameras": {
|
|
24607
24644
|
capName: "pipeline-orchestrator",
|
|
24608
24645
|
capScope: "system",
|
|
@@ -214499,6 +214536,30 @@ function buildRawState(reader) {
|
|
|
214499
214536
|
};
|
|
214500
214537
|
}
|
|
214501
214538
|
//#endregion
|
|
214539
|
+
//#region src/native-sdp-overlay.ts
|
|
214540
|
+
/**
|
|
214541
|
+
* Return a new descriptor list in which every native `pull-rfc4571` entry with
|
|
214542
|
+
* a live upstream server carries that server's real `tcp://` URL + real SDP.
|
|
214543
|
+
* Pure + immutable: non-native or cold entries pass through unchanged;
|
|
214544
|
+
* upgraded entries are fresh objects and sibling metadata keys are preserved.
|
|
214545
|
+
*/
|
|
214546
|
+
function overlayLiveNativeRfc4571Sdp(descriptors, liveServerFor) {
|
|
214547
|
+
return descriptors.map((descriptor) => {
|
|
214548
|
+
if (descriptor.kind !== "pull-rfc4571") return descriptor;
|
|
214549
|
+
const live = liveServerFor(descriptor.camStreamId);
|
|
214550
|
+
if (!live) return descriptor;
|
|
214551
|
+
const auth = `${encodeURIComponent(live.username)}:${encodeURIComponent(live.password)}`;
|
|
214552
|
+
return {
|
|
214553
|
+
...descriptor,
|
|
214554
|
+
url: `tcp://${auth}@${live.host}:${live.port}`,
|
|
214555
|
+
metadata: {
|
|
214556
|
+
...descriptor.metadata,
|
|
214557
|
+
sdp: live.sdp
|
|
214558
|
+
}
|
|
214559
|
+
};
|
|
214560
|
+
});
|
|
214561
|
+
}
|
|
214562
|
+
//#endregion
|
|
214502
214563
|
//#region src/accessory-probe-flags.ts
|
|
214503
214564
|
var FLAG_KEYS = [
|
|
214504
214565
|
"hasBattery",
|
|
@@ -220509,17 +220570,39 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
220509
220570
|
* session or touches the broker.
|
|
220510
220571
|
*/
|
|
220511
220572
|
async buildStreamCatalog() {
|
|
220512
|
-
if (this.cachedStreamDescriptors?.length) return this.cachedStreamDescriptors;
|
|
220513
|
-
if (this.buildStreamCatalogInFlight) return this.buildStreamCatalogInFlight;
|
|
220573
|
+
if (this.cachedStreamDescriptors?.length) return this.withLiveNativeSdp(this.cachedStreamDescriptors);
|
|
220574
|
+
if (this.buildStreamCatalogInFlight) return this.withLiveNativeSdp(await this.buildStreamCatalogInFlight);
|
|
220514
220575
|
const build = this.buildStreamCatalogUncached();
|
|
220515
220576
|
this.buildStreamCatalogInFlight = build;
|
|
220516
220577
|
try {
|
|
220517
|
-
return await build;
|
|
220578
|
+
return this.withLiveNativeSdp(await build);
|
|
220518
220579
|
} finally {
|
|
220519
220580
|
this.buildStreamCatalogInFlight = null;
|
|
220520
220581
|
}
|
|
220521
220582
|
}
|
|
220522
220583
|
/**
|
|
220584
|
+
* Upgrade native `pull-rfc4571` descriptors to the live upstream server's
|
|
220585
|
+
* real `tcp://` URL + real (sprop-bearing) SDP whenever a server is
|
|
220586
|
+
* currently listening in `this.active`. The synthetic catalog SDP omits
|
|
220587
|
+
* `sprop-parameter-sets`, which the raw ffmpeg decode reader cannot recover
|
|
220588
|
+
* (it has no in-band SPS/PPS merge) — so a decode-path consumer that pulls
|
|
220589
|
+
* the catalog after `materializeStreamSocket` must still see the real SDP.
|
|
220590
|
+
* See `native-sdp-overlay.ts`.
|
|
220591
|
+
*/
|
|
220592
|
+
withLiveNativeSdp(descriptors) {
|
|
220593
|
+
return overlayLiveNativeRfc4571Sdp(descriptors, (camStreamId) => {
|
|
220594
|
+
const server = this.active.get(camStreamId)?.server;
|
|
220595
|
+
if (!server?.server?.listening) return null;
|
|
220596
|
+
return {
|
|
220597
|
+
host: server.host,
|
|
220598
|
+
port: server.port,
|
|
220599
|
+
username: server.username,
|
|
220600
|
+
password: server.password,
|
|
220601
|
+
sdp: server.sdp
|
|
220602
|
+
};
|
|
220603
|
+
});
|
|
220604
|
+
}
|
|
220605
|
+
/**
|
|
220523
220606
|
* Synthesize the HTTP-FLV pull URL for a (channel, profile) pair. FLV is
|
|
220524
220607
|
* served off the Reolink Baichuan media port (default 1935, app `bcs`) as
|
|
220525
220608
|
* `channel<channel>_<profile>.bcs` — the same shape Frigate/go2rtc use. The
|
|
@@ -220743,13 +220826,16 @@ var ReolinkCamera = class ReolinkCamera extends BaseDevice {
|
|
|
220743
220826
|
}
|
|
220744
220827
|
const url = `tcp://${`${encodeURIComponent(server.username)}:${encodeURIComponent(server.password)}`}@${server.host}:${server.port}`;
|
|
220745
220828
|
const codec = server.videoType === "H265" ? "h265" : "h264";
|
|
220829
|
+
const descriptor = this.cachedStreamDescriptors?.find((d) => d.camStreamId === camStreamId);
|
|
220746
220830
|
await this.publishOne({
|
|
220747
220831
|
camStreamId,
|
|
220748
220832
|
kind: "pull-rfc4571",
|
|
220749
|
-
label: camStreamId,
|
|
220833
|
+
label: descriptor?.label ?? camStreamId,
|
|
220750
220834
|
url,
|
|
220751
220835
|
codec,
|
|
220752
220836
|
autoEligible: true,
|
|
220837
|
+
...descriptor?.resolution ? { resolution: descriptor.resolution } : {},
|
|
220838
|
+
...descriptor?.fps !== void 0 ? { fps: descriptor.fps } : {},
|
|
220753
220839
|
metadata: { sdp: server.sdp }
|
|
220754
220840
|
});
|
|
220755
220841
|
this.ctx.logger.info("materialized rfc4571 stream socket on broker demand", {
|