@camstack/addon-pipeline 1.2.344 → 1.2.345

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.
Files changed (30) hide show
  1. package/dist/audio-analyzer/index.js +3 -3
  2. package/dist/audio-analyzer/index.mjs +3 -3
  3. package/dist/{custom-model-catalog-CG8fXDWC.mjs → custom-model-catalog-C7zLb7ze.mjs} +2 -2
  4. package/dist/{custom-model-catalog-Cu1C2kTA.js → custom-model-catalog-CrEsRBe_.js} +2 -2
  5. package/dist/detection-pipeline/index.js +4 -4
  6. package/dist/detection-pipeline/index.mjs +4 -4
  7. package/dist/{dist-DNsARIUD.js → dist-_I6JkuJ8.js} +16 -1
  8. package/dist/{dist-DUr_0s5c.mjs → dist-cT7hhXh9.mjs} +16 -1
  9. package/dist/{model-catalogs-Y509H8MT.js → model-catalogs-BrKLOMBe.js} +1 -1
  10. package/dist/{model-catalogs-BMsnPwTI.mjs → model-catalogs-CPAmiLRa.mjs} +1 -1
  11. package/dist/motion-wasm/index.js +1 -1
  12. package/dist/motion-wasm/index.mjs +1 -1
  13. package/dist/{node-D-U3T-h-.js → node-6zL5ddry.js} +1 -1
  14. package/dist/{node-DhrskFZ_.mjs → node-Dmga8QNL.mjs} +1 -1
  15. package/dist/pipeline-runner/index.js +3 -3
  16. package/dist/pipeline-runner/index.mjs +3 -3
  17. package/dist/{process-memory-BUrTDsRR.js → process-memory-CstCtC3A.js} +1 -1
  18. package/dist/{process-memory-DXtI2GWk.mjs → process-memory-DZcnBnb1.mjs} +1 -1
  19. package/dist/recorder/index.js +2 -2
  20. package/dist/recorder/index.mjs +2 -2
  21. package/dist/{segment-demux-js-vZ6iniOU.js → segment-demux-js-DPtDBph6.js} +1 -1
  22. package/dist/{segment-demux-js-Bv7s-_uv.mjs → segment-demux-js-qzo-pQK7.mjs} +1 -1
  23. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BH3o1g9i.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Drg8iwTA.mjs} +1 -1
  24. package/dist/stream-broker/demux-worker-child.js +1 -1
  25. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  26. package/dist/stream-broker/{hostInit-op1zWltj.mjs → hostInit-Bz5eB0VL.mjs} +1 -1
  27. package/dist/stream-broker/index.js +222 -21
  28. package/dist/stream-broker/index.mjs +222 -21
  29. package/dist/stream-broker/remoteEntry.js +1 -1
  30. package/package.json +1 -1
@@ -3,9 +3,9 @@ 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-DNsARIUD.js");
7
- const require_model_catalogs = require("../model-catalogs-Y509H8MT.js");
8
- const require_process_memory = require("../process-memory-BUrTDsRR.js");
6
+ const require_dist = require("../dist-_I6JkuJ8.js");
7
+ const require_model_catalogs = require("../model-catalogs-BrKLOMBe.js");
8
+ const require_process_memory = require("../process-memory-CstCtC3A.js");
9
9
  let node_fs = require("node:fs");
10
10
  node_fs = require_chunk.__toESM(node_fs);
11
11
  let node_path = require("node:path");
@@ -1,7 +1,7 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { Dn as errMsg, In as expandAudioChunkToF32le, Ln as hydrateSchema, Mn as audioChunkBytesPerSample, N as PoolMemoryWatchdog, Nt as mapAudioLabelToMacro, Vn as nodePin, X as audioAnalyzerCapability, Y as audioAnalysisCapability, an as resolvePoolMemoryPolicy, h as DEFAULT_AUDIO_ANALYZER_CONFIG, kn as BaseAddon, r as AUDIO_BACKEND_CHOICES, rr as EventCategory } from "../dist-DUr_0s5c.mjs";
3
- import { n as AUDIO_CLASSIFIER_MODELS } from "../model-catalogs-BMsnPwTI.mjs";
4
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DXtI2GWk.mjs";
2
+ import { Dn as errMsg, In as expandAudioChunkToF32le, Ln as hydrateSchema, Mn as audioChunkBytesPerSample, N as PoolMemoryWatchdog, Nt as mapAudioLabelToMacro, Vn as nodePin, X as audioAnalyzerCapability, Y as audioAnalysisCapability, an as resolvePoolMemoryPolicy, h as DEFAULT_AUDIO_ANALYZER_CONFIG, kn as BaseAddon, r as AUDIO_BACKEND_CHOICES, rr as EventCategory } from "../dist-cT7hhXh9.mjs";
3
+ import { n as AUDIO_CLASSIFIER_MODELS } from "../model-catalogs-CPAmiLRa.mjs";
4
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DZcnBnb1.mjs";
5
5
  import * as fs from "node:fs";
6
6
  import * as path$1 from "node:path";
7
7
  import { ensureModel } from "@camstack/system/addon-utils";
@@ -1,5 +1,5 @@
1
- import { Dt as inferModelProvider, Z as audioKindId, b as DEVICE_BACKEND_TO_FORMAT, f as COCO_80_LABELS, i as AUDIO_MACRO_LABELS, k as LABEL_SUPPLY_VOCABULARIES, p as COCO_TO_MACRO, un as stepModelRunsOnFormat } from "./dist-DUr_0s5c.mjs";
2
- import { a as FACE_DETECTION_MODELS, c as OBJECT_DETECTION_MODELS, d as PLATE_OCR_MODELS, f as SEGMENTATION_REFINER_MODELS, i as CLIP_EMBEDDING_MODELS, l as PACKAGE_DETECTION_MODELS, n as AUDIO_CLASSIFIER_MODELS, o as FACE_EMBEDDING_MODELS, p as VEHICLE_CLASSIFIER_MODELS, r as BIRD_CLASSIFIER_MODELS, s as INSTANCE_SEGMENTATION_MODELS, t as ANIMAL_CLASSIFIER_MODELS, u as PLATE_DETECTION_MODELS } from "./model-catalogs-BMsnPwTI.mjs";
1
+ import { Dt as inferModelProvider, Z as audioKindId, b as DEVICE_BACKEND_TO_FORMAT, f as COCO_80_LABELS, i as AUDIO_MACRO_LABELS, k as LABEL_SUPPLY_VOCABULARIES, p as COCO_TO_MACRO, un as stepModelRunsOnFormat } from "./dist-cT7hhXh9.mjs";
2
+ import { a as FACE_DETECTION_MODELS, c as OBJECT_DETECTION_MODELS, d as PLATE_OCR_MODELS, f as SEGMENTATION_REFINER_MODELS, i as CLIP_EMBEDDING_MODELS, l as PACKAGE_DETECTION_MODELS, n as AUDIO_CLASSIFIER_MODELS, o as FACE_EMBEDDING_MODELS, p as VEHICLE_CLASSIFIER_MODELS, r as BIRD_CLASSIFIER_MODELS, s as INSTANCE_SEGMENTATION_MODELS, t as ANIMAL_CLASSIFIER_MODELS, u as PLATE_DETECTION_MODELS } from "./model-catalogs-CPAmiLRa.mjs";
3
3
  import { t as isWorkerReply } from "./worker-protocol-D_NzPcnh.mjs";
4
4
  import { randomUUID } from "node:crypto";
5
5
  //#region src/detection-pipeline/registry/effective-confidence.ts
@@ -1,5 +1,5 @@
1
- const require_dist = require("./dist-DNsARIUD.js");
2
- const require_model_catalogs = require("./model-catalogs-Y509H8MT.js");
1
+ const require_dist = require("./dist-_I6JkuJ8.js");
2
+ const require_model_catalogs = require("./model-catalogs-BrKLOMBe.js");
3
3
  const require_worker_protocol = require("./worker-protocol-C-G8qmye.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  //#region src/detection-pipeline/registry/effective-confidence.ts
@@ -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-DNsARIUD.js");
7
- const require_node = require("../node-D-U3T-h-.js");
8
- const require_custom_model_catalog = require("../custom-model-catalog-Cu1C2kTA.js");
6
+ const require_dist = require("../dist-_I6JkuJ8.js");
7
+ const require_node = require("../node-6zL5ddry.js");
8
+ const require_custom_model_catalog = require("../custom-model-catalog-CrEsRBe_.js");
9
9
  const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
10
- const require_process_memory = require("../process-memory-BUrTDsRR.js");
10
+ const require_process_memory = require("../process-memory-CstCtC3A.js");
11
11
  let node_os = require("node:os");
12
12
  node_os = require_chunk.__toESM(node_os);
13
13
  let node_fs = require("node:fs");
@@ -1,9 +1,9 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { Bt as modelBindingKey, Dn as errMsg$1, Et as hfModelUrl, G as YAMNET_TO_MACRO, Ht as overlayClusterStepSettings, J as applyModelBoundSettings, Kn as array, Ln as hydrateSchema, N as PoolMemoryWatchdog, Nn as createEvent, O as LABEL_SUPPLY_MACRO, Qn as object, Vn as nodePin, Wn as sleep, Wt as pickClusterStepSettings, _t as evaluateZoneRules, an as resolvePoolMemoryPolicy, cn as rootSuppliesOf, ct as defaultDeviceFor$1, d as CLUSTER_MODEL_SCOPED_STEPS, en as resolveClusterStepModelId, g as DEFAULT_CLUSTER_STEP_SETTINGS, gt as enumerateInferenceDevices, hn as supportedRuntimes$1, it as containingParentIndex, jt as loadContributionCapability, kn as BaseAddon, kt as linkedLabelStepId, ln as runtimeDevices$1, n as APPLE_SA_TO_MACRO, nr as union, pt as detectionPipelineCapability, qt as pipelineExecutorCapability, rr as EventCategory, rt as collectModelBoundKeys, tr as string, un as stepModelRunsOnFormat } from "../dist-DUr_0s5c.mjs";
3
- import { s as readProcessCost } from "../node-DhrskFZ_.mjs";
4
- import { C as resolveModelDefaultConfidence, S as landmarkPrecisionVerdict, _ as ALL_STEPS, b as getStepDefinition, f as localFrameRegistry, g as ALL_PIPELINE_STEPS, l as resolveDefaultDetectionModel, n as mergeCustomModels, o as deviceKeyOf, r as buildSubtreeCanRun, s as resolveDeviceEngine, t as CustomModelCatalog, u as macroGateVerdict, v as getDefaultModelForFormat, x as resolveModelForFormat, y as getStep } from "../custom-model-catalog-CG8fXDWC.mjs";
2
+ import { Bt as modelBindingKey, Dn as errMsg$1, Et as hfModelUrl, G as YAMNET_TO_MACRO, Ht as overlayClusterStepSettings, J as applyModelBoundSettings, Kn as array, Ln as hydrateSchema, N as PoolMemoryWatchdog, Nn as createEvent, O as LABEL_SUPPLY_MACRO, Qn as object, Vn as nodePin, Wn as sleep, Wt as pickClusterStepSettings, _t as evaluateZoneRules, an as resolvePoolMemoryPolicy, cn as rootSuppliesOf, ct as defaultDeviceFor$1, d as CLUSTER_MODEL_SCOPED_STEPS, en as resolveClusterStepModelId, g as DEFAULT_CLUSTER_STEP_SETTINGS, gt as enumerateInferenceDevices, hn as supportedRuntimes$1, it as containingParentIndex, jt as loadContributionCapability, kn as BaseAddon, kt as linkedLabelStepId, ln as runtimeDevices$1, n as APPLE_SA_TO_MACRO, nr as union, pt as detectionPipelineCapability, qt as pipelineExecutorCapability, rr as EventCategory, rt as collectModelBoundKeys, tr as string, un as stepModelRunsOnFormat } from "../dist-cT7hhXh9.mjs";
3
+ import { s as readProcessCost } from "../node-Dmga8QNL.mjs";
4
+ import { C as resolveModelDefaultConfidence, S as landmarkPrecisionVerdict, _ as ALL_STEPS, b as getStepDefinition, f as localFrameRegistry, g as ALL_PIPELINE_STEPS, l as resolveDefaultDetectionModel, n as mergeCustomModels, o as deviceKeyOf, r as buildSubtreeCanRun, s as resolveDeviceEngine, t as CustomModelCatalog, u as macroGateVerdict, v as getDefaultModelForFormat, x as resolveModelForFormat, y as getStep } from "../custom-model-catalog-C7zLb7ze.mjs";
5
5
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
6
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DXtI2GWk.mjs";
6
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DZcnBnb1.mjs";
7
7
  import * as os from "node:os";
8
8
  import * as fs from "node:fs";
9
9
  import * as path$1 from "node:path";
@@ -32138,7 +32138,22 @@ var webrtcSessionCapability = {
32138
32138
  * field their hints were silently stripped by the schema and the
32139
32139
  * adaptive ladder started blind on the client's display size.
32140
32140
  */
32141
- hints: webrtcClientHintsSchema.optional()
32141
+ hints: webrtcClientHintsSchema.optional(),
32142
+ /**
32143
+ * Talk-back (D771): relay the PEER's audio to the device's speaker
32144
+ * through the `intercom` cap's push-talk triple. When `true` and the
32145
+ * offer lets the peer send audio, the answer's audio is `sendrecv`
32146
+ * and every inbound frame goes to `intercom.pushTalkAudio` for this
32147
+ * `deviceId`; absent/false answers `sendonly`, as for every viewer.
32148
+ *
32149
+ * TRUSTED-CALLER ONLY. Set by the Alexa export for an Echo on a camera
32150
+ * with `intercom`, when the linked user may control that camera. The
32151
+ * hub STRIPS it from every request-bound call (a browser), exactly as
32152
+ * it overwrites `relayOnly` — a viewer's talk permission is the
32153
+ * intercom cap's own surface (share tokens gate it there), and this
32154
+ * flag must not become a second door to the camera's speaker.
32155
+ */
32156
+ talkback: boolean().optional()
32142
32157
  }), object({
32143
32158
  sessionId: string(),
32144
32159
  sdpAnswer: string()
@@ -32138,7 +32138,22 @@ var webrtcSessionCapability = {
32138
32138
  * field their hints were silently stripped by the schema and the
32139
32139
  * adaptive ladder started blind on the client's display size.
32140
32140
  */
32141
- hints: webrtcClientHintsSchema.optional()
32141
+ hints: webrtcClientHintsSchema.optional(),
32142
+ /**
32143
+ * Talk-back (D771): relay the PEER's audio to the device's speaker
32144
+ * through the `intercom` cap's push-talk triple. When `true` and the
32145
+ * offer lets the peer send audio, the answer's audio is `sendrecv`
32146
+ * and every inbound frame goes to `intercom.pushTalkAudio` for this
32147
+ * `deviceId`; absent/false answers `sendonly`, as for every viewer.
32148
+ *
32149
+ * TRUSTED-CALLER ONLY. Set by the Alexa export for an Echo on a camera
32150
+ * with `intercom`, when the linked user may control that camera. The
32151
+ * hub STRIPS it from every request-bound call (a browser), exactly as
32152
+ * it overwrites `relayOnly` — a viewer's talk permission is the
32153
+ * intercom cap's own surface (share tokens gate it there), and this
32154
+ * flag must not become a second door to the camera's speaker.
32155
+ */
32156
+ talkback: boolean().optional()
32142
32157
  }), object({
32143
32158
  sessionId: string(),
32144
32159
  sdpAnswer: string()
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-DNsARIUD.js");
1
+ const require_dist = require("./dist-_I6JkuJ8.js");
2
2
  //#region src/detection-pipeline/registry/model-licenses.ts
3
3
  var COCO_DATA = {
4
4
  name: "COCO 2017",
@@ -1,4 +1,4 @@
1
- import { Et as hfModelUrl } from "./dist-DUr_0s5c.mjs";
1
+ import { Et as hfModelUrl } from "./dist-cT7hhXh9.mjs";
2
2
  //#region src/detection-pipeline/registry/model-licenses.ts
3
3
  var COCO_DATA = {
4
4
  name: "COCO 2017",
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-DNsARIUD.js");
5
+ const require_dist = require("../dist-_I6JkuJ8.js");
6
6
  const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
7
7
  let node_fs = require("node:fs");
8
8
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { En as DeviceType, Ln as hydrateSchema, Vt as motionDetectionCapability, _t as evaluateZoneRules, kn as BaseAddon } from "../dist-DUr_0s5c.mjs";
1
+ import { En as DeviceType, Ln as hydrateSchema, Vt as motionDetectionCapability, _t as evaluateZoneRules, kn as BaseAddon } from "../dist-cT7hhXh9.mjs";
2
2
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { join } from "node:path";
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-emK7D4bc.js");
2
- const require_dist = require("./dist-DNsARIUD.js");
2
+ const require_dist = require("./dist-_I6JkuJ8.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_fs = require("node:fs");
5
5
  node_fs = require_chunk.__toESM(node_fs, 1);
@@ -1,4 +1,4 @@
1
- import { Dn as errMsg, bn as Fmp4BoxSplitter, wn as isSoftwareDecode, xn as buildFfmpegArgs } from "./dist-DUr_0s5c.mjs";
1
+ import { Dn as errMsg, bn as Fmp4BoxSplitter, wn as isSoftwareDecode, xn as buildFfmpegArgs } from "./dist-cT7hhXh9.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { realpathSync } from "node:fs";
4
4
  import path from "node:path";
@@ -3,9 +3,9 @@ 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-DNsARIUD.js");
7
- const require_node = require("../node-D-U3T-h-.js");
8
- const require_custom_model_catalog = require("../custom-model-catalog-Cu1C2kTA.js");
6
+ const require_dist = require("../dist-_I6JkuJ8.js");
7
+ const require_node = require("../node-6zL5ddry.js");
8
+ const require_custom_model_catalog = require("../custom-model-catalog-CrEsRBe_.js");
9
9
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
10
10
  const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
11
11
  const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
@@ -1,6 +1,6 @@
1
- import { $ as cameraOwnsMotionViaSensor, A as NativeLeaseAdmissionSchema, At as linkedStepOf, Dn as errMsg, Fn as defineCustomActions, Gn as _enum, Gt as pickDetailCropConvention, Jt as pipelineRunnerCapability, Kn as array, Kt as pickNativeLeaseOverride, Nn as createEvent, Pn as customAction, Qn as object, T as FailureCounters, Vn as nodePin, Xn as literal, Yn as lazy, Zn as number, _ as DEFAULT_DETAIL_CROP_CONVENTION, a as BackgroundRunRegistry, cn as rootSuppliesOf, ft as deriveRootFaceRefineRect, in as resolveModelBoundSetting, j as NativeLeaseSettingsSchema, jt as loadContributionCapability, kn as BaseAddon, m as CROP_SUPPLY_SOURCES, q as allowedSuppliedEffect, qn as boolean, rr as EventCategory, sn as resolveRootSupply, tr as string, ut as deriveDetailCropRect, xt as failureContributionCapability, y as DEFAULT_NATIVE_LEASE_SETTINGS, z as ROOT_SUPPLIABLE_STEP_IDS } from "../dist-DUr_0s5c.mjs";
2
- import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-DhrskFZ_.mjs";
3
- import { a as stepsForElectedPool, b as getStepDefinition, d as rootObjectGate, f as localFrameRegistry, h as resolveFrameViewGeometry, i as placeDetailStep, l as resolveDefaultDetectionModel, m as createSessionDecodeCoordinator, p as isSessionDecodeReadGone, s as resolveDeviceEngine, t as CustomModelCatalog, u as macroGateVerdict, y as getStep } from "../custom-model-catalog-CG8fXDWC.mjs";
1
+ import { $ as cameraOwnsMotionViaSensor, A as NativeLeaseAdmissionSchema, At as linkedStepOf, Dn as errMsg, Fn as defineCustomActions, Gn as _enum, Gt as pickDetailCropConvention, Jt as pipelineRunnerCapability, Kn as array, Kt as pickNativeLeaseOverride, Nn as createEvent, Pn as customAction, Qn as object, T as FailureCounters, Vn as nodePin, Xn as literal, Yn as lazy, Zn as number, _ as DEFAULT_DETAIL_CROP_CONVENTION, a as BackgroundRunRegistry, cn as rootSuppliesOf, ft as deriveRootFaceRefineRect, in as resolveModelBoundSetting, j as NativeLeaseSettingsSchema, jt as loadContributionCapability, kn as BaseAddon, m as CROP_SUPPLY_SOURCES, q as allowedSuppliedEffect, qn as boolean, rr as EventCategory, sn as resolveRootSupply, tr as string, ut as deriveDetailCropRect, xt as failureContributionCapability, y as DEFAULT_NATIVE_LEASE_SETTINGS, z as ROOT_SUPPLIABLE_STEP_IDS } from "../dist-cT7hhXh9.mjs";
2
+ import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-Dmga8QNL.mjs";
3
+ import { a as stepsForElectedPool, b as getStepDefinition, d as rootObjectGate, f as localFrameRegistry, h as resolveFrameViewGeometry, i as placeDetailStep, l as resolveDefaultDetectionModel, m as createSessionDecodeCoordinator, p as isSessionDecodeReadGone, s as resolveDeviceEngine, t as CustomModelCatalog, u as macroGateVerdict, y as getStep } from "../custom-model-catalog-C7zLb7ze.mjs";
4
4
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
5
5
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
6
6
  import { c as withDetectionIntent, o as preRollRequestOf, t as DETECTION_PRE_ROLL_REQUEST_MS } from "../restream-intent-DyGmLAU9.mjs";
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-emK7D4bc.js");
2
- const require_dist = require("./dist-DNsARIUD.js");
2
+ const require_dist = require("./dist-_I6JkuJ8.js");
3
3
  let node_fs = require("node:fs");
4
4
  node_fs = require_chunk.__toESM(node_fs);
5
5
  let node_child_process = require("node:child_process");
@@ -1,4 +1,4 @@
1
- import { Ut as parseProcStatus } from "./dist-DUr_0s5c.mjs";
1
+ import { Ut as parseProcStatus } from "./dist-cT7hhXh9.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import { execFile } from "node:child_process";
4
4
  //#region src/shared/node-topology-platform.ts
@@ -3,8 +3,8 @@ 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-DNsARIUD.js");
7
- const require_node = require("../node-D-U3T-h-.js");
6
+ const require_dist = require("../dist-_I6JkuJ8.js");
7
+ const require_node = require("../node-6zL5ddry.js");
8
8
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
9
9
  const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
10
10
  const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
@@ -1,5 +1,5 @@
1
- import { $n as preprocess, $t as recordingSignalCapability, B as RecordingConfigSchema, Ct as gbToBytes, Dn as errMsg$1, En as DeviceType, Fn as defineCustomActions, Ft as mayReadLocation, Gn as _enum, I as RECORDING_EXPORT_MAX_READ_BYTES, It as mayWriteToLocation, Kn as array, L as RECORDING_SOURCE_CAMSTACK, Ln as hydrateSchema, Lt as memoizePinnedFfmpeg, M as OpsLogEntrySchema, Ot as isFirstLevelMacroClass, Pn as customAction, Q as batteryCapability, Qn as object, Qt as recordingExportCapability, R as RECORDING_SOURCE_CAMSTACK_ADDON, Rt as migrateLegacyDeviceSignalConfig, S as EVENT_PAD_MS, Sn as evaluateSensorEdge, Tn as DeviceFeature, U as VIDEOCLIPS_MAX_OFFER_BYTES, Un as selectAssignedProfileSlots, V as RecordingSignalStatusSchema, Vn as nodePin, W as VISIT_MERGE_GAP_MS, Wn as sleep$1, Xt as recordingArchiveCapability, Zn as number, Zt as recordingCapability, bt as exportSubjectOf, dn as storageEvictableCapability, dt as deriveRecordingMode, er as record, fn as storageOccupancyCapability, gn as videoclipsCapability, jt as loadContributionCapability, kn as BaseAddon, lt as deriveBatteryPresence, mn as stripRetiredBandPreBufferSec, nt as clipExportFailureOf, o as BatteryStatusSchema, on as resolveRecordingProfiles, qn as boolean, rn as resolveLocationMode, rr as EventCategory, s as CLIP_BROKER_PACED_RATES, tn as resolveCreateExportSubject, tr as string, tt as clipExportFailure, v as DEFAULT_EVENTS_BAND_BUFFER_SEC, vt as evictionPolicyForMode, w as ExportRecordSchema, x as EVENT_OWNER_TYPES, yt as evictionPolicyOfLocation, zt as modeMayWrite } from "../dist-DUr_0s5c.mjs";
2
- import { a as physicalRootOf, i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-DhrskFZ_.mjs";
1
+ import { $n as preprocess, $t as recordingSignalCapability, B as RecordingConfigSchema, Ct as gbToBytes, Dn as errMsg$1, En as DeviceType, Fn as defineCustomActions, Ft as mayReadLocation, Gn as _enum, I as RECORDING_EXPORT_MAX_READ_BYTES, It as mayWriteToLocation, Kn as array, L as RECORDING_SOURCE_CAMSTACK, Ln as hydrateSchema, Lt as memoizePinnedFfmpeg, M as OpsLogEntrySchema, Ot as isFirstLevelMacroClass, Pn as customAction, Q as batteryCapability, Qn as object, Qt as recordingExportCapability, R as RECORDING_SOURCE_CAMSTACK_ADDON, Rt as migrateLegacyDeviceSignalConfig, S as EVENT_PAD_MS, Sn as evaluateSensorEdge, Tn as DeviceFeature, U as VIDEOCLIPS_MAX_OFFER_BYTES, Un as selectAssignedProfileSlots, V as RecordingSignalStatusSchema, Vn as nodePin, W as VISIT_MERGE_GAP_MS, Wn as sleep$1, Xt as recordingArchiveCapability, Zn as number, Zt as recordingCapability, bt as exportSubjectOf, dn as storageEvictableCapability, dt as deriveRecordingMode, er as record, fn as storageOccupancyCapability, gn as videoclipsCapability, jt as loadContributionCapability, kn as BaseAddon, lt as deriveBatteryPresence, mn as stripRetiredBandPreBufferSec, nt as clipExportFailureOf, o as BatteryStatusSchema, on as resolveRecordingProfiles, qn as boolean, rn as resolveLocationMode, rr as EventCategory, s as CLIP_BROKER_PACED_RATES, tn as resolveCreateExportSubject, tr as string, tt as clipExportFailure, v as DEFAULT_EVENTS_BAND_BUFFER_SEC, vt as evictionPolicyForMode, w as ExportRecordSchema, x as EVENT_OWNER_TYPES, yt as evictionPolicyOfLocation, zt as modeMayWrite } from "../dist-cT7hhXh9.mjs";
2
+ import { a as physicalRootOf, i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-Dmga8QNL.mjs";
3
3
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
4
4
  import { d as PREBUFFER_MAX_MS, l as withRecordingIntent, r as RECORDING_PRE_ROLL_REQUEST_MS } from "../restream-intent-DyGmLAU9.mjs";
5
5
  import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DZvlso2l.mjs";
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-emK7D4bc.js");
2
- const require_dist = require("./dist-DNsARIUD.js");
2
+ const require_dist = require("./dist-_I6JkuJ8.js");
3
3
  let node_child_process = require("node:child_process");
4
4
  //#region src/stream-broker/recorded/avcc-annexb.ts
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./chunk-DnnnRqeS.mjs";
2
- import { Dn as errMsg } from "./dist-DUr_0s5c.mjs";
2
+ import { Dn as errMsg } from "./dist-cT7hhXh9.mjs";
3
3
  import { spawn } from "node:child_process";
4
4
  //#region src/stream-broker/recorded/avcc-annexb.ts
5
5
  /**
@@ -18,7 +18,7 @@ var e = {
18
18
  },
19
19
  "@camstack/types": {
20
20
  name: "@camstack/types",
21
- version: "1.2.324",
21
+ version: "1.2.325",
22
22
  scope: ["default"],
23
23
  loaded: !1,
24
24
  from: "addon_stream_broker_widgets",
@@ -1,4 +1,4 @@
1
- const require_segment_demux_js = require("../segment-demux-js-vZ6iniOU.js");
1
+ const require_segment_demux_js = require("../segment-demux-js-DPtDBph6.js");
2
2
  let node_worker_threads = require("node:worker_threads");
3
3
  //#region src/stream-broker/recorded/demux-worker-child.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as demuxSegmentFullJs } from "../segment-demux-js-Bv7s-_uv.mjs";
1
+ import { t as demuxSegmentFullJs } from "../segment-demux-js-qzo-pQK7.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.324",
39
+ version: "1.2.325",
40
40
  scope: "default",
41
41
  shareConfig: {
42
42
  singleton: !0,
@@ -3,12 +3,12 @@ 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-DNsARIUD.js");
7
- const require_node = require("../node-D-U3T-h-.js");
6
+ const require_dist = require("../dist-_I6JkuJ8.js");
7
+ const require_node = require("../node-6zL5ddry.js");
8
8
  const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
9
9
  const require_remote_restream = require("../remote-restream-CO36Sr30.js");
10
10
  const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
11
- const require_segment_demux_js = require("../segment-demux-js-vZ6iniOU.js");
11
+ const require_segment_demux_js = require("../segment-demux-js-DPtDBph6.js");
12
12
  let node_os = require("node:os");
13
13
  node_os = require_chunk.__toESM(node_os);
14
14
  let node_crypto = require("node:crypto");
@@ -21337,6 +21337,169 @@ function shouldWriteLossLine(input) {
21337
21337
  };
21338
21338
  }
21339
21339
  //#endregion
21340
+ //#region src/stream-broker/webrtc/talkback-bridge.ts
21341
+ /** A frame this small is Opus DTX / comfort noise, not speech. */
21342
+ var DTX_MAX_BYTES = 3;
21343
+ /** How the push-talk triple names each WebRTC audio codec, or null when the
21344
+ * intercom path cannot take it. */
21345
+ function talkCodecOf(format) {
21346
+ switch (format) {
21347
+ case "Opus": return {
21348
+ codec: "opus",
21349
+ sampleRate: 48e3
21350
+ };
21351
+ case "Pcmu": return {
21352
+ codec: "g711ulaw",
21353
+ sampleRate: 8e3
21354
+ };
21355
+ case "Pcma": return {
21356
+ codec: "g711alaw",
21357
+ sampleRate: 8e3
21358
+ };
21359
+ default: return null;
21360
+ }
21361
+ }
21362
+ var TalkbackBridge = class {
21363
+ deviceId;
21364
+ port;
21365
+ logger;
21366
+ state = "idle";
21367
+ /** Set by `close()`; no frame is accepted after it. */
21368
+ closing = false;
21369
+ /** A talk session was opened at the camera and must be ended. */
21370
+ started = false;
21371
+ sequence = 0;
21372
+ chain = Promise.resolve();
21373
+ dropped = 0;
21374
+ refusedCodecLogged = false;
21375
+ constructor(deviceId, port, logger) {
21376
+ this.deviceId = deviceId;
21377
+ this.port = port;
21378
+ this.logger = logger;
21379
+ }
21380
+ /** One inbound RTP payload from the peer. Never throws. */
21381
+ onAudio(payload, format) {
21382
+ if (this.closing) return;
21383
+ if (payload.length <= DTX_MAX_BYTES) return;
21384
+ const talk = talkCodecOf(format);
21385
+ if (talk === null) {
21386
+ if (!this.refusedCodecLogged) {
21387
+ this.refusedCodecLogged = true;
21388
+ this.logger.warn("talk-back: the peer sends a codec the intercom path cannot take", {
21389
+ tags: { deviceId: this.deviceId },
21390
+ meta: { format }
21391
+ });
21392
+ }
21393
+ return;
21394
+ }
21395
+ if (this.state === "idle") {
21396
+ this.state = "opening";
21397
+ this.chain = this.chain.then(() => this.open());
21398
+ }
21399
+ const frame = {
21400
+ deviceId: this.deviceId,
21401
+ audioBase64: payload.toString("base64"),
21402
+ codec: talk.codec,
21403
+ sampleRate: talk.sampleRate,
21404
+ channels: 1,
21405
+ sequenceNumber: ++this.sequence
21406
+ };
21407
+ this.chain = this.chain.then(() => this.push(frame));
21408
+ }
21409
+ /** End the talk session (if one opened). Idempotent. */
21410
+ async close() {
21411
+ if (this.closing) return;
21412
+ this.closing = true;
21413
+ await this.chain.catch(() => {});
21414
+ if (!this.started) return;
21415
+ await this.port.endTalkSession(this.deviceId).catch((err) => {
21416
+ this.logger.warn("talk-back: endTalkSession failed", {
21417
+ tags: { deviceId: this.deviceId },
21418
+ meta: { error: require_dist.errMsg(err) }
21419
+ });
21420
+ });
21421
+ this.logger.info("talk-back: ended", {
21422
+ tags: { deviceId: this.deviceId },
21423
+ meta: {
21424
+ frames: this.sequence,
21425
+ dropped: this.dropped
21426
+ }
21427
+ });
21428
+ }
21429
+ async open() {
21430
+ if (this.state !== "opening") return;
21431
+ try {
21432
+ await this.port.startTalkSession(this.deviceId);
21433
+ this.started = true;
21434
+ if (this.state === "opening") this.state = "open";
21435
+ this.logger.info("talk-back: the peer is talking — camera talk session opened", { tags: { deviceId: this.deviceId } });
21436
+ } catch (err) {
21437
+ if (this.state === "opening") this.state = "idle";
21438
+ this.logger.warn("talk-back: startTalkSession failed — will retry on the next frame", {
21439
+ tags: { deviceId: this.deviceId },
21440
+ meta: { error: require_dist.errMsg(err) }
21441
+ });
21442
+ }
21443
+ }
21444
+ async push(frame) {
21445
+ if (this.state !== "open") {
21446
+ this.dropped += 1;
21447
+ return;
21448
+ }
21449
+ try {
21450
+ if (!(await this.port.pushTalkAudio(frame)).accepted) this.dropped += 1;
21451
+ } catch (err) {
21452
+ this.dropped += 1;
21453
+ if (this.state === "open") this.state = "idle";
21454
+ this.logger.warn("talk-back: pushTalkAudio failed — reopening on the next frame", {
21455
+ tags: { deviceId: this.deviceId },
21456
+ meta: {
21457
+ error: require_dist.errMsg(err),
21458
+ sequence: frame.sequenceNumber
21459
+ }
21460
+ });
21461
+ }
21462
+ }
21463
+ };
21464
+ /**
21465
+ * Does the client's offer let the PEER send audio? (Its `m=audio` section is
21466
+ * `sendrecv` or `sendonly`; absent direction means `sendrecv`, RFC 3264.)
21467
+ */
21468
+ function offerLetsPeerSendAudio(offerSdp) {
21469
+ let inAudio = false;
21470
+ let direction = null;
21471
+ let sawAudio = false;
21472
+ for (const raw of offerSdp.split(/\r?\n/)) {
21473
+ const line = raw.trim();
21474
+ if (line.startsWith("m=")) {
21475
+ if (inAudio) break;
21476
+ inAudio = line.startsWith("m=audio");
21477
+ if (inAudio) sawAudio = true;
21478
+ continue;
21479
+ }
21480
+ if (inAudio && /^a=(sendrecv|sendonly|recvonly|inactive)$/.test(line)) direction = line.slice(2);
21481
+ }
21482
+ if (!sawAudio) return false;
21483
+ return direction === null || direction === "sendrecv" || direction === "sendonly";
21484
+ }
21485
+ /**
21486
+ * The direction to ANSWER a client offer's audio with: `sendrecv` only when
21487
+ * talk-back was asked for AND the peer offered to send audio; otherwise the
21488
+ * `sendonly` every viewer has always had.
21489
+ */
21490
+ function clientOfferAudioDirection(talkback, offerSdp) {
21491
+ return talkback && offerLetsPeerSendAudio(offerSdp) ? "sendrecv" : "sendonly";
21492
+ }
21493
+ /** The codec an inbound RTP packet carries, by its payload type. */
21494
+ function audioCodecForPayloadType(codecs, payloadType) {
21495
+ switch (codecs.find((c) => c.payloadType === payloadType)?.mimeType.toLowerCase()) {
21496
+ case "audio/opus": return "Opus";
21497
+ case "audio/pcmu": return "Pcmu";
21498
+ case "audio/pcma": return "Pcma";
21499
+ default: return null;
21500
+ }
21501
+ }
21502
+ //#endregion
21340
21503
  //#region src/stream-broker/webrtc/mdns-resolve.ts
21341
21504
  /**
21342
21505
  * Rewrite mDNS (`*.local`) candidates in an SDP by resolving each
@@ -23531,23 +23694,7 @@ var AdaptiveSession = class AdaptiveSession {
23531
23694
  const audioDir = this.intercom ? "sendrecv" : "sendonly";
23532
23695
  const audioTransceiver = this.pc.addTransceiver(this.audioTrack, { direction: audioDir });
23533
23696
  this.audioSender = audioTransceiver.sender;
23534
- if (this.intercom) {
23535
- const cb = this.intercom.onAudioReceived;
23536
- audioTransceiver.onTrack.subscribe((track) => {
23537
- track.onReceiveRtp.subscribe((pkt) => {
23538
- try {
23539
- const payload = pkt.payload;
23540
- if (payload?.length > 0) cb(payload, "Opus");
23541
- } catch (err) {
23542
- this.logger.error("Intercom error", { meta: {
23543
- phase: "session",
23544
- sessionId: this.sessionId,
23545
- error: require_dist.errMsg(err)
23546
- } });
23547
- }
23548
- });
23549
- });
23550
- }
23697
+ if (this.intercom) this.subscribeInboundAudio(audioTransceiver);
23551
23698
  const offer = await this.pc.createOffer();
23552
23699
  await this.pc.setLocalDescription(offer);
23553
23700
  await this.waitForIceGatheringFast();
@@ -23647,6 +23794,33 @@ var AdaptiveSession = class AdaptiveSession {
23647
23794
  this.startFeedingFrames();
23648
23795
  }
23649
23796
  /**
23797
+ * Relay the peer's audio to `intercom.onAudioReceived`, naming each packet's
23798
+ * codec from the payload type werift negotiated — never assumed: the offer
23799
+ * carries PCMU as well as Opus, and a PCMU frame labelled Opus is noise at
23800
+ * the camera. Packets of a codec the intercom path cannot take are dropped.
23801
+ */
23802
+ subscribeInboundAudio(transceiver) {
23803
+ const intercom = this.intercom;
23804
+ if (intercom === void 0) return;
23805
+ transceiver.onTrack.subscribe((track) => {
23806
+ track.onReceiveRtp.subscribe((pkt) => {
23807
+ try {
23808
+ const payload = pkt.payload;
23809
+ if (payload === void 0 || payload.length === 0) return;
23810
+ const format = audioCodecForPayloadType(transceiver.codecs ?? [], pkt.header.payloadType);
23811
+ if (format === null) return;
23812
+ intercom.onAudioReceived(payload, format);
23813
+ } catch (err) {
23814
+ this.logger.error("Intercom error", { meta: {
23815
+ phase: "session",
23816
+ sessionId: this.sessionId,
23817
+ error: require_dist.errMsg(err)
23818
+ } });
23819
+ }
23820
+ });
23821
+ });
23822
+ }
23823
+ /**
23650
23824
  * Handle WHEP offer: client sends SDP offer, we create answer.
23651
23825
  *
23652
23826
  * Uses the server-creates-offer pattern internally: we create our own offer
@@ -23730,10 +23904,12 @@ var AdaptiveSession = class AdaptiveSession {
23730
23904
  } });
23731
23905
  }
23732
23906
  } else if (kind === "audio" && !this.audioTrack) {
23733
- t.setDirection("sendonly");
23907
+ const audioDirection = clientOfferAudioDirection(this.intercom !== void 0, clientOffer.sdp);
23908
+ t.setDirection(audioDirection);
23734
23909
  this.audioTrack = new werift.MediaStreamTrack({ kind: "audio" });
23735
23910
  await t.sender.replaceTrack(this.audioTrack);
23736
23911
  this.audioSender = t.sender;
23912
+ if (audioDirection === "sendrecv") this.subscribeInboundAudio(t);
23737
23913
  }
23738
23914
  }
23739
23915
  if (!this.videoTrack) {
@@ -33836,6 +34012,7 @@ var BrokerWebrtcServer = class {
33836
34012
  staticIceServers;
33837
34013
  icePortRange;
33838
34014
  iceAdditionalHostAddresses;
34015
+ talkbackIntercom;
33839
34016
  clientNetworkStats;
33840
34017
  locateRecordedSegment;
33841
34018
  readRecordedSegmentBytes;
@@ -33938,6 +34115,7 @@ var BrokerWebrtcServer = class {
33938
34115
  this.staticIceServers = options.iceServers;
33939
34116
  this.icePortRange = options.icePortRange;
33940
34117
  this.iceAdditionalHostAddresses = options.iceAdditionalHostAddresses;
34118
+ this.talkbackIntercom = options.talkbackIntercom;
33941
34119
  this.clientNetworkStats = options.clientNetworkStats;
33942
34120
  this.locateRecordedSegment = options.locateRecordedSegment;
33943
34121
  this.readRecordedSegmentBytes = options.readRecordedSegmentBytes;
@@ -34460,9 +34638,12 @@ var BrokerWebrtcServer = class {
34460
34638
  sourceProfileLevelId,
34461
34639
  offeredProfileLevelIds
34462
34640
  } });
34641
+ const talkback = opts.talkback === true && this.talkbackIntercom !== void 0 ? new TalkbackBridge(deviceId, this.talkbackIntercom, sessionLogger) : void 0;
34642
+ if (opts.talkback === true && talkback === void 0) sessionLogger.warn("talk-back requested but no intercom port is wired — audio stays one-way", { meta: { sessionId } });
34463
34643
  session = new AdaptiveSession({
34464
34644
  sessionId,
34465
34645
  source,
34646
+ ...talkback !== void 0 ? { intercom: { onAudioReceived: (data, format) => talkback.onAudio(data, format) } } : {},
34466
34647
  sourceCodec: sessionCodec,
34467
34648
  transcodeToBaseline,
34468
34649
  transcodeProfile: effectiveTranscodeProfile,
@@ -34558,6 +34739,7 @@ var BrokerWebrtcServer = class {
34558
34739
  unsubSdpParams,
34559
34740
  unsubSourceRestart,
34560
34741
  closeSource,
34742
+ ...talkback !== void 0 ? { closeTalkback: () => void talkback.close() } : {},
34561
34743
  rebind: {
34562
34744
  deviceId,
34563
34745
  sessionCodec,
@@ -35787,6 +35969,7 @@ var BrokerWebrtcServer = class {
35787
35969
  entry.unsubSourceRestart();
35788
35970
  entry.releaseOpusEgress?.();
35789
35971
  entry.releaseOpusEgress = void 0;
35972
+ entry.closeTalkback?.();
35790
35973
  entry.closeSource();
35791
35974
  }
35792
35975
  resolveBrokerId(streamId, hints = {}) {
@@ -36392,6 +36575,7 @@ var WebrtcSessionProvider = class WebrtcSessionProvider {
36392
36575
  nonTrickle: input.nonTrickle === true,
36393
36576
  disableTurn: input.disableTurn === true,
36394
36577
  disableIpv6: input.disableIpv6 === true,
36578
+ talkback: input.talkback === true,
36395
36579
  transcodeProfile,
36396
36580
  ...input.consumerAttribution !== void 0 ? { consumerAttribution: input.consumerAttribution } : {}
36397
36581
  });
@@ -36884,8 +37068,25 @@ var StreamBrokerAddon = class extends require_dist.BaseAddon {
36884
37068
  });
36885
37069
  const cameraStreamsProvider = new CameraStreamsProvider(this.brokerManager);
36886
37070
  const turnApi = this.ctx.api;
37071
+ const intercomApi = this.ctx.api.intercom;
36887
37072
  const webrtcServer = new BrokerWebrtcServer({
36888
37073
  logger: this.ctx.logger.child("webrtc"),
37074
+ talkbackIntercom: {
37075
+ startTalkSession: async (deviceId) => {
37076
+ await intercomApi.startTalkSession.mutate({ deviceId });
37077
+ },
37078
+ pushTalkAudio: (frame) => intercomApi.pushTalkAudio.mutate({
37079
+ deviceId: frame.deviceId,
37080
+ audioBase64: frame.audioBase64,
37081
+ codec: frame.codec,
37082
+ sampleRate: frame.sampleRate,
37083
+ channels: frame.channels,
37084
+ sequenceNumber: frame.sequenceNumber
37085
+ }),
37086
+ endTalkSession: async (deviceId) => {
37087
+ await intercomApi.endTalkSession.mutate({ deviceId });
37088
+ }
37089
+ },
36889
37090
  getIceServers: async () => {
36890
37091
  if (!turnApi.turnProvider) return [];
36891
37092
  try {
@@ -1,10 +1,10 @@
1
1
  import { r as __toESM } from "../chunk-DnnnRqeS.mjs";
2
- import { An as CAM_PROFILE_ORDER, Bn as makeSourceBrokerId, C as EncodeProfileSchema, Cn as invocationFromEncodeProfile, Dn as errMsg, E as G711_SCALE_CORRECTION_DB, En as DeviceType, F as RATE_CONTROL_TIGHT, Gn as _enum, H as RingBuffer, Hn as parseProfileBrokerId, In as expandAudioChunkToF32le, Jn as discriminatedUnion, K as addonWidgetsSourceCapability, Kn as array, Lt as memoizePinnedFfmpeg, Mt as logChannelsCapability, Nn as createEvent, On as BOOT_RECOVERY_BACKOFF_MS, P as RATE_CONTROL_RELAXED, Pt as maskUrlCredentials, Q as batteryCapability, Qn as object, Rn as isEvent, St as ffmpegRate, Tn as DeviceFeature, Tt as gifFromMp4Args, Vn as nodePin, Xn as literal, Yt as rankStreams, Zn as number, _n as webrtcSessionCapability, at as createHwAccelCache, c as CLIP_STILL_REASON_CODE_HEADER, er as record, et as cameraStreamsCapability, ht as egressTransportFromRequest, jn as CamProfileSchema, jt as loadContributionCapability, kn as BaseAddon, lt as deriveBatteryPresence, mt as egressTranscodeSharingKey, nn as resolveEgressDecodeHwAccel, nr as union, nt as clipExportFailureOf, o as BatteryStatusSchema, ot as createLogChannelsProvider, pn as streamBrokerCapability, qn as boolean, rr as EventCategory, s as CLIP_BROKER_PACED_RATES, st as declareLogChannel, tr as string, vn as AUDIO_PRESETS, wn as isSoftwareDecode, wt as gifDeriveSpeed, xn as buildFfmpegArgs, zn as makeProfileBrokerId } from "../dist-DUr_0s5c.mjs";
3
- import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, o as probeFfmpegBinary, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-DhrskFZ_.mjs";
2
+ import { An as CAM_PROFILE_ORDER, Bn as makeSourceBrokerId, C as EncodeProfileSchema, Cn as invocationFromEncodeProfile, Dn as errMsg, E as G711_SCALE_CORRECTION_DB, En as DeviceType, F as RATE_CONTROL_TIGHT, Gn as _enum, H as RingBuffer, Hn as parseProfileBrokerId, In as expandAudioChunkToF32le, Jn as discriminatedUnion, K as addonWidgetsSourceCapability, Kn as array, Lt as memoizePinnedFfmpeg, Mt as logChannelsCapability, Nn as createEvent, On as BOOT_RECOVERY_BACKOFF_MS, P as RATE_CONTROL_RELAXED, Pt as maskUrlCredentials, Q as batteryCapability, Qn as object, Rn as isEvent, St as ffmpegRate, Tn as DeviceFeature, Tt as gifFromMp4Args, Vn as nodePin, Xn as literal, Yt as rankStreams, Zn as number, _n as webrtcSessionCapability, at as createHwAccelCache, c as CLIP_STILL_REASON_CODE_HEADER, er as record, et as cameraStreamsCapability, ht as egressTransportFromRequest, jn as CamProfileSchema, jt as loadContributionCapability, kn as BaseAddon, lt as deriveBatteryPresence, mt as egressTranscodeSharingKey, nn as resolveEgressDecodeHwAccel, nr as union, nt as clipExportFailureOf, o as BatteryStatusSchema, ot as createLogChannelsProvider, pn as streamBrokerCapability, qn as boolean, rr as EventCategory, s as CLIP_BROKER_PACED_RATES, st as declareLogChannel, tr as string, vn as AUDIO_PRESETS, wn as isSoftwareDecode, wt as gifDeriveSpeed, xn as buildFfmpegArgs, zn as makeProfileBrokerId } from "../dist-cT7hhXh9.mjs";
3
+ import { i as NO_COST_CLAIM, n as Fmp4FragmentChild, o as probeFfmpegBinary, r as Fmp4FragmentPlane, t as ChildCostRegistry } from "../node-Dmga8QNL.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-DyGmLAU9.mjs";
5
5
  import { n as profileForStreamId } from "../remote-restream-BeHi78PZ.mjs";
6
6
  import { n as RowMapStore, t as retireRootKeys } from "../retire-root-keys-DZvlso2l.mjs";
7
- 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-Bv7s-_uv.mjs";
7
+ 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-qzo-pQK7.mjs";
8
8
  import { createRequire } from "node:module";
9
9
  import * as os from "node:os";
10
10
  import { networkInterfaces, tmpdir } from "node:os";
@@ -21333,6 +21333,169 @@ function shouldWriteLossLine(input) {
21333
21333
  };
21334
21334
  }
21335
21335
  //#endregion
21336
+ //#region src/stream-broker/webrtc/talkback-bridge.ts
21337
+ /** A frame this small is Opus DTX / comfort noise, not speech. */
21338
+ var DTX_MAX_BYTES = 3;
21339
+ /** How the push-talk triple names each WebRTC audio codec, or null when the
21340
+ * intercom path cannot take it. */
21341
+ function talkCodecOf(format) {
21342
+ switch (format) {
21343
+ case "Opus": return {
21344
+ codec: "opus",
21345
+ sampleRate: 48e3
21346
+ };
21347
+ case "Pcmu": return {
21348
+ codec: "g711ulaw",
21349
+ sampleRate: 8e3
21350
+ };
21351
+ case "Pcma": return {
21352
+ codec: "g711alaw",
21353
+ sampleRate: 8e3
21354
+ };
21355
+ default: return null;
21356
+ }
21357
+ }
21358
+ var TalkbackBridge = class {
21359
+ deviceId;
21360
+ port;
21361
+ logger;
21362
+ state = "idle";
21363
+ /** Set by `close()`; no frame is accepted after it. */
21364
+ closing = false;
21365
+ /** A talk session was opened at the camera and must be ended. */
21366
+ started = false;
21367
+ sequence = 0;
21368
+ chain = Promise.resolve();
21369
+ dropped = 0;
21370
+ refusedCodecLogged = false;
21371
+ constructor(deviceId, port, logger) {
21372
+ this.deviceId = deviceId;
21373
+ this.port = port;
21374
+ this.logger = logger;
21375
+ }
21376
+ /** One inbound RTP payload from the peer. Never throws. */
21377
+ onAudio(payload, format) {
21378
+ if (this.closing) return;
21379
+ if (payload.length <= DTX_MAX_BYTES) return;
21380
+ const talk = talkCodecOf(format);
21381
+ if (talk === null) {
21382
+ if (!this.refusedCodecLogged) {
21383
+ this.refusedCodecLogged = true;
21384
+ this.logger.warn("talk-back: the peer sends a codec the intercom path cannot take", {
21385
+ tags: { deviceId: this.deviceId },
21386
+ meta: { format }
21387
+ });
21388
+ }
21389
+ return;
21390
+ }
21391
+ if (this.state === "idle") {
21392
+ this.state = "opening";
21393
+ this.chain = this.chain.then(() => this.open());
21394
+ }
21395
+ const frame = {
21396
+ deviceId: this.deviceId,
21397
+ audioBase64: payload.toString("base64"),
21398
+ codec: talk.codec,
21399
+ sampleRate: talk.sampleRate,
21400
+ channels: 1,
21401
+ sequenceNumber: ++this.sequence
21402
+ };
21403
+ this.chain = this.chain.then(() => this.push(frame));
21404
+ }
21405
+ /** End the talk session (if one opened). Idempotent. */
21406
+ async close() {
21407
+ if (this.closing) return;
21408
+ this.closing = true;
21409
+ await this.chain.catch(() => {});
21410
+ if (!this.started) return;
21411
+ await this.port.endTalkSession(this.deviceId).catch((err) => {
21412
+ this.logger.warn("talk-back: endTalkSession failed", {
21413
+ tags: { deviceId: this.deviceId },
21414
+ meta: { error: errMsg(err) }
21415
+ });
21416
+ });
21417
+ this.logger.info("talk-back: ended", {
21418
+ tags: { deviceId: this.deviceId },
21419
+ meta: {
21420
+ frames: this.sequence,
21421
+ dropped: this.dropped
21422
+ }
21423
+ });
21424
+ }
21425
+ async open() {
21426
+ if (this.state !== "opening") return;
21427
+ try {
21428
+ await this.port.startTalkSession(this.deviceId);
21429
+ this.started = true;
21430
+ if (this.state === "opening") this.state = "open";
21431
+ this.logger.info("talk-back: the peer is talking — camera talk session opened", { tags: { deviceId: this.deviceId } });
21432
+ } catch (err) {
21433
+ if (this.state === "opening") this.state = "idle";
21434
+ this.logger.warn("talk-back: startTalkSession failed — will retry on the next frame", {
21435
+ tags: { deviceId: this.deviceId },
21436
+ meta: { error: errMsg(err) }
21437
+ });
21438
+ }
21439
+ }
21440
+ async push(frame) {
21441
+ if (this.state !== "open") {
21442
+ this.dropped += 1;
21443
+ return;
21444
+ }
21445
+ try {
21446
+ if (!(await this.port.pushTalkAudio(frame)).accepted) this.dropped += 1;
21447
+ } catch (err) {
21448
+ this.dropped += 1;
21449
+ if (this.state === "open") this.state = "idle";
21450
+ this.logger.warn("talk-back: pushTalkAudio failed — reopening on the next frame", {
21451
+ tags: { deviceId: this.deviceId },
21452
+ meta: {
21453
+ error: errMsg(err),
21454
+ sequence: frame.sequenceNumber
21455
+ }
21456
+ });
21457
+ }
21458
+ }
21459
+ };
21460
+ /**
21461
+ * Does the client's offer let the PEER send audio? (Its `m=audio` section is
21462
+ * `sendrecv` or `sendonly`; absent direction means `sendrecv`, RFC 3264.)
21463
+ */
21464
+ function offerLetsPeerSendAudio(offerSdp) {
21465
+ let inAudio = false;
21466
+ let direction = null;
21467
+ let sawAudio = false;
21468
+ for (const raw of offerSdp.split(/\r?\n/)) {
21469
+ const line = raw.trim();
21470
+ if (line.startsWith("m=")) {
21471
+ if (inAudio) break;
21472
+ inAudio = line.startsWith("m=audio");
21473
+ if (inAudio) sawAudio = true;
21474
+ continue;
21475
+ }
21476
+ if (inAudio && /^a=(sendrecv|sendonly|recvonly|inactive)$/.test(line)) direction = line.slice(2);
21477
+ }
21478
+ if (!sawAudio) return false;
21479
+ return direction === null || direction === "sendrecv" || direction === "sendonly";
21480
+ }
21481
+ /**
21482
+ * The direction to ANSWER a client offer's audio with: `sendrecv` only when
21483
+ * talk-back was asked for AND the peer offered to send audio; otherwise the
21484
+ * `sendonly` every viewer has always had.
21485
+ */
21486
+ function clientOfferAudioDirection(talkback, offerSdp) {
21487
+ return talkback && offerLetsPeerSendAudio(offerSdp) ? "sendrecv" : "sendonly";
21488
+ }
21489
+ /** The codec an inbound RTP packet carries, by its payload type. */
21490
+ function audioCodecForPayloadType(codecs, payloadType) {
21491
+ switch (codecs.find((c) => c.payloadType === payloadType)?.mimeType.toLowerCase()) {
21492
+ case "audio/opus": return "Opus";
21493
+ case "audio/pcmu": return "Pcmu";
21494
+ case "audio/pcma": return "Pcma";
21495
+ default: return null;
21496
+ }
21497
+ }
21498
+ //#endregion
21336
21499
  //#region src/stream-broker/webrtc/mdns-resolve.ts
21337
21500
  /**
21338
21501
  * Rewrite mDNS (`*.local`) candidates in an SDP by resolving each
@@ -23527,23 +23690,7 @@ var AdaptiveSession = class AdaptiveSession {
23527
23690
  const audioDir = this.intercom ? "sendrecv" : "sendonly";
23528
23691
  const audioTransceiver = this.pc.addTransceiver(this.audioTrack, { direction: audioDir });
23529
23692
  this.audioSender = audioTransceiver.sender;
23530
- if (this.intercom) {
23531
- const cb = this.intercom.onAudioReceived;
23532
- audioTransceiver.onTrack.subscribe((track) => {
23533
- track.onReceiveRtp.subscribe((pkt) => {
23534
- try {
23535
- const payload = pkt.payload;
23536
- if (payload?.length > 0) cb(payload, "Opus");
23537
- } catch (err) {
23538
- this.logger.error("Intercom error", { meta: {
23539
- phase: "session",
23540
- sessionId: this.sessionId,
23541
- error: errMsg(err)
23542
- } });
23543
- }
23544
- });
23545
- });
23546
- }
23693
+ if (this.intercom) this.subscribeInboundAudio(audioTransceiver);
23547
23694
  const offer = await this.pc.createOffer();
23548
23695
  await this.pc.setLocalDescription(offer);
23549
23696
  await this.waitForIceGatheringFast();
@@ -23643,6 +23790,33 @@ var AdaptiveSession = class AdaptiveSession {
23643
23790
  this.startFeedingFrames();
23644
23791
  }
23645
23792
  /**
23793
+ * Relay the peer's audio to `intercom.onAudioReceived`, naming each packet's
23794
+ * codec from the payload type werift negotiated — never assumed: the offer
23795
+ * carries PCMU as well as Opus, and a PCMU frame labelled Opus is noise at
23796
+ * the camera. Packets of a codec the intercom path cannot take are dropped.
23797
+ */
23798
+ subscribeInboundAudio(transceiver) {
23799
+ const intercom = this.intercom;
23800
+ if (intercom === void 0) return;
23801
+ transceiver.onTrack.subscribe((track) => {
23802
+ track.onReceiveRtp.subscribe((pkt) => {
23803
+ try {
23804
+ const payload = pkt.payload;
23805
+ if (payload === void 0 || payload.length === 0) return;
23806
+ const format = audioCodecForPayloadType(transceiver.codecs ?? [], pkt.header.payloadType);
23807
+ if (format === null) return;
23808
+ intercom.onAudioReceived(payload, format);
23809
+ } catch (err) {
23810
+ this.logger.error("Intercom error", { meta: {
23811
+ phase: "session",
23812
+ sessionId: this.sessionId,
23813
+ error: errMsg(err)
23814
+ } });
23815
+ }
23816
+ });
23817
+ });
23818
+ }
23819
+ /**
23646
23820
  * Handle WHEP offer: client sends SDP offer, we create answer.
23647
23821
  *
23648
23822
  * Uses the server-creates-offer pattern internally: we create our own offer
@@ -23726,10 +23900,12 @@ var AdaptiveSession = class AdaptiveSession {
23726
23900
  } });
23727
23901
  }
23728
23902
  } else if (kind === "audio" && !this.audioTrack) {
23729
- t.setDirection("sendonly");
23903
+ const audioDirection = clientOfferAudioDirection(this.intercom !== void 0, clientOffer.sdp);
23904
+ t.setDirection(audioDirection);
23730
23905
  this.audioTrack = new werift.MediaStreamTrack({ kind: "audio" });
23731
23906
  await t.sender.replaceTrack(this.audioTrack);
23732
23907
  this.audioSender = t.sender;
23908
+ if (audioDirection === "sendrecv") this.subscribeInboundAudio(t);
23733
23909
  }
23734
23910
  }
23735
23911
  if (!this.videoTrack) {
@@ -33832,6 +34008,7 @@ var BrokerWebrtcServer = class {
33832
34008
  staticIceServers;
33833
34009
  icePortRange;
33834
34010
  iceAdditionalHostAddresses;
34011
+ talkbackIntercom;
33835
34012
  clientNetworkStats;
33836
34013
  locateRecordedSegment;
33837
34014
  readRecordedSegmentBytes;
@@ -33934,6 +34111,7 @@ var BrokerWebrtcServer = class {
33934
34111
  this.staticIceServers = options.iceServers;
33935
34112
  this.icePortRange = options.icePortRange;
33936
34113
  this.iceAdditionalHostAddresses = options.iceAdditionalHostAddresses;
34114
+ this.talkbackIntercom = options.talkbackIntercom;
33937
34115
  this.clientNetworkStats = options.clientNetworkStats;
33938
34116
  this.locateRecordedSegment = options.locateRecordedSegment;
33939
34117
  this.readRecordedSegmentBytes = options.readRecordedSegmentBytes;
@@ -34456,9 +34634,12 @@ var BrokerWebrtcServer = class {
34456
34634
  sourceProfileLevelId,
34457
34635
  offeredProfileLevelIds
34458
34636
  } });
34637
+ const talkback = opts.talkback === true && this.talkbackIntercom !== void 0 ? new TalkbackBridge(deviceId, this.talkbackIntercom, sessionLogger) : void 0;
34638
+ if (opts.talkback === true && talkback === void 0) sessionLogger.warn("talk-back requested but no intercom port is wired — audio stays one-way", { meta: { sessionId } });
34459
34639
  session = new AdaptiveSession({
34460
34640
  sessionId,
34461
34641
  source,
34642
+ ...talkback !== void 0 ? { intercom: { onAudioReceived: (data, format) => talkback.onAudio(data, format) } } : {},
34462
34643
  sourceCodec: sessionCodec,
34463
34644
  transcodeToBaseline,
34464
34645
  transcodeProfile: effectiveTranscodeProfile,
@@ -34554,6 +34735,7 @@ var BrokerWebrtcServer = class {
34554
34735
  unsubSdpParams,
34555
34736
  unsubSourceRestart,
34556
34737
  closeSource,
34738
+ ...talkback !== void 0 ? { closeTalkback: () => void talkback.close() } : {},
34557
34739
  rebind: {
34558
34740
  deviceId,
34559
34741
  sessionCodec,
@@ -35783,6 +35965,7 @@ var BrokerWebrtcServer = class {
35783
35965
  entry.unsubSourceRestart();
35784
35966
  entry.releaseOpusEgress?.();
35785
35967
  entry.releaseOpusEgress = void 0;
35968
+ entry.closeTalkback?.();
35786
35969
  entry.closeSource();
35787
35970
  }
35788
35971
  resolveBrokerId(streamId, hints = {}) {
@@ -36388,6 +36571,7 @@ var WebrtcSessionProvider = class WebrtcSessionProvider {
36388
36571
  nonTrickle: input.nonTrickle === true,
36389
36572
  disableTurn: input.disableTurn === true,
36390
36573
  disableIpv6: input.disableIpv6 === true,
36574
+ talkback: input.talkback === true,
36391
36575
  transcodeProfile,
36392
36576
  ...input.consumerAttribution !== void 0 ? { consumerAttribution: input.consumerAttribution } : {}
36393
36577
  });
@@ -36880,8 +37064,25 @@ var StreamBrokerAddon = class extends BaseAddon {
36880
37064
  });
36881
37065
  const cameraStreamsProvider = new CameraStreamsProvider(this.brokerManager);
36882
37066
  const turnApi = this.ctx.api;
37067
+ const intercomApi = this.ctx.api.intercom;
36883
37068
  const webrtcServer = new BrokerWebrtcServer({
36884
37069
  logger: this.ctx.logger.child("webrtc"),
37070
+ talkbackIntercom: {
37071
+ startTalkSession: async (deviceId) => {
37072
+ await intercomApi.startTalkSession.mutate({ deviceId });
37073
+ },
37074
+ pushTalkAudio: (frame) => intercomApi.pushTalkAudio.mutate({
37075
+ deviceId: frame.deviceId,
37076
+ audioBase64: frame.audioBase64,
37077
+ codec: frame.codec,
37078
+ sampleRate: frame.sampleRate,
37079
+ channels: frame.channels,
37080
+ sequenceNumber: frame.sequenceNumber
37081
+ }),
37082
+ endTalkSession: async (deviceId) => {
37083
+ await intercomApi.endTalkSession.mutate({ deviceId });
37084
+ }
37085
+ },
36885
37086
  getIceServers: async () => {
36886
37087
  if (!turnApi.turnProvider) return [];
36887
37088
  try {
@@ -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-BH3o1g9i.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Drg8iwTA.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.344",
3
+ "version": "1.2.345",
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",