@camstack/addon-pipeline 1.2.128 → 1.2.130
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{addon-utils-BnprivSs.js → addon-utils-DH78p79i.js} +1 -1
- package/dist/audio-analyzer/index.js +3 -3
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/detection-pipeline/index.js +241 -95
- package/dist/detection-pipeline/index.mjs +239 -93
- package/dist/{dist-BZUXb5S5.js → dist-DOw-izoI.js} +243 -75
- package/dist/{dist-HLAOw6Pe.mjs → dist-Wt81pN5Y.mjs} +243 -75
- package/dist/{event-loop-stall-monitor-BdArVUlx.js → event-loop-stall-monitor-Bld7jNCb.js} +1 -1
- package/dist/{event-loop-stall-monitor-BH-cL_hg.mjs → event-loop-stall-monitor-CtQCOZqm.mjs} +1 -1
- package/dist/{lazy-sharp-DTDXrhMG.js → lazy-sharp-BbNI2ZD-.js} +1 -1
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +4 -4
- package/dist/pipeline-runner/index.mjs +3 -3
- package/dist/{process-memory-CDPRLalN.mjs → process-memory-1_D3EZT9.mjs} +1 -1
- package/dist/{process-memory-Dh1SyzdJ.js → process-memory-D9H5qjDl.js} +1 -1
- package/dist/recorder/index.js +467 -29
- package/dist/recorder/index.mjs +465 -28
- package/dist/{segment-demux-js-D-TLcHW5.mjs → segment-demux-js-BW-Q-j2A.mjs} +1 -1
- package/dist/{segment-demux-js-DRutggd6.js → segment-demux-js-C2jBBqGW.js} +1 -1
- package/dist/session-decode/decode-worker-child.js +2 -2
- package/dist/session-decode/decode-worker-child.mjs +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BDR5z0Z9.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Dw-iwP4y.mjs} +3 -3
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Bme2OZQp.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-Do2DEtRt.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-D36MoVV1.mjs} +1 -1
- 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-Dmw5LWmP.mjs → hostInit-DEVCEYgu.mjs} +3 -3
- package/dist/stream-broker/index.js +906 -423
- package/dist/stream-broker/index.mjs +906 -423
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-BxkCoVjw.js → worker-protocol-nAZl_Rsv.js} +1 -1
- package/dist/{worker-protocol-h7Smb_0i.mjs → worker-protocol-rpnr7Ldd.mjs} +1 -1
- package/package.json +1 -1
- package/python/__pycache__/inference_pool.cpython-312.pyc +0 -0
- package/python/__pycache__/inference_pool.cpython-313.pyc +0 -0
- package/python/__pycache__/inference_pool.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_backpressure.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/__pycache__/test_inference_pool_backpressure.cpython-312.pyc +0 -0
- package/python/__pycache__/test_inference_pool_backpressure.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_coreml_cache.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/__pycache__/test_inference_pool_coreml_cache.cpython-312.pyc +0 -0
- package/python/__pycache__/test_inference_pool_coreml_cache.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_device_selection.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/__pycache__/test_inference_pool_device_selection.cpython-312.pyc +0 -0
- package/python/__pycache__/test_inference_pool_device_selection.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_layout.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/__pycache__/test_inference_pool_layout.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_memstats.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/__pycache__/test_inference_pool_memstats.cpython-312.pyc +0 -0
- package/python/__pycache__/test_inference_pool_memstats.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_ov_ppp.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/__pycache__/test_inference_pool_ov_ppp.cpython-312.pyc +0 -0
- package/python/__pycache__/test_inference_pool_ov_ppp.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_preprocess.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/__pycache__/test_inference_pool_preprocess.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_reconfigure.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_static_batch.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/__pycache__/test_inference_pool_static_batch.cpython-312.pyc +0 -0
- package/python/__pycache__/test_inference_pool_static_batch.cpython-314.pyc +0 -0
- package/python/__pycache__/yamnet_audio.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/_safety.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/clip.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/clip.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/clip.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/plate_slots.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/plate_slots.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/rfdetr.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/rfdetr.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/ssd.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/ssd.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/ssd.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/test_clip.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_clip.cpython-313-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-313-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/test_plate_slots.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_rfdetr.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_rfdetr.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/test_saliency.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_saliency.cpython-313-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_saliency.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/test_softmax.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_softmax.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/test_yolo_nms.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_yolo_nms.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/test_yolo_nms.cpython-39.pyc +0 -0
- package/python/postprocessors/__pycache__/test_yolonas.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-39.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/yolonas.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yolonas.cpython-314.pyc +0 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Cs8bmrWP.mjs +0 -26
package/dist/recorder/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as deriveRecordingMode, Dt as hydrateSchema, Gt as string, Ht as number, M as batteryCapability, Pt as selectAssignedProfileSlots, R as deriveBatteryPresence, St as BaseAddon, T as RecordingConfigSchema, Tt as DeviceType, Ut as object, Wt as record, at as recordingCapability, b as OpsLogEntrySchema, d as DEFAULT_EVENTS_BAND_BUFFER_SEC, ft as storageEvictableCapability, g as ExportRecordSchema, gt as errMsg, i as BatteryStatusSchema, jt as nodePin, m as EVENT_PAD_MS, ot as recordingExportCapability, qt as EventCategory, ut as resolveRecordingProfiles, w as RECORDING_EXPORT_MAX_READ_BYTES, wt as DeviceFeature } from "../dist-
|
|
1
|
+
import { B as deriveRecordingMode, Dt as hydrateSchema, F as customAction, Gt as string, Ht as number, L as defineCustomActions, Lt as array, M as batteryCapability, Pt as selectAssignedProfileSlots, R as deriveBatteryPresence, Rt as boolean, St as BaseAddon, T as RecordingConfigSchema, Tt as DeviceType, Ut as object, Wt as record, at as recordingCapability, b as OpsLogEntrySchema, d as DEFAULT_EVENTS_BAND_BUFFER_SEC, ft as storageEvictableCapability, g as ExportRecordSchema, gt as errMsg, i as BatteryStatusSchema, jt as nodePin, m as EVENT_PAD_MS, ot as recordingExportCapability, qt as EventCategory, ut as resolveRecordingProfiles, w as RECORDING_EXPORT_MAX_READ_BYTES, wt as DeviceFeature } from "../dist-Wt81pN5Y.mjs";
|
|
2
2
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
3
3
|
import { r as withRecordingIntent } from "../restream-intent-B4BXZra7.mjs";
|
|
4
4
|
import { n as createFileDataPlaneHandler, s as parseRangeHeader, t as contentTypeFor } from "../addon-utils-CgBCF-mE.mjs";
|
|
@@ -335,6 +335,70 @@ function fragmentRangeFor(index, offsetTicks) {
|
|
|
335
335
|
sampleIndex: chosen
|
|
336
336
|
};
|
|
337
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* Convert a byte budget into the SET of consecutive fragments that fits,
|
|
340
|
+
* starting at the fragment covering `offsetTicks` and walking FORWARD —
|
|
341
|
+
* matching the read direction a scrub or a sequential-forward strategy
|
|
342
|
+
* actually uses. Pure: `index` is the already-parsed `tfra` table, so this
|
|
343
|
+
* never touches the segment's payload.
|
|
344
|
+
*
|
|
345
|
+
* Greedy: adds the next fragment only while the running total stays within
|
|
346
|
+
* `maxBytes`. The anchor fragment is ALWAYS included, even when it alone
|
|
347
|
+
* exceeds `maxBytes` — {@link FragmentBudgetPlan.oversizeFragment} says so
|
|
348
|
+
* explicitly rather than the caller receiving an empty set and reading it as
|
|
349
|
+
* "nothing to read" (D49's letter, applied to a byte budget: a fallible
|
|
350
|
+
* computation must never silently look like an unbind).
|
|
351
|
+
*/
|
|
352
|
+
function fragmentsWithinBudget(index, offsetTicks, maxBytes) {
|
|
353
|
+
const { samples, mfraOffset } = index;
|
|
354
|
+
let lo = 0;
|
|
355
|
+
let hi = samples.length - 1;
|
|
356
|
+
let anchor = 0;
|
|
357
|
+
while (lo <= hi) {
|
|
358
|
+
const mid = lo + hi >> 1;
|
|
359
|
+
const s = samples[mid];
|
|
360
|
+
if (s === void 0) break;
|
|
361
|
+
if (s.timeTicks <= offsetTicks) {
|
|
362
|
+
anchor = mid;
|
|
363
|
+
lo = mid + 1;
|
|
364
|
+
} else hi = mid - 1;
|
|
365
|
+
}
|
|
366
|
+
const endOf = (i) => samples[i + 1]?.moofOffset ?? mfraOffset;
|
|
367
|
+
const anchorStart = samples[anchor]?.moofOffset ?? 0;
|
|
368
|
+
const anchorEnd = endOf(anchor);
|
|
369
|
+
const fragments = [{
|
|
370
|
+
start: anchorStart,
|
|
371
|
+
end: anchorEnd,
|
|
372
|
+
sampleIndex: anchor
|
|
373
|
+
}];
|
|
374
|
+
let total = anchorEnd - anchorStart;
|
|
375
|
+
const oversizeFragment = total > maxBytes;
|
|
376
|
+
let i = anchor;
|
|
377
|
+
while (i + 1 < samples.length) {
|
|
378
|
+
const nextIndex = i + 1;
|
|
379
|
+
const nextSample = samples[nextIndex];
|
|
380
|
+
if (nextSample === void 0) break;
|
|
381
|
+
const nextStart = nextSample.moofOffset;
|
|
382
|
+
const nextEnd = endOf(nextIndex);
|
|
383
|
+
const nextSize = nextEnd - nextStart;
|
|
384
|
+
if (total + nextSize > maxBytes) break;
|
|
385
|
+
fragments.push({
|
|
386
|
+
start: nextStart,
|
|
387
|
+
end: nextEnd,
|
|
388
|
+
sampleIndex: nextIndex
|
|
389
|
+
});
|
|
390
|
+
total += nextSize;
|
|
391
|
+
i = nextIndex;
|
|
392
|
+
}
|
|
393
|
+
const last = fragments[fragments.length - 1];
|
|
394
|
+
return {
|
|
395
|
+
fragments,
|
|
396
|
+
start: fragments[0].start,
|
|
397
|
+
end: last.end,
|
|
398
|
+
reachesSegmentEnd: last.end >= mfraOffset,
|
|
399
|
+
oversizeFragment
|
|
400
|
+
};
|
|
401
|
+
}
|
|
338
402
|
//#endregion
|
|
339
403
|
//#region src/recorder/mfra-capture.ts
|
|
340
404
|
/**
|
|
@@ -2736,6 +2800,271 @@ function activeModeForConfig(config) {
|
|
|
2736
2800
|
return deriveRecordingMode(config);
|
|
2737
2801
|
}
|
|
2738
2802
|
//#endregion
|
|
2803
|
+
//#region src/recorder/addon/store/read-census.ts
|
|
2804
|
+
/**
|
|
2805
|
+
* Longest window the census may be armed for, in ms.
|
|
2806
|
+
*
|
|
2807
|
+
* Ten minutes is several report windows - enough to catch a sweep that fires
|
|
2808
|
+
* every few minutes - and short enough that an operator who forgets about it
|
|
2809
|
+
* pays for ten minutes, not until the next restart.
|
|
2810
|
+
*/
|
|
2811
|
+
var CENSUS_MAX_WINDOW_MS = 10 * 6e4;
|
|
2812
|
+
/** Store procedures worth attributing. Reads only: a write is an operator
|
|
2813
|
+
* gesture or a pipeline product, and neither is a mystery. */
|
|
2814
|
+
var CENSUSED_PROCEDURES = new Set([
|
|
2815
|
+
"query",
|
|
2816
|
+
"count",
|
|
2817
|
+
"get",
|
|
2818
|
+
"histogram",
|
|
2819
|
+
"getAll"
|
|
2820
|
+
]);
|
|
2821
|
+
/**
|
|
2822
|
+
* Can `new Proxy` wrap this, and is it worth wrapping?
|
|
2823
|
+
*
|
|
2824
|
+
* Functions count. The generated store client is a **tRPC proxy** and every
|
|
2825
|
+
* intermediate node of one is CALLABLE — `typeof client.query` is `'function'`,
|
|
2826
|
+
* not `'object'`. A wrapper that tested only for `'object'` handed the whole
|
|
2827
|
+
* client back unwrapped, deployed, and reported zero `query` and zero `count`
|
|
2828
|
+
* call sites while the engine was recording thousands a minute against the same
|
|
2829
|
+
* tables. Silence read as "nobody in this addon does it".
|
|
2830
|
+
*/
|
|
2831
|
+
function isProxyable(value) {
|
|
2832
|
+
return typeof value === "object" && value !== null || typeof value === "function";
|
|
2833
|
+
}
|
|
2834
|
+
function rowsOf(value) {
|
|
2835
|
+
if (Array.isArray(value)) return value.length;
|
|
2836
|
+
if (typeof value === "number") return value;
|
|
2837
|
+
if (value === void 0 || value === null) return 0;
|
|
2838
|
+
return 1;
|
|
2839
|
+
}
|
|
2840
|
+
/**
|
|
2841
|
+
* One V8 stack line reduced to `Function@line`.
|
|
2842
|
+
*
|
|
2843
|
+
* A deployed addon is ONE bundled file, so the path is identical on every frame
|
|
2844
|
+
* and carries no information; the line number does. A frame that parses as
|
|
2845
|
+
* neither keeps its trimmed text rather than being dropped - an unrecognised
|
|
2846
|
+
* frame is still an attribution, and dropping it would silently shift the site
|
|
2847
|
+
* one frame up.
|
|
2848
|
+
*/
|
|
2849
|
+
function compactFrame(line) {
|
|
2850
|
+
const trimmed = line.trim().replace(/^at\s+/, "");
|
|
2851
|
+
const named = /^(.+?)\s+\((?:.*?):(\d+):\d+\)$/.exec(trimmed);
|
|
2852
|
+
if (named !== null) return `${named[1]}@${named[2]}`;
|
|
2853
|
+
const bare = /^(?:.*?):(\d+):\d+$/.exec(trimmed);
|
|
2854
|
+
if (bare !== null) return `@${bare[1]}`;
|
|
2855
|
+
return trimmed;
|
|
2856
|
+
}
|
|
2857
|
+
/** The census's view of a stack: the top {@link CENSUS_STACK_FRAMES} frames,
|
|
2858
|
+
* innermost first, joined by ` < ` so a line reads caller-ward. */
|
|
2859
|
+
function siteFromStack(stack) {
|
|
2860
|
+
if (stack === void 0) return "unknown";
|
|
2861
|
+
const frames = stack.split("\n").slice(1, 4);
|
|
2862
|
+
if (frames.length === 0) return "unknown";
|
|
2863
|
+
return frames.map(compactFrame).join(" < ");
|
|
2864
|
+
}
|
|
2865
|
+
/**
|
|
2866
|
+
* Armed-window call-site counter.
|
|
2867
|
+
*
|
|
2868
|
+
* Disarmed it is one comparison per read and captures nothing - the stack is
|
|
2869
|
+
* the whole cost, and it is not taken.
|
|
2870
|
+
*/
|
|
2871
|
+
var StoreReadCensus = class {
|
|
2872
|
+
now;
|
|
2873
|
+
counts = /* @__PURE__ */ new Map();
|
|
2874
|
+
armedUntil = 0;
|
|
2875
|
+
armedAt = 0;
|
|
2876
|
+
constructor(now = () => Date.now()) {
|
|
2877
|
+
this.now = now;
|
|
2878
|
+
}
|
|
2879
|
+
/** Arm for `forMs`, clamped to {@link CENSUS_MAX_WINDOW_MS}. Re-arming
|
|
2880
|
+
* restarts the window and CLEARS the counts: two overlapping measurements in
|
|
2881
|
+
* one table is a table nobody can divide by a duration. */
|
|
2882
|
+
arm(forMs) {
|
|
2883
|
+
const at = this.now();
|
|
2884
|
+
this.counts.clear();
|
|
2885
|
+
this.armedAt = at;
|
|
2886
|
+
this.armedUntil = at + Math.max(0, Math.min(forMs, CENSUS_MAX_WINDOW_MS));
|
|
2887
|
+
}
|
|
2888
|
+
disarm() {
|
|
2889
|
+
this.armedUntil = 0;
|
|
2890
|
+
}
|
|
2891
|
+
get armed() {
|
|
2892
|
+
return this.now() < this.armedUntil;
|
|
2893
|
+
}
|
|
2894
|
+
/** How long the current (or just-finished) window collected, in ms. The
|
|
2895
|
+
* divisor for a calls-per-minute rate - a count without it is a number that
|
|
2896
|
+
* cannot be compared to the next one. */
|
|
2897
|
+
elapsedMs() {
|
|
2898
|
+
const at = this.now();
|
|
2899
|
+
return Math.max(0, Math.min(at, this.armedUntil) - this.armedAt);
|
|
2900
|
+
}
|
|
2901
|
+
/**
|
|
2902
|
+
* The call site of whoever called `cutoff`, or `null` when disarmed.
|
|
2903
|
+
*
|
|
2904
|
+
* **Taken BEFORE the await, always.** The first version of this class
|
|
2905
|
+
* captured the stack next to the counter, after the wrapped call had
|
|
2906
|
+
* resolved - and by then the synchronous caller is gone: V8 stitches an async
|
|
2907
|
+
* frame in its place and the site reads
|
|
2908
|
+
* `Proxy.<anonymous> < processTicksAndRejections`, which is the census
|
|
2909
|
+
* describing itself. It passed one of its own tests anyway, because that one
|
|
2910
|
+
* caller happened to RETURN the promise rather than await it. An instrument
|
|
2911
|
+
* that reports its own frames is worse than no instrument: the counts are
|
|
2912
|
+
* real, so the wrong name gets believed.
|
|
2913
|
+
*
|
|
2914
|
+
* `cutoff` is the wrapper function itself, so every frame from the wrapper
|
|
2915
|
+
* inwards is dropped and frame 0 is the code that asked.
|
|
2916
|
+
*/
|
|
2917
|
+
siteOf(cutoff) {
|
|
2918
|
+
if (!this.armed) return null;
|
|
2919
|
+
const holder = {};
|
|
2920
|
+
Error.captureStackTrace(holder, cutoff);
|
|
2921
|
+
return siteFromStack(holder.stack);
|
|
2922
|
+
}
|
|
2923
|
+
/**
|
|
2924
|
+
* Count one read at an already-captured site.
|
|
2925
|
+
*
|
|
2926
|
+
* A `null` site means the census was disarmed when the call STARTED. It is
|
|
2927
|
+
* not counted even if it lands inside a later window - a read belongs to the
|
|
2928
|
+
* window that issued it.
|
|
2929
|
+
*/
|
|
2930
|
+
record(op, site, result) {
|
|
2931
|
+
if (site === null) return;
|
|
2932
|
+
const key = `${op} ${site}`;
|
|
2933
|
+
const existing = this.counts.get(key);
|
|
2934
|
+
if (existing === void 0) {
|
|
2935
|
+
this.counts.set(key, {
|
|
2936
|
+
op,
|
|
2937
|
+
site,
|
|
2938
|
+
calls: 1,
|
|
2939
|
+
rows: rowsOf(result)
|
|
2940
|
+
});
|
|
2941
|
+
return;
|
|
2942
|
+
}
|
|
2943
|
+
existing.calls += 1;
|
|
2944
|
+
existing.rows += rowsOf(result);
|
|
2945
|
+
}
|
|
2946
|
+
/** Busiest first. Does NOT clear - a window may be read as many times as the
|
|
2947
|
+
* operator likes and always describes the same window. */
|
|
2948
|
+
rows() {
|
|
2949
|
+
return [...this.counts.values()].map((r) => ({
|
|
2950
|
+
op: r.op,
|
|
2951
|
+
site: r.site,
|
|
2952
|
+
calls: r.calls,
|
|
2953
|
+
rows: r.rows
|
|
2954
|
+
})).sort((a, b) => b.calls - a.calls);
|
|
2955
|
+
}
|
|
2956
|
+
};
|
|
2957
|
+
/**
|
|
2958
|
+
* Wrap a settings-store client so every read is counted.
|
|
2959
|
+
*
|
|
2960
|
+
* A `Proxy` over the generated tRPC client rather than a hand-written facade:
|
|
2961
|
+
* the client has a procedure per cap method and a facade would need updating
|
|
2962
|
+
* every time the cap gains one - which is how a diagnostic quietly stops seeing
|
|
2963
|
+
* half the traffic. Unrecognised procedures pass straight through.
|
|
2964
|
+
*/
|
|
2965
|
+
function censusStoreClient(client, census) {
|
|
2966
|
+
return new Proxy(client, { get(target, prop, receiver) {
|
|
2967
|
+
const procedure = Reflect.get(target, prop, receiver);
|
|
2968
|
+
if (typeof prop !== "string" || !CENSUSED_PROCEDURES.has(prop)) return procedure;
|
|
2969
|
+
if (!isProxyable(procedure)) return procedure;
|
|
2970
|
+
const op = prop;
|
|
2971
|
+
return new Proxy(procedure, { get(procTarget, procProp, procReceiver) {
|
|
2972
|
+
const call = Reflect.get(procTarget, procProp, procReceiver);
|
|
2973
|
+
if (procProp !== "query" && procProp !== "mutate") return call;
|
|
2974
|
+
if (typeof call !== "function") return call;
|
|
2975
|
+
const wrapped = async (...args) => {
|
|
2976
|
+
const site = census.siteOf(wrapped);
|
|
2977
|
+
const result = await Reflect.apply(call, procTarget, args);
|
|
2978
|
+
census.record(op, site, result);
|
|
2979
|
+
return result;
|
|
2980
|
+
};
|
|
2981
|
+
return wrapped;
|
|
2982
|
+
} });
|
|
2983
|
+
} });
|
|
2984
|
+
}
|
|
2985
|
+
/** Log the census as one line, including when it collected nothing - silence
|
|
2986
|
+
* after an arm is indistinguishable from a census that never armed. */
|
|
2987
|
+
function logCensus(census, logger, topN) {
|
|
2988
|
+
const rows = census.rows();
|
|
2989
|
+
const elapsedMs = census.elapsedMs();
|
|
2990
|
+
const perMin = (calls) => elapsedMs === 0 ? 0 : Math.round(calls * 6e4 / elapsedMs);
|
|
2991
|
+
logger.info("store read census", { meta: {
|
|
2992
|
+
elapsedMs,
|
|
2993
|
+
sites: rows.length,
|
|
2994
|
+
calls: rows.reduce((acc, r) => acc + r.calls, 0),
|
|
2995
|
+
top: rows.slice(0, topN).map((r) => ({
|
|
2996
|
+
op: r.op,
|
|
2997
|
+
site: r.site,
|
|
2998
|
+
calls: r.calls,
|
|
2999
|
+
perMin: perMin(r.calls),
|
|
3000
|
+
rows: r.rows
|
|
3001
|
+
}))
|
|
3002
|
+
} });
|
|
3003
|
+
return rows;
|
|
3004
|
+
}
|
|
3005
|
+
/**
|
|
3006
|
+
* `armMs: 0` (or omitted) READS the window that already ran — that is how a
|
|
3007
|
+
* measurement is collected after its window closed, and re-arming to read
|
|
3008
|
+
* would throw away exactly the numbers being asked for (`StoreReadCensus.arm`
|
|
3009
|
+
* clears on every call).
|
|
3010
|
+
*/
|
|
3011
|
+
var StoreCensusInputSchema = object({
|
|
3012
|
+
armMs: number().int().min(0).max(CENSUS_MAX_WINDOW_MS).optional(),
|
|
3013
|
+
limit: number().int().positive().max(200).optional()
|
|
3014
|
+
});
|
|
3015
|
+
var StoreCensusRowSchema = object({
|
|
3016
|
+
op: string(),
|
|
3017
|
+
site: string(),
|
|
3018
|
+
calls: number(),
|
|
3019
|
+
/** Calls extrapolated to a minute, directly comparable with the live-hub
|
|
3020
|
+
* profiler's own `get recorder:recording-configs` rate. */
|
|
3021
|
+
perMin: number(),
|
|
3022
|
+
rows: number()
|
|
3023
|
+
});
|
|
3024
|
+
var recorderDebugActions = defineCustomActions({ "debug.storeCensus": customAction(StoreCensusInputSchema, object({
|
|
3025
|
+
armed: boolean(),
|
|
3026
|
+
elapsedMs: number(),
|
|
3027
|
+
sites: number(),
|
|
3028
|
+
calls: number(),
|
|
3029
|
+
rows: array(StoreCensusRowSchema).readonly()
|
|
3030
|
+
}), { auth: "admin" }) });
|
|
3031
|
+
/**
|
|
3032
|
+
* Arm-or-read, pulled out of the addon class so it is testable without
|
|
3033
|
+
* booting `RecorderV2Addon` — feed it a bare `StoreReadCensus` and a logger.
|
|
3034
|
+
*
|
|
3035
|
+
* The result is also logged (via {@link logCensus}), because a measurement
|
|
3036
|
+
* that exists only in an HTTP response is a measurement that is gone when the
|
|
3037
|
+
* next session asks what happened.
|
|
3038
|
+
*/
|
|
3039
|
+
function handleStoreCensusAction(census, logger, input) {
|
|
3040
|
+
const limit = input.limit ?? 200;
|
|
3041
|
+
if (input.armMs !== void 0 && input.armMs > 0) {
|
|
3042
|
+
census.arm(input.armMs);
|
|
3043
|
+
return {
|
|
3044
|
+
armed: true,
|
|
3045
|
+
elapsedMs: 0,
|
|
3046
|
+
sites: 0,
|
|
3047
|
+
calls: 0,
|
|
3048
|
+
rows: []
|
|
3049
|
+
};
|
|
3050
|
+
}
|
|
3051
|
+
const rows = logCensus(census, logger, limit);
|
|
3052
|
+
const elapsedMs = census.elapsedMs();
|
|
3053
|
+
return {
|
|
3054
|
+
armed: census.armed,
|
|
3055
|
+
elapsedMs,
|
|
3056
|
+
sites: rows.length,
|
|
3057
|
+
calls: rows.reduce((acc, r) => acc + r.calls, 0),
|
|
3058
|
+
rows: rows.slice(0, limit).map((r) => ({
|
|
3059
|
+
op: r.op,
|
|
3060
|
+
site: r.site,
|
|
3061
|
+
calls: r.calls,
|
|
3062
|
+
perMin: elapsedMs === 0 ? 0 : Math.round(r.calls * 6e4 / elapsedMs),
|
|
3063
|
+
rows: r.rows
|
|
3064
|
+
}))
|
|
3065
|
+
};
|
|
3066
|
+
}
|
|
3067
|
+
//#endregion
|
|
2739
3068
|
//#region src/recorder/addon/directory-handler.ts
|
|
2740
3069
|
var HOUR_MS$3 = 36e5;
|
|
2741
3070
|
/** A window wider than this is refused: it is a client bug, and answering it
|
|
@@ -4093,6 +4422,18 @@ function buildMasterPlaylist(variants) {
|
|
|
4093
4422
|
* against a real captured segment with every read recorded — "never the whole
|
|
4094
4423
|
* file" is asserted in bytes.
|
|
4095
4424
|
*/
|
|
4425
|
+
/**
|
|
4426
|
+
* Byte budget for the `readGopBytes` fallback read, used with
|
|
4427
|
+
* {@link GopRangeArgs.maxBytes}.
|
|
4428
|
+
*
|
|
4429
|
+
* Same conceptual ceiling as `SCRUB_WHOLE_SEGMENT_MAX_BYTES` in
|
|
4430
|
+
* `stream-broker/recorded/recorded-feeder.ts` (D163, 1.5 MB) — declared here
|
|
4431
|
+
* independently rather than imported, because that module is the CLIENT
|
|
4432
|
+
* feeder (a different addon-internal concern; importing its whole dependency
|
|
4433
|
+
* graph for one number is the wrong direction). If D163's number moves,
|
|
4434
|
+
* this one moves with it.
|
|
4435
|
+
*/
|
|
4436
|
+
var SCRUB_GOP_BUDGET_MAX_BYTES = 15e5;
|
|
4096
4437
|
/** Ticks → ms on the video timescale, rounded like the demux anchors samples. */
|
|
4097
4438
|
function ticksToMs(ticks, timescale) {
|
|
4098
4439
|
return Math.round(ticks / timescale * 1e3);
|
|
@@ -4122,11 +4463,36 @@ async function readGopRange(file, args) {
|
|
|
4122
4463
|
if (init === null) return null;
|
|
4123
4464
|
const videoIndex = index.trackId === init.videoTrackId ? index : parsed === null ? null : reparseTail(parsed.tail, file.size, init.videoTrackId);
|
|
4124
4465
|
if (videoIndex === null) return null;
|
|
4125
|
-
const
|
|
4466
|
+
const offsetTicks = Math.max(0, args.epochMs - args.segmentStartMs) / 1e3 * init.videoTimescale;
|
|
4467
|
+
let start;
|
|
4468
|
+
let end;
|
|
4469
|
+
let firstSampleIndex;
|
|
4470
|
+
let lastSampleIndex;
|
|
4471
|
+
let reachesSegmentEnd;
|
|
4472
|
+
let oversizeFragment;
|
|
4473
|
+
if (args.maxBytes === void 0) {
|
|
4474
|
+
const single = fragmentRangeFor(videoIndex, offsetTicks);
|
|
4475
|
+
start = single.start;
|
|
4476
|
+
end = single.end;
|
|
4477
|
+
firstSampleIndex = single.sampleIndex;
|
|
4478
|
+
lastSampleIndex = single.sampleIndex;
|
|
4479
|
+
reachesSegmentEnd = videoIndex.samples[single.sampleIndex + 1] === void 0;
|
|
4480
|
+
oversizeFragment = false;
|
|
4481
|
+
} else {
|
|
4482
|
+
const plan = fragmentsWithinBudget(videoIndex, offsetTicks, args.maxBytes);
|
|
4483
|
+
const firstFragment = plan.fragments[0];
|
|
4484
|
+
const lastFragment = plan.fragments[plan.fragments.length - 1];
|
|
4485
|
+
start = plan.start;
|
|
4486
|
+
end = plan.end;
|
|
4487
|
+
firstSampleIndex = firstFragment.sampleIndex;
|
|
4488
|
+
lastSampleIndex = lastFragment.sampleIndex;
|
|
4489
|
+
reachesSegmentEnd = plan.reachesSegmentEnd;
|
|
4490
|
+
oversizeFragment = plan.oversizeFragment;
|
|
4491
|
+
}
|
|
4126
4492
|
if (start <= 0 || end <= start || end > file.size) return null;
|
|
4127
4493
|
const fragment = await read(start, end - start);
|
|
4128
|
-
const startTicks = videoIndex.samples[
|
|
4129
|
-
const nextTicks = videoIndex.samples[
|
|
4494
|
+
const startTicks = videoIndex.samples[firstSampleIndex]?.timeTicks ?? 0;
|
|
4495
|
+
const nextTicks = videoIndex.samples[lastSampleIndex + 1]?.timeTicks;
|
|
4130
4496
|
const gopStartOffsetMs = ticksToMs(startTicks, init.videoTimescale);
|
|
4131
4497
|
const gopDurMs = nextTicks !== void 0 ? ticksToMs(nextTicks - startTicks, init.videoTimescale) : Math.max(1, args.segmentDurMs - gopStartOffsetMs);
|
|
4132
4498
|
const data = new Uint8Array(head.length + fragment.length);
|
|
@@ -4136,7 +4502,9 @@ async function readGopRange(file, args) {
|
|
|
4136
4502
|
data,
|
|
4137
4503
|
gopStartMs: args.segmentStartMs + gopStartOffsetMs,
|
|
4138
4504
|
gopDurMs,
|
|
4139
|
-
bytesRead
|
|
4505
|
+
bytesRead,
|
|
4506
|
+
reachesSegmentEnd,
|
|
4507
|
+
oversizeFragment
|
|
4140
4508
|
};
|
|
4141
4509
|
}
|
|
4142
4510
|
/**
|
|
@@ -4669,6 +5037,30 @@ function resolveSegmentFile(deps, deviceId, profile, startMs) {
|
|
|
4669
5037
|
abs: path.join(loc.root, seg.path)
|
|
4670
5038
|
};
|
|
4671
5039
|
}
|
|
5040
|
+
/**
|
|
5041
|
+
* The log line's `meta`, or null when `readGopBytes` served nothing worth a
|
|
5042
|
+
* line. Split out from the handler so the decision is testable against a
|
|
5043
|
+
* plain object — no real fMP4 bytes needed to prove a >1.5 MB fragment
|
|
5044
|
+
* triggers it.
|
|
5045
|
+
*
|
|
5046
|
+
* The single-fragment budget overshoot is the notable case, not the routine
|
|
5047
|
+
* one: a `high`/`mid` scrub goes through this path on every tick by design
|
|
5048
|
+
* (client-side `profile-degraded`, already logged once per drag on the
|
|
5049
|
+
* feeder), and logging every such call here would spam nothing new. A
|
|
5050
|
+
* fragment that alone exceeds the budget is different — it is never returned
|
|
5051
|
+
* empty (never-empty is {@link fragmentsWithinBudget}'s contract), but an
|
|
5052
|
+
* operator debugging a slow drag needs to know it happened.
|
|
5053
|
+
*/
|
|
5054
|
+
function oversizeFragmentLogMeta(gop, args) {
|
|
5055
|
+
if (!gop.oversizeFragment) return null;
|
|
5056
|
+
return {
|
|
5057
|
+
profile: args.profile,
|
|
5058
|
+
startMs: args.startMs,
|
|
5059
|
+
epochMs: args.epochMs,
|
|
5060
|
+
fragmentBytes: gop.data.length,
|
|
5061
|
+
maxBytes: SCRUB_GOP_BUDGET_MAX_BYTES
|
|
5062
|
+
};
|
|
5063
|
+
}
|
|
4672
5064
|
/** Default ranged opener: ONE `fs.open` per GOP answer serving all its reads. */
|
|
4673
5065
|
async function openRangeFromDisk(absPath, size) {
|
|
4674
5066
|
const handle = await promises.open(absPath, "r");
|
|
@@ -4888,13 +5280,25 @@ function buildRecordingProvider(deps) {
|
|
|
4888
5280
|
segmentStartMs: seg.startMs,
|
|
4889
5281
|
segmentDurMs: seg.durMs,
|
|
4890
5282
|
epochMs,
|
|
4891
|
-
seededIndex: deps.mfraFor?.(deviceId, profile, startMs)
|
|
5283
|
+
seededIndex: deps.mfraFor?.(deviceId, profile, startMs),
|
|
5284
|
+
maxBytes: SCRUB_GOP_BUDGET_MAX_BYTES
|
|
4892
5285
|
});
|
|
4893
|
-
if (gop !== null)
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
5286
|
+
if (gop !== null) {
|
|
5287
|
+
const oversizeMeta = oversizeFragmentLogMeta(gop, {
|
|
5288
|
+
profile,
|
|
5289
|
+
startMs,
|
|
5290
|
+
epochMs
|
|
5291
|
+
});
|
|
5292
|
+
if (oversizeMeta !== null) deps.logger.warn("recording: readGopBytes served one fragment that alone exceeds the scrub budget", {
|
|
5293
|
+
tags: { deviceId },
|
|
5294
|
+
meta: oversizeMeta
|
|
5295
|
+
});
|
|
5296
|
+
return {
|
|
5297
|
+
data: gop.data,
|
|
5298
|
+
gopStartMs: gop.gopStartMs,
|
|
5299
|
+
gopDurMs: gop.gopDurMs
|
|
5300
|
+
};
|
|
5301
|
+
}
|
|
4898
5302
|
} finally {
|
|
4899
5303
|
await file.close();
|
|
4900
5304
|
}
|
|
@@ -11175,6 +11579,23 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
11175
11579
|
retentionSweeper = null;
|
|
11176
11580
|
/** Reversible migration pause lease; never reflected in RecordingConfig. */
|
|
11177
11581
|
storageMigrationLeaseId = null;
|
|
11582
|
+
/**
|
|
11583
|
+
* Call-site attribution for `recorder:recording-configs` / `-exports` /
|
|
11584
|
+
* `-ops-log` row reads (`store/read-census.ts`).
|
|
11585
|
+
*
|
|
11586
|
+
* Disarmed by default; armed for a bounded window through
|
|
11587
|
+
* `debug.storeCensus`. It exists because the live-hub profiler names a
|
|
11588
|
+
* TABLE — `get recorder:recording-configs` ran 581-892 calls/min on
|
|
11589
|
+
* 2026-08-26, finding a row only ~56% of the time — and cannot say WHICH of
|
|
11590
|
+
* `loadDeviceConfig`'s several cap-handler call sites (`getStatus`,
|
|
11591
|
+
* `getDeviceConfig`, `rescanStorage`, `pruneFootage`) is issuing them.
|
|
11592
|
+
* Picking the reader that LOOKS like a loop has cost this repo half a day
|
|
11593
|
+
* twice, wrong both times — this measures instead.
|
|
11594
|
+
*/
|
|
11595
|
+
readCensus = new StoreReadCensus();
|
|
11596
|
+
/** Memoised so every `configStore()` / `exportsStore()` / `opsLogStore()`
|
|
11597
|
+
* call shares ONE census instead of each wrapping the raw client afresh. */
|
|
11598
|
+
censusedSettingsStoreClient = null;
|
|
11178
11599
|
constructor() {
|
|
11179
11600
|
super({ ...DEFAULT_CONFIG });
|
|
11180
11601
|
}
|
|
@@ -11579,20 +12000,24 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
11579
12000
|
}
|
|
11580
12001
|
});
|
|
11581
12002
|
warnLostBands(this.configStore(), this.ctx.logger);
|
|
11582
|
-
return {
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
|
|
11590
|
-
|
|
11591
|
-
|
|
11592
|
-
|
|
11593
|
-
|
|
11594
|
-
|
|
11595
|
-
|
|
12003
|
+
return {
|
|
12004
|
+
providers: [
|
|
12005
|
+
{
|
|
12006
|
+
capability: recordingCapability,
|
|
12007
|
+
provider: recordingProvider
|
|
12008
|
+
},
|
|
12009
|
+
{
|
|
12010
|
+
capability: storageEvictableCapability,
|
|
12011
|
+
provider: evictableProvider
|
|
12012
|
+
},
|
|
12013
|
+
{
|
|
12014
|
+
capability: recordingExportCapability,
|
|
12015
|
+
provider: exportProvider
|
|
12016
|
+
}
|
|
12017
|
+
],
|
|
12018
|
+
customActions: recorderDebugActions,
|
|
12019
|
+
actionHandlers: { "debug.storeCensus": async (input) => handleStoreCensusAction(this.readCensus, this.ctx.logger.child("Census"), input) }
|
|
12020
|
+
};
|
|
11596
12021
|
}
|
|
11597
12022
|
async onShutdown() {
|
|
11598
12023
|
this.eventUnsub?.();
|
|
@@ -12241,17 +12666,29 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
12241
12666
|
this.ctx.logger.warn("recorder: retiring the flattened settings keys failed", { meta: { error: errMsg(err) } });
|
|
12242
12667
|
}
|
|
12243
12668
|
}
|
|
12669
|
+
/**
|
|
12670
|
+
* `ctx.api.settingsStore`, wrapped ONCE through {@link censusStoreClient}.
|
|
12671
|
+
*
|
|
12672
|
+
* LAZY (see `calendar` above): `ctx` is not assigned until `initialize()`
|
|
12673
|
+
* runs, so this cannot be a field initialiser. The wrap is permanent and
|
|
12674
|
+
* cheap when disarmed (one `get` trap and a comparison) — what is armed and
|
|
12675
|
+
* disarmed is `this.readCensus`, through `debug.storeCensus`, not this seam.
|
|
12676
|
+
*/
|
|
12677
|
+
censusedSettingsStore() {
|
|
12678
|
+
this.censusedSettingsStoreClient ??= censusStoreClient(this.ctx.api.settingsStore, this.readCensus);
|
|
12679
|
+
return this.censusedSettingsStoreClient;
|
|
12680
|
+
}
|
|
12244
12681
|
configStore() {
|
|
12245
|
-
return recordingConfigsState(this.
|
|
12682
|
+
return recordingConfigsState(this.censusedSettingsStore(), this.ctx.logger);
|
|
12246
12683
|
}
|
|
12247
12684
|
/** Durable handle over the exportId→ExportRecord blob (same `BaseAddon.state()`
|
|
12248
12685
|
* wrapper as the config store). */
|
|
12249
12686
|
exportsStore() {
|
|
12250
|
-
return recordingExportsState(this.
|
|
12687
|
+
return recordingExportsState(this.censusedSettingsStore(), this.ctx.logger);
|
|
12251
12688
|
}
|
|
12252
12689
|
/** Durable handle over the bounded recordings ops-log ring. */
|
|
12253
12690
|
opsLogStore() {
|
|
12254
|
-
return recordingOpsLogState(this.
|
|
12691
|
+
return recordingOpsLogState(this.censusedSettingsStore(), this.ctx.logger);
|
|
12255
12692
|
}
|
|
12256
12693
|
/** Durable handle over the recorder-owned placement blob (assignments + volume ids). */
|
|
12257
12694
|
placementStore() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __toESM, t as __commonJSMin } from "./chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { gt as errMsg } from "./dist-
|
|
2
|
+
import { gt as errMsg } from "./dist-Wt81pN5Y.mjs";
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
//#region ../../node_modules/mp4box/dist/mp4box.all.js
|
|
5
5
|
var require_mp4box_all = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_dist = require("./dist-
|
|
1
|
+
const require_dist = require("./dist-DOw-izoI.js");
|
|
2
2
|
let node_child_process = require("node:child_process");
|
|
3
3
|
//#region ../../node_modules/mp4box/dist/mp4box.all.js
|
|
4
4
|
var require_mp4box_all = /* @__PURE__ */ require_dist.__commonJSMin(((exports) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_worker_protocol = require("../worker-protocol-
|
|
3
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
2
|
+
const require_worker_protocol = require("../worker-protocol-nAZl_Rsv.js");
|
|
3
|
+
const require_lazy_sharp = require("../lazy-sharp-BbNI2ZD-.js");
|
|
4
4
|
//#region src/session-decode/color-conversion.ts
|
|
5
5
|
/**
|
|
6
6
|
* Explicit YUV→RGB colorspace/range resolution for the session-decode worker.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as formatNativeLeaseKnobs, n as isWorkerRequest, o as resolveNativeLeaseKnobs, r as logLevelForLine } from "../worker-protocol-
|
|
1
|
+
import { i as formatNativeLeaseKnobs, n as isWorkerRequest, o as resolveNativeLeaseKnobs, r as logLevelForLine } from "../worker-protocol-rpnr7Ldd.mjs";
|
|
2
2
|
import { n as setSharpWarnSink, r as hostExternalEntryUrls, t as getSharp } from "../lazy-sharp-BtT5x-qP.mjs";
|
|
3
3
|
//#region src/session-decode/color-conversion.ts
|
|
4
4
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-
|
|
1
|
+
import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, p as c, r as l, s as u, t as d, u as f } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-D36MoVV1.mjs";
|
|
2
2
|
import { a as p, i as m, n as h, o as g, r as _, t as v } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.js-C9j-2lBe.mjs";
|
|
3
3
|
import { n as y, r as b, t as x } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-XO0-Pyu6.mjs";
|
|
4
|
-
import { t as S } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-
|
|
4
|
+
import { t as S } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Bme2OZQp.mjs";
|
|
5
5
|
import { n as C, t as w } from "./_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-BO7TIbJV.mjs";
|
|
6
6
|
//#region ../../node_modules/lucide-react/dist/esm/shared/src/utils.js
|
|
7
7
|
var T = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), E = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), D = (e) => {
|
|
@@ -3,7 +3,7 @@ import "./dist-CYZr2fwk.mjs";
|
|
|
3
3
|
var e = {
|
|
4
4
|
"@camstack/sdk": {
|
|
5
5
|
name: "@camstack/sdk",
|
|
6
|
-
version: "1.2.
|
|
6
|
+
version: "1.2.32",
|
|
7
7
|
scope: ["default"],
|
|
8
8
|
loaded: !1,
|
|
9
9
|
from: "addon_stream_broker_widgets",
|
|
@@ -18,7 +18,7 @@ var e = {
|
|
|
18
18
|
},
|
|
19
19
|
"@camstack/types": {
|
|
20
20
|
name: "@camstack/types",
|
|
21
|
-
version: "1.2.
|
|
21
|
+
version: "1.2.110",
|
|
22
22
|
scope: ["default"],
|
|
23
23
|
loaded: !1,
|
|
24
24
|
from: "addon_stream_broker_widgets",
|
|
@@ -33,7 +33,7 @@ var e = {
|
|
|
33
33
|
},
|
|
34
34
|
"@camstack/ui-library": {
|
|
35
35
|
name: "@camstack/ui-library",
|
|
36
|
-
version: "1.2.
|
|
36
|
+
version: "1.2.73",
|
|
37
37
|
scope: ["default"],
|
|
38
38
|
loaded: !1,
|
|
39
39
|
from: "addon_stream_broker_widgets",
|