aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-06-21 23:04:20 +0800
committer魏曹先生 <1992414357@qq.com>2026-06-21 23:04:20 +0800
commit2f0c1f3fda6025da64636a4cfd01d4f98bc7d50b (patch)
treed1f61d2c388398adb9e7dfb06d47a41d592881c2 /src
parentc6885ae2312a1be589e945129bdd9d268f14c370 (diff)
feat(cli): add --models-dir option for custom model path
Diffstat (limited to 'src')
-rw-r--r--src/args.rs6
-rw-r--r--src/main.rs83
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);