[feat] improve error handling for file operations and subprocess execution; refactor main to modularize execution flow
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
use crate::OutputEntry;
|
||||
use crate::{decode_audio_to_pcm_f32_ffmpeg, find_model_file};
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
#[cfg(not(test))]
|
||||
use libloading::Library;
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -52,15 +50,8 @@ fn check_lib(names: &[&str]) -> bool {
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
if std::env::var("POLYSCRIBE_DISABLE_DLOPEN").ok().as_deref() == Some("1") {
|
||||
return false;
|
||||
}
|
||||
for n in names {
|
||||
// Attempt to dlopen; ignore errors
|
||||
if let Ok(_lib) = unsafe { Library::new(n) } {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Disabled runtime dlopen probing to avoid loader instability; rely on environment overrides.
|
||||
let _ = names;
|
||||
false
|
||||
}
|
||||
}
|
||||
|
19
src/lib.rs
19
src/lib.rs
@@ -302,7 +302,7 @@ pub fn find_model_file() -> Result<PathBuf> {
|
||||
|
||||
/// Decode an input media file to 16kHz mono f32 PCM using ffmpeg available on PATH.
|
||||
pub fn decode_audio_to_pcm_f32_ffmpeg(audio_path: &Path) -> Result<Vec<f32>> {
|
||||
let output = Command::new("ffmpeg")
|
||||
let output = match Command::new("ffmpeg")
|
||||
.arg("-i")
|
||||
.arg(audio_path)
|
||||
.arg("-f")
|
||||
@@ -313,7 +313,22 @@ pub fn decode_audio_to_pcm_f32_ffmpeg(audio_path: &Path) -> Result<Vec<f32>> {
|
||||
.arg("16000")
|
||||
.arg("pipe:1")
|
||||
.output()
|
||||
.with_context(|| format!("Failed to execute ffmpeg for {}", audio_path.display()))?;
|
||||
{
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
if e.kind() == std::io::ErrorKind::NotFound {
|
||||
return Err(anyhow!(
|
||||
"ffmpeg not found on PATH. Please install ffmpeg and ensure it is available."
|
||||
));
|
||||
} else {
|
||||
return Err(anyhow!(
|
||||
"Failed to execute ffmpeg for {}: {}",
|
||||
audio_path.display(),
|
||||
e
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
if !output.status.success() {
|
||||
return Err(anyhow!(
|
||||
"ffmpeg failed for {}: {}",
|
||||
|
33
src/main.rs
33
src/main.rs
@@ -159,11 +159,15 @@ fn prompt_speaker_name_for_path(path: &Path, default_name: &str, enabled: bool)
|
||||
let mut buf = String::new();
|
||||
match io::stdin().read_line(&mut buf) {
|
||||
Ok(_) => {
|
||||
let s = buf.trim();
|
||||
if s.is_empty() {
|
||||
let raw = buf.trim();
|
||||
if raw.is_empty() {
|
||||
return default_name.to_string();
|
||||
}
|
||||
let sanitized = sanitize_speaker_name(raw);
|
||||
if sanitized.is_empty() {
|
||||
default_name.to_string()
|
||||
} else {
|
||||
s.to_string()
|
||||
sanitized
|
||||
}
|
||||
}
|
||||
Err(_) => default_name.to_string(),
|
||||
@@ -196,11 +200,16 @@ struct LastModelCleanup {
|
||||
impl Drop for LastModelCleanup {
|
||||
fn drop(&mut self) {
|
||||
// Ensure .last_model does not persist across program runs
|
||||
let _ = std::fs::remove_file(&self.path);
|
||||
if let Err(e) = std::fs::remove_file(&self.path) {
|
||||
// Best-effort cleanup; ignore missing file; warn for other errors
|
||||
if e.kind() != std::io::ErrorKind::NotFound {
|
||||
warnlog!("Failed to remove {}: {}", self.path.display(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
fn run() -> Result<()> {
|
||||
// Parse CLI
|
||||
let args = Args::parse();
|
||||
|
||||
@@ -692,6 +701,20 @@ fn main() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = run() {
|
||||
errorlog!("{}", e);
|
||||
if VERBOSE.load(Ordering::Relaxed) >= 1 {
|
||||
let mut src = e.source();
|
||||
while let Some(s) = src {
|
||||
errorlog!("caused by: {}", s);
|
||||
src = s.source();
|
||||
}
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
Reference in New Issue
Block a user