@camstack/addon-pipeline 1.2.632 → 1.2.634
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/CHANGELOG.md +12 -0
- package/dist/audio-analyzer/index.js +3 -3
- package/dist/audio-analyzer/index.mjs +3 -3
- package/dist/{custom-model-catalog-B2w26VBG.mjs → custom-model-catalog-BjkdcgOE.mjs} +2 -2
- package/dist/{custom-model-catalog-DN4xBVQE.js → custom-model-catalog-CgSsz_wK.js} +2 -2
- package/dist/detection-pipeline/index.js +4 -4
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-CLo3QHtG.js → dist-C5sQVajZ.js} +685 -13
- package/dist/{dist-DWkdwtle.mjs → dist-DlB7gVjz.mjs} +685 -13
- package/dist/{model-catalogs-DIviCtiQ.js → model-catalogs-D6iqJdhC.js} +1 -1
- package/dist/{model-catalogs-rs7okKyp.mjs → model-catalogs-XdVK-cpH.mjs} +1 -1
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-CAJ1Dal-.mjs → node-DI6cJT3H.mjs} +1 -1
- package/dist/{node-CPqDCFas.js → node-DqynP4Sn.js} +1 -1
- package/dist/pipeline-runner/index.js +3 -3
- package/dist/pipeline-runner/index.mjs +3 -3
- package/dist/{process-memory-BrKzYxim.js → process-memory-BWsvhswo.js} +1 -1
- package/dist/{process-memory-DJWthb6k.mjs → process-memory-CdsO2dxD.mjs} +1 -1
- package/dist/recorder/index.js +8 -2
- package/dist/recorder/index.mjs +8 -2
- package/dist/{segment-demux-js-Bt5bxfyh.js → segment-demux-js-CEqPvaCD.js} +1 -1
- package/dist/{segment-demux-js-CZdgio0n.mjs → segment-demux-js-jzhozTBr.mjs} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CjjdxZUq.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BfutHWHx.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DfXSkf61.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CGcEN1m1.mjs +26 -0
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-MWvZi8Nq.mjs → hostInit-oZNKK5YV.mjs} +2 -2
- package/dist/stream-broker/index.js +115 -19
- package/dist/stream-broker/index.mjs +115 -19
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DZmxw-we.mjs +0 -26
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CFflpMdb.mjs +0 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as demuxSegmentFullJs } from "../segment-demux-js-
|
|
1
|
+
import { t as demuxSegmentFullJs } from "../segment-demux-js-jzhozTBr.mjs";
|
|
2
2
|
import { parentPort } from "node:worker_threads";
|
|
3
3
|
//#region src/stream-broker/recorded/demux-worker-child.ts
|
|
4
4
|
/**
|
|
@@ -36,7 +36,7 @@ async function r() {
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"@camstack/types": {
|
|
39
|
-
version: "1.2.
|
|
39
|
+
version: "1.2.442",
|
|
40
40
|
scope: "default",
|
|
41
41
|
shareConfig: {
|
|
42
42
|
singleton: !0,
|
|
@@ -81,7 +81,7 @@ async function r() {
|
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
83
|
"@camstack/ui-library": {
|
|
84
|
-
version: "1.2.
|
|
84
|
+
version: "1.2.348",
|
|
85
85
|
scope: "default",
|
|
86
86
|
shareConfig: {
|
|
87
87
|
singleton: !0,
|
|
@@ -3,11 +3,11 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_node = require("../node-
|
|
6
|
+
const require_dist = require("../dist-C5sQVajZ.js");
|
|
7
|
+
const require_node = require("../node-DqynP4Sn.js");
|
|
8
8
|
const require_restream_intent = require("../restream-intent-DzrZ_EHP.js");
|
|
9
9
|
const require_remote_restream = require("../remote-restream-CO36Sr30.js");
|
|
10
|
-
const require_segment_demux_js = require("../segment-demux-js-
|
|
10
|
+
const require_segment_demux_js = require("../segment-demux-js-CEqPvaCD.js");
|
|
11
11
|
let node_os = require("node:os");
|
|
12
12
|
node_os = require_chunk.__toESM(node_os);
|
|
13
13
|
let node_crypto = require("node:crypto");
|
|
@@ -874,7 +874,10 @@ function healthEventIsOperatorFacing(camStreamId) {
|
|
|
874
874
|
*
|
|
875
875
|
* - asleep and nobody asked for the stream — NOT an outage (`asleep`);
|
|
876
876
|
* - asleep, a stream was DEMANDED and none arrived — `wake-timeout`;
|
|
877
|
-
* - reported awake
|
|
877
|
+
* - reported awake, the stream is gone, and the camera has been awake longer
|
|
878
|
+
* than a wake needs (`WAKE_DEMAND_BOUND_MS`) — `connection-error`; inside
|
|
879
|
+
* that window it is the normal wake (sleeping flipped, first keyframe not
|
|
880
|
+
* yet here) and is suppressed, then re-judged;
|
|
878
881
|
* - silent past the battery refresh window — `battery-unreachable`.
|
|
879
882
|
*
|
|
880
883
|
* A sleep verdict needs a sleep state that was actually READ. A mirror that
|
|
@@ -911,10 +914,17 @@ function judgeStaleStream(input) {
|
|
|
911
914
|
kind: "outage",
|
|
912
915
|
reason: "battery-unreachable"
|
|
913
916
|
};
|
|
914
|
-
if (presence === "awake")
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
917
|
+
if (presence === "awake") {
|
|
918
|
+
const awakeSince = input.battery.facts.awakeSince;
|
|
919
|
+
if (awakeSince !== void 0 && input.nowMs - awakeSince < 45e3) return {
|
|
920
|
+
kind: "suppressed",
|
|
921
|
+
presence
|
|
922
|
+
};
|
|
923
|
+
return {
|
|
924
|
+
kind: "outage",
|
|
925
|
+
reason: "connection-error"
|
|
926
|
+
};
|
|
927
|
+
}
|
|
918
928
|
if (input.demanded) return {
|
|
919
929
|
kind: "outage",
|
|
920
930
|
reason: "wake-timeout"
|
|
@@ -17620,6 +17630,25 @@ function resolveBrokerTier(brokerId, localLookup, remoteBrokerTiers) {
|
|
|
17620
17630
|
*/
|
|
17621
17631
|
var STREAM_STALE_TIMEOUT_MS = 12e4;
|
|
17622
17632
|
var STREAM_HEALTH_POLL_MS = 15e3;
|
|
17633
|
+
/**
|
|
17634
|
+
* `awakeSince` for a sleep fact just observed: stamped when `sleeping` flips to
|
|
17635
|
+
* false (from asleep, or from nothing known — the event IS the flip), kept while
|
|
17636
|
+
* it stays awake, absent while asleep.
|
|
17637
|
+
*/
|
|
17638
|
+
function awakeSinceFor(previous, sleeping, nowMs) {
|
|
17639
|
+
if (sleeping) return {};
|
|
17640
|
+
if (previous !== null && !previous.sleeping && previous.awakeSince !== void 0) return { awakeSince: previous.awakeSince };
|
|
17641
|
+
return { awakeSince: nowMs };
|
|
17642
|
+
}
|
|
17643
|
+
/** A slice READ carries no flip time: keep the one an event gave while the camera stays awake. */
|
|
17644
|
+
function carryAwakeSince(previous, read) {
|
|
17645
|
+
if (read === null || read.sleeping) return read;
|
|
17646
|
+
if (previous === null || previous.sleeping || previous.awakeSince === void 0) return read;
|
|
17647
|
+
return {
|
|
17648
|
+
...read,
|
|
17649
|
+
awakeSince: previous.awakeSince
|
|
17650
|
+
};
|
|
17651
|
+
}
|
|
17623
17652
|
/** How often an unanswered / stale battery probe is asked again. */
|
|
17624
17653
|
var BATTERY_PROBE_RETRY_MS = 6e4;
|
|
17625
17654
|
/** A wake-only outage with no further failed wake for this long is over: the demand is gone. */
|
|
@@ -20685,7 +20714,7 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
20685
20714
|
markSleepSuppressed(brokerId, context, presence, lastPacketAt) {
|
|
20686
20715
|
this.sleepSuppressedBrokers.add(brokerId);
|
|
20687
20716
|
this.streamOfflineReasonByBroker.delete(brokerId);
|
|
20688
|
-
this.logger.info("stream quiet on a sleeping battery camera — not an outage", {
|
|
20717
|
+
this.logger.info(presence === "awake" ? "stream quiet on a battery camera that just woke — not an outage yet, judged again after the wake bound" : "stream quiet on a sleeping battery camera — not an outage", {
|
|
20689
20718
|
tags: { deviceId: context.deviceId },
|
|
20690
20719
|
meta: {
|
|
20691
20720
|
camStreamId: context.camStreamId,
|
|
@@ -20852,7 +20881,7 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
20852
20881
|
this.batteryProbe.set(deviceId, {
|
|
20853
20882
|
state: "done",
|
|
20854
20883
|
isBattery: true,
|
|
20855
|
-
facts: facts ?? current?.facts ?? null,
|
|
20884
|
+
facts: carryAwakeSince(current?.facts ?? null, facts) ?? current?.facts ?? null,
|
|
20856
20885
|
readAt: Date.now()
|
|
20857
20886
|
});
|
|
20858
20887
|
}).finally(() => this.batteryProbeInFlight.delete(deviceId));
|
|
@@ -20874,9 +20903,11 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
20874
20903
|
}
|
|
20875
20904
|
recordBatterySleep(deviceId, status) {
|
|
20876
20905
|
const previous = this.batteryProbe.get(deviceId);
|
|
20906
|
+
const nowMs = Date.now();
|
|
20877
20907
|
const facts = status && typeof status.sleeping === "boolean" ? {
|
|
20878
20908
|
sleeping: status.sleeping,
|
|
20879
|
-
...typeof status.lastContactAt === "number" ? { lastContactAt: status.lastContactAt } : {}
|
|
20909
|
+
...typeof status.lastContactAt === "number" ? { lastContactAt: status.lastContactAt } : {},
|
|
20910
|
+
...awakeSinceFor(previous?.facts ?? null, status.sleeping, nowMs)
|
|
20880
20911
|
} : null;
|
|
20881
20912
|
this.batteryProbe.set(deviceId, {
|
|
20882
20913
|
state: "done",
|
|
@@ -24649,6 +24680,45 @@ var RembWatch = class {
|
|
|
24649
24680
|
}
|
|
24650
24681
|
};
|
|
24651
24682
|
//#endregion
|
|
24683
|
+
//#region src/stream-broker/webrtc/inbound-stun-probe.ts
|
|
24684
|
+
var MAX_SOURCES = 8;
|
|
24685
|
+
var InboundStunProbe = class {
|
|
24686
|
+
onFirst;
|
|
24687
|
+
now;
|
|
24688
|
+
requests = 0;
|
|
24689
|
+
first = null;
|
|
24690
|
+
sources = /* @__PURE__ */ new Set();
|
|
24691
|
+
createdAt;
|
|
24692
|
+
constructor(onFirst, now = Date.now) {
|
|
24693
|
+
this.onFirst = onFirst;
|
|
24694
|
+
this.now = now;
|
|
24695
|
+
this.createdAt = now();
|
|
24696
|
+
}
|
|
24697
|
+
/** Pass as werift's `iceFilterStunResponse`. Always lets the request through. */
|
|
24698
|
+
filter = (_message, addr, _protocol) => {
|
|
24699
|
+
const from = `${addr[0]}:${addr[1]}`;
|
|
24700
|
+
this.requests += 1;
|
|
24701
|
+
if (this.sources.size < MAX_SOURCES) this.sources.add(from);
|
|
24702
|
+
if (this.first === null) {
|
|
24703
|
+
const afterMs = this.now() - this.createdAt;
|
|
24704
|
+
this.first = {
|
|
24705
|
+
from,
|
|
24706
|
+
atMs: afterMs
|
|
24707
|
+
};
|
|
24708
|
+
this.onFirst(from, afterMs);
|
|
24709
|
+
}
|
|
24710
|
+
return true;
|
|
24711
|
+
};
|
|
24712
|
+
summary() {
|
|
24713
|
+
return {
|
|
24714
|
+
requests: this.requests,
|
|
24715
|
+
firstFrom: this.first?.from ?? null,
|
|
24716
|
+
firstAfterMs: this.first?.atMs ?? null,
|
|
24717
|
+
sources: [...this.sources]
|
|
24718
|
+
};
|
|
24719
|
+
}
|
|
24720
|
+
};
|
|
24721
|
+
//#endregion
|
|
24652
24722
|
//#region src/stream-broker/webrtc/transcode-egress-leg.ts
|
|
24653
24723
|
/**
|
|
24654
24724
|
* The request a browser session makes. Structured only: the primitive's schema
|
|
@@ -25182,6 +25252,8 @@ var AdaptiveSession = class AdaptiveSession {
|
|
|
25182
25252
|
audioSender = null;
|
|
25183
25253
|
feedAbort = null;
|
|
25184
25254
|
closed = false;
|
|
25255
|
+
/** Armed by `handleOffer`; counts the peer's inbound ICE checks. */
|
|
25256
|
+
inboundStun = null;
|
|
25185
25257
|
statsTimer = null;
|
|
25186
25258
|
/**
|
|
25187
25259
|
* Notification hook invoked exactly once when `close()` finishes. The
|
|
@@ -25875,6 +25947,18 @@ var AdaptiveSession = class AdaptiveSession {
|
|
|
25875
25947
|
async handleOffer(clientOffer, opts) {
|
|
25876
25948
|
const negotiateStart = Date.now();
|
|
25877
25949
|
const { werift, pcOptions } = await this.buildPcOptions();
|
|
25950
|
+
this.inboundStun = new InboundStunProbe((from, afterMs) => {
|
|
25951
|
+
this.logger.info("ICE first inbound STUN binding request from the peer", {
|
|
25952
|
+
tags: { deviceId: this.deviceId },
|
|
25953
|
+
meta: {
|
|
25954
|
+
phase: "session",
|
|
25955
|
+
sessionId: this.sessionId,
|
|
25956
|
+
from,
|
|
25957
|
+
afterMs
|
|
25958
|
+
}
|
|
25959
|
+
});
|
|
25960
|
+
});
|
|
25961
|
+
pcOptions.iceFilterStunResponse = this.inboundStun.filter;
|
|
25878
25962
|
this.pc = new werift.RTCPeerConnection(pcOptions);
|
|
25879
25963
|
const pcSetupMs = Date.now() - negotiateStart;
|
|
25880
25964
|
this.wireControlChannel();
|
|
@@ -25913,14 +25997,17 @@ var AdaptiveSession = class AdaptiveSession {
|
|
|
25913
25997
|
const resolvedOfferSdp = await resolveMdnsCandidatesInSdp(clientOffer.sdp, this.logger, `session:${this.sessionId}`);
|
|
25914
25998
|
const mdnsMs = Date.now() - mdnsStart;
|
|
25915
25999
|
const offerCandidates = resolvedOfferSdp.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("a=candidate:"));
|
|
25916
|
-
|
|
25917
|
-
|
|
25918
|
-
|
|
25919
|
-
|
|
25920
|
-
|
|
25921
|
-
|
|
25922
|
-
|
|
25923
|
-
|
|
26000
|
+
this.logger.info("client offer REMOTE ICE candidates", {
|
|
26001
|
+
tags: { deviceId: this.deviceId },
|
|
26002
|
+
meta: {
|
|
26003
|
+
phase: "session",
|
|
26004
|
+
sessionId: this.sessionId,
|
|
26005
|
+
deviceId: this.deviceId,
|
|
26006
|
+
count: offerCandidates.length,
|
|
26007
|
+
candidateTypes: summarizeCandidates(resolvedOfferSdp),
|
|
26008
|
+
candidates: offerCandidates
|
|
26009
|
+
}
|
|
26010
|
+
});
|
|
25924
26011
|
const remoteDesc = new werift.RTCSessionDescription(resolvedOfferSdp, clientOffer.type);
|
|
25925
26012
|
const setRemoteStart = Date.now();
|
|
25926
26013
|
await this.pc.setRemoteDescription(remoteDesc);
|
|
@@ -26178,6 +26265,15 @@ var AdaptiveSession = class AdaptiveSession {
|
|
|
26178
26265
|
phase: "session",
|
|
26179
26266
|
sessionId: this.sessionId
|
|
26180
26267
|
} });
|
|
26268
|
+
if (this.inboundStun !== null) this.logger.info("ICE inbound STUN summary at close", {
|
|
26269
|
+
tags: { deviceId: this.deviceId },
|
|
26270
|
+
meta: {
|
|
26271
|
+
phase: "session",
|
|
26272
|
+
sessionId: this.sessionId,
|
|
26273
|
+
iceConnectionState: this.pc?.iceConnectionState ?? "unknown",
|
|
26274
|
+
...this.inboundStun.summary()
|
|
26275
|
+
}
|
|
26276
|
+
});
|
|
26181
26277
|
if (this.statsTimer) {
|
|
26182
26278
|
clearInterval(this.statsTimer);
|
|
26183
26279
|
this.statsTimer = null;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { r as __toESM } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { Bn as isSoftwareDecode, Cr as record, D as G711_SCALE_CORRECTION_DB, Er as EventCategory, Et as egressTransportFromRequest, Gn as BaseAddon, Hn as DeviceType, Jt as memoizePinnedFfmpeg, K as RingBuffer, Kn as CAM_PROFILE_ORDER, L as RATE_CONTROL_RELAXED, Ln as buildFfmpegArgs, Lt as gifDeriveSpeed, Nn as webrtcSessionCapability, Pn as AUDIO_PRESETS, Pt as ffmpegRate, R as RATE_CONTROL_TIGHT, Rt as gifFromMp4Args, St as deviceRemovalHookCapability, Tr as union, Tt as egressTranscodeSharingKey, Un as errMsg, Ut as loadContributionCapability, Vn as DeviceFeature, Wn as BOOT_RECOVERY_BACKOFF_MS, Wt as logChannelsCapability, X as addonWidgetsSourceCapability, Zn as createEvent, _r as discriminatedUnion, _t as deriveBatteryPresence, ar as isSecretMarker, br as number, c as CLIP_STILL_REASON_CODE_HEADER, cr as maskUrlCredentials, et as armRemovalReconcile, gn as resolveEgressDecodeHwAccel, gr as boolean, hr as array, ht as declareLogChannel, ir as isEvent, it as batteryCapability, kn as streamBrokerCapability, lr as nodePin, lt as clipExportFailureOf, mr as _enum, mt as createLogChannelsProvider, o as BatteryStatusSchema, or as makeProfileBrokerId, pt as createHwAccelCache, qn as CamProfileSchema, s as CLIP_BROKER_PACED_RATES, sn as rankStreams, sr as makeSourceBrokerId, st as cameraStreamsCapability, tr as expandAudioChunkToF32le, ur as parseProfileBrokerId, w as EncodeProfileSchema, wr as string, xr as object, yr as literal, zn as invocationFromEncodeProfile } from "../dist-
|
|
3
|
-
import { a as defaultFfmpegSpawn, i as NO_COST_CLAIM, n as Fmp4FragmentChild, r as Fmp4FragmentPlane, s as probeFfmpegBinary, t as ChildCostRegistry } from "../node-
|
|
2
|
+
import { Bn as isSoftwareDecode, Cr as record, D as G711_SCALE_CORRECTION_DB, Er as EventCategory, Et as egressTransportFromRequest, Gn as BaseAddon, Hn as DeviceType, Jt as memoizePinnedFfmpeg, K as RingBuffer, Kn as CAM_PROFILE_ORDER, L as RATE_CONTROL_RELAXED, Ln as buildFfmpegArgs, Lt as gifDeriveSpeed, Nn as webrtcSessionCapability, Pn as AUDIO_PRESETS, Pt as ffmpegRate, R as RATE_CONTROL_TIGHT, Rt as gifFromMp4Args, St as deviceRemovalHookCapability, Tr as union, Tt as egressTranscodeSharingKey, Un as errMsg, Ut as loadContributionCapability, Vn as DeviceFeature, Wn as BOOT_RECOVERY_BACKOFF_MS, Wt as logChannelsCapability, X as addonWidgetsSourceCapability, Zn as createEvent, _r as discriminatedUnion, _t as deriveBatteryPresence, ar as isSecretMarker, br as number, c as CLIP_STILL_REASON_CODE_HEADER, cr as maskUrlCredentials, et as armRemovalReconcile, gn as resolveEgressDecodeHwAccel, gr as boolean, hr as array, ht as declareLogChannel, ir as isEvent, it as batteryCapability, kn as streamBrokerCapability, lr as nodePin, lt as clipExportFailureOf, mr as _enum, mt as createLogChannelsProvider, o as BatteryStatusSchema, or as makeProfileBrokerId, pt as createHwAccelCache, qn as CamProfileSchema, s as CLIP_BROKER_PACED_RATES, sn as rankStreams, sr as makeSourceBrokerId, st as cameraStreamsCapability, tr as expandAudioChunkToF32le, ur as parseProfileBrokerId, w as EncodeProfileSchema, wr as string, xr as object, yr as literal, zn as invocationFromEncodeProfile } from "../dist-DlB7gVjz.mjs";
|
|
3
|
+
import { a as defaultFfmpegSpawn, i as NO_COST_CLAIM, n as Fmp4FragmentChild, r as Fmp4FragmentPlane, s as probeFfmpegBinary, t as ChildCostRegistry } from "../node-DI6cJT3H.mjs";
|
|
4
4
|
import { a as parseRestreamPath, d as PREBUFFER_MAX_MS, f as capPreRollRequestMs, i as isLiveEdgeOnlyDial, m as resolvePrebuffer, n as NO_DECLARATION, p as prebufferRetentionMs, s as sdpVariantFor, u as withSentryIntent } from "../restream-intent-DvzCnthK.mjs";
|
|
5
5
|
import { n as profileForStreamId } from "../remote-restream-BeHi78PZ.mjs";
|
|
6
|
-
import { a as require_mp4box_all, c as parseNalLengthSize, i as runFfmpegOnce, n as demuxSegmentPreferJs, o as avccSampleToAnnexB, r as FfmpegFallbackRefusedError, s as buildKeyframeAnnexB, t as demuxSegmentFullJs } from "../segment-demux-js-
|
|
6
|
+
import { a as require_mp4box_all, c as parseNalLengthSize, i as runFfmpegOnce, n as demuxSegmentPreferJs, o as avccSampleToAnnexB, r as FfmpegFallbackRefusedError, s as buildKeyframeAnnexB, t as demuxSegmentFullJs } from "../segment-demux-js-jzhozTBr.mjs";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import * as os$1 from "node:os";
|
|
9
9
|
import { networkInterfaces, tmpdir } from "node:os";
|
|
@@ -870,7 +870,10 @@ function healthEventIsOperatorFacing(camStreamId) {
|
|
|
870
870
|
*
|
|
871
871
|
* - asleep and nobody asked for the stream — NOT an outage (`asleep`);
|
|
872
872
|
* - asleep, a stream was DEMANDED and none arrived — `wake-timeout`;
|
|
873
|
-
* - reported awake
|
|
873
|
+
* - reported awake, the stream is gone, and the camera has been awake longer
|
|
874
|
+
* than a wake needs (`WAKE_DEMAND_BOUND_MS`) — `connection-error`; inside
|
|
875
|
+
* that window it is the normal wake (sleeping flipped, first keyframe not
|
|
876
|
+
* yet here) and is suppressed, then re-judged;
|
|
874
877
|
* - silent past the battery refresh window — `battery-unreachable`.
|
|
875
878
|
*
|
|
876
879
|
* A sleep verdict needs a sleep state that was actually READ. A mirror that
|
|
@@ -907,10 +910,17 @@ function judgeStaleStream(input) {
|
|
|
907
910
|
kind: "outage",
|
|
908
911
|
reason: "battery-unreachable"
|
|
909
912
|
};
|
|
910
|
-
if (presence === "awake")
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
913
|
+
if (presence === "awake") {
|
|
914
|
+
const awakeSince = input.battery.facts.awakeSince;
|
|
915
|
+
if (awakeSince !== void 0 && input.nowMs - awakeSince < 45e3) return {
|
|
916
|
+
kind: "suppressed",
|
|
917
|
+
presence
|
|
918
|
+
};
|
|
919
|
+
return {
|
|
920
|
+
kind: "outage",
|
|
921
|
+
reason: "connection-error"
|
|
922
|
+
};
|
|
923
|
+
}
|
|
914
924
|
if (input.demanded) return {
|
|
915
925
|
kind: "outage",
|
|
916
926
|
reason: "wake-timeout"
|
|
@@ -17616,6 +17626,25 @@ function resolveBrokerTier(brokerId, localLookup, remoteBrokerTiers) {
|
|
|
17616
17626
|
*/
|
|
17617
17627
|
var STREAM_STALE_TIMEOUT_MS = 12e4;
|
|
17618
17628
|
var STREAM_HEALTH_POLL_MS = 15e3;
|
|
17629
|
+
/**
|
|
17630
|
+
* `awakeSince` for a sleep fact just observed: stamped when `sleeping` flips to
|
|
17631
|
+
* false (from asleep, or from nothing known — the event IS the flip), kept while
|
|
17632
|
+
* it stays awake, absent while asleep.
|
|
17633
|
+
*/
|
|
17634
|
+
function awakeSinceFor(previous, sleeping, nowMs) {
|
|
17635
|
+
if (sleeping) return {};
|
|
17636
|
+
if (previous !== null && !previous.sleeping && previous.awakeSince !== void 0) return { awakeSince: previous.awakeSince };
|
|
17637
|
+
return { awakeSince: nowMs };
|
|
17638
|
+
}
|
|
17639
|
+
/** A slice READ carries no flip time: keep the one an event gave while the camera stays awake. */
|
|
17640
|
+
function carryAwakeSince(previous, read) {
|
|
17641
|
+
if (read === null || read.sleeping) return read;
|
|
17642
|
+
if (previous === null || previous.sleeping || previous.awakeSince === void 0) return read;
|
|
17643
|
+
return {
|
|
17644
|
+
...read,
|
|
17645
|
+
awakeSince: previous.awakeSince
|
|
17646
|
+
};
|
|
17647
|
+
}
|
|
17619
17648
|
/** How often an unanswered / stale battery probe is asked again. */
|
|
17620
17649
|
var BATTERY_PROBE_RETRY_MS = 6e4;
|
|
17621
17650
|
/** A wake-only outage with no further failed wake for this long is over: the demand is gone. */
|
|
@@ -20681,7 +20710,7 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
20681
20710
|
markSleepSuppressed(brokerId, context, presence, lastPacketAt) {
|
|
20682
20711
|
this.sleepSuppressedBrokers.add(brokerId);
|
|
20683
20712
|
this.streamOfflineReasonByBroker.delete(brokerId);
|
|
20684
|
-
this.logger.info("stream quiet on a sleeping battery camera — not an outage", {
|
|
20713
|
+
this.logger.info(presence === "awake" ? "stream quiet on a battery camera that just woke — not an outage yet, judged again after the wake bound" : "stream quiet on a sleeping battery camera — not an outage", {
|
|
20685
20714
|
tags: { deviceId: context.deviceId },
|
|
20686
20715
|
meta: {
|
|
20687
20716
|
camStreamId: context.camStreamId,
|
|
@@ -20848,7 +20877,7 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
20848
20877
|
this.batteryProbe.set(deviceId, {
|
|
20849
20878
|
state: "done",
|
|
20850
20879
|
isBattery: true,
|
|
20851
|
-
facts: facts ?? current?.facts ?? null,
|
|
20880
|
+
facts: carryAwakeSince(current?.facts ?? null, facts) ?? current?.facts ?? null,
|
|
20852
20881
|
readAt: Date.now()
|
|
20853
20882
|
});
|
|
20854
20883
|
}).finally(() => this.batteryProbeInFlight.delete(deviceId));
|
|
@@ -20870,9 +20899,11 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
20870
20899
|
}
|
|
20871
20900
|
recordBatterySleep(deviceId, status) {
|
|
20872
20901
|
const previous = this.batteryProbe.get(deviceId);
|
|
20902
|
+
const nowMs = Date.now();
|
|
20873
20903
|
const facts = status && typeof status.sleeping === "boolean" ? {
|
|
20874
20904
|
sleeping: status.sleeping,
|
|
20875
|
-
...typeof status.lastContactAt === "number" ? { lastContactAt: status.lastContactAt } : {}
|
|
20905
|
+
...typeof status.lastContactAt === "number" ? { lastContactAt: status.lastContactAt } : {},
|
|
20906
|
+
...awakeSinceFor(previous?.facts ?? null, status.sleeping, nowMs)
|
|
20876
20907
|
} : null;
|
|
20877
20908
|
this.batteryProbe.set(deviceId, {
|
|
20878
20909
|
state: "done",
|
|
@@ -24645,6 +24676,45 @@ var RembWatch = class {
|
|
|
24645
24676
|
}
|
|
24646
24677
|
};
|
|
24647
24678
|
//#endregion
|
|
24679
|
+
//#region src/stream-broker/webrtc/inbound-stun-probe.ts
|
|
24680
|
+
var MAX_SOURCES = 8;
|
|
24681
|
+
var InboundStunProbe = class {
|
|
24682
|
+
onFirst;
|
|
24683
|
+
now;
|
|
24684
|
+
requests = 0;
|
|
24685
|
+
first = null;
|
|
24686
|
+
sources = /* @__PURE__ */ new Set();
|
|
24687
|
+
createdAt;
|
|
24688
|
+
constructor(onFirst, now = Date.now) {
|
|
24689
|
+
this.onFirst = onFirst;
|
|
24690
|
+
this.now = now;
|
|
24691
|
+
this.createdAt = now();
|
|
24692
|
+
}
|
|
24693
|
+
/** Pass as werift's `iceFilterStunResponse`. Always lets the request through. */
|
|
24694
|
+
filter = (_message, addr, _protocol) => {
|
|
24695
|
+
const from = `${addr[0]}:${addr[1]}`;
|
|
24696
|
+
this.requests += 1;
|
|
24697
|
+
if (this.sources.size < MAX_SOURCES) this.sources.add(from);
|
|
24698
|
+
if (this.first === null) {
|
|
24699
|
+
const afterMs = this.now() - this.createdAt;
|
|
24700
|
+
this.first = {
|
|
24701
|
+
from,
|
|
24702
|
+
atMs: afterMs
|
|
24703
|
+
};
|
|
24704
|
+
this.onFirst(from, afterMs);
|
|
24705
|
+
}
|
|
24706
|
+
return true;
|
|
24707
|
+
};
|
|
24708
|
+
summary() {
|
|
24709
|
+
return {
|
|
24710
|
+
requests: this.requests,
|
|
24711
|
+
firstFrom: this.first?.from ?? null,
|
|
24712
|
+
firstAfterMs: this.first?.atMs ?? null,
|
|
24713
|
+
sources: [...this.sources]
|
|
24714
|
+
};
|
|
24715
|
+
}
|
|
24716
|
+
};
|
|
24717
|
+
//#endregion
|
|
24648
24718
|
//#region src/stream-broker/webrtc/transcode-egress-leg.ts
|
|
24649
24719
|
/**
|
|
24650
24720
|
* The request a browser session makes. Structured only: the primitive's schema
|
|
@@ -25178,6 +25248,8 @@ var AdaptiveSession = class AdaptiveSession {
|
|
|
25178
25248
|
audioSender = null;
|
|
25179
25249
|
feedAbort = null;
|
|
25180
25250
|
closed = false;
|
|
25251
|
+
/** Armed by `handleOffer`; counts the peer's inbound ICE checks. */
|
|
25252
|
+
inboundStun = null;
|
|
25181
25253
|
statsTimer = null;
|
|
25182
25254
|
/**
|
|
25183
25255
|
* Notification hook invoked exactly once when `close()` finishes. The
|
|
@@ -25871,6 +25943,18 @@ var AdaptiveSession = class AdaptiveSession {
|
|
|
25871
25943
|
async handleOffer(clientOffer, opts) {
|
|
25872
25944
|
const negotiateStart = Date.now();
|
|
25873
25945
|
const { werift, pcOptions } = await this.buildPcOptions();
|
|
25946
|
+
this.inboundStun = new InboundStunProbe((from, afterMs) => {
|
|
25947
|
+
this.logger.info("ICE first inbound STUN binding request from the peer", {
|
|
25948
|
+
tags: { deviceId: this.deviceId },
|
|
25949
|
+
meta: {
|
|
25950
|
+
phase: "session",
|
|
25951
|
+
sessionId: this.sessionId,
|
|
25952
|
+
from,
|
|
25953
|
+
afterMs
|
|
25954
|
+
}
|
|
25955
|
+
});
|
|
25956
|
+
});
|
|
25957
|
+
pcOptions.iceFilterStunResponse = this.inboundStun.filter;
|
|
25874
25958
|
this.pc = new werift.RTCPeerConnection(pcOptions);
|
|
25875
25959
|
const pcSetupMs = Date.now() - negotiateStart;
|
|
25876
25960
|
this.wireControlChannel();
|
|
@@ -25909,14 +25993,17 @@ var AdaptiveSession = class AdaptiveSession {
|
|
|
25909
25993
|
const resolvedOfferSdp = await resolveMdnsCandidatesInSdp(clientOffer.sdp, this.logger, `session:${this.sessionId}`);
|
|
25910
25994
|
const mdnsMs = Date.now() - mdnsStart;
|
|
25911
25995
|
const offerCandidates = resolvedOfferSdp.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("a=candidate:"));
|
|
25912
|
-
|
|
25913
|
-
|
|
25914
|
-
|
|
25915
|
-
|
|
25916
|
-
|
|
25917
|
-
|
|
25918
|
-
|
|
25919
|
-
|
|
25996
|
+
this.logger.info("client offer REMOTE ICE candidates", {
|
|
25997
|
+
tags: { deviceId: this.deviceId },
|
|
25998
|
+
meta: {
|
|
25999
|
+
phase: "session",
|
|
26000
|
+
sessionId: this.sessionId,
|
|
26001
|
+
deviceId: this.deviceId,
|
|
26002
|
+
count: offerCandidates.length,
|
|
26003
|
+
candidateTypes: summarizeCandidates(resolvedOfferSdp),
|
|
26004
|
+
candidates: offerCandidates
|
|
26005
|
+
}
|
|
26006
|
+
});
|
|
25920
26007
|
const remoteDesc = new werift.RTCSessionDescription(resolvedOfferSdp, clientOffer.type);
|
|
25921
26008
|
const setRemoteStart = Date.now();
|
|
25922
26009
|
await this.pc.setRemoteDescription(remoteDesc);
|
|
@@ -26174,6 +26261,15 @@ var AdaptiveSession = class AdaptiveSession {
|
|
|
26174
26261
|
phase: "session",
|
|
26175
26262
|
sessionId: this.sessionId
|
|
26176
26263
|
} });
|
|
26264
|
+
if (this.inboundStun !== null) this.logger.info("ICE inbound STUN summary at close", {
|
|
26265
|
+
tags: { deviceId: this.deviceId },
|
|
26266
|
+
meta: {
|
|
26267
|
+
phase: "session",
|
|
26268
|
+
sessionId: this.sessionId,
|
|
26269
|
+
iceConnectionState: this.pc?.iceConnectionState ?? "unknown",
|
|
26270
|
+
...this.inboundStun.summary()
|
|
26271
|
+
}
|
|
26272
|
+
});
|
|
26177
26273
|
if (this.statsTimer) {
|
|
26178
26274
|
clearInterval(this.statsTimer);
|
|
26179
26275
|
this.statsTimer = null;
|
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BfutHWHx.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.634",
|
|
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",
|