@camstack/addon-pipeline 1.2.236 → 1.2.237
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/stream-broker/index.js +36 -29
- package/dist/stream-broker/index.mjs +36 -29
- package/package.json +1 -1
|
@@ -12107,33 +12107,6 @@ var PrestreamPump = class {
|
|
|
12107
12107
|
});
|
|
12108
12108
|
}
|
|
12109
12109
|
/**
|
|
12110
|
-
* Prepare the picture NOW, so the next wake does not have to.
|
|
12111
|
-
*
|
|
12112
|
-
* The window is ~6 s wide and the preparation was measured at 2.5-5.5 s of
|
|
12113
|
-
* it (Baby monitor, 2026-09-14) — the placeholder was ready with under a
|
|
12114
|
-
* second left and emitted ONE frame, which is indistinguishable from the
|
|
12115
|
-
* prestream not working, and is how the operator reported it. The encode
|
|
12116
|
-
* cache upstream was built for exactly this and missed every time: it is
|
|
12117
|
-
* keyed on the snapshot's digest, and a fresh snapshot is captured during
|
|
12118
|
-
* every stream window, so the key changed on every wake.
|
|
12119
|
-
*
|
|
12120
|
-
* Called when the camera is ALREADY awake and nobody is waiting (the broker
|
|
12121
|
-
* suspends), which is also the moment its snapshot is the freshest it will
|
|
12122
|
-
* be until the next wake — so the digest that gets cached is the digest the
|
|
12123
|
-
* next wake will compute. It opens NO window, emits nothing and arms no
|
|
12124
|
-
* timer: the only effect it wants is the one it has upstream, a warm cache.
|
|
12125
|
-
*
|
|
12126
|
-
* A failure is swallowed on purpose. This is an optimisation running on
|
|
12127
|
-
* nobody's behalf; reporting it as a fault would put a warn line on every
|
|
12128
|
-
* camera that sleeps with a busy encoder.
|
|
12129
|
-
*/
|
|
12130
|
-
warm(sourceUrl) {
|
|
12131
|
-
if (this.active) return;
|
|
12132
|
-
this.options.prepare({ sourceUrl }).then(() => {
|
|
12133
|
-
this.options.logger?.debug("prestream: picture warmed for the next wake", { ...this.tags });
|
|
12134
|
-
}).catch(() => {});
|
|
12135
|
-
}
|
|
12136
|
-
/**
|
|
12137
12110
|
* Close the window. Called on the first NON-placeholder packet — the one edge
|
|
12138
12111
|
* the prestream is defined by — and on the broker's own teardown paths so a
|
|
12139
12112
|
* stopped broker leaves no timer behind.
|
|
@@ -13603,8 +13576,6 @@ var StreamBroker = class StreamBroker {
|
|
|
13603
13576
|
this.placeholderTimer = void 0;
|
|
13604
13577
|
}
|
|
13605
13578
|
this.prestreamPump?.stop("broker suspended");
|
|
13606
|
-
const warmUrl = this.source?.url;
|
|
13607
|
-
if (warmUrl !== void 0 && warmUrl.length > 0) this.prestreamPump?.warm(warmUrl);
|
|
13608
13579
|
this.prestreamWindowClosed = false;
|
|
13609
13580
|
this.preBuffer.clear();
|
|
13610
13581
|
this.decoderSeedBuffer.clear();
|
|
@@ -16315,6 +16286,8 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
16315
16286
|
* was made from. One entry is one still image — kilobytes — and it is
|
|
16316
16287
|
* dropped with the broker in `releaseBroker`.
|
|
16317
16288
|
*/
|
|
16289
|
+
/** Brokers with a background prestream re-encode in flight (single-flight). */
|
|
16290
|
+
prestreamRefreshing = /* @__PURE__ */ new Set();
|
|
16318
16291
|
prestreamFrames = /* @__PURE__ */ new Map();
|
|
16319
16292
|
/** Monotonic insertion counter per device — feeds `CameraStreamInternal.order`. */
|
|
16320
16293
|
streamOrderSeq = /* @__PURE__ */ new Map();
|
|
@@ -17307,6 +17280,26 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
17307
17280
|
});
|
|
17308
17281
|
return cached.frame;
|
|
17309
17282
|
}
|
|
17283
|
+
const cachedGeometry = cached ? cached.key.slice(cached.key.indexOf(":")) : null;
|
|
17284
|
+
const wantedGeometry = key.slice(key.indexOf(":"));
|
|
17285
|
+
if (cached && cachedGeometry === wantedGeometry) {
|
|
17286
|
+
logger.info("prestream: serving the previous picture while the new one encodes", {
|
|
17287
|
+
tags: { deviceId },
|
|
17288
|
+
meta: { bytes: cached.frame.annexB.length }
|
|
17289
|
+
});
|
|
17290
|
+
this.encodePrestreamInBackground(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger);
|
|
17291
|
+
return cached.frame;
|
|
17292
|
+
}
|
|
17293
|
+
return await this.composeAndEncodePrestream(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger);
|
|
17294
|
+
}
|
|
17295
|
+
/**
|
|
17296
|
+
* Compose the treatment and encode ONE IDR, then cache it under `key`.
|
|
17297
|
+
*
|
|
17298
|
+
* Split out so the wake path and the background refresh share it byte for
|
|
17299
|
+
* byte — two encoders that drifted apart would put two different pictures in
|
|
17300
|
+
* front of the operator depending on which wake they caught.
|
|
17301
|
+
*/
|
|
17302
|
+
async composeAndEncodePrestream(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger) {
|
|
17310
17303
|
const picture = await composePrestreamPicture({
|
|
17311
17304
|
cachedJpeg,
|
|
17312
17305
|
deviceName,
|
|
@@ -17350,6 +17343,20 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
17350
17343
|
});
|
|
17351
17344
|
return frame;
|
|
17352
17345
|
}
|
|
17346
|
+
/**
|
|
17347
|
+
* Encode the CURRENT picture for the NEXT wake, off the wake path.
|
|
17348
|
+
*
|
|
17349
|
+
* Single-flight per broker: a camera that wakes twice inside one encode must
|
|
17350
|
+
* not spawn a second ffmpeg — that is CPU taken from the live stream the
|
|
17351
|
+
* operator is actually waiting for.
|
|
17352
|
+
*/
|
|
17353
|
+
encodePrestreamInBackground(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger) {
|
|
17354
|
+
if (this.prestreamRefreshing.has(brokerId)) return;
|
|
17355
|
+
this.prestreamRefreshing.add(brokerId);
|
|
17356
|
+
this.composeAndEncodePrestream(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger).catch(() => {}).finally(() => {
|
|
17357
|
+
this.prestreamRefreshing.delete(brokerId);
|
|
17358
|
+
});
|
|
17359
|
+
}
|
|
17353
17360
|
subscribePlaceholderStateSources(bus) {
|
|
17354
17361
|
bus.subscribe({ category: require_dist.EventCategory.BatteryOnStatusChanged }, (event) => {
|
|
17355
17362
|
const data = event.data;
|
|
@@ -12103,33 +12103,6 @@ var PrestreamPump = class {
|
|
|
12103
12103
|
});
|
|
12104
12104
|
}
|
|
12105
12105
|
/**
|
|
12106
|
-
* Prepare the picture NOW, so the next wake does not have to.
|
|
12107
|
-
*
|
|
12108
|
-
* The window is ~6 s wide and the preparation was measured at 2.5-5.5 s of
|
|
12109
|
-
* it (Baby monitor, 2026-09-14) — the placeholder was ready with under a
|
|
12110
|
-
* second left and emitted ONE frame, which is indistinguishable from the
|
|
12111
|
-
* prestream not working, and is how the operator reported it. The encode
|
|
12112
|
-
* cache upstream was built for exactly this and missed every time: it is
|
|
12113
|
-
* keyed on the snapshot's digest, and a fresh snapshot is captured during
|
|
12114
|
-
* every stream window, so the key changed on every wake.
|
|
12115
|
-
*
|
|
12116
|
-
* Called when the camera is ALREADY awake and nobody is waiting (the broker
|
|
12117
|
-
* suspends), which is also the moment its snapshot is the freshest it will
|
|
12118
|
-
* be until the next wake — so the digest that gets cached is the digest the
|
|
12119
|
-
* next wake will compute. It opens NO window, emits nothing and arms no
|
|
12120
|
-
* timer: the only effect it wants is the one it has upstream, a warm cache.
|
|
12121
|
-
*
|
|
12122
|
-
* A failure is swallowed on purpose. This is an optimisation running on
|
|
12123
|
-
* nobody's behalf; reporting it as a fault would put a warn line on every
|
|
12124
|
-
* camera that sleeps with a busy encoder.
|
|
12125
|
-
*/
|
|
12126
|
-
warm(sourceUrl) {
|
|
12127
|
-
if (this.active) return;
|
|
12128
|
-
this.options.prepare({ sourceUrl }).then(() => {
|
|
12129
|
-
this.options.logger?.debug("prestream: picture warmed for the next wake", { ...this.tags });
|
|
12130
|
-
}).catch(() => {});
|
|
12131
|
-
}
|
|
12132
|
-
/**
|
|
12133
12106
|
* Close the window. Called on the first NON-placeholder packet — the one edge
|
|
12134
12107
|
* the prestream is defined by — and on the broker's own teardown paths so a
|
|
12135
12108
|
* stopped broker leaves no timer behind.
|
|
@@ -13599,8 +13572,6 @@ var StreamBroker = class StreamBroker {
|
|
|
13599
13572
|
this.placeholderTimer = void 0;
|
|
13600
13573
|
}
|
|
13601
13574
|
this.prestreamPump?.stop("broker suspended");
|
|
13602
|
-
const warmUrl = this.source?.url;
|
|
13603
|
-
if (warmUrl !== void 0 && warmUrl.length > 0) this.prestreamPump?.warm(warmUrl);
|
|
13604
13575
|
this.prestreamWindowClosed = false;
|
|
13605
13576
|
this.preBuffer.clear();
|
|
13606
13577
|
this.decoderSeedBuffer.clear();
|
|
@@ -16311,6 +16282,8 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
16311
16282
|
* was made from. One entry is one still image — kilobytes — and it is
|
|
16312
16283
|
* dropped with the broker in `releaseBroker`.
|
|
16313
16284
|
*/
|
|
16285
|
+
/** Brokers with a background prestream re-encode in flight (single-flight). */
|
|
16286
|
+
prestreamRefreshing = /* @__PURE__ */ new Set();
|
|
16314
16287
|
prestreamFrames = /* @__PURE__ */ new Map();
|
|
16315
16288
|
/** Monotonic insertion counter per device — feeds `CameraStreamInternal.order`. */
|
|
16316
16289
|
streamOrderSeq = /* @__PURE__ */ new Map();
|
|
@@ -17303,6 +17276,26 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
17303
17276
|
});
|
|
17304
17277
|
return cached.frame;
|
|
17305
17278
|
}
|
|
17279
|
+
const cachedGeometry = cached ? cached.key.slice(cached.key.indexOf(":")) : null;
|
|
17280
|
+
const wantedGeometry = key.slice(key.indexOf(":"));
|
|
17281
|
+
if (cached && cachedGeometry === wantedGeometry) {
|
|
17282
|
+
logger.info("prestream: serving the previous picture while the new one encodes", {
|
|
17283
|
+
tags: { deviceId },
|
|
17284
|
+
meta: { bytes: cached.frame.annexB.length }
|
|
17285
|
+
});
|
|
17286
|
+
this.encodePrestreamInBackground(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger);
|
|
17287
|
+
return cached.frame;
|
|
17288
|
+
}
|
|
17289
|
+
return await this.composeAndEncodePrestream(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger);
|
|
17290
|
+
}
|
|
17291
|
+
/**
|
|
17292
|
+
* Compose the treatment and encode ONE IDR, then cache it under `key`.
|
|
17293
|
+
*
|
|
17294
|
+
* Split out so the wake path and the background refresh share it byte for
|
|
17295
|
+
* byte — two encoders that drifted apart would put two different pictures in
|
|
17296
|
+
* front of the operator depending on which wake they caught.
|
|
17297
|
+
*/
|
|
17298
|
+
async composeAndEncodePrestream(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger) {
|
|
17306
17299
|
const picture = await composePrestreamPicture({
|
|
17307
17300
|
cachedJpeg,
|
|
17308
17301
|
deviceName,
|
|
@@ -17346,6 +17339,20 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
17346
17339
|
});
|
|
17347
17340
|
return frame;
|
|
17348
17341
|
}
|
|
17342
|
+
/**
|
|
17343
|
+
* Encode the CURRENT picture for the NEXT wake, off the wake path.
|
|
17344
|
+
*
|
|
17345
|
+
* Single-flight per broker: a camera that wakes twice inside one encode must
|
|
17346
|
+
* not spawn a second ffmpeg — that is CPU taken from the live stream the
|
|
17347
|
+
* operator is actually waiting for.
|
|
17348
|
+
*/
|
|
17349
|
+
encodePrestreamInBackground(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger) {
|
|
17350
|
+
if (this.prestreamRefreshing.has(brokerId)) return;
|
|
17351
|
+
this.prestreamRefreshing.add(brokerId);
|
|
17352
|
+
this.composeAndEncodePrestream(deviceId, brokerId, plan, key, cachedJpeg, deviceName, logger).catch(() => {}).finally(() => {
|
|
17353
|
+
this.prestreamRefreshing.delete(brokerId);
|
|
17354
|
+
});
|
|
17355
|
+
}
|
|
17349
17356
|
subscribePlaceholderStateSources(bus) {
|
|
17350
17357
|
bus.subscribe({ category: EventCategory.BatteryOnStatusChanged }, (event) => {
|
|
17351
17358
|
const data = event.data;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.237",
|
|
4
4
|
"description": "Pipeline bundle — runner, detection, motion, audio + stream broker. Multi-entry npm package shipping pipeline addons under a single bundle.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|