@camstack/types 1.2.274 → 1.2.276
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/capabilities/core-blocks.cap.d.ts +52 -21
- package/dist/capabilities/index.d.ts +2 -2
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +40 -0
- package/dist/composition/composable-caps.d.ts +70 -0
- package/dist/composition/evaluate-field.d.ts +0 -31
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/presets/doorbell-feature.d.ts +20 -0
- package/dist/{composition-BRxAnxtU.js → composition-DG4jVTfB.js} +221 -0
- package/dist/{composition-BK-GTFYb.mjs → composition-Dq42XWp0.mjs} +186 -1
- package/dist/constants.d.ts +0 -1
- package/dist/ffmpeg/pinned-binary.d.ts +27 -0
- package/dist/ffmpeg/pinned-spawn.d.ts +29 -0
- package/dist/generated/addon-api.d.ts +14 -0
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +2 -2
- package/dist/generated/system-proxy.d.ts +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1664 -1414
- package/dist/index.mjs +1654 -1415
- package/dist/node.d.ts +2 -0
- package/dist/node.js +60 -200
- package/dist/node.mjs +44 -187
- package/package.json +1 -1
|
@@ -714,6 +714,191 @@ function replaceWithSortedKeys(_key, value) {
|
|
|
714
714
|
return value;
|
|
715
715
|
}
|
|
716
716
|
//#endregion
|
|
717
|
+
//#region src/deps/ffmpeg-artifacts.ts
|
|
718
|
+
/**
|
|
719
|
+
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
720
|
+
*
|
|
721
|
+
* ## Why a download, on every node, including the container
|
|
722
|
+
*
|
|
723
|
+
* The version of ffmpeg used to be CODE: baked into the image, changeable only
|
|
724
|
+
* by rebuilding and rolling it. Now it is DATA — this file states the release,
|
|
725
|
+
* and a node that boots with a different one downloads it. Changing ffmpeg is a
|
|
726
|
+
* framework bump, not an image rebuild.
|
|
727
|
+
*
|
|
728
|
+
* It also settles the licence question by removing it. FFmpeg's licence is
|
|
729
|
+
* chosen at compile time: the core is LGPL 2.1+, `--enable-gpl` makes it GPL
|
|
730
|
+
* (for x264/x265), `--enable-version3` makes that v3, and `--enable-nonfree`
|
|
731
|
+
* makes the result undistributable. These are GPL v3 builds, and we do not
|
|
732
|
+
* distribute them: the user's own node fetches the archive from the project
|
|
733
|
+
* that publishes it, so we convey no GPL work and inherit none of the
|
|
734
|
+
* obligations that come with conveying one. That is the whole reason the image
|
|
735
|
+
* no longer installs ffmpeg at all — not a technical preference.
|
|
736
|
+
*
|
|
737
|
+
* ## Why jellyfin-ffmpeg
|
|
738
|
+
*
|
|
739
|
+
* One vendor covering linux-amd64, linux-arm64, darwin-arm64 and darwin-x64
|
|
740
|
+
* from one release, with the widest hardware surface of anything maintained:
|
|
741
|
+
* VAAPI, QSV, NVENC/NVDEC, AMF, Vulkan, OpenCL and DRM on amd64, plus Rockchip
|
|
742
|
+
* MPP on arm64. It reaches the vendor libraries through dlopen trampolines,
|
|
743
|
+
* so the binary is not linked against a driver stack it may not find.
|
|
744
|
+
*
|
|
745
|
+
* **What it still needs from the host, measured 2026-09-19.** On the Unraid
|
|
746
|
+
* HOST, which has no libva, `-vaapi_device` aborts the process outright —
|
|
747
|
+
* `implib-gen: libva-drm.so.2: failed to load library ... Assertion '0 &&
|
|
748
|
+
* "Assertion in generated code"' failed`. Inside our container, which installs
|
|
749
|
+
* libva plus the iHD driver, the same command encodes: verified end to end with
|
|
750
|
+
* `testsrc → format=nv12,hwupload → h264_vaapi`. So the image drops ffmpeg and
|
|
751
|
+
* KEEPS the Intel media stack; the drivers are the part a binary cannot bring.
|
|
752
|
+
*
|
|
753
|
+
* ## Why each artifact carries a checksum and a claim
|
|
754
|
+
*
|
|
755
|
+
* The download is now the only source, so `sha256` is verified before anything
|
|
756
|
+
* is extracted — jellyfin publishes no checksums on its release assets, so
|
|
757
|
+
* these are ours, taken at the version bump. And `expectedHwaccels` is what the
|
|
758
|
+
* build is supposed to be able to do: a binary that probes short of its own
|
|
759
|
+
* claim is a source that changed under us, which is precisely what went
|
|
760
|
+
* unnoticed for months when a static build turned out to carry no VAAPI at all
|
|
761
|
+
* (D536).
|
|
762
|
+
*/
|
|
763
|
+
/** The pinned jellyfin-ffmpeg release. Changing this is the version change. */
|
|
764
|
+
var FFMPEG_RELEASE = "8.1.2-5";
|
|
765
|
+
var BASE = `https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v${FFMPEG_RELEASE}`;
|
|
766
|
+
function portable(target) {
|
|
767
|
+
return `${BASE}/jellyfin-ffmpeg_${FFMPEG_RELEASE}_portable_${target}-gpl.tar.xz`;
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Every artifact below was fetched and hashed on 2026-09-19, and each one's
|
|
771
|
+
* capability claim was verified by RUNNING it: the linux64 build on the hub
|
|
772
|
+
* itself, the two macOS builds on an M-series Mac (the x86_64 one under
|
|
773
|
+
* Rosetta, which translates x86 to arm — never the reverse, which is why the
|
|
774
|
+
* darwin split matters at all).
|
|
775
|
+
*
|
|
776
|
+
* linux-arm64 is hashed but NOT executed — there is no arm64 Linux node in
|
|
777
|
+
* this cluster yet. Its claim is taken from the project's build script, so the
|
|
778
|
+
* first ARM node to boot will either confirm it or trip the assertion, which is
|
|
779
|
+
* the outcome the assertion exists for.
|
|
780
|
+
*/
|
|
781
|
+
var FFMPEG_ARTIFACTS = {
|
|
782
|
+
"linux-x64": {
|
|
783
|
+
url: portable("linux64"),
|
|
784
|
+
archiveFormat: "tar.xz",
|
|
785
|
+
sha256: "1fd859927053c44a4f2dbf67ae8b9ba8d29fb3b8930df0dd57d91aa60589363d",
|
|
786
|
+
sizeBytes: 60255400,
|
|
787
|
+
expectedHwaccels: [
|
|
788
|
+
"vaapi",
|
|
789
|
+
"qsv",
|
|
790
|
+
"drm",
|
|
791
|
+
"vulkan",
|
|
792
|
+
"opencl"
|
|
793
|
+
]
|
|
794
|
+
},
|
|
795
|
+
"linux-arm64": {
|
|
796
|
+
url: portable("linuxarm64"),
|
|
797
|
+
archiveFormat: "tar.xz",
|
|
798
|
+
sha256: "1bd4fafaf4c309cad896d3479152c31d6b7604d4be8b8526882ea16cc6d5f589",
|
|
799
|
+
sizeBytes: 53958064,
|
|
800
|
+
expectedHwaccels: ["vaapi", "drm"]
|
|
801
|
+
},
|
|
802
|
+
"darwin-arm64": {
|
|
803
|
+
url: portable("macarm64"),
|
|
804
|
+
archiveFormat: "tar.xz",
|
|
805
|
+
sha256: "b2ac80bb184e9a2f3f7c236876b2f56a5639596a95b42f41ced34fab66ad720d",
|
|
806
|
+
sizeBytes: 32896684,
|
|
807
|
+
expectedHwaccels: ["videotoolbox"]
|
|
808
|
+
},
|
|
809
|
+
"darwin-x64": {
|
|
810
|
+
url: portable("mac64"),
|
|
811
|
+
archiveFormat: "tar.xz",
|
|
812
|
+
sha256: "021cd321ea169722cd2e4aca35884305449666a0d231d3378af7f87d6a5626e5",
|
|
813
|
+
sizeBytes: 37852180,
|
|
814
|
+
expectedHwaccels: ["videotoolbox"]
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
/** The artifact for this node, or a refusal naming what was asked for. */
|
|
818
|
+
function getFfmpegArtifact(platform, arch) {
|
|
819
|
+
const artifact = FFMPEG_ARTIFACTS[`${platform}-${arch}`];
|
|
820
|
+
if (!artifact) throw new Error(`Unsupported platform/architecture for ffmpeg: ${platform}-${arch}. Point CAMSTACK_FFMPEG_PATH at a binary this node can run.`);
|
|
821
|
+
return artifact;
|
|
822
|
+
}
|
|
823
|
+
/** The URL alone, for a caller that wants nothing else. */
|
|
824
|
+
function getFfmpegDownloadUrl(platform, arch) {
|
|
825
|
+
return getFfmpegArtifact(platform, arch).url;
|
|
826
|
+
}
|
|
827
|
+
//#endregion
|
|
828
|
+
//#region src/deps/ffmpeg-binary-source.ts
|
|
829
|
+
/**
|
|
830
|
+
* WHICH ffmpeg a node runs — one rule, on every node.
|
|
831
|
+
*
|
|
832
|
+
* ## The rule
|
|
833
|
+
*
|
|
834
|
+
* 1. `CAMSTACK_FFMPEG_PATH`, when the operator set it and it exists. Pointing
|
|
835
|
+
* at your own build is a deliberate act and it wins over everything.
|
|
836
|
+
* 2. The pinned build this node has already downloaded, named by release
|
|
837
|
+
* (`ffmpeg-<release>`), in `<dataDir>/deps`.
|
|
838
|
+
* 3. Nothing — the caller downloads it. See `ffmpeg-artifacts.ts`.
|
|
839
|
+
*
|
|
840
|
+
* The system PATH is not on that list and must never be. A host binary is an
|
|
841
|
+
* unknown version with unknown vendor libraries, and it changes under us on any
|
|
842
|
+
* host update; a self-hosted NVR cannot assume the host has ffmpeg at all
|
|
843
|
+
* (D536).
|
|
844
|
+
*
|
|
845
|
+
* ## Why the container image is not special any more
|
|
846
|
+
*
|
|
847
|
+
* It was, for one day: the image installed ffmpeg, CamStack preferred it, and
|
|
848
|
+
* that made the answer depend on where a node ran — an image node got VAAPI, a
|
|
849
|
+
* native one got a portable build with none. Now every node downloads the same
|
|
850
|
+
* pinned build, so:
|
|
851
|
+
*
|
|
852
|
+
* - the ffmpeg version is DATA, not code: changing it is a framework bump, not
|
|
853
|
+
* an image rebuild and a container swap on every machine;
|
|
854
|
+
* - we ship no ffmpeg binary, so we convey no GPL work — the node fetches it
|
|
855
|
+
* from the project that publishes it;
|
|
856
|
+
* - one binary, one set of capabilities, everywhere. A bug that depends on
|
|
857
|
+
* which ffmpeg answered stops being possible.
|
|
858
|
+
*
|
|
859
|
+
* What the image still owes is the DRIVERS, which no binary can bring: libva
|
|
860
|
+
* plus the iHD media driver for Intel. Measured 2026-09-19 — the portable build
|
|
861
|
+
* encodes VAAPI inside our container and ABORTS on the bare Unraid host, where
|
|
862
|
+
* `libva-drm.so.2` does not exist.
|
|
863
|
+
*
|
|
864
|
+
* ## Absent is absent
|
|
865
|
+
*
|
|
866
|
+
* The naming carries the release, so two versions coexist during a change and a
|
|
867
|
+
* rollback is a file that is already on disk rather than a download.
|
|
868
|
+
*/
|
|
869
|
+
/** Operator override. Unset on every node unless a human deliberately set it. */
|
|
870
|
+
var FFMPEG_PATH_ENV = "CAMSTACK_FFMPEG_PATH";
|
|
871
|
+
/**
|
|
872
|
+
* The file name the pinned build is stored under.
|
|
873
|
+
*
|
|
874
|
+
* Versioned on purpose: a download is then idempotent, two releases can sit
|
|
875
|
+
* side by side while a change rolls through a cluster, and going back is a path
|
|
876
|
+
* that already exists instead of a fetch that has to succeed.
|
|
877
|
+
*/
|
|
878
|
+
function ffmpegBinaryName(platform) {
|
|
879
|
+
return `ffmpeg-${FFMPEG_RELEASE}${platform === "win32" ? ".exe" : ""}`;
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* The binary to use, or `null` when it has to be downloaded first.
|
|
883
|
+
*
|
|
884
|
+
* An override that does not exist is NOT silently skipped — it is an operator
|
|
885
|
+
* mistake, and falling through to a different binary than the one they named
|
|
886
|
+
* would hide it. The caller reports it and carries on with the pinned build,
|
|
887
|
+
* which is the only safe direction: a typo must not stop a node serving video.
|
|
888
|
+
*/
|
|
889
|
+
function chooseFfmpegBinary(input) {
|
|
890
|
+
const override = input.override?.trim() ?? "";
|
|
891
|
+
if (override.length > 0 && input.exists(override)) return {
|
|
892
|
+
origin: "override",
|
|
893
|
+
path: override
|
|
894
|
+
};
|
|
895
|
+
if (input.exists(input.pinnedPath)) return {
|
|
896
|
+
origin: "downloaded",
|
|
897
|
+
path: input.pinnedPath
|
|
898
|
+
};
|
|
899
|
+
return null;
|
|
900
|
+
}
|
|
901
|
+
//#endregion
|
|
717
902
|
//#region src/catalogs/sensor-active-state.ts
|
|
718
903
|
/**
|
|
719
904
|
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
@@ -2268,6 +2453,18 @@ Object.defineProperty(exports, "ExpressionParseError", {
|
|
|
2268
2453
|
return ExpressionParseError;
|
|
2269
2454
|
}
|
|
2270
2455
|
});
|
|
2456
|
+
Object.defineProperty(exports, "FFMPEG_PATH_ENV", {
|
|
2457
|
+
enumerable: true,
|
|
2458
|
+
get: function() {
|
|
2459
|
+
return FFMPEG_PATH_ENV;
|
|
2460
|
+
}
|
|
2461
|
+
});
|
|
2462
|
+
Object.defineProperty(exports, "FFMPEG_RELEASE", {
|
|
2463
|
+
enumerable: true,
|
|
2464
|
+
get: function() {
|
|
2465
|
+
return FFMPEG_RELEASE;
|
|
2466
|
+
}
|
|
2467
|
+
});
|
|
2271
2468
|
Object.defineProperty(exports, "Fmp4BoxSplitter", {
|
|
2272
2469
|
enumerable: true,
|
|
2273
2470
|
get: function() {
|
|
@@ -2394,6 +2591,12 @@ Object.defineProperty(exports, "canonicalHash", {
|
|
|
2394
2591
|
return canonicalHash;
|
|
2395
2592
|
}
|
|
2396
2593
|
});
|
|
2594
|
+
Object.defineProperty(exports, "chooseFfmpegBinary", {
|
|
2595
|
+
enumerable: true,
|
|
2596
|
+
get: function() {
|
|
2597
|
+
return chooseFfmpegBinary;
|
|
2598
|
+
}
|
|
2599
|
+
});
|
|
2397
2600
|
Object.defineProperty(exports, "cloneStatefulExpressionMemory", {
|
|
2398
2601
|
enumerable: true,
|
|
2399
2602
|
get: function() {
|
|
@@ -2520,12 +2723,30 @@ Object.defineProperty(exports, "featureSources", {
|
|
|
2520
2723
|
return featureSources;
|
|
2521
2724
|
}
|
|
2522
2725
|
});
|
|
2726
|
+
Object.defineProperty(exports, "ffmpegBinaryName", {
|
|
2727
|
+
enumerable: true,
|
|
2728
|
+
get: function() {
|
|
2729
|
+
return ffmpegBinaryName;
|
|
2730
|
+
}
|
|
2731
|
+
});
|
|
2523
2732
|
Object.defineProperty(exports, "fieldReads", {
|
|
2524
2733
|
enumerable: true,
|
|
2525
2734
|
get: function() {
|
|
2526
2735
|
return fieldReads;
|
|
2527
2736
|
}
|
|
2528
2737
|
});
|
|
2738
|
+
Object.defineProperty(exports, "getFfmpegArtifact", {
|
|
2739
|
+
enumerable: true,
|
|
2740
|
+
get: function() {
|
|
2741
|
+
return getFfmpegArtifact;
|
|
2742
|
+
}
|
|
2743
|
+
});
|
|
2744
|
+
Object.defineProperty(exports, "getFfmpegDownloadUrl", {
|
|
2745
|
+
enumerable: true,
|
|
2746
|
+
get: function() {
|
|
2747
|
+
return getFfmpegDownloadUrl;
|
|
2748
|
+
}
|
|
2749
|
+
});
|
|
2529
2750
|
Object.defineProperty(exports, "invocationFromEncodeProfile", {
|
|
2530
2751
|
enumerable: true,
|
|
2531
2752
|
get: function() {
|
|
@@ -714,6 +714,191 @@ function replaceWithSortedKeys(_key, value) {
|
|
|
714
714
|
return value;
|
|
715
715
|
}
|
|
716
716
|
//#endregion
|
|
717
|
+
//#region src/deps/ffmpeg-artifacts.ts
|
|
718
|
+
/**
|
|
719
|
+
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
720
|
+
*
|
|
721
|
+
* ## Why a download, on every node, including the container
|
|
722
|
+
*
|
|
723
|
+
* The version of ffmpeg used to be CODE: baked into the image, changeable only
|
|
724
|
+
* by rebuilding and rolling it. Now it is DATA — this file states the release,
|
|
725
|
+
* and a node that boots with a different one downloads it. Changing ffmpeg is a
|
|
726
|
+
* framework bump, not an image rebuild.
|
|
727
|
+
*
|
|
728
|
+
* It also settles the licence question by removing it. FFmpeg's licence is
|
|
729
|
+
* chosen at compile time: the core is LGPL 2.1+, `--enable-gpl` makes it GPL
|
|
730
|
+
* (for x264/x265), `--enable-version3` makes that v3, and `--enable-nonfree`
|
|
731
|
+
* makes the result undistributable. These are GPL v3 builds, and we do not
|
|
732
|
+
* distribute them: the user's own node fetches the archive from the project
|
|
733
|
+
* that publishes it, so we convey no GPL work and inherit none of the
|
|
734
|
+
* obligations that come with conveying one. That is the whole reason the image
|
|
735
|
+
* no longer installs ffmpeg at all — not a technical preference.
|
|
736
|
+
*
|
|
737
|
+
* ## Why jellyfin-ffmpeg
|
|
738
|
+
*
|
|
739
|
+
* One vendor covering linux-amd64, linux-arm64, darwin-arm64 and darwin-x64
|
|
740
|
+
* from one release, with the widest hardware surface of anything maintained:
|
|
741
|
+
* VAAPI, QSV, NVENC/NVDEC, AMF, Vulkan, OpenCL and DRM on amd64, plus Rockchip
|
|
742
|
+
* MPP on arm64. It reaches the vendor libraries through dlopen trampolines,
|
|
743
|
+
* so the binary is not linked against a driver stack it may not find.
|
|
744
|
+
*
|
|
745
|
+
* **What it still needs from the host, measured 2026-09-19.** On the Unraid
|
|
746
|
+
* HOST, which has no libva, `-vaapi_device` aborts the process outright —
|
|
747
|
+
* `implib-gen: libva-drm.so.2: failed to load library ... Assertion '0 &&
|
|
748
|
+
* "Assertion in generated code"' failed`. Inside our container, which installs
|
|
749
|
+
* libva plus the iHD driver, the same command encodes: verified end to end with
|
|
750
|
+
* `testsrc → format=nv12,hwupload → h264_vaapi`. So the image drops ffmpeg and
|
|
751
|
+
* KEEPS the Intel media stack; the drivers are the part a binary cannot bring.
|
|
752
|
+
*
|
|
753
|
+
* ## Why each artifact carries a checksum and a claim
|
|
754
|
+
*
|
|
755
|
+
* The download is now the only source, so `sha256` is verified before anything
|
|
756
|
+
* is extracted — jellyfin publishes no checksums on its release assets, so
|
|
757
|
+
* these are ours, taken at the version bump. And `expectedHwaccels` is what the
|
|
758
|
+
* build is supposed to be able to do: a binary that probes short of its own
|
|
759
|
+
* claim is a source that changed under us, which is precisely what went
|
|
760
|
+
* unnoticed for months when a static build turned out to carry no VAAPI at all
|
|
761
|
+
* (D536).
|
|
762
|
+
*/
|
|
763
|
+
/** The pinned jellyfin-ffmpeg release. Changing this is the version change. */
|
|
764
|
+
var FFMPEG_RELEASE = "8.1.2-5";
|
|
765
|
+
var BASE = `https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v${FFMPEG_RELEASE}`;
|
|
766
|
+
function portable(target) {
|
|
767
|
+
return `${BASE}/jellyfin-ffmpeg_${FFMPEG_RELEASE}_portable_${target}-gpl.tar.xz`;
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Every artifact below was fetched and hashed on 2026-09-19, and each one's
|
|
771
|
+
* capability claim was verified by RUNNING it: the linux64 build on the hub
|
|
772
|
+
* itself, the two macOS builds on an M-series Mac (the x86_64 one under
|
|
773
|
+
* Rosetta, which translates x86 to arm — never the reverse, which is why the
|
|
774
|
+
* darwin split matters at all).
|
|
775
|
+
*
|
|
776
|
+
* linux-arm64 is hashed but NOT executed — there is no arm64 Linux node in
|
|
777
|
+
* this cluster yet. Its claim is taken from the project's build script, so the
|
|
778
|
+
* first ARM node to boot will either confirm it or trip the assertion, which is
|
|
779
|
+
* the outcome the assertion exists for.
|
|
780
|
+
*/
|
|
781
|
+
var FFMPEG_ARTIFACTS = {
|
|
782
|
+
"linux-x64": {
|
|
783
|
+
url: portable("linux64"),
|
|
784
|
+
archiveFormat: "tar.xz",
|
|
785
|
+
sha256: "1fd859927053c44a4f2dbf67ae8b9ba8d29fb3b8930df0dd57d91aa60589363d",
|
|
786
|
+
sizeBytes: 60255400,
|
|
787
|
+
expectedHwaccels: [
|
|
788
|
+
"vaapi",
|
|
789
|
+
"qsv",
|
|
790
|
+
"drm",
|
|
791
|
+
"vulkan",
|
|
792
|
+
"opencl"
|
|
793
|
+
]
|
|
794
|
+
},
|
|
795
|
+
"linux-arm64": {
|
|
796
|
+
url: portable("linuxarm64"),
|
|
797
|
+
archiveFormat: "tar.xz",
|
|
798
|
+
sha256: "1bd4fafaf4c309cad896d3479152c31d6b7604d4be8b8526882ea16cc6d5f589",
|
|
799
|
+
sizeBytes: 53958064,
|
|
800
|
+
expectedHwaccels: ["vaapi", "drm"]
|
|
801
|
+
},
|
|
802
|
+
"darwin-arm64": {
|
|
803
|
+
url: portable("macarm64"),
|
|
804
|
+
archiveFormat: "tar.xz",
|
|
805
|
+
sha256: "b2ac80bb184e9a2f3f7c236876b2f56a5639596a95b42f41ced34fab66ad720d",
|
|
806
|
+
sizeBytes: 32896684,
|
|
807
|
+
expectedHwaccels: ["videotoolbox"]
|
|
808
|
+
},
|
|
809
|
+
"darwin-x64": {
|
|
810
|
+
url: portable("mac64"),
|
|
811
|
+
archiveFormat: "tar.xz",
|
|
812
|
+
sha256: "021cd321ea169722cd2e4aca35884305449666a0d231d3378af7f87d6a5626e5",
|
|
813
|
+
sizeBytes: 37852180,
|
|
814
|
+
expectedHwaccels: ["videotoolbox"]
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
/** The artifact for this node, or a refusal naming what was asked for. */
|
|
818
|
+
function getFfmpegArtifact(platform, arch) {
|
|
819
|
+
const artifact = FFMPEG_ARTIFACTS[`${platform}-${arch}`];
|
|
820
|
+
if (!artifact) throw new Error(`Unsupported platform/architecture for ffmpeg: ${platform}-${arch}. Point CAMSTACK_FFMPEG_PATH at a binary this node can run.`);
|
|
821
|
+
return artifact;
|
|
822
|
+
}
|
|
823
|
+
/** The URL alone, for a caller that wants nothing else. */
|
|
824
|
+
function getFfmpegDownloadUrl(platform, arch) {
|
|
825
|
+
return getFfmpegArtifact(platform, arch).url;
|
|
826
|
+
}
|
|
827
|
+
//#endregion
|
|
828
|
+
//#region src/deps/ffmpeg-binary-source.ts
|
|
829
|
+
/**
|
|
830
|
+
* WHICH ffmpeg a node runs — one rule, on every node.
|
|
831
|
+
*
|
|
832
|
+
* ## The rule
|
|
833
|
+
*
|
|
834
|
+
* 1. `CAMSTACK_FFMPEG_PATH`, when the operator set it and it exists. Pointing
|
|
835
|
+
* at your own build is a deliberate act and it wins over everything.
|
|
836
|
+
* 2. The pinned build this node has already downloaded, named by release
|
|
837
|
+
* (`ffmpeg-<release>`), in `<dataDir>/deps`.
|
|
838
|
+
* 3. Nothing — the caller downloads it. See `ffmpeg-artifacts.ts`.
|
|
839
|
+
*
|
|
840
|
+
* The system PATH is not on that list and must never be. A host binary is an
|
|
841
|
+
* unknown version with unknown vendor libraries, and it changes under us on any
|
|
842
|
+
* host update; a self-hosted NVR cannot assume the host has ffmpeg at all
|
|
843
|
+
* (D536).
|
|
844
|
+
*
|
|
845
|
+
* ## Why the container image is not special any more
|
|
846
|
+
*
|
|
847
|
+
* It was, for one day: the image installed ffmpeg, CamStack preferred it, and
|
|
848
|
+
* that made the answer depend on where a node ran — an image node got VAAPI, a
|
|
849
|
+
* native one got a portable build with none. Now every node downloads the same
|
|
850
|
+
* pinned build, so:
|
|
851
|
+
*
|
|
852
|
+
* - the ffmpeg version is DATA, not code: changing it is a framework bump, not
|
|
853
|
+
* an image rebuild and a container swap on every machine;
|
|
854
|
+
* - we ship no ffmpeg binary, so we convey no GPL work — the node fetches it
|
|
855
|
+
* from the project that publishes it;
|
|
856
|
+
* - one binary, one set of capabilities, everywhere. A bug that depends on
|
|
857
|
+
* which ffmpeg answered stops being possible.
|
|
858
|
+
*
|
|
859
|
+
* What the image still owes is the DRIVERS, which no binary can bring: libva
|
|
860
|
+
* plus the iHD media driver for Intel. Measured 2026-09-19 — the portable build
|
|
861
|
+
* encodes VAAPI inside our container and ABORTS on the bare Unraid host, where
|
|
862
|
+
* `libva-drm.so.2` does not exist.
|
|
863
|
+
*
|
|
864
|
+
* ## Absent is absent
|
|
865
|
+
*
|
|
866
|
+
* The naming carries the release, so two versions coexist during a change and a
|
|
867
|
+
* rollback is a file that is already on disk rather than a download.
|
|
868
|
+
*/
|
|
869
|
+
/** Operator override. Unset on every node unless a human deliberately set it. */
|
|
870
|
+
var FFMPEG_PATH_ENV = "CAMSTACK_FFMPEG_PATH";
|
|
871
|
+
/**
|
|
872
|
+
* The file name the pinned build is stored under.
|
|
873
|
+
*
|
|
874
|
+
* Versioned on purpose: a download is then idempotent, two releases can sit
|
|
875
|
+
* side by side while a change rolls through a cluster, and going back is a path
|
|
876
|
+
* that already exists instead of a fetch that has to succeed.
|
|
877
|
+
*/
|
|
878
|
+
function ffmpegBinaryName(platform) {
|
|
879
|
+
return `ffmpeg-${FFMPEG_RELEASE}${platform === "win32" ? ".exe" : ""}`;
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* The binary to use, or `null` when it has to be downloaded first.
|
|
883
|
+
*
|
|
884
|
+
* An override that does not exist is NOT silently skipped — it is an operator
|
|
885
|
+
* mistake, and falling through to a different binary than the one they named
|
|
886
|
+
* would hide it. The caller reports it and carries on with the pinned build,
|
|
887
|
+
* which is the only safe direction: a typo must not stop a node serving video.
|
|
888
|
+
*/
|
|
889
|
+
function chooseFfmpegBinary(input) {
|
|
890
|
+
const override = input.override?.trim() ?? "";
|
|
891
|
+
if (override.length > 0 && input.exists(override)) return {
|
|
892
|
+
origin: "override",
|
|
893
|
+
path: override
|
|
894
|
+
};
|
|
895
|
+
if (input.exists(input.pinnedPath)) return {
|
|
896
|
+
origin: "downloaded",
|
|
897
|
+
path: input.pinnedPath
|
|
898
|
+
};
|
|
899
|
+
return null;
|
|
900
|
+
}
|
|
901
|
+
//#endregion
|
|
717
902
|
//#region src/catalogs/sensor-active-state.ts
|
|
718
903
|
/**
|
|
719
904
|
* LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
|
|
@@ -2076,4 +2261,4 @@ function featureSources(feature) {
|
|
|
2076
2261
|
return featureFieldEntries(feature).map((e) => e.source);
|
|
2077
2262
|
}
|
|
2078
2263
|
//#endregion
|
|
2079
|
-
export { MAX_EXPRESSION_AST_NODES as $, compositionFeatureEnabled as A,
|
|
2264
|
+
export { MAX_EXPRESSION_AST_NODES as $, compositionFeatureEnabled as A, AUDIO_PRESETS as At, createStatefulExpressionMemory as B, resolveStreamMaps as Bt, CompositionTargetSchema as C, chooseFfmpegBinary as Ct, MAX_COMPOSITION_ITEMS as D, getFfmpegDownloadUrl as Dt, MAX_COMPOSITION_FIELDS_PER_FEATURE as E, getFfmpegArtifact as Et, featureFieldEntries as F, buildVideoArgs as Ft, createExpressionScope as G, evaluateStatefulExpressionCall as H, featureSources as I, invocationFromEncodeProfile as It, compileExpressionSafe as J, evaluateAst as K, fieldReads as L, isSoftwareDecode as Lt, compositionReadKey as M, buildAudioArgs as Mt, compositionSliceKey as N, buildFfmpegArgs as Nt, composedDeviceRef as O, canonicalHash as Ot, compositionSourceKey as P, buildInputArgs as Pt, EXPRESSION_IDENTIFIER_RE as Q, EXPRESSION_INJECTED_NOW as R, logBannerArgs as Rt, CompositionSourceRefSchema as S, FFMPEG_PATH_ENV as St, MAX_COMPOSITION_FEATURES as T, FFMPEG_RELEASE as Tt, toExpressionValue as U, evaluateExpressionSource as V, validateExpressionSource as W, tokenize as X, parseExpression as Y, EXPRESSION_COMPILE_CACHE_CAPACITY as Z, CompositionItemEntrySchema as _, evaluateSensorEdge as _t, CUSTOMIZATION_BLOCK_NAME_PREFIX as a, EXPRESSION_BUILTINS as at, CompositionPassthroughFeatureSchema as b, sliceActiveValue as bt, CompositionCommandTargetSchema as c, evaluateRose as ct, CompositionFeatureSchema as d, ExpressionParseError as dt, MAX_EXPRESSION_BINDINGS as et, CompositionFieldReadSchema as f, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as ft, CompositionFromSourceSchema as g, SOURCE_DEVICE_TYPES as gt, CompositionForwardCommandSchema as h, SOURCE_CAP_CHANGED_AT_FIELD as ht, COMPOSITION_ITEM_KEY_RE as i, RESERVED_BINDING_NAMES as it, compositionItemFieldPath as j, audioPlanFromEncodeProfile as jt, composedDeviceStableId as k, Fmp4BoxSplitter as kt, CompositionExistingTargetSchema as l, isStatefulBuiltin as lt, CompositionFieldsFeatureSchema as m, SOURCE_CAP_ACTIVE_FIELD as mt, COMPOSER_ADDON_ID as n, MAX_EXPRESSION_EVAL_STEPS as nt, CompositionBindingSchema as o, EXPRESSION_BUILTIN_NAMES as ot, CompositionFieldSourceSchema as p, SOURCE_CAPS as pt, compileExpression as q, COMPOSITION_ITEM_ARRAY_PATH as r, MAX_EXPRESSION_SOURCE_LENGTH as rt, CompositionCodeSourceSchema as s, evaluateCount as st, COMPOSED_DEVICE_STABLE_ID_PREFIX as t, MAX_EXPRESSION_CALL_ARGS as tt, CompositionExpressionSourceSchema as u, ExpressionEvalError as ut, CompositionLiteralBindingSchema as v, evaluateSensorLevelEdge as vt, MAX_COMPOSITION_CODE_LENGTH as w, ffmpegBinaryName as wt, CompositionSchema as x, sliceChangedAt as xt, CompositionNewTargetSchema as y, isSourceCap as yt, cloneStatefulExpressionMemory as z, pickVideoEncoder as zt };
|
package/dist/constants.d.ts
CHANGED
|
@@ -54,7 +54,6 @@ export interface RuntimeDefaultsShape {
|
|
|
54
54
|
'storage.provider': string;
|
|
55
55
|
'storage.locations': Record<string, string>;
|
|
56
56
|
providers: RuntimeDefaultsProvider[];
|
|
57
|
-
'ffmpeg.binaryPath': string;
|
|
58
57
|
'ffmpeg.hwAccel': string;
|
|
59
58
|
'ffmpeg.threadCount': number;
|
|
60
59
|
'auth.tokenExpiry': string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a runtime site gets the ffmpeg it spawns: the node's PINNED build, asked
|
|
3
|
+
* of `ctx.deps.ensureFfmpeg()` and never looked up on PATH (D540).
|
|
4
|
+
*
|
|
5
|
+
* Why a memo and not a bare `ensureFfmpeg()` per spawn: every call takes the
|
|
6
|
+
* deps file lock, probes the binary (`-version`, `-hwaccels`, `-encoders` —
|
|
7
|
+
* three children) and logs the resolution. That is right once per process and
|
|
8
|
+
* wrong once per still, per fragment or per preview.
|
|
9
|
+
*
|
|
10
|
+
* Why a memo and not a string resolved at init with a default: a default is
|
|
11
|
+
* what this repo kept writing — `ffmpegPath ?? 'ffmpeg'`, `binaryPath =
|
|
12
|
+
* 'ffmpeg'` — and every one of them turned "the pinned build is unavailable"
|
|
13
|
+
* into "run the host's binary" without a line in the log. A resolver that
|
|
14
|
+
* REJECTS has no such value to fall back to; the caller must say what it
|
|
15
|
+
* refused. `scripts/check-no-bare-ffmpeg.ts` refuses the default at commit.
|
|
16
|
+
*/
|
|
17
|
+
/** The pinned ffmpeg for this node; rejects when there is none to be had. */
|
|
18
|
+
export type PinnedFfmpegResolver = () => Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Memoize `ensure` on SUCCESS only.
|
|
21
|
+
*
|
|
22
|
+
* A failure is not remembered: the next caller asks again, so a node whose
|
|
23
|
+
* first download failed (no network at boot) recovers on the next spawn that
|
|
24
|
+
* needs it — with no timer and no retry loop, because the ask is driven by
|
|
25
|
+
* work that actually wants the binary.
|
|
26
|
+
*/
|
|
27
|
+
export declare function memoizePinnedFfmpeg(ensure: () => Promise<string>): PinnedFfmpegResolver;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The spawn a one-shot ffmpeg site uses: the spec's seam when one is injected,
|
|
3
|
+
* else the node's PINNED binary (D540), else `null` — and the site refuses by
|
|
4
|
+
* name. There is no fourth answer: the `?? 'ffmpeg'` this replaces made "no
|
|
5
|
+
* pinned build" mean "run the host's", silently, at every clip site that had it.
|
|
6
|
+
*
|
|
7
|
+
* Node-only (`node:child_process`), so it lives under `@camstack/types/node`.
|
|
8
|
+
*/
|
|
9
|
+
import { type ChildProcess, type SpawnOptions } from 'node:child_process';
|
|
10
|
+
/** One ffmpeg child from its argv. */
|
|
11
|
+
export type FfmpegArgvSpawn = (args: readonly string[]) => ChildProcess;
|
|
12
|
+
/** The detail a site refusing for want of a binary puts in its refusal. */
|
|
13
|
+
export declare const NO_PINNED_FFMPEG_DETAIL = "no pinned ffmpeg on this node (D540)";
|
|
14
|
+
/** What a site gets when it asks for its spawn: one, or the refusal to name. */
|
|
15
|
+
export type PinnedFfmpegSpawnAnswer = {
|
|
16
|
+
readonly kind: 'ready';
|
|
17
|
+
readonly spawn: FfmpegArgvSpawn;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'refused';
|
|
20
|
+
readonly detail: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* {@link pinnedFfmpegSpawner}, asked at the point of use through the node's
|
|
24
|
+
* resolver (`memoizePinnedFfmpeg`). A site that keeps the RESOLVER rather than
|
|
25
|
+
* a path captured at init recovers when a later resolution succeeds; a path
|
|
26
|
+
* captured as `null` at boot stayed `null` until the runner restarted.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolvePinnedFfmpegSpawner(seam: FfmpegArgvSpawn | undefined, resolveFfmpeg: () => Promise<string>, options: SpawnOptions): Promise<PinnedFfmpegSpawnAnswer>;
|
|
29
|
+
export declare function pinnedFfmpegSpawner(seam: FfmpegArgvSpawn | undefined, ffmpegBinaryPath: string | null, options: SpawnOptions): FfmpegArgvSpawn | null;
|
|
@@ -1631,6 +1631,13 @@ export type AppRouter = TrpcCoreRouter<{
|
|
|
1631
1631
|
output: z.infer<typeof coreBlocksCapability.methods.getCustomization.output>;
|
|
1632
1632
|
meta: object;
|
|
1633
1633
|
}>;
|
|
1634
|
+
listComposableCaps: TRPCQueryProcedure<{
|
|
1635
|
+
input: {
|
|
1636
|
+
[x: string]: unknown;
|
|
1637
|
+
} & z.input<typeof coreBlocksCapability.methods.listComposableCaps.input>;
|
|
1638
|
+
output: z.infer<typeof coreBlocksCapability.methods.listComposableCaps.output>;
|
|
1639
|
+
meta: object;
|
|
1640
|
+
}>;
|
|
1634
1641
|
validateComposition: TRPCMutationProcedure<{
|
|
1635
1642
|
input: {
|
|
1636
1643
|
[x: string]: unknown;
|
|
@@ -6390,6 +6397,13 @@ export type AppRouter = TrpcCoreRouter<{
|
|
|
6390
6397
|
output: z.infer<typeof pipelineOrchestratorCapability.methods.getCameraStatuses.output>;
|
|
6391
6398
|
meta: object;
|
|
6392
6399
|
}>;
|
|
6400
|
+
setCameraSensors: TRPCMutationProcedure<{
|
|
6401
|
+
input: {
|
|
6402
|
+
[x: string]: unknown;
|
|
6403
|
+
} & z.input<typeof pipelineOrchestratorCapability.methods.setCameraSensors.input>;
|
|
6404
|
+
output: z.infer<typeof pipelineOrchestratorCapability.methods.setCameraSensors.output>;
|
|
6405
|
+
meta: object;
|
|
6406
|
+
}>;
|
|
6393
6407
|
reconcileFromDisk: TRPCMutationProcedure<{
|
|
6394
6408
|
input: {
|
|
6395
6409
|
nodeId?: string | undefined;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* scope+access check inside `protectedProcedure` (see
|
|
7
7
|
* `server/backend/src/api/trpc/trpc.middleware.ts`).
|
|
8
8
|
*
|
|
9
|
-
* Coverage:
|
|
9
|
+
* Coverage: 1191 method paths across 162 capabilities.
|
|
10
10
|
*/
|
|
11
11
|
import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
|
|
12
12
|
export interface MethodAccessRecord {
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* system-scope cap that takes a deviceId was previously never device-filtered
|
|
7
7
|
* — see the generator header).
|
|
8
8
|
*
|
|
9
|
-
* Coverage:
|
|
10
|
-
*
|
|
9
|
+
* Coverage: 403 methods carry a device reference, of which
|
|
10
|
+
* 144 are on SYSTEM-scope caps.
|
|
11
11
|
*
|
|
12
12
|
* Top-level fields, number arrays, and one-level arrays of objects carrying
|
|
13
13
|
* a numeric device field (targets[].deviceId) are all mapped; the matcher
|
|
@@ -65,7 +65,7 @@ export interface SystemProxy {
|
|
|
65
65
|
readonly backup: Pick<InferProvider<typeof backupCapability>, 'listDestinations' | 'trigger' | 'listRuns' | 'cancel' | 'list' | 'listLocations' | 'getEntries' | 'restore' | 'delete' | 'listArchives' | 'upsertDestinationPolicy' | 'previewSchedule' | 'listSchedules' | 'upsertSchedule' | 'deleteSchedule'>;
|
|
66
66
|
readonly broker: Pick<InferProvider<typeof brokerCapability>, 'list' | 'get' | 'listProviders' | 'add' | 'remove' | 'testConnection' | 'getSettings' | 'setSettings' | 'getBrokerConfig' | 'getSettingsSchema' | 'testSettings' | 'publish' | 'subscribe' | 'unsubscribe' | 'getState' | 'getStatus'>;
|
|
67
67
|
readonly connectionTest: Pick<InferProvider<typeof connectionTestCapability>, 'testSettings' | 'describeTest'>;
|
|
68
|
-
readonly coreBlocks: Pick<InferProvider<typeof coreBlocksCapability>, 'list' | 'get' | 'create' | 'update' | 'delete' | 'setEnabled' | 'restart' | 'compile' | 'getTypeDefs' | 'createComposition' | 'updateComposition' | 'getComposition' | 'listCompositions' | 'getCustomization' | 'validateComposition'>;
|
|
68
|
+
readonly coreBlocks: Pick<InferProvider<typeof coreBlocksCapability>, 'list' | 'get' | 'create' | 'update' | 'delete' | 'setEnabled' | 'restart' | 'compile' | 'getTypeDefs' | 'createComposition' | 'updateComposition' | 'getComposition' | 'listCompositions' | 'getCustomization' | 'listComposableCaps' | 'validateComposition'>;
|
|
69
69
|
readonly decoder: Pick<InferProvider<typeof decoderCapability>, 'supportsCodec' | 'getInfo' | 'createSession' | 'destroySession' | 'pushPacket' | 'openStream' | 'pullFrames' | 'pullHandles' | 'getFrame' | 'getShmStats' | 'updateConfig' | 'getStats' | 'listActiveSessions' | 'reprobeHwaccel'>;
|
|
70
70
|
readonly deviceAdoption: Pick<InferProvider<typeof deviceAdoptionCapability>, 'listCandidateFilters' | 'listCandidates' | 'getCandidate' | 'refresh' | 'adopt' | 'release' | 'resync'>;
|
|
71
71
|
readonly deviceExport: Pick<InferProvider<typeof deviceExportCapability>, 'getStatus' | 'listSupportedDeviceKinds' | 'listExposedDevices' | 'exposeDevice' | 'unexposeDevice'>;
|
|
@@ -86,7 +86,7 @@ export interface SystemProxy {
|
|
|
86
86
|
readonly notificationRules: Pick<InferProvider<typeof notificationRulesCapability>, 'listRules' | 'getRule' | 'createRule' | 'updateRule' | 'deleteRule' | 'setRuleEnabled' | 'getClipRetentionAsks' | 'listDeviceMutes' | 'testRule' | 'previewStateSummary' | 'getConditionCatalog' | 'getTemplateCatalog' | 'previewTemplate' | 'getHistory' | 'getRuleLastRuns' | 'resolveArtifactUrl' | 'listSnoozes' | 'createSnooze' | 'cancelSnooze' | 'getAlarmConfig' | 'setAlarmConfig'>;
|
|
87
87
|
readonly osdManager: Pick<InferProvider<typeof osdManagerCapability>, 'getConditionSupport' | 'copyDeviceConfiguration'>;
|
|
88
88
|
readonly pipelineExecutor: Pick<InferProvider<typeof pipelineExecutorCapability>, 'getAvailableEngines' | 'getSelectedEngine' | 'getDefaultSteps' | 'getEngineProvisioning' | 'getVideoPipelineSteps' | 'setVideoPipelineSteps' | 'clearDeviceOverrides' | 'getInferenceDeviceHealth' | 'rearmInferenceDevice' | 'getSchema' | 'getGlobalSteps' | 'getGlobalPipelineConfig' | 'getOrchestratorConfigSchema' | 'validatePipeline' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate' | 'getCapabilities' | 'getAddonModels' | 'downloadModel' | 'deleteModel' | 'cacheFrameInPool' | 'inferCached' | 'uncacheFrame' | 'getEffectiveTuning' | 'listLoadedEngines' | 'spinEngine' | 'killEngine' | 'listReferenceImages' | 'getReferenceImage' | 'getReferenceAudioFiles' | 'getReferenceAudio' | 'getAudioCapabilities' | 'runAudioTest' | 'getDetectionConfigSchema'>;
|
|
89
|
-
readonly pipelineOrchestrator: Pick<InferProvider<typeof pipelineOrchestratorCapability>, 'pauseForStorageMigration' | 'resumeForStorageMigration' | 'rebalance' | 'getPipelineAssignments' | 'getAgentLoad' | 'getClusterModelChoice' | 'getGlobalMetrics' | 'getCapabilityBindings' | 'setCapabilityBinding' | 'getIngestOwner' | 'getAudioNodeLoad' | 'getAudioAssignments' | 'getAgentSettings' | 'listAgentSettings' | 'removeAgentSettings' | 'setAgentMaxCameras' | 'setAgentDetectWeight' | 'setAgentCapabilities' | 'setAgentDecodeLimits' | 'setAgentReachableHost' | 'setAgentInferenceDevices' | 'getNodeInferenceDevices' | 'resetNodePipelineDefaults' | 'getCameraStatuses' | 'reconcileFromDisk' | 'getReconcileFromDiskStatus' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate'>;
|
|
89
|
+
readonly pipelineOrchestrator: Pick<InferProvider<typeof pipelineOrchestratorCapability>, 'pauseForStorageMigration' | 'resumeForStorageMigration' | 'rebalance' | 'getPipelineAssignments' | 'getAgentLoad' | 'getClusterModelChoice' | 'getGlobalMetrics' | 'getCapabilityBindings' | 'setCapabilityBinding' | 'getIngestOwner' | 'getAudioNodeLoad' | 'getAudioAssignments' | 'getAgentSettings' | 'listAgentSettings' | 'removeAgentSettings' | 'setAgentMaxCameras' | 'setAgentDetectWeight' | 'setAgentCapabilities' | 'setAgentDecodeLimits' | 'setAgentReachableHost' | 'setAgentInferenceDevices' | 'getNodeInferenceDevices' | 'resetNodePipelineDefaults' | 'getCameraStatuses' | 'setCameraSensors' | 'reconcileFromDisk' | 'getReconcileFromDiskStatus' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate'>;
|
|
90
90
|
readonly pipelineRunner: Pick<InferProvider<typeof pipelineRunnerCapability>, 'attachCamera' | 'reportMotion' | 'getLocalLoad' | 'getLocalMetrics' | 'getAllCameraMetrics' | 'getLocalCameras' | 'getNativeCrop' | 'runStatelessStep'>;
|
|
91
91
|
readonly plateGallery: Pick<InferProvider<typeof plateGalleryCapability>, 'getPlateMedia' | 'searchPlates' | 'suggestPlateClusters' | 'correctPlateText' | 'deletePlate' | 'listVehicles' | 'createVehicle' | 'renameVehicle' | 'deleteVehicle' | 'listVehicleSamples' | 'removeVehicleSample' | 'assignPlate' | 'unassignPlate' | 'assignPlates' | 'unassignPlates'>;
|
|
92
92
|
readonly recordingArchive: Pick<InferProvider<typeof recordingArchiveCapability>, 'getAvailabilityBatch' | 'getDaysWithRecordingsBatch' | 'getStorageUsage' | 'listOpsLog' | 'pauseForStorageMigration' | 'resumeForStorageMigration' | 'refreshStorageLocationsForMigration' | 'startStorageMigrationMove' | 'getStorageMigrationMoveStatus' | 'cancelStorageMigrationMove' | 'relocateFootage' | 'listRelocateJobs' | 'getRelocateResidue' | 'reconcileLedgerAgainstDisk' | 'cancelRelocateJob' | 'planStorageRebalance' | 'startStorageRebalance' | 'getPlacement' | 'setDevicePlacement'>;
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export * from './ffmpeg/hwaccel.js';
|
|
|
19
19
|
export * from './ffmpeg/gif-derive.js';
|
|
20
20
|
export * from './ffmpeg/invocation.js';
|
|
21
21
|
export * from './ffmpeg/sharing-key.js';
|
|
22
|
+
export * from './ffmpeg/pinned-binary.js';
|
|
23
|
+
export { FFMPEG_PATH_ENV } from './deps/ffmpeg-binary-source.js';
|
|
22
24
|
export * from './health/wiring-health.js';
|
|
23
25
|
export type * from './interfaces/addon.js';
|
|
24
26
|
export { DEFAULT_ADDON_PLACEMENT, isAgentOnlyPlacement, isDeployableToAgent, isIsolatedBuiltin, resolveAddonExecution, resolveAddonGroup, resolveAddonPlacement, resolveRunnerId, } from './interfaces/addon.js';
|