use std::path::{Path, PathBuf};
use hf_hub::HFClientSync;
fn parse_repo(repo_id: &str) -> (&str, &str) {
let (owner, name) = repo_id
.split_once('/')
.unwrap_or_else(|| panic!("repo_id 必须是 owner/name 形式,收到: {repo_id}"));
(owner, name)
}
fn download_or_get(repo_id: &str, path_in_repo: &str) -> Result<PathBuf, String> {
let local = Path::new(path_in_repo);
if local.is_file() {
println!("本地已存在,直接使用: {}", local.display());
return Ok(local.to_path_buf());
}
println!("本地不存在 {path_in_repo},从 {repo_id} 下载…");
let client = HFClientSync::new().map_err(|e| format!("创建 HF 客户端失败: {e}"))?;
let (owner, name) = parse_repo(repo_id);
let repo = client.model(owner, name);
let path = repo
.download_file()
.filename(path_in_repo.to_string())
.send()
.map_err(|e| format!("下载失败: {e}"))?;
println!("已下载: {}", path.display());
Ok(path)
}
fn main() -> Result<(), audio_cpp::Error> {
let args: Vec<String> = std::env::args().collect();
if args.len() < 3 {
eprintln!("用法: download_model <repo_id owner/name> <仓库内模型路径> [family_hint]");
eprintln!(
" 例: download_model audio-cpp/audio.cpp-gguf Qwen3-ASR-0.6B-GGUF/qwen3-asr-0.6b-q8_0.gguf"
);
eprintln!(
" 例: download_model audio-cpp/audio.cpp-gguf Qwen3-ASR-0.6B-GGUF/qwen3-asr-0.6b-q8_0.gguf qwen3_asr"
);
eprintln!(
"缓存位置用 HF_HOME 环境变量控制;模型族需用对应 feature 编译(如 qwen3_asr → model-qwen3-asr)"
);
std::process::exit(1);
}
let repo_id = &args[1];
let path_in_repo = &args[2];
let family_hint = args
.get(3)
.filter(|s| !s.starts_with("--"))
.map(String::as_str)
.map(audio_cpp::ModelFamily::from);
let model_path = download_or_get(repo_id, path_in_repo).map_err(audio_cpp::Error::Other)?;
let registry = audio_cpp::Registry::new()?;
let model = registry.load(&model_path.to_string_lossy(), family_hint.clone(), None)?;
println!(
"模型加载成功: {} family_hint={family_hint:?}",
model_path.display()
);
if let Some(family) = family_hint {
let family_str = family.as_str();
if matches!(family_str, "silero_vad" | "marblenet_vad") {
let session = model.create_task_session(
audio_cpp::TaskKind::Vad,
audio_cpp::RunMode::Offline,
audio_cpp::Backend::Cpu,
0, 4, None,
)?;
let wav = "audio-cpp-sys/audio.cpp/assets/resources/sample_16k.wav";
let threshold_key = if session.family() == "marblenet_vad" {
"threshold"
} else {
"vad_threshold"
};
let result =
session.run_offline(audio_cpp::Request::vad(wav).option(threshold_key, 0.5))?;
println!(
"VAD 验证({wav}):检测到 {} 段语音",
result.speech_segments.len()
);
} else {
println!("family_hint={family_str} 非 VAD 族,跳过 VAD 验证(仅验证下载+加载)");
}
}
Ok(())
}