utterpy 0.0.6__cp39-abi3-win_amd64.whl

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.
utterpy/__init__.py ADDED
@@ -0,0 +1,23 @@
1
+ """Python bindings for utter with the vosk wheel's object surface."""
2
+
3
+ from ._utterpy import (
4
+ UTTER_REVISION,
5
+ UTTER_VERSION,
6
+ KaldiRecognizer,
7
+ Model,
8
+ Recognizer,
9
+ SetLogLevel,
10
+ SpkModel,
11
+ __version__,
12
+ )
13
+
14
+ __all__ = [
15
+ "UTTER_REVISION",
16
+ "UTTER_VERSION",
17
+ "KaldiRecognizer",
18
+ "Model",
19
+ "Recognizer",
20
+ "SetLogLevel",
21
+ "SpkModel",
22
+ "__version__",
23
+ ]
utterpy/__init__.pyi ADDED
@@ -0,0 +1,95 @@
1
+ from typing import Any, final
2
+
3
+ __all__ = [
4
+ "UTTER_REVISION",
5
+ "UTTER_VERSION",
6
+ "KaldiRecognizer",
7
+ "Model",
8
+ "Recognizer",
9
+ "SetLogLevel",
10
+ "SpkModel",
11
+ "__version__",
12
+ ]
13
+
14
+ __version__: str
15
+ UTTER_REVISION: str
16
+ UTTER_VERSION: str
17
+
18
+ @final
19
+ class Model:
20
+ def __new__(cls, path: str) -> Model: ...
21
+ def FindWord(self, word: str) -> int:
22
+ """Word id for a word, -1 when the model does not know it (vosk's FindWord)."""
23
+
24
+ @final
25
+ class SpkModel:
26
+ """vosk's SpkModel: a speaker model directory, the vosk-model-spk-0.4 layout or TitaNet-small."""
27
+
28
+ def __new__(cls, path: str) -> SpkModel: ...
29
+ def dim(self) -> int:
30
+ """The length of the speaker vector."""
31
+
32
+ def embed(self, data: bytes, sample_rate: float = 16000.0) -> list[float]:
33
+ """The TitaNet embedding of a span without a recognizer.
34
+
35
+ Little-endian float32 samples in [-1, 1] at sample_rate Hz, 16 kHz or faster.
36
+ ValueError for an x-vector model, and on a span under 25 ms or over 30 s.
37
+ """
38
+
39
+ @final
40
+ class KaldiRecognizer:
41
+ """vosk's KaldiRecognizer: a streaming recognizer over one model and one grammar."""
42
+
43
+ def __new__(
44
+ cls,
45
+ model: Model,
46
+ sample_rate: float,
47
+ grammar: str,
48
+ unknown_cost: float | None = None,
49
+ spk_model: SpkModel | None = None,
50
+ ) -> KaldiRecognizer:
51
+ """The grammar is a JSON array of strings as vosk takes it."""
52
+
53
+ def SetSpkModel(self, spk_model: SpkModel | None) -> None:
54
+ """vosk's SetSpkModel; None removes it. Audio already fed in the current stream counts.
55
+
56
+ While set, a span of at least 25 pooled 10 ms frames carries "spk", "spk_frames",
57
+ "spk_start" and "spk_end" at the top level and on every word entry. A TitaNet model
58
+ puts them on word entries only.
59
+ """
60
+
61
+ def SetWords(self, on: Any) -> None:
62
+ """Any value Python considers truthy, as the vosk wheel accepts."""
63
+
64
+ def SetPartialWords(self, on: Any) -> None: ...
65
+ def SetEndpointBound(
66
+ self,
67
+ trailing_ms: float | None,
68
+ extending_veto_nats: float | None = None,
69
+ ) -> None:
70
+ """A host endpoint bound: a final once the trailing silence reaches trailing_ms."""
71
+
72
+ def SetEndpointFloorMargin(self, margin_db: float | None) -> None:
73
+ """A margin in dB over the floor within which the bound reads a wordless path as silence.
74
+
75
+ Only a span at least as long as the bound is read that way, so a quiet word's first
76
+ frames are not. Such a final names "floor" as its endpoint. 0 or None removes the margin.
77
+ """
78
+
79
+ def SetPartialAlternatives(self, n: int) -> None: ...
80
+ def SetMaxAlternatives(self, n: int) -> None: ...
81
+ def AcceptWaveform(self, data: bytes) -> bool:
82
+ """16-bit little-endian mono PCM. Returns True when an endpoint fired."""
83
+
84
+ def DecodedSample(self) -> int:
85
+ """The sample position of the last decoded frame after the last AcceptWaveform."""
86
+
87
+ def PartialResult(self) -> str: ...
88
+ def Result(self) -> str: ...
89
+ def FinalResult(self) -> str: ...
90
+ def Reset(self) -> None: ...
91
+
92
+ Recognizer = KaldiRecognizer
93
+
94
+ def SetLogLevel(_level: int) -> None:
95
+ """vosk's SetLogLevel; utter logs nothing by default, so this only records the request."""
utterpy/_utterpy.pyd ADDED
Binary file
utterpy/py.typed ADDED
File without changes
@@ -0,0 +1,235 @@
1
+ Metadata-Version: 2.4
2
+ Name: utterpy
3
+ Version: 0.0.6
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: 3.9
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
13
+ Classifier: Typing :: Typed
14
+ License-File: LICENSE
15
+ Summary: Python bindings for utter, the zero-dependency pure-Rust streaming speech decoder for Vosk (Kaldi nnet3) models
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
18
+
19
+ # utterpy
20
+
21
+ [![PyPI](https://img.shields.io/pypi/v/utterpy)](https://pypi.org/project/utterpy/)
22
+ [![Python](https://img.shields.io/pypi/pyversions/utterpy)](https://pypi.org/project/utterpy/)
23
+ [![Wheels](https://github.com/pyscape/utterpy/actions/workflows/wheels.yml/badge.svg)](https://github.com/pyscape/utterpy/actions/workflows/wheels.yml)
24
+ [![CodeQL](https://github.com/pyscape/utterpy/actions/workflows/codeql.yml/badge.svg)](https://github.com/pyscape/utterpy/actions/workflows/codeql.yml)
25
+ [![cargo-deny](https://github.com/pyscape/utterpy/actions/workflows/deny.yml/badge.svg)](https://github.com/pyscape/utterpy/actions/workflows/deny.yml)
26
+ [![Scorecard](https://api.scorecard.dev/projects/github.com/pyscape/utterpy/badge)](https://scorecard.dev/viewer/?uri=github.com/pyscape/utterpy)
27
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
28
+
29
+ Python bindings for [utter](https://github.com/pyscape/utter), the
30
+ zero-dependency pure-Rust streaming speech decoder for Vosk (Kaldi
31
+ nnet3) models. Drop-in for the vosk
32
+ wheel's API: feed 16 kHz audio, read the partial after every block, the
33
+ live n-best from the beam, word times, endpoints. No C toolchain, no
34
+ Docker, no cloud.
35
+
36
+ ## Why
37
+
38
+ The vosk wheel is a C++ wrapper around Kaldi: no Windows build without
39
+ Docker, and one more field out of the decoder means a fork. utter
40
+ reimplements what a Vosk model needs, in Rust, from a stock model
41
+ directory, and is checked block for block against the wheel. Figures
42
+ are from the [benchmark pages](https://github.com/pyscape/utter/blob/main/docs/benchmarks/README.md),
43
+ paired against the wheel on identical audio.
44
+
45
+ - **Silence is in the stream.** Every partial says `[sil]` or
46
+ `[speech]` when it carries no word; every final names the rule that
47
+ closed it; every word carries its energy against the room floor and
48
+ how long it held. The wheel gives a bare string, so a phantom over
49
+ mic hiss and a spoken word look the same
50
+ ([TD-10](https://github.com/pyscape/utter/blob/main/docs/td/0010-a-wordless-reading-says-whether-a-word-has-begun.md),
51
+ [TD-11](https://github.com/pyscape/utter/blob/main/docs/td/0011-a-final-says-what-closed-it-and-how-long-its-words-held.md)).
52
+ - **Phantoms are tellable, not fewer.** On wordless audio both engines
53
+ read alike: no rank-0 word on cold silence under 92 entries, 0.56 per
54
+ minute after speech. Here each carries `stable_ms` and `energy_dbfs`,
55
+ so a stale word is told from a fresh one, and the partial stream is
56
+ as steady as the wheel's: first word later revised on 12.4% of clips
57
+ against 12.3% ([speech-commands.md](https://github.com/pyscape/utter/blob/main/docs/benchmarks/speech-commands.md)).
58
+ - **A host endpoint bound.** A final after N ms of trailing silence,
59
+ vetoed while a rival is within a margin. Median finish 866 to 660 ms
60
+ on built streams, same finishes called, no word lost or split
61
+ ([partial-states.md](https://github.com/pyscape/utter/blob/main/docs/benchmarks/partial-states.md),
62
+ [TD-8](https://github.com/pyscape/utter/blob/main/docs/td/0008-silence-is-the-hosts-gate.md)).
63
+ - **Distinct rivals with their motion** on every partial, where the
64
+ wheel's alternatives repeat readings
65
+ ([TD-9](https://github.com/pyscape/utter/blob/main/docs/td/0009-readings-carry-their-relation-and-their-leads-motion.md)).
66
+ - **Parity, not a gain, on hearing.** 91.79% against 91.49% on 11,005
67
+ clips, finals identical on 99.2%, word times to the frame, same 40 ms
68
+ first appearance, less compute
69
+ ([word-times.md](https://github.com/pyscape/utter/blob/main/docs/benchmarks/word-times.md)).
70
+ - **Pure Rust, typed.** No C toolchain, no Docker, no cloud. Wheels for
71
+ Linux, macOS and Windows, one abi3 build from Python 3.9, with a stub
72
+ and py.typed checked by stubtest.
73
+
74
+ | Speech Commands v2, 11,005 clips | Vosk 0.3.45 | utter |
75
+ |---|---|---|
76
+ | Accuracy, full grammar | 91.49% | 91.79% |
77
+ | First word shown after the clip ends, p50 / p90 | 40 / 250 ms | 40 / 250 ms |
78
+ | First word shown later revised | 12.3% | 12.4% |
79
+ | Real-time factor, decode only | 0.0168 | 0.0143 |
80
+
81
+ Pre-alpha; the decoder still moves between revisions.
82
+
83
+ ## Use
84
+
85
+ ```python
86
+ import json, utterpy
87
+
88
+ model = utterpy.Model("vosk-model-small-en-us-0.15")
89
+ rec = utterpy.KaldiRecognizer(model, 16000, json.dumps(["yes", "no", "stop"]))
90
+ rec.SetWords(True)
91
+ rec.SetPartialWords(True)
92
+ rec.SetPartialAlternatives(3)
93
+
94
+ for block in blocks_of_16k_mono_int16_pcm: # bytes, 40 ms works well
95
+ if rec.AcceptWaveform(block): # an endpoint fired
96
+ print(json.loads(rec.Result())) # {"result": [...], "text": ...}
97
+ else:
98
+ print(json.loads(rec.PartialResult())) # {"partial": ..., "partial_alternatives": [...], "partial_result": [...]}
99
+ print(json.loads(rec.FinalResult()))
100
+ ```
101
+
102
+ The method names are vosk's, and the JSON keeps vosk's layout. On top of
103
+ it: `partial_alternatives` (distinct readings alive in the beam, with
104
+ `confidence` as the negated cost), `partial_result` entries with
105
+ `start_sample`, `end_sample`, `energy_dbfs` and `stable_ms`, `[sil]` as
106
+ the reading when the best path carries no word and sits on silence and
107
+ `[speech]` when it has entered a word's phones, `endpoint` on a final
108
+ naming what closed it (`rule1` to `rule5`, `bound`, `floor`, `flush`
109
+ or `host`), `stable_ms` on each final word for the hold it had in the
110
+ partial, `floor_dbfs` for the room's noise floor, and an optional
111
+ `unknown_cost` argument to the recognizer that admits the model's
112
+ unknown-word symbol. `DecodedSample()` gives the position, in samples fed,
113
+ of the last decoded frame.
114
+
115
+ With a speaker model, `SpkModel("vosk-model-spk-0.4")` passed as
116
+ `spk_model=` or through `SetSpkModel`, every partial and final and each
117
+ word entry carries `spk`, the speaker vector of its own span, with
118
+ `spk_frames`, `spk_start` and `spk_end`, once the span holds 25 pooled
119
+ 10 ms frames. The wheel puts one vector on a final. These follow Kaldi's
120
+ network but not the wheel's normalisation or frame selection
121
+ ([TD-14](https://github.com/pyscape/utter/blob/main/docs/td/0014-every-word-carries-the-speaker-evidence-of-its-own-span.md)):
122
+ rebuild speaker profiles from your enrolment audio with utterpy, and do
123
+ not reuse vectors or thresholds from the wheel.
124
+
125
+ A TitaNet-small directory, as utter's `scripts/titanet_convert.py`
126
+ writes it, opens the same way and gives 192-number vectors
127
+ ([TD-15](https://github.com/pyscape/utter/blob/main/docs/td/0015-titanet-small-is-a-native-speaker-model.md)).
128
+ Its evidence rides the word entries only, and it is embedded between
129
+ decoder advances, so feed blocks shorter than one decoder chunk: 40 ms
130
+ works. `SpkModel.embed(data, sample_rate=16000)` embeds any span of
131
+ little-endian float32 samples in [-1, 1] without a recognizer, 25 ms to
132
+ 30 s, at 16 kHz or faster; an x-vector model raises ValueError.
133
+
134
+ ## Configure
135
+
136
+ The calls are the wheel's, so switching is the import. The setup the
137
+ pages measure:
138
+
139
+ ```python
140
+ rec = utterpy.KaldiRecognizer(model, 16000, json.dumps(grammar))
141
+ rec.SetWords(True) # word times, energy_dbfs, stable_ms on finals
142
+ rec.SetPartialWords(True) # word entries on partials, with [sil]/[speech]
143
+ rec.SetPartialAlternatives(4) # four distinct readings per partial
144
+ rec.SetMaxAlternatives(4) # n-best finals
145
+ rec.SetEndpointBound(300, 8) # host bound with veto; (ms, 0) bare, (0) off
146
+ rec.SetEndpointFloorMargin(6) # the bound reads a wordless path within 6 dB of the floor as silence
147
+ ```
148
+
149
+ Feed 40 ms blocks, 1280 bytes at 16 kHz mono int16. Two clocks: a
150
+ word shows in the partial 40 ms after it ends, the block size, for
151
+ both engines; the final arrives 866 ms after under the model's rules
152
+ and 660 ms with the bound. Compute is not the wait, at 0.04 ms per
153
+ block. The trailing `[sil]` entry shows in the partial before the
154
+ endpoint fires, so a host can act on a settled partial plus visible
155
+ silence.
156
+
157
+ - Expose the bound as one host setting with an off spelling, and
158
+ measure off against on on your own replays before retuning it.
159
+ - Model conf carries over: `frames_per_chunk` and
160
+ `min-trailing-silence` tuned for the wheel keep their effect.
161
+ - `unknown_cost` does not fight phantoms; the page measured no change
162
+ in rank-0 words. The fields and the bound are the levers.
163
+ - Grammar size sets the stale-partial rate after speech: about 0.6 per
164
+ minute at 92 entries, 3 at 150.
165
+ - Keep a trace of raw partial and final payloads. `SetLogLevel(-1)`
166
+ silences the runtime as with the wheel.
167
+
168
+ ## Silence
169
+
170
+ Host rules that have held up, each keyed off one field:
171
+
172
+ - `[sil]` and `[speech]` are no word: never dispatched, ranked or
173
+ shown. When rank 0 is wordless, offer nothing; the rivals beneath
174
+ it on floor audio are short grammar words at low confidence.
175
+ - Drop a final word with `"endpoint": "rule5"` and `"stable_ms": 0`.
176
+ That is Kaldi's 20 s length cap naming the cheapest word over
177
+ silence, every 21 s on mic hiss, on the wheel too. When the drop
178
+ empties the final, still close the utterance, or the phantom returns
179
+ as a partial. Do not widen this to `rule2`: a never-shown word there
180
+ can be a real rescored reading.
181
+ - Keep the bound on with the veto. Shorter bounds are fine with it
182
+ and cut phrases into pieces without it.
183
+ - On a quiet room, set a floor margin. The model reads mic hiss as a
184
+ word's first phone, no silence rule fires, and the 20 s cap forces
185
+ a word. With `SetEndpointFloorMargin`, a wordless path within the
186
+ margin of `floor_dbfs`, and at least as long as the bound, counts as
187
+ trailing silence and the bound closes it with `"endpoint": "floor"`,
188
+ an empty `result` and the text `[sil]` or `[speech]`. A quiet word's
189
+ first frames after a pause are shorter than that and are left alone.
190
+ Off by default; output is unchanged when unset
191
+ ([TD-12](https://github.com/pyscape/utter/blob/main/docs/td/0012-the-bound-reads-a-wordless-path-at-the-floor-as-silence.md)).
192
+ - Gate on `energy_dbfs` at least 8 dB above `floor_dbfs` only after
193
+ scoring it on your replays: it removes about half the worded finals
194
+ on room silence and costs real words near the floor. `energy_dbfs`
195
+ is `null` when there is no signal under the word, and `floor_dbfs`
196
+ is absent while the quietest windows of the last ten seconds are
197
+ digital silence, so a gate is not handed a number every word sits
198
+ above.
199
+
200
+ ## Build
201
+
202
+ ```sh
203
+ python -m venv .venv && . .venv/bin/activate
204
+ pip install maturin
205
+ maturin develop --release # into the venv
206
+ maturin build --release # a wheel under target/wheels
207
+ ```
208
+
209
+ The core is the utter crate from crates.io at the version Cargo.toml
210
+ names. To build against a checkout beside this one instead, put this
211
+ in `.cargo/config.toml` (ignored by git):
212
+
213
+ ```toml
214
+ [patch.crates-io]
215
+ utter = { path = "../utter" }
216
+ ```
217
+
218
+ The wheel has no runtime dependencies.
219
+
220
+ The wheel carries py.typed and a stub for the module, so a type checker
221
+ sees the API without a separate stubs package.
222
+
223
+ ## Release
224
+
225
+ GitHub Actions builds wheels for Linux x86_64 and aarch64 (manylinux
226
+ 2_28 and musllinux 1.2), Windows x64 and arm64, and macOS x86_64 and
227
+ arm64 on every push, runs the tests on Python 3.9 to 3.14, and on a
228
+ `v*` tag attaches them to a GitHub release with the notes under
229
+ `docs/release-notes` as its body and publishes to PyPI through trusted
230
+ publishing. Every wheel carries a build-provenance attestation, and the
231
+ release attaches its Sigstore bundle and provenance envelope. Publishing works once the PyPI project names this
232
+ repository's `wheels.yml` workflow and the `pypi` environment as a
233
+ trusted publisher and the repository variable `PYPI_PUBLISH` is `true`;
234
+ no token lives in the repository.
235
+
@@ -0,0 +1,9 @@
1
+ utterpy/__init__.py,sha256=V3JXg0RysPeic5ddImYWj2xv837PhvZnSDeHMW9IxO4,421
2
+ utterpy/__init__.pyi,sha256=x-peALMH0CyW9ASYvty33zV-R3Kh8BbdD6NZkrvFXrI,3381
3
+ utterpy/_utterpy.pyd,sha256=MIgnLjPHk3BZcSnN5NRmb8LAxilfCSvbdDhvmwK_LuA,1136128
4
+ utterpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ utterpy-0.0.6.dist-info/METADATA,sha256=UUdA12BiVD4EFEbRzfYOvVZKo4V88PkQd2wtCaZHmDw,12587
6
+ utterpy-0.0.6.dist-info/WHEEL,sha256=xe4_tbg8wYdeh4O7nLbnWckzIQtCR4nODDgwke_TKy8,95
7
+ utterpy-0.0.6.dist-info/licenses/LICENSE,sha256=1qKNBMjt5rvKxX_rqX4gIp01mwC5DrM_wwEBTE-XsK4,1088
8
+ utterpy-0.0.6.dist-info/sboms/utterpy.cyclonedx.json,sha256=RSEb_OFNCDD6PFQ7p0ugegvmNF5rWZ7fZt4S1QnUVto,17259
9
+ utterpy-0.0.6.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.15.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp39-abi3-win_amd64
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jared Hall
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,572 @@
1
+ {
2
+ "bomFormat": "CycloneDX",
3
+ "specVersion": "1.5",
4
+ "version": 1,
5
+ "serialNumber": "urn:uuid:1ec30fb4-ffc2-4ea3-9eb7-f18496b69d2c",
6
+ "metadata": {
7
+ "timestamp": "2026-09-30T19:07:25.100174600Z",
8
+ "tools": [
9
+ {
10
+ "vendor": "CycloneDX",
11
+ "name": "cargo-cyclonedx",
12
+ "version": "0.5.9"
13
+ }
14
+ ],
15
+ "component": {
16
+ "type": "library",
17
+ "bom-ref": "path+file:///D:/a/utterpy/utterpy#0.0.6",
18
+ "name": "utterpy",
19
+ "version": "0.0.6",
20
+ "description": "Python bindings for utter, the zero-dependency pure-Rust streaming speech decoder for Vosk (Kaldi nnet3) models",
21
+ "scope": "required",
22
+ "licenses": [
23
+ {
24
+ "expression": "MIT"
25
+ }
26
+ ],
27
+ "purl": "pkg:cargo/utterpy@0.0.6?download_url=file://.",
28
+ "externalReferences": [
29
+ {
30
+ "type": "vcs",
31
+ "url": "https://github.com/pyscape/utterpy"
32
+ }
33
+ ],
34
+ "components": [
35
+ {
36
+ "type": "library",
37
+ "bom-ref": "path+file:///D:/a/utterpy/utterpy#0.0.6 bin-target-0",
38
+ "name": "utterpy",
39
+ "version": "0.0.6",
40
+ "purl": "pkg:cargo/utterpy@0.0.6?download_url=file://.#src/lib.rs"
41
+ }
42
+ ]
43
+ },
44
+ "properties": [
45
+ {
46
+ "name": "cdx:rustc:sbom:target:all_targets",
47
+ "value": "true"
48
+ }
49
+ ]
50
+ },
51
+ "components": [
52
+ {
53
+ "type": "library",
54
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0",
55
+ "name": "heck",
56
+ "version": "0.5.0",
57
+ "description": "heck is a case conversion library.",
58
+ "scope": "required",
59
+ "hashes": [
60
+ {
61
+ "alg": "SHA-256",
62
+ "content": "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
63
+ }
64
+ ],
65
+ "licenses": [
66
+ {
67
+ "expression": "MIT OR Apache-2.0"
68
+ }
69
+ ],
70
+ "purl": "pkg:cargo/heck@0.5.0",
71
+ "externalReferences": [
72
+ {
73
+ "type": "vcs",
74
+ "url": "https://github.com/withoutboats/heck"
75
+ }
76
+ ]
77
+ },
78
+ {
79
+ "type": "library",
80
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.189",
81
+ "name": "libc",
82
+ "version": "0.2.189",
83
+ "description": "Raw FFI bindings to platform libraries like libc.",
84
+ "scope": "required",
85
+ "hashes": [
86
+ {
87
+ "alg": "SHA-256",
88
+ "content": "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
89
+ }
90
+ ],
91
+ "licenses": [
92
+ {
93
+ "expression": "MIT OR Apache-2.0"
94
+ }
95
+ ],
96
+ "purl": "pkg:cargo/libc@0.2.189",
97
+ "externalReferences": [
98
+ {
99
+ "type": "vcs",
100
+ "url": "https://github.com/rust-lang/libc"
101
+ }
102
+ ]
103
+ },
104
+ {
105
+ "type": "library",
106
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4",
107
+ "author": "Aleksey Kladov <aleksey.kladov@gmail.com>",
108
+ "name": "once_cell",
109
+ "version": "1.21.4",
110
+ "description": "Single assignment cells and lazy values.",
111
+ "scope": "required",
112
+ "hashes": [
113
+ {
114
+ "alg": "SHA-256",
115
+ "content": "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
116
+ }
117
+ ],
118
+ "licenses": [
119
+ {
120
+ "expression": "MIT OR Apache-2.0"
121
+ }
122
+ ],
123
+ "purl": "pkg:cargo/once_cell@1.21.4",
124
+ "externalReferences": [
125
+ {
126
+ "type": "documentation",
127
+ "url": "https://docs.rs/once_cell"
128
+ },
129
+ {
130
+ "type": "vcs",
131
+ "url": "https://github.com/matklad/once_cell"
132
+ }
133
+ ]
134
+ },
135
+ {
136
+ "type": "library",
137
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.107",
138
+ "author": "David Tolnay <dtolnay@gmail.com>, Alex Crichton <alex@alexcrichton.com>",
139
+ "name": "proc-macro2",
140
+ "version": "1.0.107",
141
+ "description": "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case.",
142
+ "scope": "required",
143
+ "hashes": [
144
+ {
145
+ "alg": "SHA-256",
146
+ "content": "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
147
+ }
148
+ ],
149
+ "licenses": [
150
+ {
151
+ "expression": "MIT OR Apache-2.0"
152
+ }
153
+ ],
154
+ "purl": "pkg:cargo/proc-macro2@1.0.107",
155
+ "externalReferences": [
156
+ {
157
+ "type": "documentation",
158
+ "url": "https://docs.rs/proc-macro2"
159
+ },
160
+ {
161
+ "type": "vcs",
162
+ "url": "https://github.com/dtolnay/proc-macro2"
163
+ }
164
+ ]
165
+ },
166
+ {
167
+ "type": "library",
168
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.29.2",
169
+ "author": "PyO3 Project and Contributors <https://github.com/PyO3>",
170
+ "name": "pyo3-build-config",
171
+ "version": "0.29.2",
172
+ "description": "Build configuration for the PyO3 ecosystem",
173
+ "scope": "excluded",
174
+ "hashes": [
175
+ {
176
+ "alg": "SHA-256",
177
+ "content": "f41027e41b4bd03f6e60f9f417fe24a6341a6bb744edd62b6f709f2a52ea30e9"
178
+ }
179
+ ],
180
+ "licenses": [
181
+ {
182
+ "expression": "MIT OR Apache-2.0"
183
+ }
184
+ ],
185
+ "purl": "pkg:cargo/pyo3-build-config@0.29.2",
186
+ "externalReferences": [
187
+ {
188
+ "type": "website",
189
+ "url": "https://github.com/pyo3/pyo3"
190
+ },
191
+ {
192
+ "type": "vcs",
193
+ "url": "https://github.com/pyo3/pyo3"
194
+ }
195
+ ]
196
+ },
197
+ {
198
+ "type": "library",
199
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-ffi@0.29.2",
200
+ "author": "PyO3 Project and Contributors <https://github.com/PyO3>",
201
+ "name": "pyo3-ffi",
202
+ "version": "0.29.2",
203
+ "description": "Python-API bindings for the PyO3 ecosystem",
204
+ "scope": "required",
205
+ "hashes": [
206
+ {
207
+ "alg": "SHA-256",
208
+ "content": "e591a95526fead067432c3b3a33fc74770b87b1e04e73671090d9c2055a2b327"
209
+ }
210
+ ],
211
+ "licenses": [
212
+ {
213
+ "expression": "MIT OR Apache-2.0"
214
+ }
215
+ ],
216
+ "purl": "pkg:cargo/pyo3-ffi@0.29.2",
217
+ "externalReferences": [
218
+ {
219
+ "type": "website",
220
+ "url": "https://github.com/pyo3/pyo3"
221
+ },
222
+ {
223
+ "type": "other",
224
+ "url": "python"
225
+ },
226
+ {
227
+ "type": "vcs",
228
+ "url": "https://github.com/pyo3/pyo3"
229
+ }
230
+ ]
231
+ },
232
+ {
233
+ "type": "library",
234
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros-backend@0.29.2",
235
+ "author": "PyO3 Project and Contributors <https://github.com/PyO3>",
236
+ "name": "pyo3-macros-backend",
237
+ "version": "0.29.2",
238
+ "description": "Code generation for PyO3 package",
239
+ "scope": "required",
240
+ "hashes": [
241
+ {
242
+ "alg": "SHA-256",
243
+ "content": "571575aa3749fa6216757dd47d2a3e7ef360f329a40f0666a9fbd14889024952"
244
+ }
245
+ ],
246
+ "licenses": [
247
+ {
248
+ "expression": "MIT OR Apache-2.0"
249
+ }
250
+ ],
251
+ "purl": "pkg:cargo/pyo3-macros-backend@0.29.2",
252
+ "externalReferences": [
253
+ {
254
+ "type": "website",
255
+ "url": "https://github.com/pyo3/pyo3"
256
+ },
257
+ {
258
+ "type": "vcs",
259
+ "url": "https://github.com/pyo3/pyo3"
260
+ }
261
+ ]
262
+ },
263
+ {
264
+ "type": "library",
265
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros@0.29.2",
266
+ "author": "PyO3 Project and Contributors <https://github.com/PyO3>",
267
+ "name": "pyo3-macros",
268
+ "version": "0.29.2",
269
+ "description": "Proc macros for PyO3 package",
270
+ "scope": "required",
271
+ "hashes": [
272
+ {
273
+ "alg": "SHA-256",
274
+ "content": "73225868fc1cd84eef2c3c230ddb91273bf1de46aeb8a4248da76d32a0924a1c"
275
+ }
276
+ ],
277
+ "licenses": [
278
+ {
279
+ "expression": "MIT OR Apache-2.0"
280
+ }
281
+ ],
282
+ "purl": "pkg:cargo/pyo3-macros@0.29.2",
283
+ "externalReferences": [
284
+ {
285
+ "type": "website",
286
+ "url": "https://github.com/pyo3/pyo3"
287
+ },
288
+ {
289
+ "type": "vcs",
290
+ "url": "https://github.com/pyo3/pyo3"
291
+ }
292
+ ]
293
+ },
294
+ {
295
+ "type": "library",
296
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3@0.29.2",
297
+ "author": "PyO3 Project and Contributors <https://github.com/PyO3>",
298
+ "name": "pyo3",
299
+ "version": "0.29.2",
300
+ "description": "Bindings to Python interpreter",
301
+ "scope": "required",
302
+ "hashes": [
303
+ {
304
+ "alg": "SHA-256",
305
+ "content": "4688ddedf473e32662b9b067670129a8afb8c18e351482c70d62ba4a88171e8b"
306
+ }
307
+ ],
308
+ "licenses": [
309
+ {
310
+ "expression": "MIT OR Apache-2.0"
311
+ }
312
+ ],
313
+ "purl": "pkg:cargo/pyo3@0.29.2",
314
+ "externalReferences": [
315
+ {
316
+ "type": "documentation",
317
+ "url": "https://docs.rs/crate/pyo3/"
318
+ },
319
+ {
320
+ "type": "website",
321
+ "url": "https://github.com/pyo3/pyo3"
322
+ },
323
+ {
324
+ "type": "other",
325
+ "url": "pyo3-python"
326
+ },
327
+ {
328
+ "type": "vcs",
329
+ "url": "https://github.com/pyo3/pyo3"
330
+ }
331
+ ]
332
+ },
333
+ {
334
+ "type": "library",
335
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.47",
336
+ "author": "David Tolnay <dtolnay@gmail.com>",
337
+ "name": "quote",
338
+ "version": "1.0.47",
339
+ "description": "Quasi-quoting macro quote!(...)",
340
+ "scope": "required",
341
+ "hashes": [
342
+ {
343
+ "alg": "SHA-256",
344
+ "content": "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
345
+ }
346
+ ],
347
+ "licenses": [
348
+ {
349
+ "expression": "MIT OR Apache-2.0"
350
+ }
351
+ ],
352
+ "purl": "pkg:cargo/quote@1.0.47",
353
+ "externalReferences": [
354
+ {
355
+ "type": "documentation",
356
+ "url": "https://docs.rs/quote/"
357
+ },
358
+ {
359
+ "type": "vcs",
360
+ "url": "https://github.com/dtolnay/quote"
361
+ }
362
+ ]
363
+ },
364
+ {
365
+ "type": "library",
366
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.119",
367
+ "author": "David Tolnay <dtolnay@gmail.com>",
368
+ "name": "syn",
369
+ "version": "2.0.119",
370
+ "description": "Parser for Rust source code",
371
+ "scope": "required",
372
+ "hashes": [
373
+ {
374
+ "alg": "SHA-256",
375
+ "content": "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
376
+ }
377
+ ],
378
+ "licenses": [
379
+ {
380
+ "expression": "MIT OR Apache-2.0"
381
+ }
382
+ ],
383
+ "purl": "pkg:cargo/syn@2.0.119",
384
+ "externalReferences": [
385
+ {
386
+ "type": "documentation",
387
+ "url": "https://docs.rs/syn"
388
+ },
389
+ {
390
+ "type": "vcs",
391
+ "url": "https://github.com/dtolnay/syn"
392
+ }
393
+ ]
394
+ },
395
+ {
396
+ "type": "library",
397
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#target-lexicon@0.13.5",
398
+ "author": "Dan Gohman <sunfish@mozilla.com>",
399
+ "name": "target-lexicon",
400
+ "version": "0.13.5",
401
+ "description": "LLVM target triple types",
402
+ "scope": "excluded",
403
+ "hashes": [
404
+ {
405
+ "alg": "SHA-256",
406
+ "content": "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
407
+ }
408
+ ],
409
+ "licenses": [
410
+ {
411
+ "expression": "Apache-2.0 WITH LLVM-exception"
412
+ }
413
+ ],
414
+ "purl": "pkg:cargo/target-lexicon@0.13.5",
415
+ "externalReferences": [
416
+ {
417
+ "type": "documentation",
418
+ "url": "https://docs.rs/target-lexicon/"
419
+ },
420
+ {
421
+ "type": "vcs",
422
+ "url": "https://github.com/bytecodealliance/target-lexicon"
423
+ }
424
+ ]
425
+ },
426
+ {
427
+ "type": "library",
428
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24",
429
+ "author": "David Tolnay <dtolnay@gmail.com>",
430
+ "name": "unicode-ident",
431
+ "version": "1.0.24",
432
+ "description": "Determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31",
433
+ "scope": "required",
434
+ "hashes": [
435
+ {
436
+ "alg": "SHA-256",
437
+ "content": "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
438
+ }
439
+ ],
440
+ "licenses": [
441
+ {
442
+ "expression": "(MIT OR Apache-2.0) AND Unicode-3.0"
443
+ }
444
+ ],
445
+ "purl": "pkg:cargo/unicode-ident@1.0.24",
446
+ "externalReferences": [
447
+ {
448
+ "type": "documentation",
449
+ "url": "https://docs.rs/unicode-ident"
450
+ },
451
+ {
452
+ "type": "vcs",
453
+ "url": "https://github.com/dtolnay/unicode-ident"
454
+ }
455
+ ]
456
+ },
457
+ {
458
+ "type": "library",
459
+ "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#utter@0.0.6",
460
+ "name": "utter",
461
+ "version": "0.0.6",
462
+ "description": "Pure-Rust streaming decoder for Vosk models: partials, alternatives, word intervals, endpointing",
463
+ "scope": "required",
464
+ "hashes": [
465
+ {
466
+ "alg": "SHA-256",
467
+ "content": "b7c2fcc627bdb733e73bc4a79adf7e943697dc6a4cfb24e79997505675fae232"
468
+ }
469
+ ],
470
+ "licenses": [
471
+ {
472
+ "expression": "MIT AND Apache-2.0"
473
+ }
474
+ ],
475
+ "purl": "pkg:cargo/utter@0.0.6",
476
+ "externalReferences": [
477
+ {
478
+ "type": "vcs",
479
+ "url": "https://github.com/pyscape/utter"
480
+ }
481
+ ]
482
+ }
483
+ ],
484
+ "dependencies": [
485
+ {
486
+ "ref": "path+file:///D:/a/utterpy/utterpy#0.0.6",
487
+ "dependsOn": [
488
+ "registry+https://github.com/rust-lang/crates.io-index#pyo3@0.29.2",
489
+ "registry+https://github.com/rust-lang/crates.io-index#utter@0.0.6"
490
+ ]
491
+ },
492
+ {
493
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0"
494
+ },
495
+ {
496
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.189"
497
+ },
498
+ {
499
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4"
500
+ },
501
+ {
502
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.107",
503
+ "dependsOn": [
504
+ "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24"
505
+ ]
506
+ },
507
+ {
508
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.29.2",
509
+ "dependsOn": [
510
+ "registry+https://github.com/rust-lang/crates.io-index#target-lexicon@0.13.5"
511
+ ]
512
+ },
513
+ {
514
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-ffi@0.29.2",
515
+ "dependsOn": [
516
+ "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.189",
517
+ "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.29.2"
518
+ ]
519
+ },
520
+ {
521
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros-backend@0.29.2",
522
+ "dependsOn": [
523
+ "registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0",
524
+ "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.107",
525
+ "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.47",
526
+ "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.119"
527
+ ]
528
+ },
529
+ {
530
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros@0.29.2",
531
+ "dependsOn": [
532
+ "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.107",
533
+ "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros-backend@0.29.2",
534
+ "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.47",
535
+ "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.119"
536
+ ]
537
+ },
538
+ {
539
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3@0.29.2",
540
+ "dependsOn": [
541
+ "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.189",
542
+ "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4",
543
+ "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.29.2",
544
+ "registry+https://github.com/rust-lang/crates.io-index#pyo3-ffi@0.29.2",
545
+ "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros@0.29.2"
546
+ ]
547
+ },
548
+ {
549
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.47",
550
+ "dependsOn": [
551
+ "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.107"
552
+ ]
553
+ },
554
+ {
555
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.119",
556
+ "dependsOn": [
557
+ "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.107",
558
+ "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.47",
559
+ "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24"
560
+ ]
561
+ },
562
+ {
563
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#target-lexicon@0.13.5"
564
+ },
565
+ {
566
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24"
567
+ },
568
+ {
569
+ "ref": "registry+https://github.com/rust-lang/crates.io-index#utter@0.0.6"
570
+ }
571
+ ]
572
+ }