#[cfg(feature = "backend-ctranslate2")]
pub mod ctranslate2;
pub mod factory;
#[cfg(feature = "backend-moonshine")]
pub mod moonshine;
#[cfg(feature = "backend-nemotron")]
pub mod nemotron;
#[cfg(any(
feature = "backend-moonshine",
feature = "backend-parakeet",
feature = "backend-nemotron",
feature = "vad-silero"
))]
pub mod onnx_utils;
#[cfg(feature = "backend-parakeet")]
pub mod parakeet;
pub mod traits;
#[cfg(feature = "backend-whisper-cpp")]
pub mod whisper_cpp;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum BackendType {
#[serde(alias = "ct2", alias = "ctranslate2")]
CTranslate2,
#[serde(alias = "whisper-cpp", alias = "whispercpp")]
WhisperCpp,
#[serde(alias = "moonshine")]
Moonshine,
Parakeet,
#[serde(alias = "nemotron")]
Nemotron,
}
#[allow(clippy::derivable_impls)]
impl Default for BackendType {
fn default() -> Self {
#[cfg(feature = "backend-ctranslate2")]
{
Self::CTranslate2
}
#[cfg(all(not(feature = "backend-ctranslate2"), feature = "backend-moonshine"))]
{
Self::Moonshine
}
#[cfg(all(
not(feature = "backend-ctranslate2"),
not(feature = "backend-moonshine"),
feature = "backend-parakeet"
))]
{
Self::Parakeet
}
#[cfg(all(
not(feature = "backend-ctranslate2"),
not(feature = "backend-moonshine"),
not(feature = "backend-parakeet"),
feature = "backend-whisper-cpp"
))]
{
Self::WhisperCpp
}
#[cfg(all(
not(feature = "backend-ctranslate2"),
not(feature = "backend-moonshine"),
not(feature = "backend-parakeet"),
not(feature = "backend-whisper-cpp")
))]
{
Self::CTranslate2
}
}
}
impl fmt::Display for BackendType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BackendType::CTranslate2 => write!(f, "ctranslate2"),
BackendType::WhisperCpp => write!(f, "whisper_cpp"),
BackendType::Moonshine => write!(f, "moonshine"),
BackendType::Parakeet => write!(f, "parakeet"),
BackendType::Nemotron => write!(f, "nemotron"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum QuantizationLevel {
High,
#[default]
Medium,
Low,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct BackendConfig {
pub backend: BackendType,
pub threads: usize,
pub gpu_enabled: bool,
pub quantization_level: QuantizationLevel,
}
impl Default for BackendConfig {
fn default() -> Self {
Self {
backend: BackendType::default(),
threads: num_cpus::get().min(4), gpu_enabled: true, quantization_level: QuantizationLevel::Medium,
}
}
}
#[derive(Debug, Clone)]
pub struct BackendCapabilities {
pub name: &'static str,
pub max_audio_duration: Option<f32>,
pub supported_languages: Option<Vec<String>>,
pub supports_streaming: bool,
pub gpu_available: bool,
}
pub enum TranscriptionBackend {
#[cfg(feature = "backend-ctranslate2")]
CTranslate2(Box<ctranslate2::CT2Backend>),
#[cfg(feature = "backend-whisper-cpp")]
WhisperCpp(Box<whisper_cpp::WhisperCppBackend>),
#[cfg(feature = "backend-moonshine")]
Moonshine(Box<moonshine::MoonshineBackend>),
#[cfg(feature = "backend-parakeet")]
Parakeet(Box<parakeet::ParakeetBackend>),
#[cfg(feature = "backend-nemotron")]
Nemotron(Box<nemotron::NemotronBackend>),
}
impl TranscriptionBackend {
pub fn backend_type(&self) -> BackendType {
match self {
#[cfg(feature = "backend-ctranslate2")]
TranscriptionBackend::CTranslate2(_) => BackendType::CTranslate2,
#[cfg(feature = "backend-whisper-cpp")]
TranscriptionBackend::WhisperCpp(_) => BackendType::WhisperCpp,
#[cfg(feature = "backend-moonshine")]
TranscriptionBackend::Moonshine(_) => BackendType::Moonshine,
#[cfg(feature = "backend-parakeet")]
TranscriptionBackend::Parakeet(_) => BackendType::Parakeet,
#[cfg(feature = "backend-nemotron")]
TranscriptionBackend::Nemotron(_) => BackendType::Nemotron,
#[cfg(all(
not(feature = "backend-ctranslate2"),
not(feature = "backend-whisper-cpp"),
not(feature = "backend-moonshine"),
not(feature = "backend-parakeet"),
not(feature = "backend-nemotron")
))]
_ => unreachable!("no transcription backend variants are enabled"),
}
}
pub fn capabilities(&self) -> BackendCapabilities {
match self {
#[cfg(feature = "backend-ctranslate2")]
TranscriptionBackend::CTranslate2(backend) => backend.capabilities(),
#[cfg(feature = "backend-whisper-cpp")]
TranscriptionBackend::WhisperCpp(backend) => backend.capabilities(),
#[cfg(feature = "backend-moonshine")]
TranscriptionBackend::Moonshine(backend) => backend.capabilities(),
#[cfg(feature = "backend-parakeet")]
TranscriptionBackend::Parakeet(backend) => backend.capabilities(),
#[cfg(feature = "backend-nemotron")]
TranscriptionBackend::Nemotron(backend) => backend.capabilities(),
#[cfg(all(
not(feature = "backend-ctranslate2"),
not(feature = "backend-whisper-cpp"),
not(feature = "backend-moonshine"),
not(feature = "backend-parakeet"),
not(feature = "backend-nemotron")
))]
_ => unreachable!("no transcription backend variants are enabled"),
}
}
pub fn supports_streaming(&self) -> bool {
self.capabilities().supports_streaming
}
pub fn stream_reset(
&self,
language: &str,
nemotron_options: &crate::config::NemotronOptions,
) -> Result<(), TranscriptionError> {
#[cfg(feature = "backend-nemotron")]
if let TranscriptionBackend::Nemotron(b) = self {
return b.stream_reset(language, nemotron_options);
}
let _ = (language, nemotron_options);
Ok(())
}
pub fn stream_push(&self, samples: &[f32]) -> Result<String, TranscriptionError> {
#[cfg(feature = "backend-nemotron")]
if let TranscriptionBackend::Nemotron(b) = self {
return b.stream_push(samples);
}
let _ = samples;
Ok(String::new())
}
pub fn stream_finish(&self) -> Result<String, TranscriptionError> {
#[cfg(feature = "backend-nemotron")]
if let TranscriptionBackend::Nemotron(b) = self {
return b.stream_finish();
}
Ok(String::new())
}
}
pub use factory::create_backend;
pub use traits::TranscriptionError;
#[cfg(test)]
mod tests {
#[cfg(feature = "backend-ctranslate2")]
use super::{BackendConfig, BackendType};
#[test]
#[cfg(feature = "backend-ctranslate2")]
fn default_backend_prefers_ctranslate2_when_available() {
assert_eq!(BackendType::default(), BackendType::CTranslate2);
assert_eq!(BackendConfig::default().backend, BackendType::CTranslate2);
}
}