@camstack/addon-pipeline 1.2.131 → 1.2.132
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-DCQ5AP_v.js → addon-utils-DzCn6z7v.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 +5 -5
- package/dist/detection-pipeline/index.mjs +3 -3
- package/dist/{dist-DO0UVhOk.mjs → dist-BZYUUBUx.mjs} +83 -2
- package/dist/{dist-CqoMNE1e.js → dist-DBP47QOz.js} +83 -2
- package/dist/{event-loop-stall-monitor-eM7_yYfn.js → event-loop-stall-monitor-CiH_MHfO.js} +1 -1
- package/dist/{event-loop-stall-monitor-D0Juf7Dn.mjs → event-loop-stall-monitor-IACE22fK.mjs} +1 -1
- package/dist/{lazy-sharp-BGrpS8yi.js → lazy-sharp-B_kETjyQ.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-Bac3FuG6.mjs → process-memory-C7rsraCR.mjs} +1 -1
- package/dist/{process-memory-xAPjvSw9.js → process-memory-CtXQAA3d.js} +1 -1
- package/dist/recorder/index.js +233 -15
- package/dist/recorder/index.mjs +232 -14
- package/dist/{segment-demux-js-skhsAZx6.mjs → segment-demux-js-BL1UDdiI.mjs} +1 -1
- package/dist/{segment-demux-js-Cu0oDMUL.js → segment-demux-js-wTzFi5UW.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-DGQkDEYw.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DlKJZ-_M.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 → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DXKTNEae.mjs} +1 -1
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CQKwHIHI.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BUw_aTfK.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-D7FwwZgj.mjs → hostInit-kDKgfUjp.mjs} +3 -3
- package/dist/stream-broker/index.js +2 -2
- package/dist/stream-broker/index.mjs +2 -2
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-G3HXTY8z.js → worker-protocol-C3zaz0Jv.js} +1 -1
- package/dist/{worker-protocol-_Ujvj1hl.mjs → worker-protocol-Cut8984B.mjs} +1 -1
- package/package.json +1 -1
package/dist/recorder/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const require_dist = require("../dist-
|
|
1
|
+
const require_dist = require("../dist-DBP47QOz.js");
|
|
2
2
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
3
3
|
const require_restream_intent = require("../restream-intent-Cv9x3jmu.js");
|
|
4
|
-
const require_addon_utils = require("../addon-utils-
|
|
4
|
+
const require_addon_utils = require("../addon-utils-DzCn6z7v.js");
|
|
5
5
|
const require_retire_root_keys = require("../retire-root-keys-KE6D6Xh_.js");
|
|
6
6
|
let node_crypto = require("node:crypto");
|
|
7
7
|
let node_child_process = require("node:child_process");
|
|
@@ -350,8 +350,13 @@ function fragmentRangeFor(index, offsetTicks) {
|
|
|
350
350
|
* "nothing to read" (D49's letter, applied to a byte budget: a fallible
|
|
351
351
|
* computation must never silently look like an unbind).
|
|
352
352
|
*/
|
|
353
|
-
|
|
354
|
-
|
|
353
|
+
/**
|
|
354
|
+
* The last sync sample at or before `offsetTicks` — the keyframe a decoder
|
|
355
|
+
* must start from. Shared by {@link fragmentsWithinBudget} and
|
|
356
|
+
* {@link fragmentsInWindow}: both walk forward from the same anchor, they
|
|
357
|
+
* only differ in the condition that stops the walk.
|
|
358
|
+
*/
|
|
359
|
+
function findAnchor(samples, offsetTicks) {
|
|
355
360
|
let lo = 0;
|
|
356
361
|
let hi = samples.length - 1;
|
|
357
362
|
let anchor = 0;
|
|
@@ -364,6 +369,11 @@ function fragmentsWithinBudget(index, offsetTicks, maxBytes) {
|
|
|
364
369
|
lo = mid + 1;
|
|
365
370
|
} else hi = mid - 1;
|
|
366
371
|
}
|
|
372
|
+
return anchor;
|
|
373
|
+
}
|
|
374
|
+
function fragmentsWithinBudget(index, offsetTicks, maxBytes) {
|
|
375
|
+
const { samples, mfraOffset } = index;
|
|
376
|
+
const anchor = findAnchor(samples, offsetTicks);
|
|
367
377
|
const endOf = (i) => samples[i + 1]?.moofOffset ?? mfraOffset;
|
|
368
378
|
const anchorStart = samples[anchor]?.moofOffset ?? 0;
|
|
369
379
|
const anchorEnd = endOf(anchor);
|
|
@@ -400,6 +410,70 @@ function fragmentsWithinBudget(index, offsetTicks, maxBytes) {
|
|
|
400
410
|
oversizeFragment
|
|
401
411
|
};
|
|
402
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* Convert a TIME WINDOW `[fromTicks, toTicks)` into the set of consecutive
|
|
415
|
+
* fragments that covers it — the replay's primitive for "give me this many
|
|
416
|
+
* seconds of one segment", as opposed to {@link fragmentsWithinBudget}'s
|
|
417
|
+
* "give me as much as fits in N bytes" (the scrub GOP read's primitive).
|
|
418
|
+
*
|
|
419
|
+
* Stops walking forward the instant the NEXT fragment's own start time
|
|
420
|
+
* already reaches `toTicks`: at that point the fragments already collected
|
|
421
|
+
* cover the whole window, because each fragment's coverage runs up to the
|
|
422
|
+
* next one's start (the same relationship {@link fragmentsWithinBudget}'s
|
|
423
|
+
* `endOf` encodes). `maxBytes` is a SAFETY CEILING, not the primary stop
|
|
424
|
+
* condition — a caller with a well-formed window is expected to hit the time
|
|
425
|
+
* condition first; the byte cap exists so a pathological request cannot pull
|
|
426
|
+
* an unbounded amount of one segment into memory.
|
|
427
|
+
*
|
|
428
|
+
* Same never-empty guarantee as {@link fragmentsWithinBudget}: the anchor
|
|
429
|
+
* fragment is always returned, even when it alone exceeds `maxBytes`.
|
|
430
|
+
*/
|
|
431
|
+
function fragmentsInWindow(index, fromTicks, toTicks, maxBytes) {
|
|
432
|
+
const { samples, mfraOffset } = index;
|
|
433
|
+
const anchor = findAnchor(samples, fromTicks);
|
|
434
|
+
const endOf = (i) => samples[i + 1]?.moofOffset ?? mfraOffset;
|
|
435
|
+
const windowCoveredAt = (i) => {
|
|
436
|
+
const next = samples[i + 1];
|
|
437
|
+
return next === void 0 || next.timeTicks >= toTicks;
|
|
438
|
+
};
|
|
439
|
+
const anchorStart = samples[anchor]?.moofOffset ?? 0;
|
|
440
|
+
const anchorEnd = endOf(anchor);
|
|
441
|
+
const fragments = [{
|
|
442
|
+
start: anchorStart,
|
|
443
|
+
end: anchorEnd,
|
|
444
|
+
sampleIndex: anchor
|
|
445
|
+
}];
|
|
446
|
+
let total = anchorEnd - anchorStart;
|
|
447
|
+
const oversizeFragment = total > maxBytes;
|
|
448
|
+
let i = anchor;
|
|
449
|
+
let reachesWindowEnd = windowCoveredAt(i);
|
|
450
|
+
while (!reachesWindowEnd) {
|
|
451
|
+
const nextIndex = i + 1;
|
|
452
|
+
const nextSample = samples[nextIndex];
|
|
453
|
+
if (nextSample === void 0) break;
|
|
454
|
+
const nextStart = nextSample.moofOffset;
|
|
455
|
+
const nextEnd = endOf(nextIndex);
|
|
456
|
+
const nextSize = nextEnd - nextStart;
|
|
457
|
+
if (total + nextSize > maxBytes) break;
|
|
458
|
+
fragments.push({
|
|
459
|
+
start: nextStart,
|
|
460
|
+
end: nextEnd,
|
|
461
|
+
sampleIndex: nextIndex
|
|
462
|
+
});
|
|
463
|
+
total += nextSize;
|
|
464
|
+
i = nextIndex;
|
|
465
|
+
reachesWindowEnd = windowCoveredAt(i);
|
|
466
|
+
}
|
|
467
|
+
const last = fragments[fragments.length - 1];
|
|
468
|
+
return {
|
|
469
|
+
fragments,
|
|
470
|
+
start: fragments[0].start,
|
|
471
|
+
end: last.end,
|
|
472
|
+
reachesSegmentEnd: last.end >= mfraOffset,
|
|
473
|
+
reachesWindowEnd,
|
|
474
|
+
oversizeFragment
|
|
475
|
+
};
|
|
476
|
+
}
|
|
403
477
|
//#endregion
|
|
404
478
|
//#region src/recorder/mfra-capture.ts
|
|
405
479
|
/**
|
|
@@ -4440,6 +4514,34 @@ var SCRUB_GOP_BUDGET_MAX_BYTES = 15e5;
|
|
|
4440
4514
|
function ticksToMs(ticks, timescale) {
|
|
4441
4515
|
return Math.round(ticks / timescale * 1e3);
|
|
4442
4516
|
}
|
|
4517
|
+
/** ms → ticks on the video timescale — the inverse of {@link ticksToMs}. */
|
|
4518
|
+
function msToTicks(ms, timescale) {
|
|
4519
|
+
return ms / 1e3 * timescale;
|
|
4520
|
+
}
|
|
4521
|
+
/**
|
|
4522
|
+
* Steps 1-2 shared by {@link readGopRange} and {@link readGopWindowRange}:
|
|
4523
|
+
* locate the `mfra` (seeded or from the tail), read the `ftyp`+`moov` head,
|
|
4524
|
+
* and pick the VIDEO track's sync table (never the audio one, which lists
|
|
4525
|
+
* every `moof` and would send a seek to bytes that do not open a GOP).
|
|
4526
|
+
* `null` on anything that does not look like a recorded segment.
|
|
4527
|
+
*/
|
|
4528
|
+
async function resolveSegmentIndex(file, seededIndex, read) {
|
|
4529
|
+
const parsed = seededIndex === void 0 ? await parseTail(file, read) : null;
|
|
4530
|
+
if (seededIndex === void 0 && parsed === null) return null;
|
|
4531
|
+
const index = seededIndex ?? parsed.index;
|
|
4532
|
+
const firstMoof = index.samples[0]?.moofOffset ?? 0;
|
|
4533
|
+
if (firstMoof <= 0 || firstMoof >= file.size) return null;
|
|
4534
|
+
const head = await read(0, firstMoof);
|
|
4535
|
+
const init = parseInitInfo(head);
|
|
4536
|
+
if (init === null) return null;
|
|
4537
|
+
const videoIndex = index.trackId === init.videoTrackId ? index : parsed === null ? null : reparseTail(parsed.tail, file.size, init.videoTrackId);
|
|
4538
|
+
if (videoIndex === null) return null;
|
|
4539
|
+
return {
|
|
4540
|
+
head,
|
|
4541
|
+
init,
|
|
4542
|
+
videoIndex
|
|
4543
|
+
};
|
|
4544
|
+
}
|
|
4443
4545
|
/**
|
|
4444
4546
|
* Read the single GOP covering `epochMs` from `file`, by byte range.
|
|
4445
4547
|
*
|
|
@@ -4455,17 +4557,10 @@ async function readGopRange(file, args) {
|
|
|
4455
4557
|
bytesRead += chunk.length;
|
|
4456
4558
|
return chunk;
|
|
4457
4559
|
};
|
|
4458
|
-
const
|
|
4459
|
-
if (
|
|
4460
|
-
const
|
|
4461
|
-
const
|
|
4462
|
-
if (firstMoof <= 0 || firstMoof >= file.size) return null;
|
|
4463
|
-
const head = await read(0, firstMoof);
|
|
4464
|
-
const init = parseInitInfo(head);
|
|
4465
|
-
if (init === null) return null;
|
|
4466
|
-
const videoIndex = index.trackId === init.videoTrackId ? index : parsed === null ? null : reparseTail(parsed.tail, file.size, init.videoTrackId);
|
|
4467
|
-
if (videoIndex === null) return null;
|
|
4468
|
-
const offsetTicks = Math.max(0, args.epochMs - args.segmentStartMs) / 1e3 * init.videoTimescale;
|
|
4560
|
+
const resolved = await resolveSegmentIndex(file, args.seededIndex, read);
|
|
4561
|
+
if (resolved === null) return null;
|
|
4562
|
+
const { head, init, videoIndex } = resolved;
|
|
4563
|
+
const offsetTicks = msToTicks(Math.max(0, args.epochMs - args.segmentStartMs), init.videoTimescale);
|
|
4469
4564
|
let start;
|
|
4470
4565
|
let end;
|
|
4471
4566
|
let firstSampleIndex;
|
|
@@ -4510,6 +4605,49 @@ async function readGopRange(file, args) {
|
|
|
4510
4605
|
};
|
|
4511
4606
|
}
|
|
4512
4607
|
/**
|
|
4608
|
+
* Read the fragments covering `[fromMs, toMs)` from `file`, by byte range —
|
|
4609
|
+
* the WINDOW twin of {@link readGopRange}'s single instant. Same shape, same
|
|
4610
|
+
* standalone-demuxable `ftyp`+`moov` head, same `null`-on-unparseable
|
|
4611
|
+
* contract; the only difference is the stop condition
|
|
4612
|
+
* ({@link fragmentsInWindow} instead of {@link fragmentRangeFor} /
|
|
4613
|
+
* {@link fragmentsWithinBudget}).
|
|
4614
|
+
*/
|
|
4615
|
+
async function readGopWindowRange(file, args) {
|
|
4616
|
+
let bytesRead = 0;
|
|
4617
|
+
const read = async (offset, length) => {
|
|
4618
|
+
const chunk = await file.read(offset, length);
|
|
4619
|
+
bytesRead += chunk.length;
|
|
4620
|
+
return chunk;
|
|
4621
|
+
};
|
|
4622
|
+
const resolved = await resolveSegmentIndex(file, args.seededIndex, read);
|
|
4623
|
+
if (resolved === null) return null;
|
|
4624
|
+
const { head, init, videoIndex } = resolved;
|
|
4625
|
+
const fromOffsetMs = Math.max(0, args.fromMs - args.segmentStartMs);
|
|
4626
|
+
const toOffsetMs = Math.max(fromOffsetMs, args.toMs - args.segmentStartMs);
|
|
4627
|
+
const plan = fragmentsInWindow(videoIndex, msToTicks(fromOffsetMs, init.videoTimescale), msToTicks(toOffsetMs, init.videoTimescale), args.maxBytes);
|
|
4628
|
+
const { start, end } = plan;
|
|
4629
|
+
if (start <= 0 || end <= start || end > file.size) return null;
|
|
4630
|
+
const fragment = await read(start, end - start);
|
|
4631
|
+
const firstSampleIndex = plan.fragments[0].sampleIndex;
|
|
4632
|
+
const lastSampleIndex = plan.fragments[plan.fragments.length - 1].sampleIndex;
|
|
4633
|
+
const startTicks = videoIndex.samples[firstSampleIndex]?.timeTicks ?? 0;
|
|
4634
|
+
const nextTicks = videoIndex.samples[lastSampleIndex + 1]?.timeTicks;
|
|
4635
|
+
const gopStartOffsetMs = ticksToMs(startTicks, init.videoTimescale);
|
|
4636
|
+
const gopDurMs = nextTicks !== void 0 ? ticksToMs(nextTicks - startTicks, init.videoTimescale) : Math.max(1, args.segmentDurMs - gopStartOffsetMs);
|
|
4637
|
+
const data = new Uint8Array(head.length + fragment.length);
|
|
4638
|
+
data.set(head, 0);
|
|
4639
|
+
data.set(fragment, head.length);
|
|
4640
|
+
return {
|
|
4641
|
+
data,
|
|
4642
|
+
gopStartMs: args.segmentStartMs + gopStartOffsetMs,
|
|
4643
|
+
gopDurMs,
|
|
4644
|
+
bytesRead,
|
|
4645
|
+
reachesSegmentEnd: plan.reachesSegmentEnd,
|
|
4646
|
+
reachesWindowEnd: plan.reachesWindowEnd,
|
|
4647
|
+
oversizeFragment: plan.oversizeFragment
|
|
4648
|
+
};
|
|
4649
|
+
}
|
|
4650
|
+
/**
|
|
4513
4651
|
* Fetch + parse the `mfra` tail, honouring `MfraParseError.needBytes` with ONE
|
|
4514
4652
|
* widened retry. Null on anything else — bytes that are not a segment.
|
|
4515
4653
|
*/
|
|
@@ -4801,6 +4939,16 @@ var RANGE_MERGE_GAP_MS = 5e3;
|
|
|
4801
4939
|
* hour but covers the requested epoch is hydrated too. Recorder segments are
|
|
4802
4940
|
* currently much shorter; the margin keeps this boundary future-safe. */
|
|
4803
4941
|
var LOCATE_HYDRATE_MARGIN_MS = 6e4;
|
|
4942
|
+
/**
|
|
4943
|
+
* Safety ceiling for one `readWindowBytes` answer — NOT the primary stop
|
|
4944
|
+
* condition (the requested `toMs` is; see `fragmentsInWindow` in
|
|
4945
|
+
* `mfra-index.ts`). Sized off `high`'s own bandwidth hint above
|
|
4946
|
+
* (`PROFILE_BANDWIDTH.high` = 4 Mbps = 500 000 B/s): a 30 s replay window at
|
|
4947
|
+
* that rate is ~15 MB, so 20 MB covers it with headroom while still bounding
|
|
4948
|
+
* a pathological request. A window this call actually truncates is reported
|
|
4949
|
+
* (`reachesRequestedEnd: false`) rather than silently shortened.
|
|
4950
|
+
*/
|
|
4951
|
+
var WINDOW_READ_MAX_BYTES = 2e7;
|
|
4804
4952
|
/** Empty "no playback" manifest. */
|
|
4805
4953
|
function noPlayback(deviceId) {
|
|
4806
4954
|
return {
|
|
@@ -5318,6 +5466,76 @@ function buildRecordingProvider(deps) {
|
|
|
5318
5466
|
gopDurMs: seg.durMs
|
|
5319
5467
|
};
|
|
5320
5468
|
},
|
|
5469
|
+
readWindowBytes: async ({ deviceId, profile, startMs, fromMs, toMs }) => {
|
|
5470
|
+
const { abs, seg } = resolveSegmentFile(deps, deviceId, profile, startMs);
|
|
5471
|
+
const segmentEndMs = seg.startMs + seg.durMs;
|
|
5472
|
+
if (toMs > segmentEndMs) {
|
|
5473
|
+
deps.logger.warn("recording: readWindowBytes refused — window runs past this segment, not silently clipped", {
|
|
5474
|
+
tags: { deviceId },
|
|
5475
|
+
meta: {
|
|
5476
|
+
profile,
|
|
5477
|
+
startMs,
|
|
5478
|
+
fromMs,
|
|
5479
|
+
toMs,
|
|
5480
|
+
segmentEndMs
|
|
5481
|
+
}
|
|
5482
|
+
});
|
|
5483
|
+
return {
|
|
5484
|
+
kind: "spans-multiple-segments",
|
|
5485
|
+
segmentEndMs
|
|
5486
|
+
};
|
|
5487
|
+
}
|
|
5488
|
+
const file = await (deps.openRangeReadable ?? openRangeFromDisk)(abs, seg.bytes);
|
|
5489
|
+
try {
|
|
5490
|
+
const gop = await readGopWindowRange(file, {
|
|
5491
|
+
segmentStartMs: seg.startMs,
|
|
5492
|
+
segmentDurMs: seg.durMs,
|
|
5493
|
+
fromMs,
|
|
5494
|
+
toMs,
|
|
5495
|
+
seededIndex: deps.mfraFor?.(deviceId, profile, startMs),
|
|
5496
|
+
maxBytes: WINDOW_READ_MAX_BYTES
|
|
5497
|
+
});
|
|
5498
|
+
if (gop !== null) {
|
|
5499
|
+
if (gop.reachesWindowEnd !== true) deps.logger.warn("recording: readWindowBytes truncated by its safety byte cap before covering the requested window", {
|
|
5500
|
+
tags: { deviceId },
|
|
5501
|
+
meta: {
|
|
5502
|
+
profile,
|
|
5503
|
+
startMs,
|
|
5504
|
+
fromMs,
|
|
5505
|
+
toMs,
|
|
5506
|
+
bytes: gop.data.length,
|
|
5507
|
+
WINDOW_READ_MAX_BYTES
|
|
5508
|
+
}
|
|
5509
|
+
});
|
|
5510
|
+
return {
|
|
5511
|
+
kind: "ok",
|
|
5512
|
+
data: gop.data,
|
|
5513
|
+
gopStartMs: gop.gopStartMs,
|
|
5514
|
+
gopDurMs: gop.gopDurMs,
|
|
5515
|
+
reachesRequestedEnd: gop.reachesWindowEnd === true
|
|
5516
|
+
};
|
|
5517
|
+
}
|
|
5518
|
+
} finally {
|
|
5519
|
+
await file.close();
|
|
5520
|
+
}
|
|
5521
|
+
deps.logger.warn("recording: readWindowBytes fell back to the WHOLE segment (mfra/moov unparseable)", {
|
|
5522
|
+
tags: { deviceId },
|
|
5523
|
+
meta: {
|
|
5524
|
+
profile,
|
|
5525
|
+
startMs,
|
|
5526
|
+
fromMs,
|
|
5527
|
+
toMs
|
|
5528
|
+
}
|
|
5529
|
+
});
|
|
5530
|
+
const data = await readFile(abs);
|
|
5531
|
+
return {
|
|
5532
|
+
kind: "ok",
|
|
5533
|
+
data: Uint8Array.from(data),
|
|
5534
|
+
gopStartMs: seg.startMs,
|
|
5535
|
+
gopDurMs: seg.durMs,
|
|
5536
|
+
reachesRequestedEnd: true
|
|
5537
|
+
};
|
|
5538
|
+
},
|
|
5321
5539
|
setDeviceConfig: async ({ deviceId, config }) => {
|
|
5322
5540
|
const saved = await saveDeviceConfig(deps.configStore, deviceId, config);
|
|
5323
5541
|
if (deps.onConfigChanged) try {
|
package/dist/recorder/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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-
|
|
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-BZYUUBUx.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";
|
|
@@ -349,8 +349,13 @@ function fragmentRangeFor(index, offsetTicks) {
|
|
|
349
349
|
* "nothing to read" (D49's letter, applied to a byte budget: a fallible
|
|
350
350
|
* computation must never silently look like an unbind).
|
|
351
351
|
*/
|
|
352
|
-
|
|
353
|
-
|
|
352
|
+
/**
|
|
353
|
+
* The last sync sample at or before `offsetTicks` — the keyframe a decoder
|
|
354
|
+
* must start from. Shared by {@link fragmentsWithinBudget} and
|
|
355
|
+
* {@link fragmentsInWindow}: both walk forward from the same anchor, they
|
|
356
|
+
* only differ in the condition that stops the walk.
|
|
357
|
+
*/
|
|
358
|
+
function findAnchor(samples, offsetTicks) {
|
|
354
359
|
let lo = 0;
|
|
355
360
|
let hi = samples.length - 1;
|
|
356
361
|
let anchor = 0;
|
|
@@ -363,6 +368,11 @@ function fragmentsWithinBudget(index, offsetTicks, maxBytes) {
|
|
|
363
368
|
lo = mid + 1;
|
|
364
369
|
} else hi = mid - 1;
|
|
365
370
|
}
|
|
371
|
+
return anchor;
|
|
372
|
+
}
|
|
373
|
+
function fragmentsWithinBudget(index, offsetTicks, maxBytes) {
|
|
374
|
+
const { samples, mfraOffset } = index;
|
|
375
|
+
const anchor = findAnchor(samples, offsetTicks);
|
|
366
376
|
const endOf = (i) => samples[i + 1]?.moofOffset ?? mfraOffset;
|
|
367
377
|
const anchorStart = samples[anchor]?.moofOffset ?? 0;
|
|
368
378
|
const anchorEnd = endOf(anchor);
|
|
@@ -399,6 +409,70 @@ function fragmentsWithinBudget(index, offsetTicks, maxBytes) {
|
|
|
399
409
|
oversizeFragment
|
|
400
410
|
};
|
|
401
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* Convert a TIME WINDOW `[fromTicks, toTicks)` into the set of consecutive
|
|
414
|
+
* fragments that covers it — the replay's primitive for "give me this many
|
|
415
|
+
* seconds of one segment", as opposed to {@link fragmentsWithinBudget}'s
|
|
416
|
+
* "give me as much as fits in N bytes" (the scrub GOP read's primitive).
|
|
417
|
+
*
|
|
418
|
+
* Stops walking forward the instant the NEXT fragment's own start time
|
|
419
|
+
* already reaches `toTicks`: at that point the fragments already collected
|
|
420
|
+
* cover the whole window, because each fragment's coverage runs up to the
|
|
421
|
+
* next one's start (the same relationship {@link fragmentsWithinBudget}'s
|
|
422
|
+
* `endOf` encodes). `maxBytes` is a SAFETY CEILING, not the primary stop
|
|
423
|
+
* condition — a caller with a well-formed window is expected to hit the time
|
|
424
|
+
* condition first; the byte cap exists so a pathological request cannot pull
|
|
425
|
+
* an unbounded amount of one segment into memory.
|
|
426
|
+
*
|
|
427
|
+
* Same never-empty guarantee as {@link fragmentsWithinBudget}: the anchor
|
|
428
|
+
* fragment is always returned, even when it alone exceeds `maxBytes`.
|
|
429
|
+
*/
|
|
430
|
+
function fragmentsInWindow(index, fromTicks, toTicks, maxBytes) {
|
|
431
|
+
const { samples, mfraOffset } = index;
|
|
432
|
+
const anchor = findAnchor(samples, fromTicks);
|
|
433
|
+
const endOf = (i) => samples[i + 1]?.moofOffset ?? mfraOffset;
|
|
434
|
+
const windowCoveredAt = (i) => {
|
|
435
|
+
const next = samples[i + 1];
|
|
436
|
+
return next === void 0 || next.timeTicks >= toTicks;
|
|
437
|
+
};
|
|
438
|
+
const anchorStart = samples[anchor]?.moofOffset ?? 0;
|
|
439
|
+
const anchorEnd = endOf(anchor);
|
|
440
|
+
const fragments = [{
|
|
441
|
+
start: anchorStart,
|
|
442
|
+
end: anchorEnd,
|
|
443
|
+
sampleIndex: anchor
|
|
444
|
+
}];
|
|
445
|
+
let total = anchorEnd - anchorStart;
|
|
446
|
+
const oversizeFragment = total > maxBytes;
|
|
447
|
+
let i = anchor;
|
|
448
|
+
let reachesWindowEnd = windowCoveredAt(i);
|
|
449
|
+
while (!reachesWindowEnd) {
|
|
450
|
+
const nextIndex = i + 1;
|
|
451
|
+
const nextSample = samples[nextIndex];
|
|
452
|
+
if (nextSample === void 0) break;
|
|
453
|
+
const nextStart = nextSample.moofOffset;
|
|
454
|
+
const nextEnd = endOf(nextIndex);
|
|
455
|
+
const nextSize = nextEnd - nextStart;
|
|
456
|
+
if (total + nextSize > maxBytes) break;
|
|
457
|
+
fragments.push({
|
|
458
|
+
start: nextStart,
|
|
459
|
+
end: nextEnd,
|
|
460
|
+
sampleIndex: nextIndex
|
|
461
|
+
});
|
|
462
|
+
total += nextSize;
|
|
463
|
+
i = nextIndex;
|
|
464
|
+
reachesWindowEnd = windowCoveredAt(i);
|
|
465
|
+
}
|
|
466
|
+
const last = fragments[fragments.length - 1];
|
|
467
|
+
return {
|
|
468
|
+
fragments,
|
|
469
|
+
start: fragments[0].start,
|
|
470
|
+
end: last.end,
|
|
471
|
+
reachesSegmentEnd: last.end >= mfraOffset,
|
|
472
|
+
reachesWindowEnd,
|
|
473
|
+
oversizeFragment
|
|
474
|
+
};
|
|
475
|
+
}
|
|
402
476
|
//#endregion
|
|
403
477
|
//#region src/recorder/mfra-capture.ts
|
|
404
478
|
/**
|
|
@@ -4438,6 +4512,34 @@ var SCRUB_GOP_BUDGET_MAX_BYTES = 15e5;
|
|
|
4438
4512
|
function ticksToMs(ticks, timescale) {
|
|
4439
4513
|
return Math.round(ticks / timescale * 1e3);
|
|
4440
4514
|
}
|
|
4515
|
+
/** ms → ticks on the video timescale — the inverse of {@link ticksToMs}. */
|
|
4516
|
+
function msToTicks(ms, timescale) {
|
|
4517
|
+
return ms / 1e3 * timescale;
|
|
4518
|
+
}
|
|
4519
|
+
/**
|
|
4520
|
+
* Steps 1-2 shared by {@link readGopRange} and {@link readGopWindowRange}:
|
|
4521
|
+
* locate the `mfra` (seeded or from the tail), read the `ftyp`+`moov` head,
|
|
4522
|
+
* and pick the VIDEO track's sync table (never the audio one, which lists
|
|
4523
|
+
* every `moof` and would send a seek to bytes that do not open a GOP).
|
|
4524
|
+
* `null` on anything that does not look like a recorded segment.
|
|
4525
|
+
*/
|
|
4526
|
+
async function resolveSegmentIndex(file, seededIndex, read) {
|
|
4527
|
+
const parsed = seededIndex === void 0 ? await parseTail(file, read) : null;
|
|
4528
|
+
if (seededIndex === void 0 && parsed === null) return null;
|
|
4529
|
+
const index = seededIndex ?? parsed.index;
|
|
4530
|
+
const firstMoof = index.samples[0]?.moofOffset ?? 0;
|
|
4531
|
+
if (firstMoof <= 0 || firstMoof >= file.size) return null;
|
|
4532
|
+
const head = await read(0, firstMoof);
|
|
4533
|
+
const init = parseInitInfo(head);
|
|
4534
|
+
if (init === null) return null;
|
|
4535
|
+
const videoIndex = index.trackId === init.videoTrackId ? index : parsed === null ? null : reparseTail(parsed.tail, file.size, init.videoTrackId);
|
|
4536
|
+
if (videoIndex === null) return null;
|
|
4537
|
+
return {
|
|
4538
|
+
head,
|
|
4539
|
+
init,
|
|
4540
|
+
videoIndex
|
|
4541
|
+
};
|
|
4542
|
+
}
|
|
4441
4543
|
/**
|
|
4442
4544
|
* Read the single GOP covering `epochMs` from `file`, by byte range.
|
|
4443
4545
|
*
|
|
@@ -4453,17 +4555,10 @@ async function readGopRange(file, args) {
|
|
|
4453
4555
|
bytesRead += chunk.length;
|
|
4454
4556
|
return chunk;
|
|
4455
4557
|
};
|
|
4456
|
-
const
|
|
4457
|
-
if (
|
|
4458
|
-
const
|
|
4459
|
-
const
|
|
4460
|
-
if (firstMoof <= 0 || firstMoof >= file.size) return null;
|
|
4461
|
-
const head = await read(0, firstMoof);
|
|
4462
|
-
const init = parseInitInfo(head);
|
|
4463
|
-
if (init === null) return null;
|
|
4464
|
-
const videoIndex = index.trackId === init.videoTrackId ? index : parsed === null ? null : reparseTail(parsed.tail, file.size, init.videoTrackId);
|
|
4465
|
-
if (videoIndex === null) return null;
|
|
4466
|
-
const offsetTicks = Math.max(0, args.epochMs - args.segmentStartMs) / 1e3 * init.videoTimescale;
|
|
4558
|
+
const resolved = await resolveSegmentIndex(file, args.seededIndex, read);
|
|
4559
|
+
if (resolved === null) return null;
|
|
4560
|
+
const { head, init, videoIndex } = resolved;
|
|
4561
|
+
const offsetTicks = msToTicks(Math.max(0, args.epochMs - args.segmentStartMs), init.videoTimescale);
|
|
4467
4562
|
let start;
|
|
4468
4563
|
let end;
|
|
4469
4564
|
let firstSampleIndex;
|
|
@@ -4508,6 +4603,49 @@ async function readGopRange(file, args) {
|
|
|
4508
4603
|
};
|
|
4509
4604
|
}
|
|
4510
4605
|
/**
|
|
4606
|
+
* Read the fragments covering `[fromMs, toMs)` from `file`, by byte range —
|
|
4607
|
+
* the WINDOW twin of {@link readGopRange}'s single instant. Same shape, same
|
|
4608
|
+
* standalone-demuxable `ftyp`+`moov` head, same `null`-on-unparseable
|
|
4609
|
+
* contract; the only difference is the stop condition
|
|
4610
|
+
* ({@link fragmentsInWindow} instead of {@link fragmentRangeFor} /
|
|
4611
|
+
* {@link fragmentsWithinBudget}).
|
|
4612
|
+
*/
|
|
4613
|
+
async function readGopWindowRange(file, args) {
|
|
4614
|
+
let bytesRead = 0;
|
|
4615
|
+
const read = async (offset, length) => {
|
|
4616
|
+
const chunk = await file.read(offset, length);
|
|
4617
|
+
bytesRead += chunk.length;
|
|
4618
|
+
return chunk;
|
|
4619
|
+
};
|
|
4620
|
+
const resolved = await resolveSegmentIndex(file, args.seededIndex, read);
|
|
4621
|
+
if (resolved === null) return null;
|
|
4622
|
+
const { head, init, videoIndex } = resolved;
|
|
4623
|
+
const fromOffsetMs = Math.max(0, args.fromMs - args.segmentStartMs);
|
|
4624
|
+
const toOffsetMs = Math.max(fromOffsetMs, args.toMs - args.segmentStartMs);
|
|
4625
|
+
const plan = fragmentsInWindow(videoIndex, msToTicks(fromOffsetMs, init.videoTimescale), msToTicks(toOffsetMs, init.videoTimescale), args.maxBytes);
|
|
4626
|
+
const { start, end } = plan;
|
|
4627
|
+
if (start <= 0 || end <= start || end > file.size) return null;
|
|
4628
|
+
const fragment = await read(start, end - start);
|
|
4629
|
+
const firstSampleIndex = plan.fragments[0].sampleIndex;
|
|
4630
|
+
const lastSampleIndex = plan.fragments[plan.fragments.length - 1].sampleIndex;
|
|
4631
|
+
const startTicks = videoIndex.samples[firstSampleIndex]?.timeTicks ?? 0;
|
|
4632
|
+
const nextTicks = videoIndex.samples[lastSampleIndex + 1]?.timeTicks;
|
|
4633
|
+
const gopStartOffsetMs = ticksToMs(startTicks, init.videoTimescale);
|
|
4634
|
+
const gopDurMs = nextTicks !== void 0 ? ticksToMs(nextTicks - startTicks, init.videoTimescale) : Math.max(1, args.segmentDurMs - gopStartOffsetMs);
|
|
4635
|
+
const data = new Uint8Array(head.length + fragment.length);
|
|
4636
|
+
data.set(head, 0);
|
|
4637
|
+
data.set(fragment, head.length);
|
|
4638
|
+
return {
|
|
4639
|
+
data,
|
|
4640
|
+
gopStartMs: args.segmentStartMs + gopStartOffsetMs,
|
|
4641
|
+
gopDurMs,
|
|
4642
|
+
bytesRead,
|
|
4643
|
+
reachesSegmentEnd: plan.reachesSegmentEnd,
|
|
4644
|
+
reachesWindowEnd: plan.reachesWindowEnd,
|
|
4645
|
+
oversizeFragment: plan.oversizeFragment
|
|
4646
|
+
};
|
|
4647
|
+
}
|
|
4648
|
+
/**
|
|
4511
4649
|
* Fetch + parse the `mfra` tail, honouring `MfraParseError.needBytes` with ONE
|
|
4512
4650
|
* widened retry. Null on anything else — bytes that are not a segment.
|
|
4513
4651
|
*/
|
|
@@ -4799,6 +4937,16 @@ var RANGE_MERGE_GAP_MS = 5e3;
|
|
|
4799
4937
|
* hour but covers the requested epoch is hydrated too. Recorder segments are
|
|
4800
4938
|
* currently much shorter; the margin keeps this boundary future-safe. */
|
|
4801
4939
|
var LOCATE_HYDRATE_MARGIN_MS = 6e4;
|
|
4940
|
+
/**
|
|
4941
|
+
* Safety ceiling for one `readWindowBytes` answer — NOT the primary stop
|
|
4942
|
+
* condition (the requested `toMs` is; see `fragmentsInWindow` in
|
|
4943
|
+
* `mfra-index.ts`). Sized off `high`'s own bandwidth hint above
|
|
4944
|
+
* (`PROFILE_BANDWIDTH.high` = 4 Mbps = 500 000 B/s): a 30 s replay window at
|
|
4945
|
+
* that rate is ~15 MB, so 20 MB covers it with headroom while still bounding
|
|
4946
|
+
* a pathological request. A window this call actually truncates is reported
|
|
4947
|
+
* (`reachesRequestedEnd: false`) rather than silently shortened.
|
|
4948
|
+
*/
|
|
4949
|
+
var WINDOW_READ_MAX_BYTES = 2e7;
|
|
4802
4950
|
/** Empty "no playback" manifest. */
|
|
4803
4951
|
function noPlayback(deviceId) {
|
|
4804
4952
|
return {
|
|
@@ -5316,6 +5464,76 @@ function buildRecordingProvider(deps) {
|
|
|
5316
5464
|
gopDurMs: seg.durMs
|
|
5317
5465
|
};
|
|
5318
5466
|
},
|
|
5467
|
+
readWindowBytes: async ({ deviceId, profile, startMs, fromMs, toMs }) => {
|
|
5468
|
+
const { abs, seg } = resolveSegmentFile(deps, deviceId, profile, startMs);
|
|
5469
|
+
const segmentEndMs = seg.startMs + seg.durMs;
|
|
5470
|
+
if (toMs > segmentEndMs) {
|
|
5471
|
+
deps.logger.warn("recording: readWindowBytes refused — window runs past this segment, not silently clipped", {
|
|
5472
|
+
tags: { deviceId },
|
|
5473
|
+
meta: {
|
|
5474
|
+
profile,
|
|
5475
|
+
startMs,
|
|
5476
|
+
fromMs,
|
|
5477
|
+
toMs,
|
|
5478
|
+
segmentEndMs
|
|
5479
|
+
}
|
|
5480
|
+
});
|
|
5481
|
+
return {
|
|
5482
|
+
kind: "spans-multiple-segments",
|
|
5483
|
+
segmentEndMs
|
|
5484
|
+
};
|
|
5485
|
+
}
|
|
5486
|
+
const file = await (deps.openRangeReadable ?? openRangeFromDisk)(abs, seg.bytes);
|
|
5487
|
+
try {
|
|
5488
|
+
const gop = await readGopWindowRange(file, {
|
|
5489
|
+
segmentStartMs: seg.startMs,
|
|
5490
|
+
segmentDurMs: seg.durMs,
|
|
5491
|
+
fromMs,
|
|
5492
|
+
toMs,
|
|
5493
|
+
seededIndex: deps.mfraFor?.(deviceId, profile, startMs),
|
|
5494
|
+
maxBytes: WINDOW_READ_MAX_BYTES
|
|
5495
|
+
});
|
|
5496
|
+
if (gop !== null) {
|
|
5497
|
+
if (gop.reachesWindowEnd !== true) deps.logger.warn("recording: readWindowBytes truncated by its safety byte cap before covering the requested window", {
|
|
5498
|
+
tags: { deviceId },
|
|
5499
|
+
meta: {
|
|
5500
|
+
profile,
|
|
5501
|
+
startMs,
|
|
5502
|
+
fromMs,
|
|
5503
|
+
toMs,
|
|
5504
|
+
bytes: gop.data.length,
|
|
5505
|
+
WINDOW_READ_MAX_BYTES
|
|
5506
|
+
}
|
|
5507
|
+
});
|
|
5508
|
+
return {
|
|
5509
|
+
kind: "ok",
|
|
5510
|
+
data: gop.data,
|
|
5511
|
+
gopStartMs: gop.gopStartMs,
|
|
5512
|
+
gopDurMs: gop.gopDurMs,
|
|
5513
|
+
reachesRequestedEnd: gop.reachesWindowEnd === true
|
|
5514
|
+
};
|
|
5515
|
+
}
|
|
5516
|
+
} finally {
|
|
5517
|
+
await file.close();
|
|
5518
|
+
}
|
|
5519
|
+
deps.logger.warn("recording: readWindowBytes fell back to the WHOLE segment (mfra/moov unparseable)", {
|
|
5520
|
+
tags: { deviceId },
|
|
5521
|
+
meta: {
|
|
5522
|
+
profile,
|
|
5523
|
+
startMs,
|
|
5524
|
+
fromMs,
|
|
5525
|
+
toMs
|
|
5526
|
+
}
|
|
5527
|
+
});
|
|
5528
|
+
const data = await readFile(abs);
|
|
5529
|
+
return {
|
|
5530
|
+
kind: "ok",
|
|
5531
|
+
data: Uint8Array.from(data),
|
|
5532
|
+
gopStartMs: seg.startMs,
|
|
5533
|
+
gopDurMs: seg.durMs,
|
|
5534
|
+
reachesRequestedEnd: true
|
|
5535
|
+
};
|
|
5536
|
+
},
|
|
5319
5537
|
setDeviceConfig: async ({ deviceId, config }) => {
|
|
5320
5538
|
const saved = await saveDeviceConfig(deps.configStore, deviceId, config);
|
|
5321
5539
|
if (deps.onConfigChanged) try {
|
|
@@ -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-BZYUUBUx.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-DBP47QOz.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-C3zaz0Jv.js");
|
|
3
|
+
const require_lazy_sharp = require("../lazy-sharp-B_kETjyQ.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-Cut8984B.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-BUw_aTfK.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-DXKTNEae.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.34",
|
|
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.112",
|
|
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.75",
|
|
37
37
|
scope: ["default"],
|
|
38
38
|
loaded: !1,
|
|
39
39
|
from: "addon_stream_broker_widgets",
|