1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! `voxora-bridge` โ the umbrella crate for the voxora model-agnostic
//! ASR bridge.
//!
//! Downstream consumers (Telora's daemon, third-party STT applications)
//! depend on this single crate and pick which engines they want through
//! Cargo features:
//!
//! ```toml
//! [dependencies]
//! voxora-bridge = { path = "../voxora-bridge", default-features = false, features = ["whisper", "qwen3asr"] }
//! ```
//!
//! This crate is a **pure re-exporter**. It owns no logic; it just
//! glues the four upstream crates
//! (`voxora-traits`, `voxora-hf`, `voxora-whisper`, `voxora-qwen3asr`)
//! behind a single import path so consumers do not have to depend on
//! four separate crates with four separate feature lists.
//!
//! ## Features
//!
//! | Feature | Re-exports | Enables |
//! |---|---|---|
//! | (none) | `voxora-traits` + `voxora-hf` | traits, types, HF resolver |
//! | `whisper` (default) | `voxora-whisper` | `WhisperEngine`, ggml models |
//! | `qwen3asr` (default) | `voxora-qwen3asr` | `QwenAsrEngine`, candle-native Qwen3-ASR |
//! | `local` | `voxora-local` | `LocalSource`, `ChainedSource` (closes #49) |
//! | `registry` | `voxora-registry` | `Registry`, `RegistryHfExt`, `builtin_local_descriptor` (closes #145) |
//!
//! Defaults are `["whisper", "qwen3asr"]` so the happy-path consumer
//! (`telora-daemon`) gets both engines wired up with one line. Set
//! `default-features = false` to slim down to a single backend.
//!
//! ## Example: load a Whisper model from Hugging Face
//!
//! The flow every consumer (Telora included) follows:
//!
//! 1. Build a [`HuggingFaceSource`] pointing at a cache directory.
//! 2. Call `WhisperEngine::from_hf` or `QwenAsrEngine::from_hf`
//! (each lives behind its engine feature) to resolve a model id
//! (e.g. `ggerganov/whisper.cpp/ggml-tiny.bin`) into an on-disk
//! directory and load the engine.
//! 3. Hold the engine behind `Arc<dyn AsrEngine>` and call
//! [`AsrEngine::transcribe`] on incoming audio.
//!
//! See `examples/bridge_demo.rs` for the full code.
//!
//! ## License compatibility
//!
//! AGPL-3 downstream consumers (Telora) depend on this Apache-2.0
//! crate. AGPL-3 ยง5 explicitly permits AGPL works to depend on
//! non-copyleft libraries without propagating copyleft to those
//! libraries.
// voxora-traits is always re-exported: every consumer needs the
// `AsrEngine` / `ModelSource` traits, regardless of which engine
// adapter they pick.
pub use ;
// voxora-hf is always re-exported too: the canonical
// `HuggingFaceSource` is the only `ModelSource` implementation we ship
// today, and the bridge constructors (`*Engine::from_hf`) all take it
// as an argument.
pub use HuggingFaceSource;
// voxora-engine owns the canonical `EngineFamily` enum. Re-export it
// here so consumers that pull in `voxora-bridge` get a single import
// path for the "which ASR engine" decision.
pub use EngineFamily;
// Engine adapters are gated. Each block keeps its re-exports behind
// `#[cfg(feature = "...")]` so a single-engine binary does not pull
// the other engine's transitive deps (candle vs. whisper.cpp).
// `cfg_attr(docsrs, doc(cfg(feature = "...")))` makes docs.rs render
// the "Available on crate feature X" badge (closes #93); the
// attribute is nightly-only, so it must stay behind `docsrs`.
pub use WhisperEngine;
pub use ;
/// Local-directory [`voxora_traits::ModelSource`] for vendored
/// weights or hermetic CI. Behind the `local` feature so the
/// default `whisper` + `qwen3asr` build stays slim. Composable
/// with `voxora_hf::HuggingFaceSource` via the chain wrapper
/// [`voxora_local::ChainedSource`].
pub use ;
/// Central model registry (closes #145). Re-exports the
/// [`voxora_registry::Registry`] struct, the [`RegistryHfExt`]
/// trait that adds `with_builtin_descriptors` and (when the
/// `voxora-registry` `local` feature is also on)
/// `with_builtin_descriptors_and_chained_source`, and the
/// [`builtin_local_descriptor`] helper for `SourceKind::Local`
/// ids. Behind the `registry` feature so the slim `whisper` +
/// `qwen3asr` build stays slim. `RegistryHfExt` itself is gated
/// behind `voxora-registry`'s `hf` feature, which is in
/// `voxora-registry`'s own `default`; the `registry` feature
/// here activates `voxora-registry` with its defaults, so
/// `RegistryHfExt` is reachable from a downstream consumer that
/// turns on `voxora-bridge`'s `registry` feature without further
/// ceremony.
pub use ;
/// Re-export of `candle_core::Device`, available only with the
/// `qwen3asr` feature (it comes from `qwen3-asr`'s transitive deps).
pub use Device;
/// Library version (matches the workspace).
pub const VERSION: &str = env!;
/// Canonical transcript normalisation for cross-engine WER.
///
/// Pulled out of the `cross_engine_parity` integration test so
/// the pure-string logic is reachable from the default offline
/// `cargo test --workspace` lane without `--features parity`.
/// The `parity` Cargo feature still gates the integration test
/// target itself (see `[[test]] required-features` in
/// `Cargo.toml`); this module is always compiled because the
/// helper is pure-string and has no engine-side cost. The
/// integration test imports it as
/// `voxora_bridge::normalize::normalize`.