add logging

This commit is contained in:
Julian Freeman
2025-12-02 10:44:14 -04:00
parent 068bc1c79e
commit d2cafc328f
6 changed files with 312 additions and 30 deletions

View File

@@ -46,6 +46,13 @@ pub struct ProgressEvent {
pub status: String, // "downloading", "processing", "finished", "error"
}
#[derive(Serialize, Clone, Debug)]
pub struct LogEvent {
pub id: String,
pub message: String,
pub level: String, // "info", "error"
}
pub async fn fetch_metadata(app: &AppHandle, url: &str, parse_mix_playlist: bool) -> Result<MetadataResult> {
let ytdlp_path = ytdlp::get_ytdlp_path(app)?;
@@ -148,31 +155,60 @@ pub async fn download_video(
let mut child = Command::new(ytdlp_path)
.args(&args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.stderr(Stdio::piped()) // Capture stderr for logs
.spawn()?;
let stdout = child.stdout.take().ok_or(anyhow!("Failed to open stdout"))?;
let mut reader = BufReader::new(stdout);
let mut line = String::new();
// Regex for progress: [download] 42.5% of 10.00MiB at 2.00MiB/s ETA 00:05
let stderr = child.stderr.take().ok_or(anyhow!("Failed to open stderr"))?;
let mut stdout_reader = BufReader::new(stdout);
let mut stderr_reader = BufReader::new(stderr);
let re = Regex::new(r"\[download\]\s+(\d+\.?\d*)%").unwrap();
while reader.read_line(&mut line).await? > 0 {
if let Some(caps) = re.captures(&line) {
if let Some(pct_match) = caps.get(1) {
if let Ok(pct) = pct_match.as_str().parse::<f64>() {
// Emit event
app.emit("download-progress", ProgressEvent {
id: id.clone(),
progress: pct,
speed: "TODO".to_string(), // Speed parsing is a bit more complex, skipping for MVP or adding regex for it
status: "downloading".to_string(),
}).ok();
// Loop to read both streams
loop {
let mut out_line = String::new();
let mut err_line = String::new();
tokio::select! {
res = stdout_reader.read_line(&mut out_line) => {
if res.unwrap_or(0) == 0 {
break; // EOF
}
// Log info
app.emit("download-log", LogEvent {
id: id.clone(),
message: out_line.trim().to_string(),
level: "info".to_string(),
}).ok();
// Parse progress
if let Some(caps) = re.captures(&out_line) {
if let Some(pct_match) = caps.get(1) {
if let Ok(pct) = pct_match.as_str().parse::<f64>() {
app.emit("download-progress", ProgressEvent {
id: id.clone(),
progress: pct,
speed: "TODO".to_string(),
status: "downloading".to_string(),
}).ok();
}
}
}
}
res = stderr_reader.read_line(&mut err_line) => {
if res.unwrap_or(0) > 0 {
// Log error
app.emit("download-log", LogEvent {
id: id.clone(),
message: err_line.trim().to_string(),
level: "error".to_string(),
}).ok();
}
}
}
line.clear();
}
let status = child.wait().await?;
@@ -194,4 +230,4 @@ pub async fn download_video(
}).ok();
Err(anyhow!("Download process failed"))
}
}
}