feat: run crispasr sidecar transcription
This commit is contained in:
1 parent
2aaad73652
commit
7b726af951
2 files changed
+49
-8
No files matched your search
@@ -1,4 +1,5 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@@ -34,16 +35,46 @@ impl Transcriber for CrispAsrTranscriber {
|
|||||||
return Err(AppError::ModelNotInstalled(input.options.model_id));
|
return Err(AppError::ModelNotInstalled(input.options.model_id));
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.config.sidecar_name.is_none() {
|
if !model_path.exists() {
|
||||||
|
return Err(AppError::InvalidModel(format!(
|
||||||
|
"modelo não encontrado em {}",
|
||||||
|
model_path.display()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(sidecar_name) = &self.config.sidecar_name else {
|
||||||
return Err(AppError::SidecarNotConfigured);
|
return Err(AppError::SidecarNotConfigured);
|
||||||
|
};
|
||||||
|
|
||||||
|
let threads = default_thread_count().to_string();
|
||||||
|
let output = Command::new(sidecar_name)
|
||||||
|
.arg("-m")
|
||||||
|
.arg(model_path)
|
||||||
|
.arg("-f")
|
||||||
|
.arg(&input.audio_path)
|
||||||
|
.arg("-t")
|
||||||
|
.arg(&threads)
|
||||||
|
.output()
|
||||||
|
.map_err(|error| AppError::Transcription(error.to_string()))?;
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
|
||||||
|
return Err(AppError::Transcription(if stderr.is_empty() {
|
||||||
|
format!("sidecar encerrou com status {}", output.status)
|
||||||
|
} else {
|
||||||
|
stderr
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||||
|
if text.is_empty() {
|
||||||
|
return Err(AppError::Transcription(
|
||||||
|
"sidecar não retornou texto transcrito".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(TranscriptionResult {
|
Ok(TranscriptionResult {
|
||||||
text: format!(
|
text,
|
||||||
"Transcrição local pendente via CrispASR para {} usando {}.",
|
|
||||||
input.audio_path.display(),
|
|
||||||
model_path.display()
|
|
||||||
),
|
|
||||||
backend: "crispasr".to_string(),
|
backend: "crispasr".to_string(),
|
||||||
model_id: input.options.model_id,
|
model_id: input.options.model_id,
|
||||||
detected_language: input.options.language,
|
detected_language: input.options.language,
|
||||||
@@ -51,6 +82,13 @@ impl Transcriber for CrispAsrTranscriber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_thread_count() -> usize {
|
||||||
|
std::thread::available_parallelism()
|
||||||
|
.map(|count| count.get())
|
||||||
|
.unwrap_or(2)
|
||||||
|
.clamp(1, 4)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -75,6 +113,9 @@ mod tests {
|
|||||||
})
|
})
|
||||||
.expect_err("modelo ausente deve falhar");
|
.expect_err("modelo ausente deve falhar");
|
||||||
|
|
||||||
assert_eq!(err, AppError::ModelNotInstalled(DEFAULT_MODEL_ID.to_string()));
|
assert_eq!(
|
||||||
|
err,
|
||||||
|
AppError::ModelNotInstalled(DEFAULT_MODEL_ID.to_string())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ pub(crate) fn stop_recording_and_transcribe(
|
|||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let transcriber = CrispAsrTranscriber::new(CrispAsrConfig {
|
let transcriber = CrispAsrTranscriber::new(CrispAsrConfig {
|
||||||
sidecar_name: None,
|
sidecar_name: Some("parakeet-main".to_string()),
|
||||||
model_path: Some(default_model_path(&state.model_dir)),
|
model_path: Some(default_model_path(&state.model_dir)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user