@camstack/addon-pipeline 1.2.12 → 1.2.13
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/audio-analyzer/index.js +1 -1
- package/dist/audio-analyzer/index.mjs +1 -1
- package/dist/detection-pipeline/index.js +2 -2
- package/dist/detection-pipeline/index.mjs +2 -2
- package/dist/{dist-B89zyHyl.js → dist-BUd2xSjP.js} +79 -0
- package/dist/{dist-DMiEnBkk.mjs → dist-DuI0Ypuu.mjs} +79 -0
- package/dist/{fmp4-keyframes-BzTPoPVn.js → fmp4-keyframes-5s8T9Mng.js} +42 -7
- package/dist/{fmp4-keyframes-qOgJBjMO.mjs → fmp4-keyframes-CV0X1mGy.mjs} +37 -12
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +2 -2
- package/dist/pipeline-runner/index.mjs +2 -2
- package/dist/recorder/index.js +36 -8
- package/dist/recorder/index.mjs +36 -8
- package/dist/{step-definitions-DLgHGq8f.js → step-definitions-Ck4_6GKK.js} +1 -1
- package/dist/{step-definitions-NeFJ6mFi.mjs → step-definitions-DqNWVeYB.mjs} +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CAvWbzaf.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-5EJfCCjk.mjs} +2 -2
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DbC3MMjB.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BDeEvhV5.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--zEZtV2N.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BGtpZkgz.mjs} +1 -1
- package/dist/stream-broker/{hostInit-Do62nL9c.mjs → hostInit-QaJMh7Ec.mjs} +2 -2
- package/dist/stream-broker/index.js +1186 -337
- package/dist/stream-broker/index.mjs +1187 -338
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-CNyCTsIC.js → MaskShapeCanvas-DI4BY7W2-Di-nvxaR.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-DOdX9Yp1.js → MotionZonesSettings-NcxxQN8r-C6Nj76Lm.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-9huXsgpT.js → PrivacyMaskSettings-APgPLF7p-DwVoJunF.js} +1 -1
- package/embed-dist/assets/{index-BxOCtm8E.js → index-CtDVz0vI.js} +15 -15
- package/embed-dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-BUd2xSjP.js");
|
|
7
7
|
const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
|
|
8
8
|
const require_model_download_service_Cp9f4dk6 = require("../model-download-service-Cp9f4dk6-fsdDExML.js");
|
|
9
9
|
let node_fs = require("node:fs");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as downloadFile, l as __require } from "../model-download-service-Cp9f4dk6-WO-foD7W.mjs";
|
|
2
|
-
import { D as mapAudioLabelToMacro, H as BaseAddon, V as errMsg, _ as audioAnalysisCapability, d as HF_BASE_URL, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG, q as hydrateSchema, v as audioAnalyzerCapability } from "../dist-
|
|
2
|
+
import { D as mapAudioLabelToMacro, H as BaseAddon, V as errMsg, _ as audioAnalysisCapability, d as HF_BASE_URL, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG, q as hydrateSchema, v as audioAnalyzerCapability } from "../dist-DuI0Ypuu.mjs";
|
|
3
3
|
import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import * as path$1 from "node:path";
|
|
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
7
|
-
const require_step_definitions = require("../step-definitions-
|
|
6
|
+
const require_dist = require("../dist-BUd2xSjP.js");
|
|
7
|
+
const require_step_definitions = require("../step-definitions-Ck4_6GKK.js");
|
|
8
8
|
const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
|
|
9
9
|
const require_model_download_service_Cp9f4dk6 = require("../model-download-service-Cp9f4dk6-fsdDExML.js");
|
|
10
10
|
let node_child_process = require("node:child_process");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as ensureModel, l as __require, o as isModelDownloaded, r as deleteModelFromDisk } from "../model-download-service-Cp9f4dk6-WO-foD7W.mjs";
|
|
2
|
-
import { C as detectionPipelineCapability, H as BaseAddon, I as runtimeDevices$1, K as createEvent, M as pipelineExecutorCapability, T as evaluateZoneRules, V as errMsg, Z as parseJsonUnknown, ct as object, dt as union, et as sleep, ft as EventCategory, h as YAMNET_TO_MACRO, j as nodePin, nt as array, q as hydrateSchema, s as DEVICE_BACKEND_TO_FORMAT, t as APPLE_SA_TO_MACRO, ut as string, w as enumerateInferenceDevices, x as defaultDeviceFor$1, z as supportedRuntimes$1 } from "../dist-
|
|
3
|
-
import { a as getStepDefinition, i as getStep, n as ALL_STEPS, o as resolveModelForFormat, r as getDefaultModelForFormat, t as ALL_PIPELINE_STEPS } from "../step-definitions-
|
|
2
|
+
import { C as detectionPipelineCapability, H as BaseAddon, I as runtimeDevices$1, K as createEvent, M as pipelineExecutorCapability, T as evaluateZoneRules, V as errMsg, Z as parseJsonUnknown, ct as object, dt as union, et as sleep, ft as EventCategory, h as YAMNET_TO_MACRO, j as nodePin, nt as array, q as hydrateSchema, s as DEVICE_BACKEND_TO_FORMAT, t as APPLE_SA_TO_MACRO, ut as string, w as enumerateInferenceDevices, x as defaultDeviceFor$1, z as supportedRuntimes$1 } from "../dist-DuI0Ypuu.mjs";
|
|
3
|
+
import { a as getStepDefinition, i as getStep, n as ALL_STEPS, o as resolveModelForFormat, r as getDefaultModelForFormat, t as ALL_PIPELINE_STEPS } from "../step-definitions-DqNWVeYB.mjs";
|
|
4
4
|
import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import sharp from "sharp";
|
|
@@ -15542,6 +15542,55 @@ method(object({
|
|
|
15542
15542
|
password: string()
|
|
15543
15543
|
}), AuthResultSchema.nullable(), { kind: "mutation" }), method(object({ state: string() }), string()), method(record(string(), string()), AuthResultSchema, { kind: "mutation" }), method(object({ token: string() }), AuthResultSchema.nullable());
|
|
15544
15544
|
/**
|
|
15545
|
+
* A live terminal session hosted by the provider addon. Output and input do
|
|
15546
|
+
* NOT flow through the capability — they use the addon data plane
|
|
15547
|
+
* (`GET /addon/terminal/<id>/out` SSE, `POST /addon/terminal/<id>/in`) because
|
|
15548
|
+
* terminal output must be ordered and lossless. The event bus is telemetry and
|
|
15549
|
+
* may drop chunks ([D8]), and a dropped chunk desynchronises the vt parser
|
|
15550
|
+
* permanently until a full repaint. The capability owns only lifecycle.
|
|
15551
|
+
*/
|
|
15552
|
+
var TerminalSessionInfoSchema = object({
|
|
15553
|
+
/** Opaque session id minted by the provider on `openSession`. */
|
|
15554
|
+
sessionId: string(),
|
|
15555
|
+
/** The pre-declared profile this session runs (never a free-form command). */
|
|
15556
|
+
profileId: string(),
|
|
15557
|
+
/** Human-readable profile label for the UI session list. */
|
|
15558
|
+
label: string(),
|
|
15559
|
+
cols: number().int().positive(),
|
|
15560
|
+
rows: number().int().positive(),
|
|
15561
|
+
/** ms-epoch the session's pty was spawned. */
|
|
15562
|
+
startedAt: number()
|
|
15563
|
+
});
|
|
15564
|
+
/**
|
|
15565
|
+
* A profile the operator may open — a pre-declared, allowlisted program
|
|
15566
|
+
* (`monitor` → `btm`). The capability accepts only these ids; a free-form
|
|
15567
|
+
* command string would be remote code execution as the server's user, so it is
|
|
15568
|
+
* deliberately not part of the contract.
|
|
15569
|
+
*/
|
|
15570
|
+
var TerminalProfileInfoSchema = object({
|
|
15571
|
+
profileId: string(),
|
|
15572
|
+
label: string(),
|
|
15573
|
+
description: string().optional()
|
|
15574
|
+
});
|
|
15575
|
+
method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
|
|
15576
|
+
profileId: string(),
|
|
15577
|
+
cols: number().int().positive(),
|
|
15578
|
+
rows: number().int().positive()
|
|
15579
|
+
}), TerminalSessionInfoSchema, {
|
|
15580
|
+
kind: "mutation",
|
|
15581
|
+
auth: "admin"
|
|
15582
|
+
}), method(object({
|
|
15583
|
+
sessionId: string(),
|
|
15584
|
+
cols: number().int().positive(),
|
|
15585
|
+
rows: number().int().positive()
|
|
15586
|
+
}), _void(), {
|
|
15587
|
+
kind: "mutation",
|
|
15588
|
+
auth: "admin"
|
|
15589
|
+
}), method(object({ sessionId: string() }), _void(), {
|
|
15590
|
+
kind: "mutation",
|
|
15591
|
+
auth: "admin"
|
|
15592
|
+
});
|
|
15593
|
+
/**
|
|
15545
15594
|
* Orchestrator-side destination metadata. The orchestrator computes
|
|
15546
15595
|
* `id = <addonId>:<subId>` from its provider lookup so consumers
|
|
15547
15596
|
* (admin UI, restore flow) see one canonical key.
|
|
@@ -26916,6 +26965,36 @@ Object.freeze({
|
|
|
26916
26965
|
addonId: null,
|
|
26917
26966
|
access: "create"
|
|
26918
26967
|
},
|
|
26968
|
+
"terminalSession.close": {
|
|
26969
|
+
capName: "terminal-session",
|
|
26970
|
+
capScope: "system",
|
|
26971
|
+
addonId: null,
|
|
26972
|
+
access: "create"
|
|
26973
|
+
},
|
|
26974
|
+
"terminalSession.listProfiles": {
|
|
26975
|
+
capName: "terminal-session",
|
|
26976
|
+
capScope: "system",
|
|
26977
|
+
addonId: null,
|
|
26978
|
+
access: "view"
|
|
26979
|
+
},
|
|
26980
|
+
"terminalSession.listSessions": {
|
|
26981
|
+
capName: "terminal-session",
|
|
26982
|
+
capScope: "system",
|
|
26983
|
+
addonId: null,
|
|
26984
|
+
access: "view"
|
|
26985
|
+
},
|
|
26986
|
+
"terminalSession.openSession": {
|
|
26987
|
+
capName: "terminal-session",
|
|
26988
|
+
capScope: "system",
|
|
26989
|
+
addonId: null,
|
|
26990
|
+
access: "create"
|
|
26991
|
+
},
|
|
26992
|
+
"terminalSession.resize": {
|
|
26993
|
+
capName: "terminal-session",
|
|
26994
|
+
capScope: "system",
|
|
26995
|
+
addonId: null,
|
|
26996
|
+
access: "create"
|
|
26997
|
+
},
|
|
26919
26998
|
"toast.onToast": {
|
|
26920
26999
|
capName: "toast",
|
|
26921
27000
|
capScope: "system",
|
|
@@ -15542,6 +15542,55 @@ method(object({
|
|
|
15542
15542
|
password: string()
|
|
15543
15543
|
}), AuthResultSchema.nullable(), { kind: "mutation" }), method(object({ state: string() }), string()), method(record(string(), string()), AuthResultSchema, { kind: "mutation" }), method(object({ token: string() }), AuthResultSchema.nullable());
|
|
15544
15544
|
/**
|
|
15545
|
+
* A live terminal session hosted by the provider addon. Output and input do
|
|
15546
|
+
* NOT flow through the capability — they use the addon data plane
|
|
15547
|
+
* (`GET /addon/terminal/<id>/out` SSE, `POST /addon/terminal/<id>/in`) because
|
|
15548
|
+
* terminal output must be ordered and lossless. The event bus is telemetry and
|
|
15549
|
+
* may drop chunks ([D8]), and a dropped chunk desynchronises the vt parser
|
|
15550
|
+
* permanently until a full repaint. The capability owns only lifecycle.
|
|
15551
|
+
*/
|
|
15552
|
+
var TerminalSessionInfoSchema = object({
|
|
15553
|
+
/** Opaque session id minted by the provider on `openSession`. */
|
|
15554
|
+
sessionId: string(),
|
|
15555
|
+
/** The pre-declared profile this session runs (never a free-form command). */
|
|
15556
|
+
profileId: string(),
|
|
15557
|
+
/** Human-readable profile label for the UI session list. */
|
|
15558
|
+
label: string(),
|
|
15559
|
+
cols: number().int().positive(),
|
|
15560
|
+
rows: number().int().positive(),
|
|
15561
|
+
/** ms-epoch the session's pty was spawned. */
|
|
15562
|
+
startedAt: number()
|
|
15563
|
+
});
|
|
15564
|
+
/**
|
|
15565
|
+
* A profile the operator may open — a pre-declared, allowlisted program
|
|
15566
|
+
* (`monitor` → `btm`). The capability accepts only these ids; a free-form
|
|
15567
|
+
* command string would be remote code execution as the server's user, so it is
|
|
15568
|
+
* deliberately not part of the contract.
|
|
15569
|
+
*/
|
|
15570
|
+
var TerminalProfileInfoSchema = object({
|
|
15571
|
+
profileId: string(),
|
|
15572
|
+
label: string(),
|
|
15573
|
+
description: string().optional()
|
|
15574
|
+
});
|
|
15575
|
+
method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
|
|
15576
|
+
profileId: string(),
|
|
15577
|
+
cols: number().int().positive(),
|
|
15578
|
+
rows: number().int().positive()
|
|
15579
|
+
}), TerminalSessionInfoSchema, {
|
|
15580
|
+
kind: "mutation",
|
|
15581
|
+
auth: "admin"
|
|
15582
|
+
}), method(object({
|
|
15583
|
+
sessionId: string(),
|
|
15584
|
+
cols: number().int().positive(),
|
|
15585
|
+
rows: number().int().positive()
|
|
15586
|
+
}), _void(), {
|
|
15587
|
+
kind: "mutation",
|
|
15588
|
+
auth: "admin"
|
|
15589
|
+
}), method(object({ sessionId: string() }), _void(), {
|
|
15590
|
+
kind: "mutation",
|
|
15591
|
+
auth: "admin"
|
|
15592
|
+
});
|
|
15593
|
+
/**
|
|
15545
15594
|
* Orchestrator-side destination metadata. The orchestrator computes
|
|
15546
15595
|
* `id = <addonId>:<subId>` from its provider lookup so consumers
|
|
15547
15596
|
* (admin UI, restore flow) see one canonical key.
|
|
@@ -26916,6 +26965,36 @@ Object.freeze({
|
|
|
26916
26965
|
addonId: null,
|
|
26917
26966
|
access: "create"
|
|
26918
26967
|
},
|
|
26968
|
+
"terminalSession.close": {
|
|
26969
|
+
capName: "terminal-session",
|
|
26970
|
+
capScope: "system",
|
|
26971
|
+
addonId: null,
|
|
26972
|
+
access: "create"
|
|
26973
|
+
},
|
|
26974
|
+
"terminalSession.listProfiles": {
|
|
26975
|
+
capName: "terminal-session",
|
|
26976
|
+
capScope: "system",
|
|
26977
|
+
addonId: null,
|
|
26978
|
+
access: "view"
|
|
26979
|
+
},
|
|
26980
|
+
"terminalSession.listSessions": {
|
|
26981
|
+
capName: "terminal-session",
|
|
26982
|
+
capScope: "system",
|
|
26983
|
+
addonId: null,
|
|
26984
|
+
access: "view"
|
|
26985
|
+
},
|
|
26986
|
+
"terminalSession.openSession": {
|
|
26987
|
+
capName: "terminal-session",
|
|
26988
|
+
capScope: "system",
|
|
26989
|
+
addonId: null,
|
|
26990
|
+
access: "create"
|
|
26991
|
+
},
|
|
26992
|
+
"terminalSession.resize": {
|
|
26993
|
+
capName: "terminal-session",
|
|
26994
|
+
capScope: "system",
|
|
26995
|
+
addonId: null,
|
|
26996
|
+
access: "create"
|
|
26997
|
+
},
|
|
26919
26998
|
"toast.onToast": {
|
|
26920
26999
|
capName: "toast",
|
|
26921
27000
|
capScope: "system",
|
|
@@ -6631,12 +6631,16 @@ function readTrack(file, segment) {
|
|
|
6631
6631
|
});
|
|
6632
6632
|
}
|
|
6633
6633
|
/**
|
|
6634
|
-
* Demux a recorded
|
|
6635
|
-
* WebCodecs decoder config, or null if the segment
|
|
6636
|
-
* decodable
|
|
6637
|
-
* epoch ms; the first sample's cts is the zero reference.
|
|
6634
|
+
* Demux a recorded `.m4s` fragment and return ALL its samples (sync + delta) in
|
|
6635
|
+
* decode order plus the WebCodecs decoder config, or null if the segment
|
|
6636
|
+
* carries no video / no decodable sample. `segmentStartMs` anchors each sample's
|
|
6637
|
+
* `ts` to absolute epoch ms; the first sample's cts is the zero reference.
|
|
6638
|
+
*
|
|
6639
|
+
* No decode, no ffmpeg — byte copies only. This is the general form used by the
|
|
6640
|
+
* recorded-playback demux; {@link extractKeyframes} filters its output to sync
|
|
6641
|
+
* samples for the scrub-pack service.
|
|
6638
6642
|
*/
|
|
6639
|
-
async function
|
|
6643
|
+
async function extractSamples(segment, segmentStartMs) {
|
|
6640
6644
|
const file = import_mp4box_all.createFile();
|
|
6641
6645
|
const ready = await readTrack(file, segment);
|
|
6642
6646
|
if (!ready) return null;
|
|
@@ -6647,10 +6651,10 @@ async function extractKeyframes(segment, segmentStartMs) {
|
|
|
6647
6651
|
file.onSamples = (_id, _user, samples) => {
|
|
6648
6652
|
for (const s of samples) {
|
|
6649
6653
|
if (firstCts === null) firstCts = s.cts;
|
|
6650
|
-
if (!s.is_sync) continue;
|
|
6651
6654
|
const ts = segmentStartMs + Math.round((s.cts - firstCts) / s.timescale * 1e3);
|
|
6652
6655
|
collected.push({
|
|
6653
6656
|
ts,
|
|
6657
|
+
isSync: s.is_sync,
|
|
6654
6658
|
data: new Uint8Array(s.data)
|
|
6655
6659
|
});
|
|
6656
6660
|
}
|
|
@@ -6664,7 +6668,26 @@ async function extractKeyframes(segment, segmentStartMs) {
|
|
|
6664
6668
|
return collected.length > 0 ? {
|
|
6665
6669
|
codec,
|
|
6666
6670
|
description,
|
|
6667
|
-
|
|
6671
|
+
samples: collected
|
|
6672
|
+
} : null;
|
|
6673
|
+
}
|
|
6674
|
+
/**
|
|
6675
|
+
* Demux a recorded LOW `.m4s` segment and return its sync samples plus the
|
|
6676
|
+
* WebCodecs decoder config, or null if the segment carries no video / no
|
|
6677
|
+
* decodable keyframe. `segmentStartMs` anchors keyframe timestamps to absolute
|
|
6678
|
+
* epoch ms; the first sample's cts is the zero reference.
|
|
6679
|
+
*/
|
|
6680
|
+
async function extractKeyframes(segment, segmentStartMs) {
|
|
6681
|
+
const extracted = await extractSamples(segment, segmentStartMs);
|
|
6682
|
+
if (!extracted) return null;
|
|
6683
|
+
const keyframes = extracted.samples.filter((s) => s.isSync).map((s) => ({
|
|
6684
|
+
ts: s.ts,
|
|
6685
|
+
data: s.data
|
|
6686
|
+
}));
|
|
6687
|
+
return keyframes.length > 0 ? {
|
|
6688
|
+
codec: extracted.codec,
|
|
6689
|
+
description: extracted.description,
|
|
6690
|
+
keyframes
|
|
6668
6691
|
} : null;
|
|
6669
6692
|
}
|
|
6670
6693
|
//#endregion
|
|
@@ -6674,3 +6697,15 @@ Object.defineProperty(exports, "extractKeyframes", {
|
|
|
6674
6697
|
return extractKeyframes;
|
|
6675
6698
|
}
|
|
6676
6699
|
});
|
|
6700
|
+
Object.defineProperty(exports, "extractSamples", {
|
|
6701
|
+
enumerable: true,
|
|
6702
|
+
get: function() {
|
|
6703
|
+
return extractSamples;
|
|
6704
|
+
}
|
|
6705
|
+
});
|
|
6706
|
+
Object.defineProperty(exports, "require_mp4box_all", {
|
|
6707
|
+
enumerable: true,
|
|
6708
|
+
get: function() {
|
|
6709
|
+
return require_mp4box_all;
|
|
6710
|
+
}
|
|
6711
|
+
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { c as __commonJSMin, u as __toESM } from "./model-download-service-Cp9f4dk6-WO-foD7W.mjs";
|
|
2
|
-
//#
|
|
3
|
-
|
|
4
|
-
var import_mp4box_all = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports) => {
|
|
2
|
+
//#region ../../node_modules/mp4box/dist/mp4box.all.js
|
|
3
|
+
var require_mp4box_all = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
5
4
|
var Log = (function() {
|
|
6
5
|
var start = /* @__PURE__ */ new Date();
|
|
7
6
|
var LOG_LEVEL_ERROR = 4;
|
|
@@ -6566,7 +6565,10 @@ var import_mp4box_all = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin((
|
|
|
6566
6565
|
return file;
|
|
6567
6566
|
};
|
|
6568
6567
|
if (typeof exports !== "undefined") exports.createFile = MP4Box.createFile;
|
|
6569
|
-
}))
|
|
6568
|
+
}));
|
|
6569
|
+
//#endregion
|
|
6570
|
+
//#region src/recorder/scrub/fmp4-keyframes.ts
|
|
6571
|
+
var import_mp4box_all = /* @__PURE__ */ __toESM(require_mp4box_all());
|
|
6570
6572
|
/**
|
|
6571
6573
|
* Normalize an RFC 6381 codec string for WebCodecs HEVC. Apple/WebKit
|
|
6572
6574
|
* WebCodecs only accepts the `hvc1.*` fourcc — a `hev1.*` string (what mp4box
|
|
@@ -6629,12 +6631,16 @@ function readTrack(file, segment) {
|
|
|
6629
6631
|
});
|
|
6630
6632
|
}
|
|
6631
6633
|
/**
|
|
6632
|
-
* Demux a recorded
|
|
6633
|
-
* WebCodecs decoder config, or null if the segment
|
|
6634
|
-
* decodable
|
|
6635
|
-
* epoch ms; the first sample's cts is the zero reference.
|
|
6634
|
+
* Demux a recorded `.m4s` fragment and return ALL its samples (sync + delta) in
|
|
6635
|
+
* decode order plus the WebCodecs decoder config, or null if the segment
|
|
6636
|
+
* carries no video / no decodable sample. `segmentStartMs` anchors each sample's
|
|
6637
|
+
* `ts` to absolute epoch ms; the first sample's cts is the zero reference.
|
|
6638
|
+
*
|
|
6639
|
+
* No decode, no ffmpeg — byte copies only. This is the general form used by the
|
|
6640
|
+
* recorded-playback demux; {@link extractKeyframes} filters its output to sync
|
|
6641
|
+
* samples for the scrub-pack service.
|
|
6636
6642
|
*/
|
|
6637
|
-
async function
|
|
6643
|
+
async function extractSamples(segment, segmentStartMs) {
|
|
6638
6644
|
const file = import_mp4box_all.createFile();
|
|
6639
6645
|
const ready = await readTrack(file, segment);
|
|
6640
6646
|
if (!ready) return null;
|
|
@@ -6645,10 +6651,10 @@ async function extractKeyframes(segment, segmentStartMs) {
|
|
|
6645
6651
|
file.onSamples = (_id, _user, samples) => {
|
|
6646
6652
|
for (const s of samples) {
|
|
6647
6653
|
if (firstCts === null) firstCts = s.cts;
|
|
6648
|
-
if (!s.is_sync) continue;
|
|
6649
6654
|
const ts = segmentStartMs + Math.round((s.cts - firstCts) / s.timescale * 1e3);
|
|
6650
6655
|
collected.push({
|
|
6651
6656
|
ts,
|
|
6657
|
+
isSync: s.is_sync,
|
|
6652
6658
|
data: new Uint8Array(s.data)
|
|
6653
6659
|
});
|
|
6654
6660
|
}
|
|
@@ -6662,8 +6668,27 @@ async function extractKeyframes(segment, segmentStartMs) {
|
|
|
6662
6668
|
return collected.length > 0 ? {
|
|
6663
6669
|
codec,
|
|
6664
6670
|
description,
|
|
6665
|
-
|
|
6671
|
+
samples: collected
|
|
6672
|
+
} : null;
|
|
6673
|
+
}
|
|
6674
|
+
/**
|
|
6675
|
+
* Demux a recorded LOW `.m4s` segment and return its sync samples plus the
|
|
6676
|
+
* WebCodecs decoder config, or null if the segment carries no video / no
|
|
6677
|
+
* decodable keyframe. `segmentStartMs` anchors keyframe timestamps to absolute
|
|
6678
|
+
* epoch ms; the first sample's cts is the zero reference.
|
|
6679
|
+
*/
|
|
6680
|
+
async function extractKeyframes(segment, segmentStartMs) {
|
|
6681
|
+
const extracted = await extractSamples(segment, segmentStartMs);
|
|
6682
|
+
if (!extracted) return null;
|
|
6683
|
+
const keyframes = extracted.samples.filter((s) => s.isSync).map((s) => ({
|
|
6684
|
+
ts: s.ts,
|
|
6685
|
+
data: s.data
|
|
6686
|
+
}));
|
|
6687
|
+
return keyframes.length > 0 ? {
|
|
6688
|
+
codec: extracted.codec,
|
|
6689
|
+
description: extracted.description,
|
|
6690
|
+
keyframes
|
|
6666
6691
|
} : null;
|
|
6667
6692
|
}
|
|
6668
6693
|
//#endregion
|
|
6669
|
-
export { extractKeyframes as t };
|
|
6694
|
+
export { extractSamples as n, require_mp4box_all as r, extractKeyframes as t };
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-BUd2xSjP.js");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
//#region src/motion-wasm/wasm-motion-detector.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as motionDetectionCapability, G as DeviceType, H as BaseAddon, T as evaluateZoneRules, q as hydrateSchema } from "../dist-
|
|
1
|
+
import { A as motionDetectionCapability, G as DeviceType, H as BaseAddon, T as evaluateZoneRules, q as hydrateSchema } from "../dist-DuI0Ypuu.mjs";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
//#region src/motion-wasm/wasm-motion-detector.ts
|
|
@@ -3,11 +3,11 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-BUd2xSjP.js");
|
|
7
7
|
const require_remote_restream = require("../remote-restream-CO36Sr30.js");
|
|
8
8
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
9
9
|
const require_worker_protocol = require("../worker-protocol-DextwlTX.js");
|
|
10
|
-
const require_step_definitions = require("../step-definitions-
|
|
10
|
+
const require_step_definitions = require("../step-definitions-Ck4_6GKK.js");
|
|
11
11
|
let node_child_process = require("node:child_process");
|
|
12
12
|
let node_url = require("node:url");
|
|
13
13
|
let sharp = require("sharp");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { H as BaseAddon, K as createEvent, N as pipelineRunnerCapability, S as defineCustomActions, V as errMsg, at as lazy, b as customAction, ct as object, ft as EventCategory, j as nodePin, nt as array, rt as boolean, s as DEVICE_BACKEND_TO_FORMAT, st as number, tt as _enum, ut as string } from "../dist-
|
|
1
|
+
import { H as BaseAddon, K as createEvent, N as pipelineRunnerCapability, S as defineCustomActions, V as errMsg, at as lazy, b as customAction, ct as object, ft as EventCategory, j as nodePin, nt as array, rt as boolean, s as DEVICE_BACKEND_TO_FORMAT, st as number, tt as _enum, ut as string } from "../dist-DuI0Ypuu.mjs";
|
|
2
2
|
import { n as profileForStreamId, t as isRemoteRestream } from "../remote-restream-BeHi78PZ.mjs";
|
|
3
3
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
4
4
|
import { t as isWorkerReply } from "../worker-protocol-D7RzZIla.mjs";
|
|
5
|
-
import { a as getStepDefinition } from "../step-definitions-
|
|
5
|
+
import { a as getStepDefinition } from "../step-definitions-DqNWVeYB.mjs";
|
|
6
6
|
import { fork } from "node:child_process";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import sharp from "sharp";
|
package/dist/recorder/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const require_chunk = require("../chunk-emK7D4bc.js");
|
|
2
|
-
const require_dist = require("../dist-
|
|
2
|
+
const require_dist = require("../dist-BUd2xSjP.js");
|
|
3
3
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
4
4
|
const require_model_download_service_Cp9f4dk6 = require("../model-download-service-Cp9f4dk6-fsdDExML.js");
|
|
5
|
-
const require_fmp4_keyframes = require("../fmp4-keyframes-
|
|
5
|
+
const require_fmp4_keyframes = require("../fmp4-keyframes-5s8T9Mng.js");
|
|
6
6
|
let node_child_process = require("node:child_process");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
let node_path = require("node:path");
|
|
@@ -2310,7 +2310,7 @@ function startSegmentWatcher(deps) {
|
|
|
2310
2310
|
}
|
|
2311
2311
|
//#endregion
|
|
2312
2312
|
//#region src/recorder/addon/ffmpeg-args.ts
|
|
2313
|
-
/** ffmpeg argv: pull RTSP (TCP), copy video / transcode audio to
|
|
2313
|
+
/** ffmpeg argv: pull RTSP (TCP), copy video / transcode audio to Opus, write
|
|
2314
2314
|
* fragmented-mp4 segments named by epoch seconds FLAT under `outDir`, plus a
|
|
2315
2315
|
* rolling `live.m3u8` playlist. The recorder segment-watcher tails the
|
|
2316
2316
|
* playlist and hands each finalized flat file to `SegmentStore.onFinalized`,
|
|
@@ -2329,7 +2329,9 @@ function buildPassthroughArgs(a) {
|
|
|
2329
2329
|
"copy",
|
|
2330
2330
|
...a.videoCodec === "H265" ? ["-tag:v", "hvc1"] : [],
|
|
2331
2331
|
"-c:a",
|
|
2332
|
-
"
|
|
2332
|
+
"libopus",
|
|
2333
|
+
"-b:a",
|
|
2334
|
+
"48k",
|
|
2333
2335
|
"-f",
|
|
2334
2336
|
"segment",
|
|
2335
2337
|
"-segment_time",
|
|
@@ -3017,8 +3019,12 @@ var ScrubPackService = class {
|
|
|
3017
3019
|
this.inflight.set(key, run);
|
|
3018
3020
|
return run;
|
|
3019
3021
|
}
|
|
3022
|
+
resolveCacheDir() {
|
|
3023
|
+
const c = this.deps.cacheDir;
|
|
3024
|
+
return typeof c === "function" ? c() : c;
|
|
3025
|
+
}
|
|
3020
3026
|
cachePath(deviceId, windowStartMs) {
|
|
3021
|
-
return node_path.default.join(this.
|
|
3027
|
+
return node_path.default.join(this.resolveCacheDir(), String(deviceId), utcDay(windowStartMs), `${windowStartMs}.pack`);
|
|
3022
3028
|
}
|
|
3023
3029
|
async getOrBuildInner(deviceId, windowStartMs) {
|
|
3024
3030
|
const now = (this.deps.now ?? Date.now)();
|
|
@@ -3095,14 +3101,15 @@ var ScrubPackService = class {
|
|
|
3095
3101
|
/** Remove per-device day directories older than the retention horizon. */
|
|
3096
3102
|
async prune(retentionDays) {
|
|
3097
3103
|
const cutoff = (this.deps.now ?? Date.now)() - retentionDays * 864e5;
|
|
3104
|
+
const cacheDir = this.resolveCacheDir();
|
|
3098
3105
|
let deviceDirs = [];
|
|
3099
3106
|
try {
|
|
3100
|
-
deviceDirs = await node_fs.promises.readdir(
|
|
3107
|
+
deviceDirs = await node_fs.promises.readdir(cacheDir);
|
|
3101
3108
|
} catch {
|
|
3102
3109
|
return;
|
|
3103
3110
|
}
|
|
3104
3111
|
for (const dev of deviceDirs) {
|
|
3105
|
-
const devPath = node_path.default.join(
|
|
3112
|
+
const devPath = node_path.default.join(cacheDir, dev);
|
|
3106
3113
|
let days = [];
|
|
3107
3114
|
try {
|
|
3108
3115
|
days = await node_fs.promises.readdir(devPath);
|
|
@@ -3597,7 +3604,7 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
3597
3604
|
const abs = this.resolveSegmentAbsPath(row);
|
|
3598
3605
|
return new Uint8Array(await node_fs.promises.readFile(abs));
|
|
3599
3606
|
},
|
|
3600
|
-
cacheDir:
|
|
3607
|
+
cacheDir: () => this.resolveScrubCacheRoot(),
|
|
3601
3608
|
logger: this.ctx.logger.child("ScrubPacks")
|
|
3602
3609
|
});
|
|
3603
3610
|
this.scrubPackService = scrubService;
|
|
@@ -3731,6 +3738,10 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
3731
3738
|
this.ctx.logger.warn("recorder: no recordings storage locations resolved — index not hydrated");
|
|
3732
3739
|
return;
|
|
3733
3740
|
}
|
|
3741
|
+
node_fs.promises.rm(node_path.default.join(this.ctx.dataDir, "scrub-packs"), {
|
|
3742
|
+
recursive: true,
|
|
3743
|
+
force: true
|
|
3744
|
+
}).catch(() => {});
|
|
3734
3745
|
try {
|
|
3735
3746
|
await this.controller?.start();
|
|
3736
3747
|
} catch (err) {
|
|
@@ -4020,6 +4031,23 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
4020
4031
|
return node_path.default.join(loc.root, row.path);
|
|
4021
4032
|
}
|
|
4022
4033
|
/**
|
|
4034
|
+
* Cache root for the scrub packs — a hidden `.scrub-packs` dir UNDER a
|
|
4035
|
+
* recordings storage root (the `recordingsLow` location the packs derive from,
|
|
4036
|
+
* else the first resolved location). Packs are a regenerable keyframe cache of
|
|
4037
|
+
* the LOW segments; keeping them beside the recordings (a top-level mount, NOT
|
|
4038
|
+
* backed up) — instead of in `addons-data` — keeps the backup perimeter pure
|
|
4039
|
+
* operator state so it can be tarred whole with no exclusion list. See ADR-0027.
|
|
4040
|
+
*
|
|
4041
|
+
* Resolved lazily: `resolvedLocations` is only populated in `onHubReachable`,
|
|
4042
|
+
* after the ScrubPackService is constructed in `onInitialize`. getOrBuild/prune
|
|
4043
|
+
* run only at request time / on a delayed timer, by when locations are ready.
|
|
4044
|
+
*/
|
|
4045
|
+
resolveScrubCacheRoot() {
|
|
4046
|
+
const loc = this.resolvedLocations.find((l) => l.type === "recordingsLow") ?? this.resolvedLocations[0];
|
|
4047
|
+
if (loc === void 0) return node_path.default.join(this.ctx.dataDir, "scrub-packs");
|
|
4048
|
+
return node_path.default.join(loc.root, ".scrub-packs");
|
|
4049
|
+
}
|
|
4050
|
+
/**
|
|
4023
4051
|
* Scrub-pack request handler: `GET /<deviceId>/<windowStartSec>` →
|
|
4024
4052
|
* `application/octet-stream` pack | 204 (no footage) | 400 (bad path / window
|
|
4025
4053
|
* not aligned to `SCRUB_WINDOW_MS`) | 500. Immutable (fully past) windows carry
|
package/dist/recorder/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as createFileDataPlaneHandler, s as parseRangeHeader, t as contentTypeFor } from "../model-download-service-Cp9f4dk6-WO-foD7W.mjs";
|
|
2
|
-
import { $ as selectAssignedProfileSlots, F as recordingExportCapability, G as DeviceType, H as BaseAddon, L as storageEvictableCapability, P as recordingCapability, V as errMsg, c as EVENT_PAD_MS, f as OpsLogEntrySchema, ft as EventCategory, j as nodePin, k as migrateConfigToBands, lt as record, nt as array, p as RecordingConfigSchema, q as hydrateSchema, u as ExportRecordSchema, ut as string } from "../dist-
|
|
2
|
+
import { $ as selectAssignedProfileSlots, F as recordingExportCapability, G as DeviceType, H as BaseAddon, L as storageEvictableCapability, P as recordingCapability, V as errMsg, c as EVENT_PAD_MS, f as OpsLogEntrySchema, ft as EventCategory, j as nodePin, k as migrateConfigToBands, lt as record, nt as array, p as RecordingConfigSchema, q as hydrateSchema, u as ExportRecordSchema, ut as string } from "../dist-DuI0Ypuu.mjs";
|
|
3
3
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
4
|
-
import { t as extractKeyframes } from "../fmp4-keyframes-
|
|
4
|
+
import { t as extractKeyframes } from "../fmp4-keyframes-CV0X1mGy.mjs";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { createReadStream, promises, realpathSync } from "node:fs";
|
|
7
7
|
import path from "node:path";
|
|
@@ -2308,7 +2308,7 @@ function startSegmentWatcher(deps) {
|
|
|
2308
2308
|
}
|
|
2309
2309
|
//#endregion
|
|
2310
2310
|
//#region src/recorder/addon/ffmpeg-args.ts
|
|
2311
|
-
/** ffmpeg argv: pull RTSP (TCP), copy video / transcode audio to
|
|
2311
|
+
/** ffmpeg argv: pull RTSP (TCP), copy video / transcode audio to Opus, write
|
|
2312
2312
|
* fragmented-mp4 segments named by epoch seconds FLAT under `outDir`, plus a
|
|
2313
2313
|
* rolling `live.m3u8` playlist. The recorder segment-watcher tails the
|
|
2314
2314
|
* playlist and hands each finalized flat file to `SegmentStore.onFinalized`,
|
|
@@ -2327,7 +2327,9 @@ function buildPassthroughArgs(a) {
|
|
|
2327
2327
|
"copy",
|
|
2328
2328
|
...a.videoCodec === "H265" ? ["-tag:v", "hvc1"] : [],
|
|
2329
2329
|
"-c:a",
|
|
2330
|
-
"
|
|
2330
|
+
"libopus",
|
|
2331
|
+
"-b:a",
|
|
2332
|
+
"48k",
|
|
2331
2333
|
"-f",
|
|
2332
2334
|
"segment",
|
|
2333
2335
|
"-segment_time",
|
|
@@ -3015,8 +3017,12 @@ var ScrubPackService = class {
|
|
|
3015
3017
|
this.inflight.set(key, run);
|
|
3016
3018
|
return run;
|
|
3017
3019
|
}
|
|
3020
|
+
resolveCacheDir() {
|
|
3021
|
+
const c = this.deps.cacheDir;
|
|
3022
|
+
return typeof c === "function" ? c() : c;
|
|
3023
|
+
}
|
|
3018
3024
|
cachePath(deviceId, windowStartMs) {
|
|
3019
|
-
return path.join(this.
|
|
3025
|
+
return path.join(this.resolveCacheDir(), String(deviceId), utcDay(windowStartMs), `${windowStartMs}.pack`);
|
|
3020
3026
|
}
|
|
3021
3027
|
async getOrBuildInner(deviceId, windowStartMs) {
|
|
3022
3028
|
const now = (this.deps.now ?? Date.now)();
|
|
@@ -3093,14 +3099,15 @@ var ScrubPackService = class {
|
|
|
3093
3099
|
/** Remove per-device day directories older than the retention horizon. */
|
|
3094
3100
|
async prune(retentionDays) {
|
|
3095
3101
|
const cutoff = (this.deps.now ?? Date.now)() - retentionDays * 864e5;
|
|
3102
|
+
const cacheDir = this.resolveCacheDir();
|
|
3096
3103
|
let deviceDirs = [];
|
|
3097
3104
|
try {
|
|
3098
|
-
deviceDirs = await promises.readdir(
|
|
3105
|
+
deviceDirs = await promises.readdir(cacheDir);
|
|
3099
3106
|
} catch {
|
|
3100
3107
|
return;
|
|
3101
3108
|
}
|
|
3102
3109
|
for (const dev of deviceDirs) {
|
|
3103
|
-
const devPath = path.join(
|
|
3110
|
+
const devPath = path.join(cacheDir, dev);
|
|
3104
3111
|
let days = [];
|
|
3105
3112
|
try {
|
|
3106
3113
|
days = await promises.readdir(devPath);
|
|
@@ -3595,7 +3602,7 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
3595
3602
|
const abs = this.resolveSegmentAbsPath(row);
|
|
3596
3603
|
return new Uint8Array(await promises.readFile(abs));
|
|
3597
3604
|
},
|
|
3598
|
-
cacheDir:
|
|
3605
|
+
cacheDir: () => this.resolveScrubCacheRoot(),
|
|
3599
3606
|
logger: this.ctx.logger.child("ScrubPacks")
|
|
3600
3607
|
});
|
|
3601
3608
|
this.scrubPackService = scrubService;
|
|
@@ -3729,6 +3736,10 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
3729
3736
|
this.ctx.logger.warn("recorder: no recordings storage locations resolved — index not hydrated");
|
|
3730
3737
|
return;
|
|
3731
3738
|
}
|
|
3739
|
+
promises.rm(path.join(this.ctx.dataDir, "scrub-packs"), {
|
|
3740
|
+
recursive: true,
|
|
3741
|
+
force: true
|
|
3742
|
+
}).catch(() => {});
|
|
3732
3743
|
try {
|
|
3733
3744
|
await this.controller?.start();
|
|
3734
3745
|
} catch (err) {
|
|
@@ -4018,6 +4029,23 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
4018
4029
|
return path.join(loc.root, row.path);
|
|
4019
4030
|
}
|
|
4020
4031
|
/**
|
|
4032
|
+
* Cache root for the scrub packs — a hidden `.scrub-packs` dir UNDER a
|
|
4033
|
+
* recordings storage root (the `recordingsLow` location the packs derive from,
|
|
4034
|
+
* else the first resolved location). Packs are a regenerable keyframe cache of
|
|
4035
|
+
* the LOW segments; keeping them beside the recordings (a top-level mount, NOT
|
|
4036
|
+
* backed up) — instead of in `addons-data` — keeps the backup perimeter pure
|
|
4037
|
+
* operator state so it can be tarred whole with no exclusion list. See ADR-0027.
|
|
4038
|
+
*
|
|
4039
|
+
* Resolved lazily: `resolvedLocations` is only populated in `onHubReachable`,
|
|
4040
|
+
* after the ScrubPackService is constructed in `onInitialize`. getOrBuild/prune
|
|
4041
|
+
* run only at request time / on a delayed timer, by when locations are ready.
|
|
4042
|
+
*/
|
|
4043
|
+
resolveScrubCacheRoot() {
|
|
4044
|
+
const loc = this.resolvedLocations.find((l) => l.type === "recordingsLow") ?? this.resolvedLocations[0];
|
|
4045
|
+
if (loc === void 0) return path.join(this.ctx.dataDir, "scrub-packs");
|
|
4046
|
+
return path.join(loc.root, ".scrub-packs");
|
|
4047
|
+
}
|
|
4048
|
+
/**
|
|
4021
4049
|
* Scrub-pack request handler: `GET /<deviceId>/<windowStartSec>` →
|
|
4022
4050
|
* `application/octet-stream` pack | 204 (no footage) | 400 (bad path / window
|
|
4023
4051
|
* not aligned to `SCRUB_WINDOW_MS`) | 500. Immutable (fully past) windows carry
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as hfModelUrl, a as COCO_TO_MACRO, i as COCO_80_LABELS, r as AUDIO_MACRO_LABELS } from "./dist-
|
|
1
|
+
import { E as hfModelUrl, a as COCO_TO_MACRO, i as COCO_80_LABELS, r as AUDIO_MACRO_LABELS } from "./dist-DuI0Ypuu.mjs";
|
|
2
2
|
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
3
3
|
var HF_REPO = "camstack/camstack-models";
|
|
4
4
|
var HF_SCRYPTED = "scrypted/plugin-models";
|