From 977ecc9f7de0485be253726d1d154cdbd345753e Mon Sep 17 00:00:00 2001 From: thewh1teagle <61390950+thewh1teagle@users.noreply.github.com> Date: Wed, 4 Dec 2024 21:16:00 +0200 Subject: [PATCH] feat: ytdlp progress --- desktop/src-tauri/locales/en-US/common.json | 1 + desktop/src-tauri/locales/es-MX/common.json | 1 + desktop/src-tauri/locales/fr-FR/common.json | 1 + desktop/src-tauri/locales/he-IL/common.json | 1 + desktop/src-tauri/locales/hi-IN/common.json | 1 + desktop/src-tauri/locales/it-IT/common.json | 1 + desktop/src-tauri/locales/pl-PL/common.json | 1 + desktop/src-tauri/locales/pt-BR/common.json | 1 + desktop/src-tauri/locales/sv-SE/common.json | 1 + desktop/src-tauri/locales/zh-CN/common.json | 1 + desktop/src-tauri/src/cmd/ytdlp.rs | 95 ++++++++++++++++----- desktop/src/lib/logs.ts | 1 - desktop/src/lib/ytdlp.ts | 5 +- desktop/src/pages/home/Page.tsx | 14 ++- desktop/src/pages/home/viewModel.ts | 26 ++++++ desktop/src/pages/settings/viewModel.ts | 1 - 16 files changed, 124 insertions(+), 28 deletions(-) diff --git a/desktop/src-tauri/locales/en-US/common.json b/desktop/src-tauri/locales/en-US/common.json index 564aae11..89bdbd9e 100644 --- a/desktop/src-tauri/locales/en-US/common.json +++ b/desktop/src-tauri/locales/en-US/common.json @@ -34,6 +34,7 @@ "download-file": "Download and transcribe", "download-model": "Download model", "download-models-link": "Download Models", + "downloading": "Downloading... {{progress}}%", "downloading-ai-models": "Downloading AI models...", "downloading-model": "Downloading OpenAI Model...", "downloading-ytdlp": "Downloading ytdlp", diff --git a/desktop/src-tauri/locales/es-MX/common.json b/desktop/src-tauri/locales/es-MX/common.json index 2325da02..eeca6f2d 100644 --- a/desktop/src-tauri/locales/es-MX/common.json +++ b/desktop/src-tauri/locales/es-MX/common.json @@ -34,6 +34,7 @@ "download-file": "Descargar y transcribir", "download-model": "Descargar modelo", "download-models-link": "Descargar Modelos", + "downloading": "Descargando... {{progreso}}%", "downloading-ai-models": "Descargando modelos de IA...", "downloading-model": "Descargando Modelo de OpenAI...", "downloading-ytdlp": "Descargando ytdlp", diff --git a/desktop/src-tauri/locales/fr-FR/common.json b/desktop/src-tauri/locales/fr-FR/common.json index f5729553..283e1afa 100644 --- a/desktop/src-tauri/locales/fr-FR/common.json +++ b/desktop/src-tauri/locales/fr-FR/common.json @@ -34,6 +34,7 @@ "download-file": "Télécharger l'audio", "download-model": "Télécharger le modèle", "download-models-link": "Télécharger les modèles", + "downloading": "Téléchargement... {{progress}} %", "downloading-ai-models": "Téléchargement de modèles d'IA...", "downloading-model": "Téléchargement du modèle OpenAI en cours…", "downloading-ytdlp": "Téléchargement de ytdlp", diff --git a/desktop/src-tauri/locales/he-IL/common.json b/desktop/src-tauri/locales/he-IL/common.json index 0f65d357..9fb96716 100644 --- a/desktop/src-tauri/locales/he-IL/common.json +++ b/desktop/src-tauri/locales/he-IL/common.json @@ -34,6 +34,7 @@ "download-file": "הורד ותמלל", "download-model": "הורד מודל", "download-models-link": "הורדת מודלים", + "downloading": "מוריד... {{progress}}%", "downloading-ai-models": "מוריד מודלים...", "downloading-model": "מוריד מודל בינה מלאכותית", "downloading-ytdlp": "מוריד ytdlp", diff --git a/desktop/src-tauri/locales/hi-IN/common.json b/desktop/src-tauri/locales/hi-IN/common.json index 357e6a8b..ae76ac55 100644 --- a/desktop/src-tauri/locales/hi-IN/common.json +++ b/desktop/src-tauri/locales/hi-IN/common.json @@ -34,6 +34,7 @@ "download-file": "डाउनलोड करें और प्रतिलेखित करें", "download-model": "मॉडल डाउनलोड करें", "download-models-link": "मॉडल डाउनलोड करें", + "downloading": "डाउनलोड हो रहा है... {{प्रगति}}%", "downloading-ai-models": "AI मॉडल डाउनलोड हो रहा है...", "downloading-model": "OpenAI मॉडल डाउनलोड हो रहा है...", "downloading-ytdlp": "Ytdlp डाउनलोड हो रहा है", diff --git a/desktop/src-tauri/locales/it-IT/common.json b/desktop/src-tauri/locales/it-IT/common.json index 0bb901b5..ebb405c2 100644 --- a/desktop/src-tauri/locales/it-IT/common.json +++ b/desktop/src-tauri/locales/it-IT/common.json @@ -34,6 +34,7 @@ "download-file": "Scarica e trascrivi", "download-model": "Scarica modello", "download-models-link": "Scarica modelli", + "downloading": "Download in corso... {{progress}}%", "downloading-ai-models": "Scaricando i modelli AI...", "downloading-model": "Scaricando i modelli di OpenAI...", "downloading-ytdlp": "Scaricando i modelli ytdlp", diff --git a/desktop/src-tauri/locales/pl-PL/common.json b/desktop/src-tauri/locales/pl-PL/common.json index a3082d4a..271a292f 100644 --- a/desktop/src-tauri/locales/pl-PL/common.json +++ b/desktop/src-tauri/locales/pl-PL/common.json @@ -34,6 +34,7 @@ "download-file": "Pobierz i transkrybuj", "download-model": "Pobierz model", "download-models-link": "Pobierz modele", + "downloading": "Pobieram... {{postęp}}%", "downloading-ai-models": "Pobieranie modeli AI...", "downloading-model": "Pobieram modele od OpenAI...", "downloading-ytdlp": "Pobieram ytdlp", diff --git a/desktop/src-tauri/locales/pt-BR/common.json b/desktop/src-tauri/locales/pt-BR/common.json index 3a84de58..d0df9277 100644 --- a/desktop/src-tauri/locales/pt-BR/common.json +++ b/desktop/src-tauri/locales/pt-BR/common.json @@ -34,6 +34,7 @@ "download-file": "Baixe e transcreva", "download-model": "Baixar modelo", "download-models-link": "Baixar modelos", + "downloading": "Baixando... {{progresso}}%", "downloading-ai-models": "Baixando modelos de IA...", "downloading-model": "Baixando o modelo OpenAI....", "downloading-ytdlp": "Baixando ytdlp", diff --git a/desktop/src-tauri/locales/sv-SE/common.json b/desktop/src-tauri/locales/sv-SE/common.json index 32575687..fe411901 100644 --- a/desktop/src-tauri/locales/sv-SE/common.json +++ b/desktop/src-tauri/locales/sv-SE/common.json @@ -34,6 +34,7 @@ "download-file": "Ladda ner och transkribera", "download-model": "Ladda ner modell", "download-models-link": "Hämta Modeller", + "downloading": "Laddar ned... {{progress}}%", "downloading-ai-models": "Laddar ner AI-modeller...", "downloading-model": "Hämtar OpenAI Model...", "downloading-ytdlp": "Laddar ner ytdlp", diff --git a/desktop/src-tauri/locales/zh-CN/common.json b/desktop/src-tauri/locales/zh-CN/common.json index 099c2248..369adc1e 100644 --- a/desktop/src-tauri/locales/zh-CN/common.json +++ b/desktop/src-tauri/locales/zh-CN/common.json @@ -34,6 +34,7 @@ "download-file": "下载并转录", "download-model": "下载模型", "download-models-link": "下载模型", + "downloading": "正在下载... {{progress}}%", "downloading-ai-models": "正在下载 AI 模型...", "downloading-model": "正在下载 OpenAI 模型...", "downloading-ytdlp": "下载 ytdlp", diff --git a/desktop/src-tauri/src/cmd/ytdlp.rs b/desktop/src-tauri/src/cmd/ytdlp.rs index 63a1439b..060cd1ed 100644 --- a/desktop/src-tauri/src/cmd/ytdlp.rs +++ b/desktop/src-tauri/src/cmd/ytdlp.rs @@ -1,11 +1,19 @@ use eyre::{bail, Context, Result}; -use tauri::{AppHandle, Manager}; +use serde_json::Value; +use std::{ + io::{BufRead, BufReader}, + sync::atomic::{AtomicBool, Ordering}, +}; +use tauri::{AppHandle, Emitter, Listener, Manager}; use vibe_core::get_vibe_temp_folder; +use crate::utils::LogError; + use super::get_ffmpeg_path; #[cfg(windows)] use std::os::windows::process::CommandExt; +use std::process::Stdio; #[cfg(windows)] const CREATE_NO_WINDOW: u32 = 0x08000000; @@ -33,7 +41,7 @@ pub fn get_temp_path(app_handle: AppHandle, ext: String, in_documents: Option Result { +pub async fn download_audio(app_handle: AppHandle, url: String, out_path: String) -> Result<()> { tracing::debug!("download audio {}", url); let name = get_binary_name(); let path = app_handle.path().app_local_data_dir().context("Can't get data directory")?; @@ -53,26 +61,75 @@ pub async fn download_audio(app_handle: AppHandle, url: String, out_path: String } let mut cmd = std::process::Command::new(path); - let cmd = cmd.args([ - "--no-playlist", - "-x", - "--audio-format", - "m4a", - "--ffmpeg-location", - &ffmpeg_path, - &url, - "-o", - &out_path, - ]); + let cmd = cmd + .args([ + "--progress-template", + "{\"progress\": \"%(progress.percent)s\", \"total_bytes\": \"%(progress.total_bytes)s\", \"progress_str\": \"%(progress._percent_str)s\"}\n", + "--no-playlist", + "-x", + "--audio-format", + "m4a", + "--ffmpeg-location", + &ffmpeg_path, + &url, + "-o", + &out_path, + ]) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); #[cfg(windows)] let cmd = cmd.creation_flags(CREATE_NO_WINDOW); - let output = cmd.output()?; - if !output.status.success() { - let stderr = String::from_utf8(output.stderr)?; - bail!("Failed to download audio: {}", stderr); + let cancel_flag = std::sync::Arc::new(AtomicBool::new(false)); + let cancel_flag_c = cancel_flag.clone(); + app_handle.once("ytdlp-cancel", move |_| { + cancel_flag_c.store(true, Ordering::Relaxed); + }); + + let mut child = cmd.spawn()?; + + if let Some(stdout) = child.stdout.take() { + let reader = BufReader::new(stdout); + + for line in reader.lines() { + if cancel_flag.load(Ordering::Relaxed) { + let _ = child.kill(); + break; + } + + let mut line = line?; + line = line.replace("\r", "").trim().to_string(); + + if line.starts_with("{\"progress") { + // try parse progress + let result: Result = serde_json::from_str(&line); + if let Ok(value) = result { + // remove % and parse to number + let percentage_str = value["progress_str"].as_str().unwrap_or_default().trim().replace("%", ""); + if let Ok(percentage_number) = percentage_str.parse::() { + app_handle + .emit("ytdlp-progress", percentage_number) + .context("failed to emit") + .log_error(); + } + } + } + } + } + + let ret = child.wait()?; + if !ret.success() && !cancel_flag.load(Ordering::Relaxed) { + let mut stderr_output: String = "".to_string(); + if let Some(stderr) = child.stderr.take() { + stderr_output = BufReader::new(stderr) + .lines() + .filter_map(|line| line.ok()) + .collect::>() + .join("\n"); + eprintln!("Error: {}", stderr_output); + } + bail!("Failed to download audio: {}", stderr_output); } - let output = String::from_utf8(output.stdout)?; - Ok(output) + Ok(()) } diff --git a/desktop/src/lib/logs.ts b/desktop/src/lib/logs.ts index 2cb4e472..707fbe28 100644 --- a/desktop/src/lib/logs.ts +++ b/desktop/src/lib/logs.ts @@ -75,7 +75,6 @@ export async function collectLogs() { .slice(-10) // Take the last 3 lines .map((line) => { try { - console.log('line => ', line) const parsed = JSON.parse(line) // Deserialize JSON return parsed?.fields?.message || 'No message found' // Extract .message or fallback } catch (e) { diff --git a/desktop/src/lib/ytdlp.ts b/desktop/src/lib/ytdlp.ts index a799460e..38fd0aab 100644 --- a/desktop/src/lib/ytdlp.ts +++ b/desktop/src/lib/ytdlp.ts @@ -15,7 +15,6 @@ async function getBinaryPath() { export async function exists() { const binaryPath = await getBinaryPath() - console.log('checking', binaryPath) return await fs.exists(binaryPath) } @@ -26,8 +25,6 @@ export async function downloadYtDlp() { export async function downloadAudio(url: string, inDocuments?: boolean) { const outPath = await invoke('get_temp_path', { ext: 'm4a', inDocuments }) - console.log('outPath is ', outPath) - let result = await invoke('download_audio', { url, outPath }) - console.log(result) + await invoke('download_audio', { url, outPath }) return outPath } diff --git a/desktop/src/pages/home/Page.tsx b/desktop/src/pages/home/Page.tsx index 97ce89ba..b19c42fd 100644 --- a/desktop/src/pages/home/Page.tsx +++ b/desktop/src/pages/home/Page.tsx @@ -164,9 +164,17 @@ export default function Home() { /> {vm.downloadingAudio ? ( - + <> +
+
+ +

{t('common.downloading', { progress: vm.ytdlpProgress })}

+ +
+
+ ) : ( <>