@camstack/addon-pipeline 1.2.58 → 1.2.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/stream-broker/index.js +59 -28
- package/dist/stream-broker/index.mjs +59 -28
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-Bxm34WFr.js → MaskShapeCanvas-DI4BY7W2-BWAtF7b-.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-S8uFj2nP.js → MotionZonesSettings-NcxxQN8r-ByQWV87C.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-nhHVCSoL.js → PrivacyMaskSettings-APgPLF7p-B9uGNcFR.js} +1 -1
- package/embed-dist/assets/{index-hICPL_hd.js → index-Dcfe-5Ig.js} +4 -4
- package/embed-dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -21718,21 +21718,32 @@ function clampPlaybackRate(rate) {
|
|
|
21718
21718
|
if (!Number.isFinite(rate) || rate <= 0) return 0;
|
|
21719
21719
|
return Math.min(4, Math.max(.25, rate));
|
|
21720
21720
|
}
|
|
21721
|
-
var ServerMessageSchema = require_dist.discriminatedUnion("t", [
|
|
21722
|
-
|
|
21723
|
-
|
|
21724
|
-
|
|
21725
|
-
|
|
21726
|
-
|
|
21727
|
-
|
|
21728
|
-
|
|
21729
|
-
|
|
21730
|
-
|
|
21731
|
-
|
|
21732
|
-
|
|
21733
|
-
|
|
21734
|
-
|
|
21735
|
-
|
|
21721
|
+
var ServerMessageSchema = require_dist.discriminatedUnion("t", [
|
|
21722
|
+
require_dist.object({
|
|
21723
|
+
t: require_dist.literal("state"),
|
|
21724
|
+
state: require_dist._enum([
|
|
21725
|
+
"live",
|
|
21726
|
+
"loading",
|
|
21727
|
+
"playing",
|
|
21728
|
+
"paused",
|
|
21729
|
+
"gap",
|
|
21730
|
+
"ended",
|
|
21731
|
+
"error"
|
|
21732
|
+
])
|
|
21733
|
+
}),
|
|
21734
|
+
require_dist.object({
|
|
21735
|
+
t: require_dist.literal("position"),
|
|
21736
|
+
epochMs: require_dist.number()
|
|
21737
|
+
}),
|
|
21738
|
+
require_dist.object({
|
|
21739
|
+
t: require_dist.literal("liveProfile"),
|
|
21740
|
+
profile: require_dist._enum([
|
|
21741
|
+
"high",
|
|
21742
|
+
"mid",
|
|
21743
|
+
"low"
|
|
21744
|
+
])
|
|
21745
|
+
})
|
|
21746
|
+
]);
|
|
21736
21747
|
function parseControlMessage(raw) {
|
|
21737
21748
|
try {
|
|
21738
21749
|
const parsed = ControlMessageSchema.safeParse(JSON.parse(raw));
|
|
@@ -22071,7 +22082,7 @@ var SEEK_DISCONTINUITY_MS = 250;
|
|
|
22071
22082
|
* sustainable there — cross-fragment moves remain paced by the demux + the
|
|
22072
22083
|
* one-in-flight guard, so this cannot spawn parallel demuxes.
|
|
22073
22084
|
*/
|
|
22074
|
-
var SCRUB_COALESCE_MS =
|
|
22085
|
+
var SCRUB_COALESCE_MS = 33;
|
|
22075
22086
|
/**
|
|
22076
22087
|
* How much forward slack two fragments may have and still count as ADJACENT
|
|
22077
22088
|
* for sweep continuity. Two real cases live inside it: the ±1 ms rounding of a
|
|
@@ -23608,6 +23619,12 @@ var TimelineSession = class {
|
|
|
23608
23619
|
mode = "live";
|
|
23609
23620
|
feeder = null;
|
|
23610
23621
|
profile = "mid";
|
|
23622
|
+
/** Transport rate belongs to the session, not to one profile-specific feeder.
|
|
23623
|
+
* Scrub pins `low`; release restores the selected playback profile and may
|
|
23624
|
+
* therefore rebuild the feeder. Carrying the rate keeps a paused scrub
|
|
23625
|
+
* paused across that required quality transition. */
|
|
23626
|
+
rate = 1;
|
|
23627
|
+
liveProfileReported = false;
|
|
23611
23628
|
/**
|
|
23612
23629
|
* The last position the viewer was SHOWN (every `_emitPosition`). Handed to
|
|
23613
23630
|
* `seek` as `travelFromMs` so the seek travel animation works across feeder
|
|
@@ -23631,6 +23648,7 @@ var TimelineSession = class {
|
|
|
23631
23648
|
return this.mode;
|
|
23632
23649
|
}
|
|
23633
23650
|
async handleControl(msg) {
|
|
23651
|
+
this.emitLiveProfile();
|
|
23634
23652
|
switch (msg.t) {
|
|
23635
23653
|
case "playRecorded": {
|
|
23636
23654
|
const profileChanged = msg.profile !== this.profile;
|
|
@@ -23659,6 +23677,7 @@ var TimelineSession = class {
|
|
|
23659
23677
|
if (this.mode === "recorded") this.feeder?.scrubAck();
|
|
23660
23678
|
break;
|
|
23661
23679
|
case "setRate":
|
|
23680
|
+
this.rate = msg.rate;
|
|
23662
23681
|
this.feeder?.setRate(msg.rate);
|
|
23663
23682
|
break;
|
|
23664
23683
|
case "stepFrame":
|
|
@@ -23683,6 +23702,7 @@ var TimelineSession = class {
|
|
|
23683
23702
|
this.deps.session.setLiveFeedGate(true);
|
|
23684
23703
|
this.mode = "recorded";
|
|
23685
23704
|
const feeder = this.deps.makeFeeder(this.profile);
|
|
23705
|
+
if (this.rate !== 1) feeder.setRate(this.rate);
|
|
23686
23706
|
this.feeder = feeder;
|
|
23687
23707
|
return feeder;
|
|
23688
23708
|
}
|
|
@@ -23710,6 +23730,14 @@ var TimelineSession = class {
|
|
|
23710
23730
|
epochMs
|
|
23711
23731
|
}));
|
|
23712
23732
|
}
|
|
23733
|
+
emitLiveProfile() {
|
|
23734
|
+
if (this.liveProfileReported || this.deps.initialLiveProfile === void 0) return;
|
|
23735
|
+
this.liveProfileReported = true;
|
|
23736
|
+
this.deps.session.sendControl(serializeServerMessage({
|
|
23737
|
+
t: "liveProfile",
|
|
23738
|
+
profile: this.deps.initialLiveProfile
|
|
23739
|
+
}));
|
|
23740
|
+
}
|
|
23713
23741
|
dispose() {
|
|
23714
23742
|
this.feeder?.dispose();
|
|
23715
23743
|
this.feeder = null;
|
|
@@ -31369,8 +31397,8 @@ var ADAPTIVE_CONFIG = {
|
|
|
31369
31397
|
analyzeWindowMs: 15e3,
|
|
31370
31398
|
minFailPercent: .05,
|
|
31371
31399
|
waitAfterResetMs: 8e3,
|
|
31372
|
-
upgradeHealthyMs:
|
|
31373
|
-
minTimeBetweenChangesMs:
|
|
31400
|
+
upgradeHealthyMs: 2e4,
|
|
31401
|
+
minTimeBetweenChangesMs: 2e4,
|
|
31374
31402
|
maxUpgradeBackoffMs: 9e5
|
|
31375
31403
|
};
|
|
31376
31404
|
/**
|
|
@@ -31538,8 +31566,7 @@ function scoreBroker(tier, broker, hints) {
|
|
|
31538
31566
|
const fallback = tier ? LABEL_DEFAULTS[tier] : void 0;
|
|
31539
31567
|
const bitrateKbps = stats.bitrateKbps > 0 ? stats.bitrateKbps : fallback?.bitrateKbps ?? 2e3;
|
|
31540
31568
|
const srcPixels = fallback?.pixels ?? 1920 * 1080;
|
|
31541
|
-
const
|
|
31542
|
-
const targetPixels = (hints.viewportWidth ?? 1920) * dpr * ((hints.viewportHeight ?? 1080) * dpr);
|
|
31569
|
+
const targetPixels = (hints.viewportWidth ?? 1920) * (hints.viewportHeight ?? 1080);
|
|
31543
31570
|
const pixelDistance = Math.abs(srcPixels - targetPixels) / 1e6;
|
|
31544
31571
|
let bandwidthPenalty = 0;
|
|
31545
31572
|
if (hints.downlinkMbps && hints.downlinkMbps > 0 && bitrateKbps > 0) {
|
|
@@ -32284,6 +32311,7 @@ var BrokerWebrtcServer = class {
|
|
|
32284
32311
|
}
|
|
32285
32312
|
});
|
|
32286
32313
|
const scrubCache = new ScrubFragmentCache();
|
|
32314
|
+
const initialLiveProfile = this.profileTierResolver?.(brokerId) ?? null;
|
|
32287
32315
|
const readGopAccessor = this.readRecordedGopBytes;
|
|
32288
32316
|
const readGop = readGopAccessor ? async (args) => {
|
|
32289
32317
|
const res = await readGopAccessor({
|
|
@@ -32303,6 +32331,7 @@ var BrokerWebrtcServer = class {
|
|
|
32303
32331
|
timeline = new TimelineSession({
|
|
32304
32332
|
session,
|
|
32305
32333
|
deviceId,
|
|
32334
|
+
...initialLiveProfile !== null ? { initialLiveProfile } : {},
|
|
32306
32335
|
warm: readGop ? (profile, epochMs) => {
|
|
32307
32336
|
warmFragment({
|
|
32308
32337
|
deviceId,
|
|
@@ -32531,9 +32560,9 @@ var BrokerWebrtcServer = class {
|
|
|
32531
32560
|
* server.
|
|
32532
32561
|
*
|
|
32533
32562
|
* The client-loss % is turned into a monotonic {@link LossSample} LOCALLY:
|
|
32534
|
-
*
|
|
32535
|
-
*
|
|
32536
|
-
*
|
|
32563
|
+
* per-controller cumulative sequence/loss counters advance for every
|
|
32564
|
+
* reported interval (including 0% loss), so a perfectly healthy LAN is real
|
|
32565
|
+
* evidence rather than silence, exactly like RTCP's cumulative fields.
|
|
32537
32566
|
* Both paths feed the same controller; the tracker naturally honours
|
|
32538
32567
|
* whichever produces the higher loss ratio across its window. The async
|
|
32539
32568
|
* poll is guarded against overlapping ticks via `tickInFlight`.
|
|
@@ -32553,7 +32582,8 @@ var BrokerWebrtcServer = class {
|
|
|
32553
32582
|
});
|
|
32554
32583
|
entry.session.onReceiverReport((s) => controller.onLoss(s, Date.now()));
|
|
32555
32584
|
entry.adaptiveController = controller;
|
|
32556
|
-
let
|
|
32585
|
+
let clientHighestSequence = 0;
|
|
32586
|
+
let clientPacketsLost = 0;
|
|
32557
32587
|
let tickInFlight = false;
|
|
32558
32588
|
const CLIENT_LOSS_SPAN = 1e3;
|
|
32559
32589
|
entry.adaptiveTimer = setInterval(() => {
|
|
@@ -32567,11 +32597,12 @@ var BrokerWebrtcServer = class {
|
|
|
32567
32597
|
}
|
|
32568
32598
|
const pct = this.clientLossPct ? await this.clientLossPct(deviceId) : null;
|
|
32569
32599
|
const now = Date.now();
|
|
32570
|
-
if (pct !== null && pct !== void 0
|
|
32571
|
-
|
|
32600
|
+
if (pct !== null && pct !== void 0) {
|
|
32601
|
+
clientHighestSequence += CLIENT_LOSS_SPAN;
|
|
32602
|
+
clientPacketsLost += Math.round(Math.max(0, Math.min(100, pct)) / 100 * CLIENT_LOSS_SPAN);
|
|
32572
32603
|
controller.onLoss({
|
|
32573
|
-
packetsLost:
|
|
32574
|
-
highestSequence:
|
|
32604
|
+
packetsLost: clientPacketsLost,
|
|
32605
|
+
highestSequence: clientHighestSequence
|
|
32575
32606
|
}, now);
|
|
32576
32607
|
}
|
|
32577
32608
|
controller.tick(now);
|
|
@@ -21712,21 +21712,32 @@ function clampPlaybackRate(rate) {
|
|
|
21712
21712
|
if (!Number.isFinite(rate) || rate <= 0) return 0;
|
|
21713
21713
|
return Math.min(4, Math.max(.25, rate));
|
|
21714
21714
|
}
|
|
21715
|
-
var ServerMessageSchema = discriminatedUnion("t", [
|
|
21716
|
-
|
|
21717
|
-
|
|
21718
|
-
|
|
21719
|
-
|
|
21720
|
-
|
|
21721
|
-
|
|
21722
|
-
|
|
21723
|
-
|
|
21724
|
-
|
|
21725
|
-
|
|
21726
|
-
|
|
21727
|
-
|
|
21728
|
-
|
|
21729
|
-
|
|
21715
|
+
var ServerMessageSchema = discriminatedUnion("t", [
|
|
21716
|
+
object({
|
|
21717
|
+
t: literal("state"),
|
|
21718
|
+
state: _enum([
|
|
21719
|
+
"live",
|
|
21720
|
+
"loading",
|
|
21721
|
+
"playing",
|
|
21722
|
+
"paused",
|
|
21723
|
+
"gap",
|
|
21724
|
+
"ended",
|
|
21725
|
+
"error"
|
|
21726
|
+
])
|
|
21727
|
+
}),
|
|
21728
|
+
object({
|
|
21729
|
+
t: literal("position"),
|
|
21730
|
+
epochMs: number()
|
|
21731
|
+
}),
|
|
21732
|
+
object({
|
|
21733
|
+
t: literal("liveProfile"),
|
|
21734
|
+
profile: _enum([
|
|
21735
|
+
"high",
|
|
21736
|
+
"mid",
|
|
21737
|
+
"low"
|
|
21738
|
+
])
|
|
21739
|
+
})
|
|
21740
|
+
]);
|
|
21730
21741
|
function parseControlMessage(raw) {
|
|
21731
21742
|
try {
|
|
21732
21743
|
const parsed = ControlMessageSchema.safeParse(JSON.parse(raw));
|
|
@@ -22065,7 +22076,7 @@ var SEEK_DISCONTINUITY_MS = 250;
|
|
|
22065
22076
|
* sustainable there — cross-fragment moves remain paced by the demux + the
|
|
22066
22077
|
* one-in-flight guard, so this cannot spawn parallel demuxes.
|
|
22067
22078
|
*/
|
|
22068
|
-
var SCRUB_COALESCE_MS =
|
|
22079
|
+
var SCRUB_COALESCE_MS = 33;
|
|
22069
22080
|
/**
|
|
22070
22081
|
* How much forward slack two fragments may have and still count as ADJACENT
|
|
22071
22082
|
* for sweep continuity. Two real cases live inside it: the ±1 ms rounding of a
|
|
@@ -23602,6 +23613,12 @@ var TimelineSession = class {
|
|
|
23602
23613
|
mode = "live";
|
|
23603
23614
|
feeder = null;
|
|
23604
23615
|
profile = "mid";
|
|
23616
|
+
/** Transport rate belongs to the session, not to one profile-specific feeder.
|
|
23617
|
+
* Scrub pins `low`; release restores the selected playback profile and may
|
|
23618
|
+
* therefore rebuild the feeder. Carrying the rate keeps a paused scrub
|
|
23619
|
+
* paused across that required quality transition. */
|
|
23620
|
+
rate = 1;
|
|
23621
|
+
liveProfileReported = false;
|
|
23605
23622
|
/**
|
|
23606
23623
|
* The last position the viewer was SHOWN (every `_emitPosition`). Handed to
|
|
23607
23624
|
* `seek` as `travelFromMs` so the seek travel animation works across feeder
|
|
@@ -23625,6 +23642,7 @@ var TimelineSession = class {
|
|
|
23625
23642
|
return this.mode;
|
|
23626
23643
|
}
|
|
23627
23644
|
async handleControl(msg) {
|
|
23645
|
+
this.emitLiveProfile();
|
|
23628
23646
|
switch (msg.t) {
|
|
23629
23647
|
case "playRecorded": {
|
|
23630
23648
|
const profileChanged = msg.profile !== this.profile;
|
|
@@ -23653,6 +23671,7 @@ var TimelineSession = class {
|
|
|
23653
23671
|
if (this.mode === "recorded") this.feeder?.scrubAck();
|
|
23654
23672
|
break;
|
|
23655
23673
|
case "setRate":
|
|
23674
|
+
this.rate = msg.rate;
|
|
23656
23675
|
this.feeder?.setRate(msg.rate);
|
|
23657
23676
|
break;
|
|
23658
23677
|
case "stepFrame":
|
|
@@ -23677,6 +23696,7 @@ var TimelineSession = class {
|
|
|
23677
23696
|
this.deps.session.setLiveFeedGate(true);
|
|
23678
23697
|
this.mode = "recorded";
|
|
23679
23698
|
const feeder = this.deps.makeFeeder(this.profile);
|
|
23699
|
+
if (this.rate !== 1) feeder.setRate(this.rate);
|
|
23680
23700
|
this.feeder = feeder;
|
|
23681
23701
|
return feeder;
|
|
23682
23702
|
}
|
|
@@ -23704,6 +23724,14 @@ var TimelineSession = class {
|
|
|
23704
23724
|
epochMs
|
|
23705
23725
|
}));
|
|
23706
23726
|
}
|
|
23727
|
+
emitLiveProfile() {
|
|
23728
|
+
if (this.liveProfileReported || this.deps.initialLiveProfile === void 0) return;
|
|
23729
|
+
this.liveProfileReported = true;
|
|
23730
|
+
this.deps.session.sendControl(serializeServerMessage({
|
|
23731
|
+
t: "liveProfile",
|
|
23732
|
+
profile: this.deps.initialLiveProfile
|
|
23733
|
+
}));
|
|
23734
|
+
}
|
|
23707
23735
|
dispose() {
|
|
23708
23736
|
this.feeder?.dispose();
|
|
23709
23737
|
this.feeder = null;
|
|
@@ -31360,8 +31388,8 @@ var ADAPTIVE_CONFIG = {
|
|
|
31360
31388
|
analyzeWindowMs: 15e3,
|
|
31361
31389
|
minFailPercent: .05,
|
|
31362
31390
|
waitAfterResetMs: 8e3,
|
|
31363
|
-
upgradeHealthyMs:
|
|
31364
|
-
minTimeBetweenChangesMs:
|
|
31391
|
+
upgradeHealthyMs: 2e4,
|
|
31392
|
+
minTimeBetweenChangesMs: 2e4,
|
|
31365
31393
|
maxUpgradeBackoffMs: 9e5
|
|
31366
31394
|
};
|
|
31367
31395
|
/**
|
|
@@ -31529,8 +31557,7 @@ function scoreBroker(tier, broker, hints) {
|
|
|
31529
31557
|
const fallback = tier ? LABEL_DEFAULTS[tier] : void 0;
|
|
31530
31558
|
const bitrateKbps = stats.bitrateKbps > 0 ? stats.bitrateKbps : fallback?.bitrateKbps ?? 2e3;
|
|
31531
31559
|
const srcPixels = fallback?.pixels ?? 1920 * 1080;
|
|
31532
|
-
const
|
|
31533
|
-
const targetPixels = (hints.viewportWidth ?? 1920) * dpr * ((hints.viewportHeight ?? 1080) * dpr);
|
|
31560
|
+
const targetPixels = (hints.viewportWidth ?? 1920) * (hints.viewportHeight ?? 1080);
|
|
31534
31561
|
const pixelDistance = Math.abs(srcPixels - targetPixels) / 1e6;
|
|
31535
31562
|
let bandwidthPenalty = 0;
|
|
31536
31563
|
if (hints.downlinkMbps && hints.downlinkMbps > 0 && bitrateKbps > 0) {
|
|
@@ -32275,6 +32302,7 @@ var BrokerWebrtcServer = class {
|
|
|
32275
32302
|
}
|
|
32276
32303
|
});
|
|
32277
32304
|
const scrubCache = new ScrubFragmentCache();
|
|
32305
|
+
const initialLiveProfile = this.profileTierResolver?.(brokerId) ?? null;
|
|
32278
32306
|
const readGopAccessor = this.readRecordedGopBytes;
|
|
32279
32307
|
const readGop = readGopAccessor ? async (args) => {
|
|
32280
32308
|
const res = await readGopAccessor({
|
|
@@ -32294,6 +32322,7 @@ var BrokerWebrtcServer = class {
|
|
|
32294
32322
|
timeline = new TimelineSession({
|
|
32295
32323
|
session,
|
|
32296
32324
|
deviceId,
|
|
32325
|
+
...initialLiveProfile !== null ? { initialLiveProfile } : {},
|
|
32297
32326
|
warm: readGop ? (profile, epochMs) => {
|
|
32298
32327
|
warmFragment({
|
|
32299
32328
|
deviceId,
|
|
@@ -32522,9 +32551,9 @@ var BrokerWebrtcServer = class {
|
|
|
32522
32551
|
* server.
|
|
32523
32552
|
*
|
|
32524
32553
|
* The client-loss % is turned into a monotonic {@link LossSample} LOCALLY:
|
|
32525
|
-
*
|
|
32526
|
-
*
|
|
32527
|
-
*
|
|
32554
|
+
* per-controller cumulative sequence/loss counters advance for every
|
|
32555
|
+
* reported interval (including 0% loss), so a perfectly healthy LAN is real
|
|
32556
|
+
* evidence rather than silence, exactly like RTCP's cumulative fields.
|
|
32528
32557
|
* Both paths feed the same controller; the tracker naturally honours
|
|
32529
32558
|
* whichever produces the higher loss ratio across its window. The async
|
|
32530
32559
|
* poll is guarded against overlapping ticks via `tickInFlight`.
|
|
@@ -32544,7 +32573,8 @@ var BrokerWebrtcServer = class {
|
|
|
32544
32573
|
});
|
|
32545
32574
|
entry.session.onReceiverReport((s) => controller.onLoss(s, Date.now()));
|
|
32546
32575
|
entry.adaptiveController = controller;
|
|
32547
|
-
let
|
|
32576
|
+
let clientHighestSequence = 0;
|
|
32577
|
+
let clientPacketsLost = 0;
|
|
32548
32578
|
let tickInFlight = false;
|
|
32549
32579
|
const CLIENT_LOSS_SPAN = 1e3;
|
|
32550
32580
|
entry.adaptiveTimer = setInterval(() => {
|
|
@@ -32558,11 +32588,12 @@ var BrokerWebrtcServer = class {
|
|
|
32558
32588
|
}
|
|
32559
32589
|
const pct = this.clientLossPct ? await this.clientLossPct(deviceId) : null;
|
|
32560
32590
|
const now = Date.now();
|
|
32561
|
-
if (pct !== null && pct !== void 0
|
|
32562
|
-
|
|
32591
|
+
if (pct !== null && pct !== void 0) {
|
|
32592
|
+
clientHighestSequence += CLIENT_LOSS_SPAN;
|
|
32593
|
+
clientPacketsLost += Math.round(Math.max(0, Math.min(100, pct)) / 100 * CLIENT_LOSS_SPAN);
|
|
32563
32594
|
controller.onLoss({
|
|
32564
|
-
packetsLost:
|
|
32565
|
-
highestSequence:
|
|
32595
|
+
packetsLost: clientPacketsLost,
|
|
32596
|
+
highestSequence: clientHighestSequence
|
|
32566
32597
|
}, now);
|
|
32567
32598
|
}
|
|
32568
32599
|
controller.tick(now);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{d as e,f as t,g as n,h as r,m as i,p as a}from"./index-
|
|
1
|
+
import{d as e,f as t,g as n,h as r,m as i,p as a}from"./index-Dcfe-5Ig.js";var o=n(t()),s=n(e(),1),c=Math.PI/180;function l(){return typeof window<`u`&&({}.toString.call(window)===`[object Window]`||{}.toString.call(window)===`[object global]`)}var u=typeof global<`u`?global:typeof window<`u`?window:typeof WorkerGlobalScope<`u`?self:{},d={_global:u,version:`10.3.0`,isBrowser:l(),isUnminified:/param/.test(function(e){}.toString()),dblClickWindow:400,getAngle(e){return d.angleDeg?e*c:e},enableTrace:!1,pointerEventsEnabled:!0,autoDrawEnabled:!0,hitOnDragEnabled:!1,capturePointerEventsEnabled:!1,_mouseListenClick:!1,_touchListenClick:!1,_pointerListenClick:!1,_mouseInDblClickWindow:!1,_touchInDblClickWindow:!1,_pointerInDblClickWindow:!1,_mouseDblClickPointerId:null,_touchDblClickPointerId:null,_pointerDblClickPointerId:null,_renderBackend:`web`,legacyTextRendering:!1,pixelRatio:typeof window<`u`&&window.devicePixelRatio||1,dragDistance:3,angleDeg:!0,showWarnings:!0,dragButtons:[0,1],isDragging(){return d.DD.isDragging},isTransforming(){return d.Transformer?.isTransforming()??!1},isDragReady(){return!!d.DD.node},releaseCanvasOnDestroy:!0,document:u.document,_injectGlobal(e){u.Konva!==void 0&&console.error(`Several Konva instances detected. It is not recommended to use multiple Konva instances in the same environment.`),u.Konva=e}},f=e=>{d[e.prototype.getClassName()]=e};d._injectGlobal(d);var p=`Konva.js unsupported environment.
|
|
2
2
|
|
|
3
3
|
Looks like you are trying to use Konva.js in Node.js environment. because "document" object is undefined.
|
|
4
4
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,d as n,f as r,g as i,l as a,o,r as s,s as c,u as l}from"./index-
|
|
1
|
+
import{a as e,c as t,d as n,f as r,g as i,l as a,o,r as s,s as c,u as l}from"./index-Dcfe-5Ig.js";import{MaskShapeCanvas as u}from"./MaskShapeCanvas-DI4BY7W2-BWAtF7b-.js";var d=i(r(),1),f=i(n(),1),p=o(`grid-2x2`,[[`path`,{d:`M12 3v18`,key:`108xh3`}],[`path`,{d:`M3 12h18`,key:`1i2n21`}],[`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`,key:`h1oib`}]]),m=110,h=`motion-zones`,g=0,_=[1,2,3],v=1,y=`rounded-md border border-border bg-surface px-2 py-1 text-[11px] font-medium text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,b=`rounded-md border border-primary/50 bg-primary/15 px-2.5 py-1 text-[11px] font-medium text-primary hover:bg-primary/25 disabled:opacity-40 transition-colors`;function x(e,t,n){let r=t*n,i=Array.from({length:r});for(let t=0;t<r;t+=1)i[t]=e[t]===!0;return i}function S(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(e[n]!==t[n])return!1;return!0}function C(e,t){return Math.ceil(e/t)}function w(e,t,n){return Math.min(n-1,Math.floor((e+.5)/t*n))}function T(e,t,n,r){let i=C(t,r),a=C(n,r),o=Array.from({length:i*a},()=>!1);for(let r=0;r<n;r+=1){let s=w(r,n,a);for(let n=0;n<t;n+=1)e[r*t+n]===!0&&(o[s*i+w(n,t,i)]=!0)}return o}function E(e,t,n,r){let i=C(t,r),a=C(n,r),o=Array.from({length:t*n},()=>!1);for(let r=0;r<n;r+=1){let s=w(r,n,a);for(let n=0;n<t;n+=1)o[r*t+n]=e[s*i+w(n,t,i)]===!0}return o}function D({deviceId:n}){let r=t(l().trpcClient,n),[i,o]=(0,d.useState)(null),[w,D]=(0,d.useState)(!1),[O,k]=(0,d.useState)(null),[A,j]=(0,d.useState)(null),[M,N]=(0,d.useState)(v),[P,F]=(0,d.useState)(!1),[I,L]=(0,d.useState)(!1),R=(0,d.useRef)(!1);(0,d.useEffect)(()=>{if(!r)return;let e=!1;return R.current=!1,o(null),D(!1),k(null),j(null),N(v),L(!1),(async()=>{try{let t=await r.motionZones?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(o(t),R.current)return;let n=await r.motionZones?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);R.current=!0;let i=n.regions.find(e=>e.shape.kind===`grid`),a=x(i?i.shape.cells:[],t.grid.width,t.grid.height);j(a),k(T(a,t.grid.width,t.grid.height,v))}catch(t){if(e)return;c(t)?D(!0):console.error(`Motion Zones load failed`,t)}})(),()=>{e=!0}},[r]);let z=i?i.grid.width:0,B=i?i.grid.height:0,V=C(z,M),H=C(B,M),U=(0,d.useMemo)(()=>O&&i?E(O,z,B,M):null,[O,i,z,B,M]),W=(0,d.useMemo)(()=>U!==null&&A!==null&&!S(U,A),[U,A]),G=(0,d.useMemo)(()=>U?U.reduce((e,t)=>t?e+1:e,0):0,[U]),K=z*B,q=V*H,J=(0,d.useCallback)(e=>{q>0&&k(Array.from({length:q},()=>e))},[q]),Y=(0,d.useCallback)(()=>{k(e=>e&&e.map(e=>!e))},[]),X=(0,d.useCallback)(()=>{A&&i&&k(T(A,z,B,M))},[A,i,z,B,M]),Z=(0,d.useCallback)(e=>{e===M||!i||k(t=>{if(!t)return N(e),t;let n=T(E(t,z,B,M),z,B,e);return N(e),n})},[M,i,z,B]),Q=(0,d.useMemo)(()=>i&&O?[{id:g,shape:{kind:`grid`,gridWidth:V,gridHeight:H,cells:[...O]}}]:[],[i,O,V,H]),$=(0,d.useCallback)((e,t)=>{t.kind===`grid`&&k(t.cells)},[]),ee=(0,d.useCallback)(async()=>{if(!(!r||!O||!i)){F(!0);try{let e=E(O,i.grid.width,i.grid.height,M),t={kind:`grid`,gridWidth:i.grid.width,gridHeight:i.grid.height,cells:e};await r.motionZones?.setZone({patch:{regions:[{id:g,enabled:!0,shape:t}]}});let n=await r.motionZones?.getStatus({});if(n){let e=n.regions.find(e=>e.shape.kind===`grid`),t=x(e?e.shape.cells:[],i.grid.width,i.grid.height);j(t),k(T(t,i.grid.width,i.grid.height,M))}}catch(e){console.error(`Motion Zones save failed`,e)}finally{F(!1)}}},[r,O,i,M]);a((0,d.useMemo)(()=>I&&!w&&i&&O?{id:h,order:m,node:(0,f.jsx)(u,{transparent:!0,items:Q,supportedShapes:[`grid`],grid:{width:V,height:H},selectedId:g,onSelect:()=>{},onShapeChange:$,onDrawComplete:()=>{},drawingKind:null})}:null,[I,w,i,O,Q,$,V,H]));let te=!w&&i!==null&&O!==null;return r?(0,f.jsx)(e,{title:`Motion Zones`,icon:(0,f.jsx)(p,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,f.jsx)(`div`,{className:`flex flex-col gap-3`,children:w?(0,f.jsx)(`p`,{className:`${s} leading-relaxed`,children:`This camera doesn't expose an on-board motion zones grid.`}):te?(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`p`,{className:`${s} leading-relaxed`,children:[`Toggle `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Edit grid`}),` to paint the region directly on the live frame, then `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Save`}),` to push the mask to the camera. Pick a bigger`,` `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Cell size`}),` for quicker, broad-stroke painting — it's resampled to the camera's native `,i.grid.width,`×`,i.grid.height,` grid on save (×1 is the finest).`]}),(0,f.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,f.jsx)(`button`,{type:`button`,onClick:()=>L(e=>!e),disabled:P,"aria-pressed":I,className:I?b:y,children:I?`Done editing`:`Edit grid`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>J(!0),disabled:P,className:y,children:`All on`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>J(!1),disabled:P,className:y,children:`All off`}),(0,f.jsx)(`button`,{type:`button`,onClick:Y,disabled:P,className:y,children:`Invert`}),(0,f.jsxs)(`div`,{className:`flex items-center gap-1 ml-1`,role:`group`,"aria-label":`Cell size`,children:[(0,f.jsx)(`span`,{className:`${s} mr-0.5`,children:`Cell size`}),_.map(e=>(0,f.jsxs)(`button`,{type:`button`,onClick:()=>Z(e),disabled:P,"aria-pressed":M===e,title:e===1?`Camera grid ${z}×${B} (finest)`:`${C(z,e)}×${C(B,e)} painting grid · cells ×${e} bigger`,className:M===e?b:y,children:[`×`,e]},e))]}),(0,f.jsxs)(`span`,{className:`${s} ml-1 tabular-nums`,children:[G,` / `,K,` cells · `,i.grid.width,`×`,i.grid.height,M===1?``:` · paint ${V}×${H}`]}),(0,f.jsx)(`span`,{className:`flex-1`}),(0,f.jsx)(`button`,{type:`button`,onClick:X,disabled:P||!W,className:`rounded-md border border-border bg-surface px-2 py-1 text-[11px] text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,children:`Revert`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>void ee(),disabled:P||!W,className:b,children:P?`Saving…`:`Save`})]})]}):(0,f.jsx)(`p`,{className:`${s} leading-relaxed`,children:`Loading the camera's grid…`})})}):null}export{D as MotionZonesSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,d as n,f as r,g as i,i as a,l as o,n as s,o as c,r as l,s as u,t as d,u as ee}from"./index-
|
|
1
|
+
import{a as e,c as t,d as n,f as r,g as i,i as a,l as o,n as s,o as c,r as l,s as u,t as d,u as ee}from"./index-Dcfe-5Ig.js";import{MaskShapeCanvas as te}from"./MaskShapeCanvas-DI4BY7W2-BWAtF7b-.js";var f=i(r(),1),p=i(n(),1),m=c(`hexagon`,[[`path`,{d:`M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z`,key:`yt0hxn`}]]),h=120,g=`privacy-mask`,_=`rounded-md border border-border bg-surface px-2 py-1 text-[11px] font-medium text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,v=`rounded-md border border-primary/50 bg-primary/15 px-2.5 py-1 text-[11px] font-medium text-primary hover:bg-primary/25 disabled:opacity-40 transition-colors`;function y(e){return e.kind===`rect`||e.kind===`polygon`?e:null}function b(e){let t=new Set(e.map(e=>e.id)),n=0;for(;t.has(n);)n+=1;return n}function x(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(JSON.stringify(e[n])!==JSON.stringify(t[n]))return!1;return!0}function S({deviceId:n}){let r=t(ee().trpcClient,n),[i,c]=(0,f.useState)(null),[S,C]=(0,f.useState)(!1),[w,T]=(0,f.useState)(null),[E,D]=(0,f.useState)(null),[O,k]=(0,f.useState)(!1),[A,j]=(0,f.useState)(!1),[M,N]=(0,f.useState)(null),[P,F]=(0,f.useState)(null),I=(0,f.useRef)(!1);(0,f.useEffect)(()=>{if(!r)return;let e=!1;return I.current=!1,c(null),C(!1),T(null),D(null),j(!1),N(null),F(null),(async()=>{try{let t=await r.privacyMask?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(c(t),I.current)return;let n=await r.privacyMask?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);I.current=!0;let i={enabled:n.enabled,regions:n.regions};D(i),T(i)}catch(t){if(e)return;u(t)?C(!0):console.error(`Privacy Mask load failed`,t)}})(),()=>{e=!0}},[r]);let L=(0,f.useMemo)(()=>w!==null&&E!==null&&(w.enabled!==E.enabled||!x(w.regions,E.regions)),[w,E]),R=w?w.regions.length:0,z=i?i.maxRegions:0,B=(0,f.useRef)(0);(0,f.useEffect)(()=>{B.current=z},[z]);let V=z>0&&R>=z,H=(0,f.useCallback)(()=>{T(e=>e&&{...e,enabled:!e.enabled})},[]),U=(0,f.useCallback)(e=>{N(typeof e==`number`?e:null)},[]),W=(0,f.useMemo)(()=>w?w.regions.map(e=>({id:e.id,shape:e.shape,enabled:e.enabled,label:`Zone ${String(e.id)}`})):[],[w]),G=(0,f.useCallback)((e,t)=>{let n=y(t);n&&T(t=>t&&{...t,regions:t.regions.map(t=>t.id===e?{...t,shape:n}:t)})},[]),K=(0,f.useCallback)(e=>{let t=y(e);t&&(F(null),T(e=>{if(!e)return e;let n=B.current;if(n>0&&e.regions.length>=n)return e;let r=b(e.regions),i={id:r,enabled:!0,shape:t};return N(r),{...e,regions:[...e.regions,i]}}))},[]),q=(0,f.useCallback)(e=>{j(!0),N(null),F(e)},[]),J=(0,f.useCallback)(e=>{j(!0),F(null),N(e)},[]),Y=(0,f.useCallback)(e=>{N(t=>t===e?null:t),T(t=>t&&{...t,regions:t.regions.filter(t=>t.id!==e)})},[]),X=(0,f.useCallback)(()=>{F(null),N(null),E&&T({enabled:E.enabled,regions:E.regions})},[E]),Z=(0,f.useCallback)(async()=>{if(!(!r||!w)){k(!0);try{await r.privacyMask?.setMask({patch:{enabled:w.enabled,regions:[...w.regions]}});let e=await r.privacyMask?.getStatus({});if(e){let t={enabled:e.enabled,regions:e.regions};D(t),T(t)}}catch(e){console.error(`Privacy Mask save failed`,e)}finally{k(!1)}}},[r,w]),ne=(0,f.useCallback)(()=>{j(e=>(e&&(F(null),N(null)),!e))},[]),Q=i?.supportedShapes??[];o((0,f.useMemo)(()=>A&&!S&&i&&w?{id:g,order:h,node:(0,p.jsx)(te,{transparent:!0,items:W,supportedShapes:Q,polygonVertices:i.polygonVertices,selectedId:M,onSelect:U,onShapeChange:G,onDrawComplete:K,drawingKind:P})}:null,[A,S,i,w,W,Q,M,U,G,K,P]));let re=i?.supportedShapes.includes(`rect`)??!1,ie=i?.supportedShapes.includes(`polygon`)??!1,$=i!==null&&(i.maxRegions<=0||i.supportedShapes.length===0),ae=!S&&!$&&i!==null&&w!==null;return r?(0,p.jsx)(e,{title:`Privacy Mask`,icon:(0,p.jsx)(d,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,p.jsx)(`div`,{className:`flex flex-col gap-3`,children:S||$?(0,p.jsx)(`p`,{className:`${l} leading-relaxed`,children:`This camera doesn't support an on-board privacy mask.`}):ae?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`p`,{className:`${l} leading-relaxed`,children:[`Toggle `,(0,p.jsx)(`strong`,{className:`text-foreground`,children:`Edit mask`}),` to draw blanked-out zones on the live frame, then `,(0,p.jsx)(`strong`,{className:`text-foreground`,children:`Save`}),` to push them to the camera. Drag a rectangle to move, its corner to resize; drag polygon vertices, click an edge midpoint to add one, or right-click a vertex to remove it.`]}),(0,p.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,p.jsx)(`button`,{type:`button`,onClick:ne,disabled:O,"aria-pressed":A,className:A?v:_,children:A?`Done editing`:`Edit mask`}),(0,p.jsx)(`button`,{type:`button`,onClick:H,disabled:O,"aria-pressed":w.enabled,className:w.enabled?v:_,children:w.enabled?`Mask on`:`Mask off`}),re&&(0,p.jsx)(`button`,{type:`button`,onClick:()=>q(`rect`),disabled:O||V,"aria-pressed":P===`rect`,className:P===`rect`?v:_,title:V?`Maximum zones reached`:`Add a rectangle zone`,children:`+ Rect`}),ie&&(0,p.jsx)(`button`,{type:`button`,onClick:()=>q(`polygon`),disabled:O||V,"aria-pressed":P===`polygon`,className:P===`polygon`?v:_,title:V?`Maximum zones reached`:`Add a polygon zone`,children:`+ Polygon`}),(0,p.jsxs)(`span`,{className:`${l} ml-1 tabular-nums`,children:[R,` / `,z,` zones`]}),(0,p.jsx)(`span`,{className:`flex-1`}),(0,p.jsx)(`button`,{type:`button`,onClick:X,disabled:O||!L,className:`rounded-md border border-border bg-surface px-2 py-1 text-[11px] text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,children:`Revert`}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>void Z(),disabled:O||!L,className:v,children:O?`Saving…`:`Save`})]}),R>0?(0,p.jsx)(`div`,{className:`flex flex-col gap-1`,children:w.regions.map(e=>{let t=M===e.id,n=e.shape.kind===`polygon`?m:s;return(0,p.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md border px-2 py-1 transition-colors ${t?`border-primary/50 bg-primary/10`:`border-border bg-surface`}`,children:[(0,p.jsxs)(`button`,{type:`button`,onClick:()=>J(e.id),disabled:O,className:`flex flex-1 items-center gap-2 text-left text-[11px] font-medium text-foreground-subtle hover:text-foreground disabled:opacity-40 transition-colors`,children:[(0,p.jsx)(n,{className:`h-3.5 w-3.5 shrink-0`}),(0,p.jsxs)(`span`,{children:[`Zone `,e.id]}),(0,p.jsx)(`span`,{className:`text-foreground-faint capitalize`,children:e.shape.kind})]}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>Y(e.id),disabled:O,"aria-label":`Delete zone ${String(e.id)}`,title:`Delete zone`,className:`inline-flex h-6 w-6 items-center justify-center rounded border border-border bg-surface text-foreground-subtle hover:border-red-400/40 hover:bg-red-500/10 hover:text-red-400 disabled:opacity-40 transition-colors`,children:(0,p.jsx)(a,{className:`h-3.5 w-3.5`})})]},e.id)})}):null]}):(0,p.jsx)(`p`,{className:`${l} leading-relaxed`,children:`Loading the camera's privacy mask…`})})}):null}export{S as PrivacyMaskSettings};
|