diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-06-21 23:04:20 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-06-21 23:04:20 +0800 |
| commit | 2f0c1f3fda6025da64636a4cfd01d4f98bc7d50b (patch) | |
| tree | d1f61d2c388398adb9e7dfb06d47a41d592881c2 /src | |
| parent | c6885ae2312a1be589e945129bdd9d268f14c370 (diff) | |
feat(cli): add --models-dir option for custom model path
Diffstat (limited to 'src')
| -rw-r--r-- | src/args.rs | 6 | ||||
| -rw-r--r-- | src/main.rs | 83 |
2 files changed, 58 insertions, 31 deletions
diff --git a/src/args.rs b/src/args.rs index 7b472c4..9fe76d6 100644 --- a/src/args.rs +++ b/src/args.rs @@ -109,7 +109,11 @@ pub struct DMVOPArguments { )] pub socket_file: PathBuf, - // Subnet mask for UDP broadcast (default: only last octet, e.g., "255.255.255.0") + // Custom directory for model files + #[arg(long = "models-dir", alias = "models", require_equals = true)] + pub models_dir: Option<PathBuf>, + + // Subnet mask for UDP broadcast (default: only last octet, e.g., "255.255.255.255.0") #[arg( long = "subnet-mask", alias = "mask", diff --git a/src/main.rs b/src/main.rs index 73b4e06..66af45f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -93,7 +93,7 @@ async fn main() { // --download-model: download a specific model and exit // --------------------------------------------------------------- if let Some(ref model_name) = args.download_model { - download_model_cli(model_name).await; + download_model_cli(model_name, args.models_dir.clone()).await; return; } @@ -116,7 +116,32 @@ async fn main() { model.display_name() ); - let mut builder = EngineBuilder::new().app_name("dmvop").model(model); + let mut builder = EngineBuilder::new().app_name("dmvop"); + + // Apply --models-dir: construct explicit model path, fail on invalid dir + if let Some(ref dir) = args.models_dir { + if dir.is_file() { + eprintln!( + "[dmvop] --models-dir '{}' is a file, not a directory.", + dir.display() + ); + std::process::exit(1); + } + if !dir.exists() { + if let Err(e) = std::fs::create_dir_all(dir) { + eprintln!( + "[dmvop] Failed to create models directory '{}': {}", + dir.display(), + e + ); + std::process::exit(1); + } + } + debug_log!("[dmvop] Models directory: {}", dir.display()); + builder = builder.models_dir(dir); + } else { + builder = builder.model(model); + } if args.instant { debug_log!("[dmvop] Instant mode: aggressive VAD for near-real-time output"); @@ -139,27 +164,6 @@ async fn main() { engine.set_ptt_mode(false); // --------------------------------------------------------------- - // Check model availability and download if needed - // --------------------------------------------------------------- - let model_status = engine.check_model_status(); - if !model_status.available { - eprintln!("[dmvop] Model not found at: {}", model_status.path); - eprintln!("[dmvop] Downloading model, please wait..."); - match engine.download_model().await { - Ok(_) => debug_log!("[dmvop] Model downloaded successfully"), - Err(e) => { - eprintln!("[dmvop] Failed to download model: {}", e); - eprintln!("[dmvop] You can manually download a model from:"); - eprintln!("[dmvop] https://huggingface.co/ggerganov/whisper.cpp/tree/main"); - eprintln!("[dmvop] Place it at: {}", model_status.path); - std::process::exit(1); - } - } - } else { - debug_log!("[dmvop] Model found: {}", model_status.path); - } - - // --------------------------------------------------------------- // List devices and exit? // --------------------------------------------------------------- let devices = engine.list_input_devices(); @@ -404,7 +408,7 @@ fn list_models() { } /// Download a specific Whisper model by identifier. -async fn download_model_cli(model_name: &str) { +async fn download_model_cli(model_name: &str, models_dir: Option<PathBuf>) { let model = match vtx_engine::WhisperModel::parse_identifier(model_name) { Some(m) => m, None => { @@ -421,12 +425,31 @@ async fn download_model_cli(model_name: &str) { model.config_key() ); - let (engine, _rx) = match EngineBuilder::new() - .app_name("dmvop") - .model(model) - .build() - .await - { + let mut builder = EngineBuilder::new().app_name("dmvop"); + if let Some(ref dir) = models_dir { + if dir.is_file() { + eprintln!( + "[dmvop] --models-dir '{}' is a file, not a directory.", + dir.display() + ); + std::process::exit(1); + } + if !dir.exists() { + if let Err(e) = std::fs::create_dir_all(dir) { + eprintln!( + "[dmvop] Failed to create models directory '{}': {}", + dir.display(), + e + ); + std::process::exit(1); + } + } + builder = builder.models_dir(dir); + } else { + builder = builder.model(model); + } + + let (engine, _rx) = match builder.build().await { Ok(e) => e, Err(e) => { eprintln!("[dmvop] Failed to build engine: {}", e); |
