@camstack/addon-pipeline 1.2.294 → 1.2.296

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.
Files changed (46) hide show
  1. package/THIRD_PARTY_MODELS.md +241 -0
  2. package/dist/audio-analyzer/index.js +2 -2
  3. package/dist/audio-analyzer/index.mjs +2 -2
  4. package/dist/{default-detection-model-0dPKRKUD.mjs → default-detection-model-Co578D8C.mjs} +181 -99
  5. package/dist/{default-detection-model-D24AJOTn.js → default-detection-model-D1daTtqT.js} +181 -99
  6. package/dist/detection-pipeline/index.js +1301 -531
  7. package/dist/detection-pipeline/index.mjs +1301 -531
  8. package/dist/{dist-CJR259Xf.js → dist-8up-f2TX.js} +3688 -2698
  9. package/dist/{dist-RXbmRAwP.mjs → dist-CCd0Q3nr.mjs} +3676 -2698
  10. package/dist/motion-wasm/index.js +1 -1
  11. package/dist/motion-wasm/index.mjs +1 -1
  12. package/dist/{node-atmRSHPk.mjs → node-DgMSXSWP.mjs} +1 -1
  13. package/dist/{node-DWg9zbY1.js → node-lpQgHes9.js} +1 -1
  14. package/dist/pipeline-runner/index.js +975 -270
  15. package/dist/pipeline-runner/index.mjs +975 -270
  16. package/dist/{process-memory-BJUXvTjd.js → process-memory-CX_92V_r.js} +1 -1
  17. package/dist/{process-memory-BgFOHFnx.mjs → process-memory-DFC_O5zE.mjs} +1 -1
  18. package/dist/recorder/index.js +14 -6
  19. package/dist/recorder/index.mjs +14 -6
  20. package/dist/{segment-demux-js-C_fPJub3.js → segment-demux-js-DzBx6NN2.js} +1 -1
  21. package/dist/{segment-demux-js-G7wFpHzn.mjs → segment-demux-js-FZbBuk3F.mjs} +1 -1
  22. package/dist/session-decode/{decode-worker-child.js → decode-worker-main.js} +481 -72
  23. package/dist/session-decode/{decode-worker-child.mjs → decode-worker-main.mjs} +482 -71
  24. package/dist/stream-broker/_stub.js +2 -2
  25. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-6IyM-BIn.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-C_i7oFBl.mjs} +2 -2
  26. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DUGQKsKL.mjs +26 -0
  27. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CkbplMHA.mjs +26 -0
  28. package/dist/stream-broker/demux-worker-child.js +1 -1
  29. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  30. package/dist/stream-broker/{hostInit-BBYHWS3M.mjs → hostInit-BPtppL3W.mjs} +2 -2
  31. package/dist/stream-broker/index.js +4 -4
  32. package/dist/stream-broker/index.mjs +4 -4
  33. package/dist/stream-broker/remoteEntry.js +1 -1
  34. package/dist/{worker-protocol-B2MfQLlu.js → worker-protocol-C-G8qmye.js} +3 -1
  35. package/dist/{worker-protocol-C_W-P_g-.mjs → worker-protocol-D_NzPcnh.mjs} +3 -1
  36. package/package.json +3 -2
  37. package/python/inference_pool.py +422 -64
  38. package/python/postprocessors/__init__.py +2 -0
  39. package/python/postprocessors/ssd.py +73 -17
  40. package/python/postprocessors/test_ssd.py +205 -0
  41. package/python/postprocessors/test_yunet.py +292 -0
  42. package/python/postprocessors/testdata/ssdlite_mobiledet_outputs.json +1 -0
  43. package/python/postprocessors/yunet.py +275 -0
  44. package/python/test_inference_pool_compile_off_loop.py +414 -0
  45. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-6IHzlLJ_.mjs +0 -26
  46. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DoyA71_q.mjs +0 -26
@@ -0,0 +1,241 @@
1
+ <!--
2
+ THIRD_PARTY_MODELS.md: the product notice for every model CamStack can download.
3
+
4
+ HAND-WRITTEN FOR NOW. Task 7 of docs/superpowers/plans/2026-09-26-model-license-compliance.md
5
+ replaces this file with generator output (scripts/gen-model-licenses.ts), built from the
6
+ licence records on the model catalogs. Until then this root file is the single source:
7
+ - packages/addon-pipeline, packages/addon-post-analysis, packages/addon-ai and server/backend
8
+ each carry a byte-identical COPY (npm cannot ship a file from outside the package).
9
+ Edit this root file, then copy it: for d in packages/addon-pipeline packages/addon-post-analysis
10
+ packages/addon-ai server/backend; do cp THIRD_PARTY_MODELS.md "$d/"; done
11
+ scripts/check-model-notices-shipped.ts fails CI when a copy drifts.
12
+ - The Hugging Face mirror (camstack/camstack-models) receives this same file, staged by
13
+ hf/camstack-models/upload.sh. Its model card points at the "Source offer" section below.
14
+ Facts: docs/superpowers/specs/2026-09-26-model-license-compliance.md (verified 2026-09-26).
15
+ Not legal advice.
16
+ -->
17
+
18
+ # Third-party models
19
+
20
+ CamStack's own source code is MIT-licensed (see `LICENSE`). CamStack does not
21
+ include model weights in its npm packages or its Docker image. It downloads
22
+ them, on demand, from the locations listed below. **Each model stays under its
23
+ own licence.** Converting a model to another format does not change its
24
+ licence: every CamStack-made build is a modified version (a "model derivative")
25
+ of the upstream weights, and the change is stated per model.
26
+
27
+ Full licence texts: `licenses/models/` in the CamStack source repository, and
28
+ [`LICENSES/`](https://huggingface.co/camstack/camstack-models/tree/main/LICENSES)
29
+ in the model mirror https://huggingface.co/camstack/camstack-models.
30
+
31
+ Some of these models are **not licensed for commercial use**. They are listed
32
+ under [Non-commercial models](#non-commercial-models).
33
+
34
+ ## Required attributions
35
+
36
+ - **Ultralytics YOLO26, YOLOv9 and YOLOv8** — © Ultralytics. Licensed under
37
+ AGPL-3.0 (`AGPL-3.0.txt`). See the [source offer](#source-offer-for-the-agpl-30-weights).
38
+ https://github.com/ultralytics/ultralytics
39
+ - **YOLOv9** (architecture) — Chien-Yao Wang, I-Hau Yeh, Hong-Yuan Mark Liao,
40
+ GPL-3.0 (`GPL-3.0.txt`). https://github.com/WongKinYiu/yolov9
41
+ - **SCRFD / InsightFace** — code MIT. The pretrained weights are released by
42
+ InsightFace for non-commercial research purposes only (`InsightFace-terms.txt`).
43
+ https://github.com/deepinsight/insightface
44
+ - **MobileCLIP** — © Apple Inc. *Apple Machine Learning Research Model is
45
+ licensed under the Apple Machine Learning Research Model License Agreement.*
46
+ (`Apple-AMLR.txt`). CamStack's MobileCLIP files are **Model Derivatives**:
47
+ the image encoders are converted to OpenVINO IR and CoreML at FP16; the text
48
+ encoders are quantised to INT8 ONNX and converted to OpenVINO IR.
49
+ https://github.com/apple/ml-mobileclip
50
+ - **Llama 3.2** — **Built with Llama.** Llama 3.2 is licensed under the Llama
51
+ 3.2 Community License, Copyright © Meta Platforms, Inc. All Rights Reserved.
52
+ (`Llama-3.2-Community.txt`; Acceptable Use Policy:
53
+ https://www.llama.com/llama3_2/use-policy)
54
+ - **fast-plate-ocr** — Copyright (c) 2024 ankandrew, MIT (`MIT-fast-plate-ocr.txt`).
55
+ https://github.com/ankandrew/fast-plate-ocr
56
+ - **RF-DETR** — © Roboflow, Apache-2.0. https://github.com/roboflow/rf-detr
57
+ - **YuNet** — weights Copyright (c) 2020 Shiqi Yu, MIT (`MIT-yunet-reference.txt`).
58
+ https://github.com/opencv/opencv_zoo/tree/main/models/face_detection_yunet ·
59
+ [license](https://github.com/opencv/opencv_zoo/blob/main/models/face_detection_yunet/LICENSE).
60
+ Training code BSD-3-Clause (`BSD-3-Clause.txt`),
61
+ https://github.com/ShiqiYu/libfacedetection.train.
62
+ Trained on WIDER FACE, whose images are CC BY-NC-ND.
63
+ - **AuraFace v1** — fal.ai, Apache-2.0. https://huggingface.co/fal/AuraFace-v1
64
+ - **SigLIP 2** — © Google LLC, Apache-2.0 (`Apache-2.0.txt`).
65
+ https://huggingface.co/google/siglip2-base-patch16-224 ·
66
+ https://github.com/google-research/big_vision. CamStack's SigLIP 2 files are
67
+ modified: the vision input scaling `2x - 1` is baked into the graph, the text
68
+ graph slices its input to the model's 64 positions, the tokenizer lower-cases,
69
+ and the towers are converted to ONNX, OpenVINO IR and CoreML FP16.
70
+ - **EasyOCR** — JaidedAI, Apache-2.0. https://github.com/JaidedAI/EasyOCR
71
+ - **U²-Net** — Xuebin Qin et al., Apache-2.0. https://github.com/xuebinqin/U-2-Net
72
+ - **YAMNet** — © Google LLC, Apache-2.0.
73
+ https://github.com/tensorflow/models/tree/master/research/audioset/yamnet
74
+ - **AIY Vision Birds V1** and the **Coral Edge TPU models** — © Google LLC,
75
+ Apache-2.0. https://github.com/google-coral/test_data
76
+ - **EfficientNet-Lite0** via **timm** — Ross Wightman, Apache-2.0.
77
+ https://github.com/huggingface/pytorch-image-models
78
+ - **torchvision MobileNetV3** — BSD-3-Clause (`BSD-3-Clause.txt`). https://github.com/pytorch/vision
79
+ - **Scrypted plugin models** — Koushik Dutta, repository tagged MIT
80
+ (`MIT-scrypted-plugin-models.txt`). https://huggingface.co/scrypted/plugin-models
81
+ - **Qwen2.5, Qwen3-VL, Qwen3.6** — Alibaba Cloud, Apache-2.0. https://huggingface.co/Qwen
82
+ - **Open Images V7** (animal-classifier training data) — annotations © Google
83
+ LLC, licensed under CC BY 4.0 (`CC-BY-4.0.txt`). Images are listed by Google
84
+ as CC BY 2.0, without warranty.
85
+ https://storage.googleapis.com/openimages/web/factsfigures_v7.html
86
+ - **Vehicle classification dataset** (vehicle-type-v1 training data) — by
87
+ DrBimmer, https://huggingface.co/datasets/DrBimmer/vehicle-classification,
88
+ licensed under CC BY-NC 4.0 (`CC-BY-NC-4.0.txt`). CamStack fine-tuned a model
89
+ on it; the resulting weights are treated as non-commercial.
90
+ - **AudioSet** ontology and labels (YAMNet) — © Google LLC, CC BY 4.0.
91
+ https://research.google.com/audioset/
92
+ - **COCO** annotations (YOLO pretraining) — COCO Consortium, CC BY 4.0. Images
93
+ remain under the terms of their Flickr owners. https://cocodataset.org/#termsofuse
94
+
95
+ ## Source offer for the AGPL-3.0 weights
96
+
97
+ <!--
98
+ This section is the ONE place the source offer is written. The package copies are
99
+ byte-identical copies of this file, and the Hugging Face model card, its LICENSE and its folder
100
+ cards link here instead of repeating it.
101
+ -->
102
+
103
+ The folders `objectDetection/yolo26`, `objectDetection/yolov9`,
104
+ `segmentation/yolo26-seg`, `plateDetection/yolov8-plate` and
105
+ `packageDetection/yolov8-package` of the model mirror hold Ultralytics weights,
106
+ modified by CamStack and distributed under AGPL-3.0. Their Corresponding Source
107
+ is the public CamStack source repository, **https://github.com/camstack/server**
108
+ (MIT), together with the upstream checkpoints it starts from:
109
+
110
+ 1. **The upstream checkpoints**, published by Ultralytics at
111
+ https://github.com/ultralytics/assets/releases: `yolo26{n,s,m,l,x}.pt`,
112
+ `yolov9{t,s,m,c}.pt`, `yolo26{n,s,m}-seg.pt`.
113
+ 2. **The export scripts** in https://github.com/camstack/server:
114
+ `scripts/build-camstack-models.py` (ONNX with a dynamic batch axis, CoreML
115
+ FP16, OpenVINO IR, OpenVINO NNCF INT8) and `scripts/export-models.py`. The
116
+ build instructions (Python environment, invocation, calibration images for
117
+ INT8) are in each script's header.
118
+ 3. **The software** that downloads and runs these weights, CamStack itself, is
119
+ the same repository.
120
+
121
+ What the repository does **not** cover yet:
122
+
123
+ - **Some hosted sizes and input resolutions.** The export scripts do not list
124
+ every variant in the mirror (for example the `-320`/`-256` YOLO26 exports,
125
+ `yolov9m`/`yolov9c`, and the `yolo26*-seg` models). Each one is the same
126
+ Ultralytics `export()` with a different model id or `imgsz`, but no script in
127
+ the repository reproduces it as-is.
128
+ - **`yolov8n-plate` has no training checkpoint.** It is a third-party model
129
+ (trained 2023-12-05 according to its own metadata, origin not identified).
130
+ The ONNX file is the only form CamStack has.
131
+ - **The `yolov8n-package` checkpoint is not published yet.** CamStack
132
+ fine-tuned it with Ultralytics.
133
+
134
+ ## Non-commercial models
135
+
136
+ These are downloaded by default or selectable, and their terms **do not allow
137
+ commercial use**:
138
+
139
+ | Model | Terms |
140
+ | --- | --- |
141
+ | `scrfd-2.5g` (face detection, selectable, not the default since 2026-09-26) | InsightFace pretrained models: non-commercial research purposes only |
142
+ | `mobileclip-s1`, `mobileclip-s2`, `mobileclip-s1-text`, `mobileclip-s2-text` (semantic search, `mobileclip-s1` default) | Apple Machine Learning Research Model License: research purposes only, no commercial product or service |
143
+ | `vehicle-type-v1` (vehicle classifier) | trained on a CC BY-NC 4.0 dataset; weights treated as non-commercial |
144
+ | `bird-nabirds-404` (hidden, pending removal) | NABirds: no reproduction, distribution or products without the Cornell Lab's written permission |
145
+
146
+ ## Models
147
+
148
+ "Mirror" means https://huggingface.co/camstack/camstack-models, folder given.
149
+ "Code / weights" gives the two licences separately because they often differ.
150
+ **Unknown** means no licence could be traced; it does not mean free to use.
151
+
152
+ ### Object detection
153
+
154
+ | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
155
+ | --- | --- | --- | --- | --- | --- |
156
+ | `yolo26n`, `yolo26s`, `yolo26m`, `yolo26l`, `yolo26x`, with every `-fp16`, `-int8`, `-320`, `-256`, `-320-int8`, `-256-int8` variant | Ultralytics YOLO26, COCO-pretrained | AGPL-3.0 / AGPL-3.0 | COCO 2017 (annotations CC BY 4.0) | exported to ONNX, OpenVINO IR (FP32/FP16) and CoreML FP16; `-320`/`-256` re-exported at that input size; `-int8` OpenVINO NNCF post-training INT8 | Mirror `objectDetection/yolo26` |
157
+ | `yolov9{t,s,m,c}-320`, `yolov9{t,s,m,c}-640`, and their `-int8` twins | Ultralytics YOLOv9 weights, COCO-pretrained; architecture by WongKinYiu | AGPL-3.0 / AGPL-3.0 (original YOLOv9 repository GPL-3.0) | COCO 2017 | exported to ONNX, OpenVINO IR FP16 and CoreML at 320 and 640; `-int8` NNCF INT8 | Mirror `objectDetection/yolov9` |
158
+ | `ssd-mobilenet-v2-coco-edgetpu`, `efficientdet-lite0-edgetpu` | Google Coral `test_data` | Apache-2.0 / Apache-2.0 | COCO | none | https://github.com/google-coral/test_data |
159
+ | `ssdlite-mobiledet-coco-edgetpu` (selectable, not the default) | Google Coral `test_data`, `ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite` (sha256 `b69e508e…434a2e`); MobileDets (Xiong et al., CVPR 2021) trained with the TensorFlow Object Detection API, https://github.com/tensorflow/models/tree/master/research/object_detection | Apache-2.0 / Apache-2.0 (`Apache-2.0.txt`; https://github.com/google-coral/test_data/blob/master/LICENSE) | COCO 2017 (annotations CC BY 4.0, images under Flickr terms) | none: mirrored byte for byte, with the CPU build and `coco_labels.txt` beside it (`scripts/build-ssdlite-mobiledet-model.py`) | Mirror `objectDetection/ssdlite-mobiledet` |
160
+
161
+ ### Package detection
162
+
163
+ | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
164
+ | --- | --- | --- | --- | --- | --- |
165
+ | `rfdetr-package` | Roboflow RF-DETR-M | Apache-2.0 / Apache-2.0 | fine-tuning set not recorded (unverified) | fine-tuned to 2 classes at 576; exported to ONNX, OpenVINO IR and CoreML; training checkpoint `.pth` also published | Mirror `packageDetection/rfdetr-package` |
166
+ | `yolov8n-package` | Ultralytics YOLOv8n | AGPL-3.0 / AGPL-3.0 | most likely Roboflow Universe `package-at-front-door` (unverified) | fine-tuned by CamStack with Ultralytics; exported to ONNX, OpenVINO IR and CoreML | Mirror `packageDetection/yolov8-package` |
167
+
168
+ ### Face detection
169
+
170
+ | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
171
+ | --- | --- | --- | --- | --- | --- |
172
+ | `scrfd-2.5g` | InsightFace SCRFD 2.5G (bnkps), via the ONNX re-upload `RuteNL/SCRFD-face-detection-ONNX` | MIT / **InsightFace: non-commercial research only** | WIDER FACE (research-oriented terms) | converted to OpenVINO IR and CoreML FP16 | Mirror `faceDetection/scrfd` |
173
+ | `yunet-2023mar` (face-detection default since 2026-09-26) | OpenCV Zoo YuNet 2023mar, `face_detection_yunet_2023mar.onnx` (fp32), https://github.com/opencv/opencv_zoo/tree/main/models/face_detection_yunet | BSD-3-Clause (training code, https://github.com/ShiqiYu/libfacedetection.train; `BSD-3-Clause.txt`) / MIT, Copyright (c) 2020 Shiqi Yu (opencv_zoo; `MIT-yunet-reference.txt`; https://github.com/opencv/opencv_zoo/blob/main/models/face_detection_yunet/LICENSE) | WIDER FACE (images CC BY-NC-ND) | input contract baked into the graph: the pool's RGB /255 becomes the upstream BGR 0..255 (`Mul(255)` plus a channel `Gather`); internal tensor names cleared in the OpenVINO IR; ONNX fp32, OpenVINO IR fp32, CoreML fp16 (`scripts/build-yunet-model.py`) | Mirror `faceDetection/yunet` |
174
+ | `scrypted-yolov9t-face` (retired from the catalog, D643; nothing downloads it) | Scrypted `plugin-models` (YOLOv9t ReLU face) | repository tagged MIT; YOLOv9 architecture GPL-3.0 upstream / **Unknown** per model | unknown | OpenVINO IR converted by CamStack | its OpenVINO IR is still on mirror `faceDetection/scrypted-yolov9-face` |
175
+ | `ssd-mobilenet-v2-face-edgetpu` (hidden) | Google Coral `test_data` | Apache-2.0 / Apache-2.0 | — | none | https://github.com/google-coral/test_data |
176
+
177
+ ### Face recognition
178
+
179
+ | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
180
+ | --- | --- | --- | --- | --- | --- |
181
+ | `arcface-r100` (a ResNet34) | re-upload `onnx-community/arcface-onnx` (itself pointing at `garavv/arcface-onnx`); original author not stated | **Unknown** / **Unknown** | not stated | converted to OpenVINO IR and CoreML FP16 | Mirror `faceRecognition/arcface` |
182
+ | `auraface-r100` | fal.ai AuraFace v1 (`glintr100.onnx` only) | Apache-2.0 / Apache-2.0 | stated upstream as commercially and publicly available sources | input scaling `y = 2x - 1` baked ahead of the first Conv (`scripts/build-auraface-model.py`); converted to OpenVINO IR and CoreML FP16 | Mirror `faceRecognition/auraface` |
183
+ | `inception-resnet-v1` | Scrypted `plugin-models` | repository tagged MIT / **Unknown** per model | not stated | OpenVINO IR converted by CamStack | ONNX and CoreML: https://huggingface.co/scrypted/plugin-models · OpenVINO: mirror `faceRecognition/inception-resnet-v1` |
184
+
185
+ ### Licence plate detection and OCR
186
+
187
+ | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
188
+ | --- | --- | --- | --- | --- | --- |
189
+ | `yolov8n-plate` | Ultralytics YOLOv8n fine-tuned for plates by a third party (trained 2023-12-05 per its metadata) | AGPL-3.0 / AGPL-3.0 | **unknown** | converted to OpenVINO IR, CoreML and TFLite fp32 (`tflite/camstack-yolov8n-plate_float32.tflite`, mirrored but not referenced by the catalog) | Mirror `plateDetection/yolov8-plate` |
190
+ | `cct-s-v2-global` | `ankandrew/fast-plate-ocr` release model | MIT / MIT | private, not released upstream | input head removed (recorded in the ONNX `doc_string`); converted to OpenVINO IR and CoreML | Mirror `plateRecognition/cct-s-v2-global` |
191
+ | `vgg-english-g2` | JaidedAI EasyOCR, via Scrypted `plugin-models` | Apache-2.0 / Apache-2.0 | — | OpenVINO IR converted by CamStack | ONNX and CoreML: https://huggingface.co/scrypted/plugin-models · OpenVINO: mirror `plateRecognition/vgg_english_g2` |
192
+
193
+ ### Classifiers
194
+
195
+ | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
196
+ | --- | --- | --- | --- | --- | --- |
197
+ | `animal-classifier` | timm EfficientNet-Lite0 | Apache-2.0 / Apache-2.0 | Open Images V7 animal subset (annotations CC BY 4.0, © Google LLC) | fine-tuned by CamStack (8 classes); exported to ONNX, OpenVINO IR and CoreML | Mirror `animalClassification/animal-classifier` |
198
+ | `animals-10` (hidden, pending removal) | origin not identified | **Unknown** / **Unknown** | unknown | converted to ONNX, OpenVINO IR and CoreML | Mirror `animalClassification/animals-10` |
199
+ | `bird-classifier` | Google AIY Vision `birds_V1` | Apache-2.0 / Apache-2.0 | — | converted from TensorFlow with tf2onnx; OpenVINO IR and CoreML derived from it | Mirror `animalClassification/bird-classifier` |
200
+ | `bird-classifier-aiy-edgetpu` (hidden) | Google Coral `test_data` | Apache-2.0 / Apache-2.0 | — | none | https://github.com/google-coral/test_data |
201
+ | `bird-nabirds-404` (hidden, pending removal) | ResNet50 trained on NABirds (origin not recorded) | **Unknown** / NABirds: no products without Cornell Lab permission | NABirds (Cornell Lab of Ornithology) | converted to ONNX, OpenVINO IR and CoreML | Mirror `animalClassification/bird-nabirds` |
202
+ | `vehicle-type-v1` | torchvision MobileNetV3-Large | BSD-3-Clause / **CC BY-NC 4.0** (from its data) | DrBimmer `vehicle-classification`, CC BY-NC 4.0 | fine-tuned by CamStack (8 classes); exported to ONNX, OpenVINO IR and CoreML | Mirror `vehicleClassification/vehicle-type-v1` |
203
+ | `vehicle-type-efficientnet` (hidden, pending removal) | trained on VMMRdb (origin not recorded) | **Unknown** / VMMRdb terms unverified | VMMRdb | converted to ONNX, OpenVINO IR and CoreML | Mirror `vehicleClassification/efficientnet` |
204
+
205
+ ### Semantic search (CLIP)
206
+
207
+ | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
208
+ | --- | --- | --- | --- | --- | --- |
209
+ | `mobileclip-s1`, `mobileclip-s2` (image) | Apple `ml-mobileclip` | MIT / **Apple Machine Learning Research Model License** | per Apple | Model Derivative: converted to OpenVINO IR and CoreML FP16 | Mirror `clip/mobileclip-s1`, `clip/mobileclip-s2` |
210
+ | `mobileclip-s1-text`, `mobileclip-s2-text` | Apple `ml-mobileclip`, with the CLIP tokenizer | MIT / **Apple Machine Learning Research Model License** | per Apple | Model Derivative: quantised to INT8 ONNX and converted to OpenVINO IR | Mirror `clip/mobileclip-s1`, `clip/mobileclip-s2` |
211
+ | `siglip2-b16-224` (image) | Google SigLIP 2 base patch16-224 (`google/siglip2-base-patch16-224`) | Apache-2.0 / Apache-2.0 | WebLI (Google internal, not released) | input scaling `y = 2x - 1` baked ahead of the patch embedding; converted to OpenVINO IR and CoreML FP16 (an FP32 ONNX is hosted as the verification reference) (`scripts/build-siglip2-model.py`) | Mirror `clip/siglip2` |
212
+ | `siglip2-b16-224-text` | Google SigLIP 2 base patch16-224, with its Gemma tokenizer | Apache-2.0 / Apache-2.0 | WebLI (Google internal, not released) | input sliced to the model's 64 positions in the graph; ONNX weights FP16, OpenVINO IR and CoreML FP16; a `Lowercase` normalizer prepended to the tokenizer | Mirror `clip/siglip2` |
213
+
214
+ ### Segmentation
215
+
216
+ | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
217
+ | --- | --- | --- | --- | --- | --- |
218
+ | `u2netp` | `xuebinqin/U-2-Net` | Apache-2.0 / Apache-2.0 | DUTS-TR (terms not checked) | converted to ONNX, OpenVINO IR and CoreML | Mirror `segmentationRefiner/u2netp` |
219
+ | `yolo26n-seg`, `yolo26s-seg`, `yolo26m-seg` | Ultralytics YOLO26-seg, COCO-pretrained | AGPL-3.0 / AGPL-3.0 | COCO 2017 | exported to ONNX, OpenVINO IR and CoreML | Mirror `segmentation/yolo26-seg` |
220
+
221
+ ### Audio
222
+
223
+ | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
224
+ | --- | --- | --- | --- | --- | --- |
225
+ | `yamnet-onnx` | `tensorflow/models` `research/audioset/yamnet` | Apache-2.0 / Apache-2.0 | AudioSet (labels CC BY 4.0, © Google LLC) | converted from TensorFlow with tf2onnx; OpenVINO IR derived from it | Mirror `audioClassification/yamnet` |
226
+ | `apple-soundanalysis` | Apple SoundAnalysis, built into macOS | under Apple's macOS licence | — | nothing downloaded | built in |
227
+
228
+ ### Language and vision-language models (AI addon, not hosted by CamStack)
229
+
230
+ | Catalog ids | Upstream | Code / weights | CamStack changes | Downloaded from |
231
+ | --- | --- | --- | --- | --- |
232
+ | `llm-qwen2.5-1.5b-instruct-q4` | Qwen2.5 1.5B Instruct | — / Apache-2.0 | none (GGUF Q4_K_M by Qwen) | https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct-GGUF |
233
+ | `llm-llama3.2-3b-instruct-q4` | Meta Llama 3.2 3B Instruct | — / Llama 3.2 Community License | none by CamStack (GGUF Q4_K_M by bartowski) | https://huggingface.co/bartowski/Llama-3.2-3B-Instruct-GGUF |
234
+ | `llm-qwen3-vl-2b-instruct-q4`, `llm-qwen3-vl-4b-instruct-q4`, `llm-qwen3-vl-8b-instruct-q4` | Qwen3-VL Instruct | — / Apache-2.0 | none by CamStack (GGUF by unsloth) | https://huggingface.co/unsloth (`Qwen3-VL-{2B,4B,8B}-Instruct-GGUF`) |
235
+ | `llm-qwen3.6-35b-a3b-ud-q4` | Qwen3.6 35B-A3B | — / Apache-2.0 | none by CamStack (GGUF UD-Q4_K_M by unsloth) | https://huggingface.co/unsloth/Qwen3.6-35B-A3B-GGUF |
236
+
237
+ ### Your own models
238
+
239
+ A model you import through Model Studio (uploaded, converted, or pulled from
240
+ Frigate+ or Scrypted) keeps whatever licence its author published. CamStack
241
+ does not change it and does not record it.
@@ -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-CJR259Xf.js");
7
- const require_process_memory = require("../process-memory-BJUXvTjd.js");
6
+ const require_dist = require("../dist-8up-f2TX.js");
7
+ const require_process_memory = require("../process-memory-CX_92V_r.js");
8
8
  let node_fs = require("node:fs");
9
9
  node_fs = require_chunk.__toESM(node_fs);
10
10
  let node_path = require("node:path");
@@ -1,6 +1,6 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { $t as errMsg, A as PoolMemoryWatchdog, Ln as EventCategory, T as HF_BASE_URL, U as audioAnalysisCapability, Ut as resolvePoolMemoryPolicy, W as audioAnalyzerCapability, bn as nodePin, d as DEFAULT_AUDIO_ANALYZER_CONFIG, dn as audioChunkBytesPerSample, gn as hydrateSchema, hn as expandAudioChunkToF32le, n as AUDIO_BACKEND_CHOICES, on as BaseAddon, yt as mapAudioLabelToMacro } from "../dist-RXbmRAwP.mjs";
3
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-BgFOHFnx.mjs";
2
+ import { E as HF_BASE_URL, G as audioAnalyzerCapability, Gt as resolvePoolMemoryPolicy, Sn as nodePin, W as audioAnalysisCapability, _n as expandAudioChunkToF32le, bt as mapAudioLabelToMacro, cn as BaseAddon, f as DEFAULT_AUDIO_ANALYZER_CONFIG, j as PoolMemoryWatchdog, n as AUDIO_BACKEND_CHOICES, pn as audioChunkBytesPerSample, tn as errMsg, vn as hydrateSchema, zn as EventCategory } from "../dist-CCd0Q3nr.mjs";
3
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DFC_O5zE.mjs";
4
4
  import * as fs from "node:fs";
5
5
  import * as path$1 from "node:path";
6
6
  import { downloadFile } from "@camstack/system/addon-utils";
@@ -1,4 +1,4 @@
1
- import { G as audioKindId, l as COCO_80_LABELS, mt as hfModelUrl, r as AUDIO_MACRO_LABELS, u as COCO_TO_MACRO } from "./dist-RXbmRAwP.mjs";
1
+ import { K as audioKindId, d as COCO_TO_MACRO, ht as hfModelUrl, r as AUDIO_MACRO_LABELS, u as COCO_80_LABELS } from "./dist-CCd0Q3nr.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  //#region src/detection-pipeline/pipeline/landmark-precision-gate.ts
4
4
  /**
@@ -384,6 +384,24 @@ var OBJECT_DETECTION_MODELS = [
384
384
  runtimes: ["python"]
385
385
  } }
386
386
  },
387
+ {
388
+ id: "ssdlite-mobiledet-coco-edgetpu",
389
+ name: "SSDLite MobileDet (Coral)",
390
+ description: "SSDLite MobileDet COCO (QAT) — EdgeTPU-compiled full-integer TFLite, 320×320; runs on the Coral USB Edge TPU. More accurate than SSD MobileNet V2 (32.9 vs 25.6 % COCO mAP, Coral-published). Scores top out near 0.77.",
391
+ inputSize: {
392
+ width: 320,
393
+ height: 320
394
+ },
395
+ labels: [],
396
+ preprocessMode: "letterbox",
397
+ postprocessor: "ssd",
398
+ license: "Apache-2.0",
399
+ formats: { tflite: {
400
+ url: hf("objectDetection/ssdlite-mobiledet/edgetpu/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite"),
401
+ sizeMB: 5.1,
402
+ runtimes: ["python"]
403
+ } }
404
+ },
387
405
  ovPrecisionVariant("yolo26n", "objectDetection/yolo26/openvino", "YOLO26 Nano", "fp16", 5, true),
388
406
  ovPrecisionVariant("yolo26n", "objectDetection/yolo26/openvino", "YOLO26 Nano", "int8", 3),
389
407
  ovPrecisionVariant("yolo26s", "objectDetection/yolo26/openvino", "YOLO26 Small", "fp16", 19, true),
@@ -502,57 +520,90 @@ var OBJECT_DETECTION_MODELS = [
502
520
  * A retired id resolves to the step's format default instead.
503
521
  */
504
522
  var RETIRED_MODEL_IDS = { "face-detection": ["scrypted-yolov9t-face"] };
505
- var FACE_DETECTION_MODELS = [{
506
- id: "scrfd-2.5g",
507
- name: "SCRFD 2.5G",
508
- description: "SCRFD 2.5G bnkps — balanced face detection with 5 keypoints (WIDER FACE 93.80/92.02/77.13). InsightFace pretrained weights.",
509
- inputSize: {
510
- width: 640,
511
- height: 640
523
+ var FACE_DETECTION_MODELS = [
524
+ {
525
+ id: "scrfd-2.5g",
526
+ name: "SCRFD 2.5G",
527
+ description: "SCRFD 2.5G bnkps — balanced face detection with 5 keypoints (WIDER FACE 93.80/92.02/77.13). InsightFace pretrained weights.",
528
+ inputSize: {
529
+ width: 640,
530
+ height: 640
531
+ },
532
+ labels: [{
533
+ id: "face",
534
+ name: "Face"
535
+ }],
536
+ preprocessMode: "letterbox",
537
+ inputNormalization: "scrfd",
538
+ license: "InsightFace-NonCommercial-Research",
539
+ formats: {
540
+ onnx: {
541
+ url: hf("faceDetection/scrfd/onnx/camstack-scrfd-2.5g.onnx"),
542
+ sizeMB: 3.1
543
+ },
544
+ coreml: {
545
+ url: hf("faceDetection/scrfd/coreml/camstack-scrfd-2.5g.mlpackage"),
546
+ sizeMB: 1.7,
547
+ isDirectory: true,
548
+ files: [...MLPACKAGE_FILES],
549
+ runtimes: ["python"]
550
+ },
551
+ openvino: ovFormat(hf("faceDetection/scrfd/openvino/camstack-scrfd-2.5g.xml"), 1.8)
552
+ }
512
553
  },
513
- labels: [{
514
- id: "face",
515
- name: "Face"
516
- }],
517
- preprocessMode: "letterbox",
518
- inputNormalization: "scrfd",
519
- license: "InsightFace-NonCommercial-Research",
520
- formats: {
521
- onnx: {
522
- url: hf("faceDetection/scrfd/onnx/camstack-scrfd-2.5g.onnx"),
523
- sizeMB: 3.1
554
+ {
555
+ id: "yunet-2023mar",
556
+ name: "YuNet 2023mar",
557
+ description: "YuNet (OpenCV Zoo, 2023mar) — tiny face detector with 5 keypoints, MIT weights (WIDER FACE AP 0.884/0.866/0.750). ~0.2 MB. Trained on WIDER FACE (CC BY-NC-ND images).",
558
+ inputSize: {
559
+ width: 640,
560
+ height: 640
524
561
  },
525
- coreml: {
526
- url: hf("faceDetection/scrfd/coreml/camstack-scrfd-2.5g.mlpackage"),
527
- sizeMB: 1.7,
528
- isDirectory: true,
529
- files: [...MLPACKAGE_FILES],
530
- runtimes: ["python"]
562
+ labels: [{
563
+ id: "face",
564
+ name: "Face"
565
+ }],
566
+ preprocessMode: "letterbox",
567
+ postprocessor: "yunet",
568
+ license: "MIT",
569
+ formats: {
570
+ onnx: {
571
+ url: hf("faceDetection/yunet/onnx/camstack-yunet-2023mar.onnx"),
572
+ sizeMB: .23
573
+ },
574
+ coreml: {
575
+ url: hf("faceDetection/yunet/coreml/camstack-yunet-2023mar.mlpackage"),
576
+ sizeMB: .2,
577
+ isDirectory: true,
578
+ files: [...MLPACKAGE_FILES],
579
+ runtimes: ["python"]
580
+ },
581
+ openvino: ovFormat(hf("faceDetection/yunet/openvino/camstack-yunet-2023mar.xml"), .36)
582
+ }
583
+ },
584
+ {
585
+ id: "ssd-mobilenet-v2-face-edgetpu",
586
+ legacy: true,
587
+ name: "SSD MobileNet V2 Face (Coral)",
588
+ description: "SSD MobileNet V2 face detector — EdgeTPU-compiled full-integer TFLite, 320×320; runs on the Coral USB Edge TPU. Requires an ssd-face postprocessor (not yet available).",
589
+ inputSize: {
590
+ width: 320,
591
+ height: 320
531
592
  },
532
- openvino: ovFormat(hf("faceDetection/scrfd/openvino/camstack-scrfd-2.5g.xml"), 1.8)
593
+ labels: [{
594
+ id: "face",
595
+ name: "Face"
596
+ }],
597
+ preprocessMode: "letterbox",
598
+ postprocessor: "ssd",
599
+ license: "Apache-2.0",
600
+ formats: { tflite: {
601
+ url: "https://github.com/google-coral/test_data/raw/master/ssd_mobilenet_v2_face_quant_postprocess_edgetpu.tflite",
602
+ sizeMB: 6.7,
603
+ runtimes: ["python"]
604
+ } }
533
605
  }
534
- }, {
535
- id: "ssd-mobilenet-v2-face-edgetpu",
536
- legacy: true,
537
- name: "SSD MobileNet V2 Face (Coral)",
538
- description: "SSD MobileNet V2 face detector — EdgeTPU-compiled full-integer TFLite, 320×320; runs on the Coral USB Edge TPU. Requires an ssd-face postprocessor (not yet available).",
539
- inputSize: {
540
- width: 320,
541
- height: 320
542
- },
543
- labels: [{
544
- id: "face",
545
- name: "Face"
546
- }],
547
- preprocessMode: "letterbox",
548
- postprocessor: "ssd",
549
- license: "Apache-2.0",
550
- formats: { tflite: {
551
- url: "https://github.com/google-coral/test_data/raw/master/ssd_mobilenet_v2_face_quant_postprocess_edgetpu.tflite",
552
- sizeMB: 6.7,
553
- runtimes: ["python"]
554
- } }
555
- }];
606
+ ];
556
607
  var FACE_EMBEDDING_MODELS = [
557
608
  {
558
609
  id: "arcface-r100",
@@ -1133,55 +1184,84 @@ var INSTANCE_SEGMENTATION_MODELS = [
1133
1184
  }
1134
1185
  }
1135
1186
  ];
1136
- var CLIP_EMBEDDING_MODELS = [{
1137
- id: "mobileclip-s1",
1138
- name: "MobileCLIP S1",
1139
- description: "MobileCLIP S1 — Apple balanced CLIP vision encoder, 512-dim, 256×256 (fp16 OpenVINO/CoreML)",
1140
- inputSize: {
1141
- width: 256,
1142
- height: 256
1187
+ var CLIP_EMBEDDING_MODELS = [
1188
+ {
1189
+ id: "mobileclip-s1",
1190
+ name: "MobileCLIP S1",
1191
+ description: "MobileCLIP S1 — Apple balanced CLIP vision encoder, 512-dim, 256×256 (fp16 OpenVINO/CoreML)",
1192
+ inputSize: {
1193
+ width: 256,
1194
+ height: 256
1195
+ },
1196
+ labels: [{
1197
+ id: "embedding",
1198
+ name: "CLIP Embedding"
1199
+ }],
1200
+ preprocessMode: "resize",
1201
+ inputNormalization: "none",
1202
+ formats: {
1203
+ openvino: ovFormat(hf("clip/mobileclip-s1/openvino/camstack-mobileclip-s1-vision.xml"), 55),
1204
+ coreml: {
1205
+ url: hf("clip/mobileclip-s1/coreml/camstack-mobileclip-s1-vision.mlpackage"),
1206
+ sizeMB: 65,
1207
+ isDirectory: true,
1208
+ files: [...MLPACKAGE_FILES],
1209
+ runtimes: ["python"]
1210
+ }
1211
+ }
1143
1212
  },
1144
- labels: [{
1145
- id: "embedding",
1146
- name: "CLIP Embedding"
1147
- }],
1148
- preprocessMode: "resize",
1149
- inputNormalization: "none",
1150
- formats: {
1151
- openvino: ovFormat(hf("clip/mobileclip-s1/openvino/camstack-mobileclip-s1-vision.xml"), 55),
1152
- coreml: {
1153
- url: hf("clip/mobileclip-s1/coreml/camstack-mobileclip-s1-vision.mlpackage"),
1154
- sizeMB: 65,
1155
- isDirectory: true,
1156
- files: [...MLPACKAGE_FILES],
1157
- runtimes: ["python"]
1213
+ {
1214
+ id: "mobileclip-s2",
1215
+ name: "MobileCLIP S2",
1216
+ description: "MobileCLIP S2 — Apple high-accuracy CLIP vision encoder, 512-dim, 256×256 (fp16 OpenVINO/CoreML)",
1217
+ inputSize: {
1218
+ width: 256,
1219
+ height: 256
1220
+ },
1221
+ labels: [{
1222
+ id: "embedding",
1223
+ name: "CLIP Embedding"
1224
+ }],
1225
+ preprocessMode: "resize",
1226
+ inputNormalization: "none",
1227
+ formats: {
1228
+ openvino: ovFormat(hf("clip/mobileclip-s2/openvino/camstack-mobileclip-s2-vision.xml"), 90),
1229
+ coreml: {
1230
+ url: hf("clip/mobileclip-s2/coreml/camstack-mobileclip-s2-vision.mlpackage"),
1231
+ sizeMB: 110,
1232
+ isDirectory: true,
1233
+ files: [...MLPACKAGE_FILES],
1234
+ runtimes: ["python"]
1235
+ }
1158
1236
  }
1159
- }
1160
- }, {
1161
- id: "mobileclip-s2",
1162
- name: "MobileCLIP S2",
1163
- description: "MobileCLIP S2 — Apple high-accuracy CLIP vision encoder, 512-dim, 256×256 (fp16 OpenVINO/CoreML)",
1164
- inputSize: {
1165
- width: 256,
1166
- height: 256
1167
1237
  },
1168
- labels: [{
1169
- id: "embedding",
1170
- name: "CLIP Embedding"
1171
- }],
1172
- preprocessMode: "resize",
1173
- inputNormalization: "none",
1174
- formats: {
1175
- openvino: ovFormat(hf("clip/mobileclip-s2/openvino/camstack-mobileclip-s2-vision.xml"), 90),
1176
- coreml: {
1177
- url: hf("clip/mobileclip-s2/coreml/camstack-mobileclip-s2-vision.mlpackage"),
1178
- sizeMB: 110,
1179
- isDirectory: true,
1180
- files: [...MLPACKAGE_FILES],
1181
- runtimes: ["python"]
1238
+ {
1239
+ id: "siglip2-b16-224",
1240
+ name: "SigLIP2 B/16",
1241
+ description: "Google SigLIP2 base, patch 16, 224×224 — Apache-2.0 CLIP vision encoder, 768-dim (fp16 OpenVINO/CoreML)",
1242
+ inputSize: {
1243
+ width: 224,
1244
+ height: 224
1245
+ },
1246
+ labels: [{
1247
+ id: "embedding",
1248
+ name: "CLIP Embedding"
1249
+ }],
1250
+ preprocessMode: "resize",
1251
+ inputNormalization: "none",
1252
+ license: "Apache-2.0",
1253
+ formats: {
1254
+ openvino: ovFormat(hf("clip/siglip2/openvino/camstack-siglip2-b16-224-vision.xml"), 186),
1255
+ coreml: {
1256
+ url: hf("clip/siglip2/coreml/camstack-siglip2-b16-224-vision.mlpackage"),
1257
+ sizeMB: 185,
1258
+ isDirectory: true,
1259
+ files: [...MLPACKAGE_FILES],
1260
+ runtimes: ["python"]
1261
+ }
1182
1262
  }
1183
1263
  }
1184
- }];
1264
+ ];
1185
1265
  var AUDIO_CLASSIFIER_MODELS = [{
1186
1266
  id: "yamnet-onnx",
1187
1267
  name: "YAMNet",
@@ -1574,7 +1654,8 @@ var STEP_FACE_DETECTION = new PipelineStepBase({
1574
1654
  inputClasses: ["person"],
1575
1655
  outputClasses: ["face"],
1576
1656
  models: [...FACE_DETECTION_MODELS],
1577
- defaultModelId: "scrfd-2.5g",
1657
+ defaultModelId: "yunet-2023mar",
1658
+ defaultModelIdByFormat: { tflite: "scrfd-2.5g" },
1578
1659
  defaultConfidence: .5,
1579
1660
  defaultMinParentScore: .7,
1580
1661
  cadence: {
@@ -1619,7 +1700,7 @@ var STEP_FACE_EMBEDDING = new FaceEmbeddingStep({
1619
1700
  outputClasses: ["identity"],
1620
1701
  labelTier: 2,
1621
1702
  models: [...FACE_EMBEDDING_MODELS],
1622
- defaultModelId: "arcface-r100",
1703
+ defaultModelId: "auraface-r100",
1623
1704
  modelScope: "cluster",
1624
1705
  defaultConfidence: 0,
1625
1706
  cadence: {
@@ -1819,11 +1900,12 @@ function getStepDefinition(stepId) {
1819
1900
  * has a build for `format`.
1820
1901
  * 2. `def.defaultModelId` — the step's plain declared default — if it
1821
1902
  * exists in `def.models` AND has a build for `format`.
1822
- * 3. The smallest-by-size model among those with a `format` build
1823
- * (legacy fallback, preserved for steps/formats with no declared
1903
+ * 3. The smallest-by-size NON-legacy model among those with a `format`
1904
+ * build (fallback, preserved for steps/formats with no declared
1824
1905
  * preference reachable).
1825
- * 4. `def.defaultModelId` unchanged, when ZERO models have a `format`
1826
- * build — an unloadable case flagged elsewhere, not resolved here.
1906
+ * 4. When NO non-legacy model has a `format` build — an unloadable case
1907
+ * flagged elsewhere, not resolved here — the declared per-format id if
1908
+ * there is one, else `def.defaultModelId`, unchanged.
1827
1909
  */
1828
1910
  function getDefaultModelForFormat(stepId, format) {
1829
1911
  return getDefaultModelForFormatFromDef(getStepDefinition(stepId), format);
@@ -1841,7 +1923,7 @@ function getDefaultModelForFormatFromDef(def, format) {
1841
1923
  if (declaredForFormat !== void 0 && hasFormatBuild(declaredForFormat)) return declaredForFormat;
1842
1924
  if (hasFormatBuild(def.defaultModelId)) return def.defaultModelId;
1843
1925
  const available = def.models.filter((m) => m.formats[format] && m.legacy !== true);
1844
- if (available.length === 0) return def.defaultModelId;
1926
+ if (available.length === 0) return declaredForFormat ?? def.defaultModelId;
1845
1927
  return [...available].toSorted((a, b) => {
1846
1928
  return (a.formats[format]?.sizeMB ?? Infinity) - (b.formats[format]?.sizeMB ?? Infinity);
1847
1929
  })[0].id;