use std::path::PathBuf;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TranscriptionConfig {
#[serde(default = "default_true")]
pub enabled: bool,
#[serde(default)]
pub model: WhisperModel,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
#[serde(default)]
pub timestamps: bool,
#[serde(default = "default_max_duration_ms")]
pub max_duration_ms: Option<u64>,
#[serde(default = "default_max_bytes")]
pub max_bytes: Option<u64>,
#[serde(default = "default_timeout_ms")]
pub timeout_ms: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model_cache_dir: Option<PathBuf>,
#[serde(default = "default_true")]
pub allow_network: bool,
#[serde(default)]
pub verify_hash: bool,
}
impl Default for TranscriptionConfig {
fn default() -> Self {
Self {
enabled: true,
model: WhisperModel::default(),
language: None,
timestamps: false,
max_duration_ms: default_max_duration_ms(),
max_bytes: default_max_bytes(),
timeout_ms: default_timeout_ms(),
model_cache_dir: None,
allow_network: true,
verify_hash: false,
}
}
}
fn default_true() -> bool {
true
}
fn default_max_duration_ms() -> Option<u64> {
Some(30 * 60 * 1000)
}
fn default_max_bytes() -> Option<u64> {
Some(512 * 1024 * 1024)
}
fn default_timeout_ms() -> Option<u64> {
Some(10 * 60 * 1000)
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum WhisperModel {
#[default]
Tiny,
Base,
Small,
Medium,
LargeV3,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config_is_sensible() {
let cfg = TranscriptionConfig::default();
assert!(cfg.enabled);
assert_eq!(cfg.model, WhisperModel::Tiny);
assert!(cfg.language.is_none());
assert!(cfg.max_duration_ms.unwrap() > 1_000_000);
assert!(cfg.allow_network);
}
#[test]
fn test_serde_roundtrip_minimal() {
let json = r#"{"enabled": true, "model": "base", "timestamps": true}"#;
let cfg: TranscriptionConfig = serde_json::from_str(json).unwrap();
assert_eq!(cfg.model, WhisperModel::Base);
assert!(cfg.timestamps);
let back = serde_json::to_string(&cfg).unwrap();
assert!(back.contains("\"model\":\"base\""));
assert!(back.contains("\"timestamps\":true"));
}
#[test]
fn test_serde_omits_none_fields() {
let cfg = TranscriptionConfig::default();
let json = serde_json::to_string(&cfg).unwrap();
assert!(!json.contains("language"));
assert!(!json.contains("model_cache_dir"));
}
}