use std::path::Path;
pub(super) const HF_REPO: &str = "istupakov/gigaam-v3-onnx";
#[cfg(feature = "net")]
pub(super) const PREQUANT_RELEASE_BASE: &str =
"https://github.com/ekhodzitsky/gigastt/releases/download/models-v3-2026-06-22";
#[cfg(all(feature = "net", feature = "ane"))]
pub(super) const ANE_RELEASE_BASE: &str =
"https://github.com/ekhodzitsky/gigastt/releases/download/ane-v3-2026-06-24";
#[cfg(feature = "ane")]
pub const ANE_BUCKETS: &[usize] = &[512, 768, 1536, 3000];
#[cfg(all(feature = "net", feature = "ane"))]
pub(super) const ANE_TAR_CHECKSUMS: &[(usize, &str)] = &[
(
512,
"307739d76bebe9805d36e695db030bcf4e71b0b105670609cdcbd3cdc4d4c629",
),
(
768,
"111bd2722c46d41c0984e246752782f05892017990f50837ee6342b0dc41b5be",
),
(
1536,
"dabb0ee21e064a79621f047c795d81f33ef95358c43157a7d242cd9a504b2e93",
),
(
3000,
"7499327eccb326f18014c222adce11f323fbaf3ff76dea7f7c0820f9adb834d4",
),
];
#[cfg(feature = "net")]
pub(super) const PUNCT_HF_REPO: &str = "ekhodzitsky/rupunct-small-onnx";
#[cfg(feature = "net")]
pub(super) const VAD_MODEL_URL: &str =
"https://github.com/snakers4/silero-vad/raw/v5.1.2/src/silero_vad/data/silero_vad.onnx";
#[cfg(feature = "net")]
pub(super) const VAD_MODEL_SHA256: &str =
"2623a2953f6ff3d2c1e61740c6cdb7168133479b267dfef114a4a3cc5bdd788f";
#[cfg(feature = "net")]
pub(super) const PUNCT_FILES: &[(&str, &str)] = &[
(
crate::punctuation::PUNCT_MODEL_FILE,
"b105da023474d98aa13ba18953ae67b04b17bd0595034bc06030c17536893933",
),
(
crate::punctuation::PUNCT_TOKENIZER_FILE,
"7ca617388c2092a3a84272025c52bbf3c6db0aee225c0351186295c0b5d3ddc6",
),
(
crate::punctuation::PUNCT_CONFIG_FILE,
"6924a8cf41ec2bd3a3aa73a387ae0ccd0aed253ec7cac4d2f53c7d27440891eb",
),
];
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum ModelVariant {
#[default]
Rnnt,
E2eRnnt,
MlCtc,
MlCtcLarge,
}
impl ModelVariant {
pub const ALL: [ModelVariant; 4] = [
ModelVariant::Rnnt,
ModelVariant::E2eRnnt,
ModelVariant::MlCtc,
ModelVariant::MlCtcLarge,
];
pub fn encoder_file(self) -> &'static str {
match self {
ModelVariant::Rnnt => "v3_rnnt_encoder.onnx",
ModelVariant::E2eRnnt => "v3_e2e_rnnt_encoder.onnx",
ModelVariant::MlCtc => "multilingual_ctc.onnx",
ModelVariant::MlCtcLarge => "multilingual_large_ctc.onnx",
}
}
pub fn encoder_int8_file(self) -> &'static str {
match self {
ModelVariant::Rnnt => "v3_rnnt_encoder_int8.onnx",
ModelVariant::E2eRnnt => "v3_e2e_rnnt_encoder_int8.onnx",
ModelVariant::MlCtc => "multilingual_ctc.int8.onnx",
ModelVariant::MlCtcLarge => "multilingual_large_ctc.int8.onnx",
}
}
pub fn decoder_file(self) -> &'static str {
match self {
ModelVariant::Rnnt => "v3_rnnt_decoder.onnx",
ModelVariant::E2eRnnt => "v3_e2e_rnnt_decoder.onnx",
ModelVariant::MlCtc | ModelVariant::MlCtcLarge => "",
}
}
pub fn joint_file(self) -> &'static str {
match self {
ModelVariant::Rnnt => "v3_rnnt_joint.onnx",
ModelVariant::E2eRnnt => "v3_e2e_rnnt_joint.onnx",
ModelVariant::MlCtc | ModelVariant::MlCtcLarge => "",
}
}
pub fn vocab_file(self) -> &'static str {
match self {
ModelVariant::Rnnt => "v3_vocab.txt",
ModelVariant::E2eRnnt => "v3_e2e_rnnt_vocab.txt",
ModelVariant::MlCtc | ModelVariant::MlCtcLarge => "multilingual_vocab.txt",
}
}
pub fn download_files(self) -> Vec<&'static str> {
match self {
ModelVariant::Rnnt | ModelVariant::E2eRnnt => vec![
self.encoder_file(),
self.decoder_file(),
self.joint_file(),
self.vocab_file(),
],
ModelVariant::MlCtc | ModelVariant::MlCtcLarge => {
vec![self.encoder_int8_file(), self.vocab_file()]
}
}
}
pub fn hf_repo(self) -> &'static str {
match self {
ModelVariant::Rnnt | ModelVariant::E2eRnnt => HF_REPO,
ModelVariant::MlCtc => "istupakov/gigaam-multilingual-ctc-onnx",
ModelVariant::MlCtcLarge => "istupakov/gigaam-multilingual-large-ctc-onnx",
}
}
pub fn checksum(self, filename: &str) -> Option<&'static str> {
let table = match self {
ModelVariant::Rnnt => RNNT_CHECKSUMS,
ModelVariant::E2eRnnt => E2E_RNNT_CHECKSUMS,
ModelVariant::MlCtc => ML_CTC_CHECKSUMS,
ModelVariant::MlCtcLarge => ML_CTC_LARGE_CHECKSUMS,
};
table
.iter()
.find(|(name, _)| *name == filename)
.and_then(|(_, hash)| *hash)
}
pub fn encoder_int8_checksum(self) -> &'static str {
match self {
ModelVariant::Rnnt => {
"c52665e9d96c4ca3a153c063d2ee9af6c567fe2975ca50fd038b75bbf2f60e7f"
}
ModelVariant::E2eRnnt => {
"cf51b300af47cea099e17c806f8fecce2c46e9e8deb4709ec203f8970a067389"
}
ModelVariant::MlCtc => {
"e08e27ae5669b39f0c378fae101bbbb9a80505f74f9b66719c309bf5b894a480"
}
ModelVariant::MlCtcLarge => {
"b2ad9c38fc04197ba758105d33f7404fd13d977958722e0f49e3f3e22521f1c6"
}
}
}
pub fn prequantized_files(self) -> Vec<&'static str> {
match self {
ModelVariant::Rnnt | ModelVariant::E2eRnnt => vec![
self.encoder_int8_file(),
self.decoder_file(),
self.joint_file(),
self.vocab_file(),
],
ModelVariant::MlCtc | ModelVariant::MlCtcLarge => {
vec![self.encoder_int8_file(), self.vocab_file()]
}
}
}
pub fn prequantized_checksum(self, filename: &str) -> Option<&'static str> {
if filename == self.encoder_int8_file() {
Some(self.encoder_int8_checksum())
} else {
self.checksum(filename)
}
}
pub fn detect_in_dir(dir: &Path) -> Option<Self> {
Self::ALL.into_iter().find(|&variant| {
dir.join(variant.encoder_file()).exists()
|| dir.join(variant.encoder_int8_file()).exists()
})
}
pub fn model_id(self) -> &'static str {
match self {
ModelVariant::Rnnt => "gigaam-v3-rnnt",
ModelVariant::E2eRnnt => "gigaam-v3-e2e-rnnt",
ModelVariant::MlCtc => "gigaam-multilingual-ctc",
ModelVariant::MlCtcLarge => "gigaam-multilingual-large-ctc",
}
}
pub fn as_str(self) -> &'static str {
match self {
ModelVariant::Rnnt => "rnnt",
ModelVariant::E2eRnnt => "e2e_rnnt",
ModelVariant::MlCtc => "ml_ctc",
ModelVariant::MlCtcLarge => "ml_ctc_large",
}
}
pub fn display_name(self) -> &'static str {
match self {
ModelVariant::Rnnt => "GigaAM v3 RNN-T",
ModelVariant::E2eRnnt => "GigaAM v3 E2E RNN-T",
ModelVariant::MlCtc => "GigaAM Multilingual CTC",
ModelVariant::MlCtcLarge => "GigaAM Multilingual CTC (large)",
}
}
pub fn is_ctc(self) -> bool {
matches!(self, ModelVariant::MlCtc | ModelVariant::MlCtcLarge)
}
}
impl std::str::FromStr for ModelVariant {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"rnnt" => Ok(ModelVariant::Rnnt),
"e2e_rnnt" | "e2e-rnnt" => Ok(ModelVariant::E2eRnnt),
"ml_ctc" | "ml-ctc" => Ok(ModelVariant::MlCtc),
"ml_ctc_large" | "ml-ctc-large" => Ok(ModelVariant::MlCtcLarge),
other => Err(format!(
"unknown model variant '{other}' \
(expected 'rnnt', 'e2e_rnnt', 'ml_ctc', or 'ml_ctc_large')"
)),
}
}
}
const RNNT_CHECKSUMS: &[(&str, Option<&str>)] = &[
(
"v3_rnnt_encoder.onnx",
Some("7ae7509c3f1128369564df0b00e2ee4950adf539de2392ac5c800a5bc04c7132"),
),
(
"v3_rnnt_decoder.onnx",
Some("443c3b7bd42b453611618135d6b1e7d9467e5dd97c8a68501da4aa355750c0da"),
),
(
"v3_rnnt_joint.onnx",
Some("fd1d02f45c2ad3d6b67cc149811ad794ab4b020ed49a0a9e2790a8619d1cddd8"),
),
(
"v3_vocab.txt",
Some("a9143c30844d3c0bee3e9e927e4084774eb1b9eeaafc473b2c4521e4911a7c07"),
),
];
const E2E_RNNT_CHECKSUMS: &[(&str, Option<&str>)] = &[
(
"v3_e2e_rnnt_encoder.onnx",
Some("cd60b3764a832e8560ae6d3ad0b10adc1a42ffae412b9476f25620aae4f4a508"),
),
(
"v3_e2e_rnnt_decoder.onnx",
Some("7b0a16d67fd2cb37061decc93c69e364a9ab27afee3c57495d55b1c974cf7231"),
),
(
"v3_e2e_rnnt_joint.onnx",
Some("602ff7017a93311aad34df1437c8d7f49911353c13d6eae7a6ee7b041339465c"),
),
(
"v3_e2e_rnnt_vocab.txt",
Some("39abae20e692998290c574e606f11a9edef2902a1995463fcff63d1490cf22b7"),
),
];
const ML_CTC_CHECKSUMS: &[(&str, Option<&str>)] = &[
(
"multilingual_ctc.int8.onnx",
Some("e08e27ae5669b39f0c378fae101bbbb9a80505f74f9b66719c309bf5b894a480"),
),
(
"multilingual_vocab.txt",
Some("4d130287892e1099fedfb3f93c4b4cf8a263151158801680b28977d1be4133f4"),
),
];
const ML_CTC_LARGE_CHECKSUMS: &[(&str, Option<&str>)] = &[
(
"multilingual_large_ctc.int8.onnx",
Some("b2ad9c38fc04197ba758105d33f7404fd13d977958722e0f49e3f3e22521f1c6"),
),
(
"multilingual_vocab.txt",
Some("4d130287892e1099fedfb3f93c4b4cf8a263151158801680b28977d1be4133f4"),
),
];
#[cfg(feature = "diarization")]
pub(super) const SPEAKER_HF_REPO: &str = "onnx-community/wespeaker-voxceleb-resnet34-LM";
#[cfg(feature = "diarization")]
pub const SPEAKER_MODEL_FILE: &str = "wespeaker_resnet34.onnx";
#[cfg(feature = "diarization")]
pub(super) const SPEAKER_MODEL_SHA256: &str =
"3955447b0499dc9e0a4541a895df08b03c69098eba4e56c02b5603e9f7f4fcbb";