diff --git a/languages/ar.json b/languages/ar.json
index 8c38248..a560206 100644
--- a/languages/ar.json
+++ b/languages/ar.json
@@ -477,22 +477,17 @@
"redownload_started": "بدأ التنزيل"
},
"ffmpeg_updater": {
- "title": "محدث FFmpeg",
+ "title": "مدقق إصدار FFmpeg",
"current_version": "الإصدار الحالي:",
"latest_version": "أحدث إصدار:",
"status_up_to_date": "✓ محدث",
- "status_update_available": "⚠ تحديث متاح",
+ "status_update_available": "⚠ يتوفر تحديث",
"status_not_installed": "✗ غير مثبت",
- "status_checking": "🔄 جارٍ التحقق من التحديثات...",
- "status_downloading": "⬇ جارٍ تنزيل FFmpeg...",
- "status_installing": "⚙ جارٍ تثبيت FFmpeg...",
- "status_verifying": "✓ جارٍ التحقق من السلامة...",
- "check_updates": "التحقق من التحديثات",
- "update_button": "تحديث FFmpeg",
- "update_success": "تم تحديث FFmpeg بنجاح إلى الإصدار {version}!",
- "update_failed": "فشل تحديث FFmpeg. يرجى المحاولة مرة أخرى.",
- "check_failed": "فشل التحقق من التحديثات. يرجى التحقق من اتصال الإنترنت.",
- "install_first": "FFmpeg غير مثبت. انقر فوق تحديث للتثبيت.",
- "description": "حافظ على تحديث FFmpeg للحصول على أفضل أداء وتوافق."
+ "status_idle": "انقر على 'التحقق من الإصدار' للبدء",
+ "status_checking": "🔄 جاري التحقق من الإصدار...",
+ "check_updates": "التحقق من الإصدار",
+ "check_failed": "فشل التحقق من الإصدار. يرجى التحقق من اتصال الإنترنت.",
+ "description": "تحقق من إصدار FFmpeg الخاص بك وقارنه بأحدث إصدار متاح.",
+ "guide_info": " لتثبيت أو تحديث FFmpeg، انقر هنا لعرض دليل التثبيت الشامل."
}
}
\ No newline at end of file
diff --git a/languages/de.json b/languages/de.json
index dbc66bc..15b9f3f 100644
--- a/languages/de.json
+++ b/languages/de.json
@@ -477,22 +477,17 @@
"redownload_started": "Download gestartet"
},
"ffmpeg_updater": {
- "title": "FFmpeg-Updater",
+ "title": "FFmpeg-Versionsprüfer",
"current_version": "Aktuelle Version:",
"latest_version": "Neueste Version:",
"status_up_to_date": "✓ Auf dem neuesten Stand",
"status_update_available": "⚠ Update verfügbar",
"status_not_installed": "✗ Nicht installiert",
- "status_checking": "🔄 Suche nach Updates...",
- "status_downloading": "⬇ FFmpeg wird heruntergeladen...",
- "status_installing": "⚙ FFmpeg wird installiert...",
- "status_verifying": "✓ Integrität wird überprüft...",
- "check_updates": "Nach Updates suchen",
- "update_button": "FFmpeg aktualisieren",
- "update_success": "FFmpeg erfolgreich auf Version {version} aktualisiert!",
- "update_failed": "FFmpeg-Update fehlgeschlagen. Bitte versuchen Sie es erneut.",
- "check_failed": "Update-Prüfung fehlgeschlagen. Bitte überprüfen Sie Ihre Internetverbindung.",
- "install_first": "FFmpeg ist nicht installiert. Klicken Sie auf Aktualisieren, um zu installieren.",
- "description": "Halten Sie FFmpeg auf dem neuesten Stand für beste Leistung und Kompatibilität."
+ "status_idle": "Klicken Sie auf 'Version prüfen' um zu beginnen",
+ "status_checking": "🔄 Version wird geprüft...",
+ "check_updates": "Version prüfen",
+ "check_failed": "Versionprüfung fehlgeschlagen. Bitte überprüfen Sie Ihre Internetverbindung.",
+ "description": "Überprüfen Sie Ihre FFmpeg-Version und vergleichen Sie sie mit der neuesten verfügbaren Version.",
+ "guide_info": " Um FFmpeg zu installieren oder zu aktualisieren, klicken Sie hier, um unseren umfassenden Installationsleitfaden anzuzeigen."
}
}
\ No newline at end of file
diff --git a/languages/en.json b/languages/en.json
index f945663..56c434f 100644
--- a/languages/en.json
+++ b/languages/en.json
@@ -477,23 +477,17 @@
"redownload_started": "Redownload started"
},
"ffmpeg_updater": {
- "title": "FFmpeg Updater",
+ "title": "FFmpeg Version Checker",
"current_version": "Current Version:",
"latest_version": "Latest Version:",
"status_up_to_date": "✓ Up to date",
"status_update_available": "⚠ Update available",
"status_not_installed": "✗ Not installed",
- "status_idle": "Click 'Check for Updates' to get started",
- "status_checking": "🔄 Checking for updates...",
- "status_downloading": "⬇ Downloading FFmpeg...",
- "status_installing": "⚙ Installing FFmpeg...",
- "status_verifying": "✓ Verifying integrity...",
- "check_updates": "Check for Updates",
- "update_button": "Update FFmpeg",
- "update_success": "FFmpeg successfully updated to version {version}!",
- "update_failed": "Failed to update FFmpeg. Please try again.",
- "check_failed": "Failed to check for updates. Please check your internet connection.",
- "install_first": "FFmpeg is not installed. Click Update to install.",
- "description": "Keep FFmpeg up to date for the best performance and compatibility."
+ "status_idle": "Click 'Check Version' to get started",
+ "status_checking": "🔄 Checking version...",
+ "check_updates": "Check Version",
+ "check_failed": "Failed to check version. Please check your internet connection.",
+ "description": "Check your FFmpeg version and compare it with the latest available version.",
+ "guide_info": " To install or update FFmpeg, click here to view our comprehensive installation guide."
}
}
\ No newline at end of file
diff --git a/languages/es.json b/languages/es.json
index a4e572c..b917369 100644
--- a/languages/es.json
+++ b/languages/es.json
@@ -460,22 +460,17 @@
"redownload_started": "Descarga iniciada"
},
"ffmpeg_updater": {
- "title": "Actualizador de FFmpeg",
+ "title": "Comprobador de Versión FFmpeg",
"current_version": "Versión Actual:",
"latest_version": "Última Versión:",
"status_up_to_date": "✓ Actualizado",
"status_update_available": "⚠ Actualización disponible",
"status_not_installed": "✗ No instalado",
- "status_checking": "🔄 Verificando actualizaciones...",
- "status_downloading": "⬇ Descargando FFmpeg...",
- "status_installing": "⚙ Instalando FFmpeg...",
- "status_verifying": "✓ Verificando integridad...",
- "check_updates": "Buscar Actualizaciones",
- "update_button": "Actualizar FFmpeg",
- "update_success": "¡FFmpeg actualizado exitosamente a la versión {version}!",
- "update_failed": "Error al actualizar FFmpeg. Por favor, inténtelo de nuevo.",
- "check_failed": "Error al verificar actualizaciones. Por favor, verifique su conexión a internet.",
- "install_first": "FFmpeg no está instalado. Haga clic en Actualizar para instalar.",
- "description": "Mantenga FFmpeg actualizado para el mejor rendimiento y compatibilidad."
+ "status_idle": "Haga clic en 'Comprobar Versión' para comenzar",
+ "status_checking": "🔄 Verificando versión...",
+ "check_updates": "Comprobar Versión",
+ "check_failed": "Error al verificar la versión. Por favor, verifique su conexión a internet.",
+ "description": "Compruebe su versión de FFmpeg y compárela con la última versión disponible.",
+ "guide_info": " Para instalar o actualizar FFmpeg, haga clic aquí para ver nuestra guía completa de instalación."
}
}
\ No newline at end of file
diff --git a/languages/fr.json b/languages/fr.json
index b8a619b..708f5af 100644
--- a/languages/fr.json
+++ b/languages/fr.json
@@ -477,22 +477,17 @@
"redownload_started": "Téléchargement démarré"
},
"ffmpeg_updater": {
- "title": "Mise à jour FFmpeg",
+ "title": "Vérificateur de Version FFmpeg",
"current_version": "Version Actuelle:",
"latest_version": "Dernière Version:",
"status_up_to_date": "✓ À jour",
"status_update_available": "⚠ Mise à jour disponible",
"status_not_installed": "✗ Non installé",
- "status_checking": "🔄 Vérification des mises à jour...",
- "status_downloading": "⬇ Téléchargement de FFmpeg...",
- "status_installing": "⚙ Installation de FFmpeg...",
- "status_verifying": "✓ Vérification de l'intégrité...",
- "check_updates": "Vérifier les mises à jour",
- "update_button": "Mettre à jour FFmpeg",
- "update_success": "FFmpeg mis à jour avec succès vers la version {version}!",
- "update_failed": "Échec de la mise à jour de FFmpeg. Veuillez réessayer.",
- "check_failed": "Échec de la vérification des mises à jour. Vérifiez votre connexion Internet.",
- "install_first": "FFmpeg n'est pas installé. Cliquez sur Mettre à jour pour installer.",
- "description": "Maintenez FFmpeg à jour pour les meilleures performances et compatibilité."
+ "status_idle": "Cliquez sur 'Vérifier la Version' pour commencer",
+ "status_checking": "🔄 Vérification de la version...",
+ "check_updates": "Vérifier la Version",
+ "check_failed": "Échec de la vérification de la version. Vérifiez votre connexion Internet.",
+ "description": "Vérifiez votre version de FFmpeg et comparez-la avec la dernière version disponible.",
+ "guide_info": " Pour installer ou mettre à jour FFmpeg, cliquez ici pour consulter notre guide d'installation complet."
}
}
\ No newline at end of file
diff --git a/languages/hi.json b/languages/hi.json
index 9335223..58f951f 100644
--- a/languages/hi.json
+++ b/languages/hi.json
@@ -477,22 +477,17 @@
"redownload_started": "डाउनलोड शुरू हुआ"
},
"ffmpeg_updater": {
- "title": "FFmpeg अपडेटर",
+ "title": "FFmpeg संस्करण जांचकर्ता",
"current_version": "वर्तमान संस्करण:",
"latest_version": "नवीनतम संस्करण:",
"status_up_to_date": "✓ अप टू डेट",
"status_update_available": "⚠ अपडेट उपलब्ध",
"status_not_installed": "✗ इंस्टॉल नहीं है",
- "status_checking": "🔄 अपडेट जांच रहे हैं...",
- "status_downloading": "⬇ FFmpeg डाउनलोड हो रहा है...",
- "status_installing": "⚙ FFmpeg इंस्टॉल हो रहा है...",
- "status_verifying": "✓ अखंडता सत्यापित कर रहे हैं...",
- "check_updates": "अपडेट जांचें",
- "update_button": "FFmpeg अपडेट करें",
- "update_success": "FFmpeg सफलतापूर्वक संस्करण {version} में अपडेट किया गया!",
- "update_failed": "FFmpeg अपडेट विफल रहा। कृपया पुनः प्रयास करें।",
- "check_failed": "अपडेट जांच विफल रही। कृपया अपना इंटरनेट कनेक्शन जांचें।",
- "install_first": "FFmpeg इंस्टॉल नहीं है। इंस्टॉल करने के लिए अपडेट पर क्लिक करें।",
- "description": "सर्वोत्तम प्रदर्शन और संगतता के लिए FFmpeg को अप टू डेट रखें।"
+ "status_idle": "शुरू करने के लिए 'संस्करण जांचें' पर क्लिक करें",
+ "status_checking": "🔄 संस्करण जांच रहे हैं...",
+ "check_updates": "संस्करण जांचें",
+ "check_failed": "संस्करण जांच विफल रही। कृपया अपना इंटरनेट कनेक्शन जांचें।",
+ "description": "अपने FFmpeg संस्करण की जांच करें और इसे नवीनतम उपलब्ध संस्करण से तुलना करें।",
+ "guide_info": " FFmpeg को इंस्टॉल या अपडेट करने के लिए, हमारी व्यापक इंस्टॉलेशन गाइड देखने के लिए यहां क्लिक करें."
}
}
\ No newline at end of file
diff --git a/languages/id.json b/languages/id.json
index dd2e99a..116612c 100644
--- a/languages/id.json
+++ b/languages/id.json
@@ -477,22 +477,17 @@
"redownload_started": "Unduhan dimulai"
},
"ffmpeg_updater": {
- "title": "Pembaruan FFmpeg",
+ "title": "Pemeriksa Versi FFmpeg",
"current_version": "Versi Saat Ini:",
"latest_version": "Versi Terbaru:",
"status_up_to_date": "✓ Terbaru",
"status_update_available": "⚠ Pembaruan tersedia",
"status_not_installed": "✗ Tidak terinstal",
- "status_checking": "🔄 Memeriksa pembaruan...",
- "status_downloading": "⬇ Mengunduh FFmpeg...",
- "status_installing": "⚙ Menginstal FFmpeg...",
- "status_verifying": "✓ Memverifikasi integritas...",
- "check_updates": "Periksa Pembaruan",
- "update_button": "Perbarui FFmpeg",
- "update_success": "FFmpeg berhasil diperbarui ke versi {version}!",
- "update_failed": "Gagal memperbarui FFmpeg. Silakan coba lagi.",
- "check_failed": "Gagal memeriksa pembaruan. Periksa koneksi internet Anda.",
- "install_first": "FFmpeg tidak terinstal. Klik Perbarui untuk menginstal.",
- "description": "Jaga FFmpeg tetap terbaru untuk performa dan kompatibilitas terbaik."
+ "status_idle": "Klik 'Periksa Versi' untuk memulai",
+ "status_checking": "🔄 Memeriksa versi...",
+ "check_updates": "Periksa Versi",
+ "check_failed": "Gagal memeriksa versi. Periksa koneksi internet Anda.",
+ "description": "Periksa versi FFmpeg Anda dan bandingkan dengan versi terbaru yang tersedia.",
+ "guide_info": " Untuk menginstal atau memperbarui FFmpeg, klik di sini untuk melihat panduan instalasi lengkap kami."
}
}
\ No newline at end of file
diff --git a/languages/it.json b/languages/it.json
index 6708a9b..eeda165 100644
--- a/languages/it.json
+++ b/languages/it.json
@@ -477,22 +477,17 @@
"redownload_started": "Download avviato"
},
"ffmpeg_updater": {
- "title": "Aggiornamento FFmpeg",
+ "title": "Controllo Versione FFmpeg",
"current_version": "Versione corrente:",
"latest_version": "Ultima versione:",
"status_up_to_date": "✓ Aggiornato",
"status_update_available": "⚠ Aggiornamento disponibile",
"status_not_installed": "✗ Non installato",
- "status_checking": "🔄 Verifica aggiornamenti...",
- "status_downloading": "⬇ Download di FFmpeg...",
- "status_installing": "⚙ Installazione di FFmpeg...",
- "status_verifying": "✓ Verifica integrità...",
- "check_updates": "Verifica aggiornamenti",
- "update_button": "Aggiorna FFmpeg",
- "update_success": "FFmpeg aggiornato con successo alla versione {version}!",
- "update_failed": "Aggiornamento di FFmpeg non riuscito. Riprova.",
- "check_failed": "Verifica aggiornamenti non riuscita. Controlla la connessione Internet.",
- "install_first": "FFmpeg non è installato. Clicca Aggiorna per installare.",
- "description": "Mantieni FFmpeg aggiornato per le migliori prestazioni e compatibilità."
+ "status_idle": "Clicca 'Controlla Versione' per iniziare",
+ "status_checking": "🔄 Verifica versione...",
+ "check_updates": "Controlla Versione",
+ "check_failed": "Verifica versione non riuscita. Controlla la connessione Internet.",
+ "description": "Controlla la tua versione di FFmpeg e confrontala con l'ultima versione disponibile.",
+ "guide_info": " Per installare o aggiornare FFmpeg, clicca qui per visualizzare la nostra guida completa all'installazione."
}
}
\ No newline at end of file
diff --git a/languages/ja.json b/languages/ja.json
index 62d3227..8ed2959 100644
--- a/languages/ja.json
+++ b/languages/ja.json
@@ -477,22 +477,17 @@
"redownload_started": "ダウンロード開始"
},
"ffmpeg_updater": {
- "title": "FFmpegアップデーター",
+ "title": "FFmpegバージョンチェッカー",
"current_version": "現在のバージョン:",
"latest_version": "最新バージョン:",
"status_up_to_date": "✓ 最新",
"status_update_available": "⚠ 更新可能",
"status_not_installed": "✗ 未インストール",
- "status_checking": "🔄 更新を確認中...",
- "status_downloading": "⬇ FFmpegをダウンロード中...",
- "status_installing": "⚙ FFmpegをインストール中...",
- "status_verifying": "✓ 整合性を検証中...",
- "check_updates": "更新を確認",
- "update_button": "FFmpegを更新",
- "update_success": "FFmpegがバージョン{version}に更新されました!",
- "update_failed": "FFmpegの更新に失敗しました。再試行してください。",
- "check_failed": "更新の確認に失敗しました。インターネット接続を確認してください。",
- "install_first": "FFmpegがインストールされていません。インストールするには「更新」をクリックしてください。",
- "description": "最高のパフォーマンスと互換性のためにFFmpegを最新の状態に保ってください。"
+ "status_idle": "開始するには「バージョンを確認」をクリック",
+ "status_checking": "🔄 バージョンを確認中...",
+ "check_updates": "バージョンを確認",
+ "check_failed": "バージョンの確認に失敗しました。インターネット接続を確認してください。",
+ "description": "FFmpegのバージョンを確認し、利用可能な最新バージョンと比較します。",
+ "guide_info": " FFmpegをインストールまたは更新するには、こちらをクリックして包括的なインストールガイドをご覧ください。"
}
}
\ No newline at end of file
diff --git a/languages/pl.json b/languages/pl.json
index 18818ff..35b2800 100644
--- a/languages/pl.json
+++ b/languages/pl.json
@@ -477,22 +477,17 @@
"redownload_started": "Rozpoczęto pobieranie"
},
"ffmpeg_updater": {
- "title": "Aktualizator FFmpeg",
+ "title": "Sprawdzanie Wersji FFmpeg",
"current_version": "Obecna wersja:",
"latest_version": "Najnowsza wersja:",
"status_up_to_date": "✓ Aktualne",
"status_update_available": "⚠ Dostępna aktualizacja",
"status_not_installed": "✗ Nie zainstalowano",
- "status_checking": "🔄 Sprawdzanie aktualizacji...",
- "status_downloading": "⬇ Pobieranie FFmpeg...",
- "status_installing": "⚙ Instalowanie FFmpeg...",
- "status_verifying": "✓ Weryfikacja integralności...",
- "check_updates": "Sprawdź aktualizacje",
- "update_button": "Aktualizuj FFmpeg",
- "update_success": "FFmpeg zaktualizowano pomyślnie do wersji {version}!",
- "update_failed": "Nie udało się zaktualizować FFmpeg. Spróbuj ponownie.",
- "check_failed": "Nie udało się sprawdzić aktualizacji. Sprawdź połączenie internetowe.",
- "install_first": "FFmpeg nie jest zainstalowany. Kliknij Aktualizuj, aby zainstalować.",
- "description": "Utrzymuj FFmpeg w aktualnej wersji dla najlepszej wydajności i kompatybilności."
+ "status_idle": "Kliknij 'Sprawdź Wersję', aby rozpocząć",
+ "status_checking": "🔄 Sprawdzanie wersji...",
+ "check_updates": "Sprawdź Wersję",
+ "check_failed": "Nie udało się sprawdzić wersji. Sprawdź połączenie internetowe.",
+ "description": "Sprawdź swoją wersję FFmpeg i porównaj ją z najnowszą dostępną wersją.",
+ "guide_info": " Aby zainstalować lub zaktualizować FFmpeg, kliknij tutaj, aby wyświetlić nasz kompleksowy przewodnik instalacji."
}
}
\ No newline at end of file
diff --git a/languages/pt.json b/languages/pt.json
index 165be32..db01578 100644
--- a/languages/pt.json
+++ b/languages/pt.json
@@ -477,22 +477,17 @@
"redownload_started": "Download iniciado"
},
"ffmpeg_updater": {
- "title": "Atualizador FFmpeg",
+ "title": "Verificador de Versão FFmpeg",
"current_version": "Versão Atual:",
"latest_version": "Última Versão:",
"status_up_to_date": "✓ Atualizado",
"status_update_available": "⚠ Atualização disponível",
"status_not_installed": "✗ Não instalado",
- "status_checking": "🔄 Verificando atualizações...",
- "status_downloading": "⬇ Baixando FFmpeg...",
- "status_installing": "⚙ Instalando FFmpeg...",
- "status_verifying": "✓ Verificando integridade...",
- "check_updates": "Verificar Atualizações",
- "update_button": "Atualizar FFmpeg",
- "update_success": "FFmpeg atualizado com sucesso para a versão {version}!",
- "update_failed": "Falha ao atualizar FFmpeg. Tente novamente.",
- "check_failed": "Falha ao verificar atualizações. Verifique sua conexão com a Internet.",
- "install_first": "FFmpeg não está instalado. Clique em Atualizar para instalar.",
- "description": "Mantenha o FFmpeg atualizado para melhor desempenho e compatibilidade."
+ "status_idle": "Clique em 'Verificar Versão' para começar",
+ "status_checking": "🔄 Verificando versão...",
+ "check_updates": "Verificar Versão",
+ "check_failed": "Falha ao verificar versão. Verifique sua conexão com a Internet.",
+ "description": "Verifique sua versão do FFmpeg e compare com a última versão disponível.",
+ "guide_info": " Para instalar ou atualizar o FFmpeg, clique aqui para ver nosso guia completo de instalação."
}
}
\ No newline at end of file
diff --git a/languages/ru.json b/languages/ru.json
index c3a8d23..52f4986 100644
--- a/languages/ru.json
+++ b/languages/ru.json
@@ -477,22 +477,17 @@
"redownload_started": "Загрузка начата"
},
"ffmpeg_updater": {
- "title": "Обновление FFmpeg",
+ "title": "Проверка версии FFmpeg",
"current_version": "Текущая версия:",
"latest_version": "Последняя версия:",
"status_up_to_date": "✓ Обновлено",
"status_update_available": "⚠ Доступно обновление",
"status_not_installed": "✗ Не установлено",
- "status_checking": "🔄 Проверка обновлений...",
- "status_downloading": "⬇ Загрузка FFmpeg...",
- "status_installing": "⚙ Установка FFmpeg...",
- "status_verifying": "✓ Проверка целостности...",
- "check_updates": "Проверить обновления",
- "update_button": "Обновить FFmpeg",
- "update_success": "FFmpeg успешно обновлен до версии {version}!",
- "update_failed": "Не удалось обновить FFmpeg. Попробуйте еще раз.",
- "check_failed": "Не удалось проверить обновления. Проверьте подключение к Интернету.",
- "install_first": "FFmpeg не установлен. Нажмите Обновить для установки.",
- "description": "Поддерживайте FFmpeg в актуальном состоянии для лучшей производительности и совместимости."
+ "status_idle": "Нажмите 'Проверить версию' для начала",
+ "status_checking": "🔄 Проверка версии...",
+ "check_updates": "Проверить версию",
+ "check_failed": "Не удалось проверить версию. Проверьте подключение к Интернету.",
+ "description": "Проверьте версию FFmpeg и сравните ее с последней доступной версией.",
+ "guide_info": " Для установки или обновления FFmpeg, нажмите здесь, чтобы просмотреть наше подробное руководство по установке."
}
}
\ No newline at end of file
diff --git a/languages/tr.json b/languages/tr.json
index 0d33adc..ca85c4e 100644
--- a/languages/tr.json
+++ b/languages/tr.json
@@ -477,22 +477,17 @@
"redownload_started": "İndirme başladı"
},
"ffmpeg_updater": {
- "title": "FFmpeg Güncelleyici",
+ "title": "FFmpeg Sürüm Denetçisi",
"current_version": "Mevcut Sürüm:",
"latest_version": "En Son Sürüm:",
"status_up_to_date": "✓ Güncel",
"status_update_available": "⚠ Güncelleme mevcut",
"status_not_installed": "✗ Yüklü değil",
- "status_checking": "🔄 Güncellemeler kontrol ediliyor...",
- "status_downloading": "⬇ FFmpeg indiriliyor...",
- "status_installing": "⚙ FFmpeg yükleniyor...",
- "status_verifying": "✓ Bütünlük doğrulanıyor...",
- "check_updates": "Güncellemeleri Kontrol Et",
- "update_button": "FFmpeg'i Güncelle",
- "update_success": "FFmpeg başarıyla {version} sürümüne güncellendi!",
- "update_failed": "FFmpeg güncellemesi başarısız oldu. Lütfen tekrar deneyin.",
- "check_failed": "Güncelleme kontrolü başarısız oldu. İnternet bağlantınızı kontrol edin.",
- "install_first": "FFmpeg yüklü değil. Yüklemek için Güncelle'ye tıklayın.",
- "description": "En iyi performans ve uyumluluk için FFmpeg'i güncel tutun."
+ "status_idle": "Başlamak için 'Sürümü Kontrol Et'e tıklayın",
+ "status_checking": "🔄 Sürüm kontrol ediliyor...",
+ "check_updates": "Sürümü Kontrol Et",
+ "check_failed": "Sürüm kontrolu başarısız oldu. İnternet bağlantınızı kontrol edin.",
+ "description": "FFmpeg sürümünüzü kontrol edin ve mevcut en son sürümle karşılaştırın.",
+ "guide_info": " FFmpeg'i yüklemek veya güncellemek için, kapsamlı kurulum kılavuzumuzu görüntülemek için buraya tıklayın."
}
}
\ No newline at end of file
diff --git a/languages/zh.json b/languages/zh.json
index 3c2cf32..32ceda2 100644
--- a/languages/zh.json
+++ b/languages/zh.json
@@ -477,22 +477,17 @@
"redownload_started": "已开始下载"
},
"ffmpeg_updater": {
- "title": "FFmpeg 更新器",
+ "title": "FFmpeg 版本检查器",
"current_version": "当前版本:",
"latest_version": "最新版本:",
"status_up_to_date": "✓ 已是最新",
"status_update_available": "⚠ 有可用更新",
"status_not_installed": "✗ 未安装",
- "status_checking": "🔄 正在检查更新...",
- "status_downloading": "⬇ 正在下载 FFmpeg...",
- "status_installing": "⚙ 正在安装 FFmpeg...",
- "status_verifying": "✓ 正在验证完整性...",
- "check_updates": "检查更新",
- "update_button": "更新 FFmpeg",
- "update_success": "FFmpeg 已成功更新到版本 {version}!",
- "update_failed": "更新 FFmpeg 失败。请重试。",
- "check_failed": "检查更新失败。请检查您的网络连接。",
- "install_first": "FFmpeg 未安装。点击更新以安装。",
- "description": "保持 FFmpeg 更新以获得最佳性能和兼容性。"
+ "status_idle": "点击「检查版本」开始",
+ "status_checking": "🔄 正在检查版本...",
+ "check_updates": "检查版本",
+ "check_failed": "检查版本失败。请检查您的网络连接。",
+ "description": "检查您的 FFmpeg 版本并与最新可用版本进行比较。",
+ "guide_info": " 要安装或更新 FFmpeg,请点击此处查看我们的综合安装指南。"
}
}
\ No newline at end of file
diff --git a/src/core/ytsage_ffmpeg.py b/src/core/ytsage_ffmpeg.py
index 57e29c4..deb1073 100644
--- a/src/core/ytsage_ffmpeg.py
+++ b/src/core/ytsage_ffmpeg.py
@@ -12,6 +12,7 @@ from src.utils.ytsage_constants import (
FFMPEG_7Z_DOWNLOAD_URL,
FFMPEG_7Z_SHA256_URL,
FFMPEG_ZIP_DOWNLOAD_URL,
+ FFMPEG_ZIP_SHA256_URL,
OS_NAME,
SUBPROCESS_CREATIONFLAGS,
)
@@ -194,7 +195,7 @@ def check_ffmpeg_installed() -> bool:
def install_ffmpeg_windows(progress_callback=None) -> bool:
- """Install FFmpeg on Windows using 7z method primarily, with zip as fallback."""
+ """Install FFmpeg on Windows using essentials build with 7z method primarily, with zip as fallback."""
# Check if already installed
if check_ffmpeg_installed():
logger.info("FFmpeg is already installed!")
@@ -203,14 +204,176 @@ def install_ffmpeg_windows(progress_callback=None) -> bool:
return True
try:
- # Import the updater for installation
- from src.core.ytsage_ffmpeg_updater import update_ffmpeg_windows
+ # Define variables for essentials build
+ extract_dir = Path(os.getenv("LOCALAPPDATA")) / "ffmpeg" # type: ignore
- # Use the updater to install the latest version
- logger.info("Installing FFmpeg using the updater module...")
+ # Create extraction directory if it doesn't exist
+ extract_dir.mkdir(exist_ok=True)
+
+ # Try 7z method first (smaller size)
+ use_7zip = check_7zip_installed()
+ success = False
+
+ if use_7zip:
+ logger.info("Using 7-Zip method (smaller download size)...")
+ if progress_callback:
+ progress_callback("⚡ Using 7-Zip method...")
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".7z").name
+
+ # Download 7z file
+ if progress_callback:
+ progress_callback("⬇ Downloading FFmpeg (7z)...")
+ if download_file(
+ FFMPEG_7Z_DOWNLOAD_URL,
+ temp_file,
+ progress_callback=progress_callback,
+ ):
+ # Verify SHA-256 hash for 7z file
+ if progress_callback:
+ progress_callback("🔐 Verifying download integrity...")
+ if verify_sha256(temp_file, FFMPEG_7Z_SHA256_URL):
+ logger.info("Extracting FFmpeg components from 7z archive...")
+ if progress_callback:
+ progress_callback("⚙ Extracting FFmpeg...")
+ try:
+ subprocess.run(
+ ["7z", "x", temp_file, f"-o{extract_dir}", "-y"],
+ creationflags=SUBPROCESS_CREATIONFLAGS,
+ timeout=300,
+ check=True,
+ )
+ success = True
+ except Exception as e:
+ logger.exception(f"7z extraction failed: {e}, trying zip fallback...")
+ if progress_callback:
+ progress_callback("❌ 7z extraction failed, trying zip fallback...")
+ else:
+ logger.error("SHA-256 verification failed for 7z file, trying zip fallback...")
+ if progress_callback:
+ progress_callback("❌ SHA-256 verification failed, trying zip fallback...")
+
+ # Clean up temp file
+ try:
+ Path(temp_file).unlink(missing_ok=True)
+ except Exception:
+ pass
+
+ # Fallback to zip method if 7z failed or not available
+ if not success:
+ logger.info("Using ZIP method as fallback...")
+ if progress_callback:
+ progress_callback("📦 Using ZIP method...")
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".zip").name
+
+ # Download zip file
+ if progress_callback:
+ progress_callback("⬇ Downloading FFmpeg (zip)...")
+ if not download_file(
+ FFMPEG_ZIP_DOWNLOAD_URL,
+ temp_file,
+ progress_callback=progress_callback,
+ ):
+ logger.error("Failed to download FFmpeg (both 7z and zip methods failed)")
+ if progress_callback:
+ progress_callback("❌ Failed to download FFmpeg")
+ return False
+
+ # Verify SHA-256 hash for zip
+ if progress_callback:
+ progress_callback("🔐 Verifying download integrity...")
+ if not verify_sha256(temp_file, FFMPEG_ZIP_SHA256_URL):
+ logger.warning("SHA-256 verification failed for zip file, proceeding anyway...")
+ if progress_callback:
+ progress_callback("⚠️ SHA-256 verification failed, proceeding anyway...")
+
+ logger.info("Extracting FFmpeg components from zip archive...")
+ if progress_callback:
+ progress_callback("⚙ Extracting FFmpeg...")
+ try:
+ import zipfile
+ with zipfile.ZipFile(temp_file, "r") as zip_ref:
+ zip_ref.extractall(extract_dir)
+ success = True
+ except Exception as e:
+ logger.exception(f"Extraction failed: {e}")
+ if progress_callback:
+ progress_callback(f"❌ Extraction failed: {e}")
+ return False
+ finally:
+ # Clean up temp file
+ try:
+ Path(temp_file).unlink(missing_ok=True)
+ except Exception:
+ pass
+
+ if not success:
+ logger.error("Both 7z and zip methods failed")
+ if progress_callback:
+ progress_callback("❌ Installation failed")
+ return False
+
+ # Find the bin directory in the extracted essentials build
+ logger.info("Locating FFmpeg binaries...")
if progress_callback:
- progress_callback("📦 Installing FFmpeg...")
- return update_ffmpeg_windows(progress_callback=progress_callback)
+ progress_callback("🔍 Locating FFmpeg binaries...")
+
+ bin_dir = None
+ # Look for any directory matching ffmpeg-*-essentials_build pattern
+ for item in extract_dir.iterdir():
+ if item.is_dir() and "essentials_build" in item.name.lower():
+ potential_bin = item / "bin"
+ if potential_bin.exists():
+ bin_dir = potential_bin
+ logger.info(f"Found FFmpeg bin directory: {bin_dir}")
+ break
+
+ if not bin_dir:
+ logger.error("Could not locate FFmpeg bin directory")
+ if progress_callback:
+ progress_callback("❌ Could not locate FFmpeg bin directory")
+ return False
+
+ logger.info("Configuring system paths...")
+ if progress_callback:
+ progress_callback("🔧 Configuring system paths...")
+
+ # Add to System Path
+ user_path = os.environ.get("PATH", "")
+ path_parts = user_path.split(os.pathsep)
+
+ # Remove old FFmpeg paths and add new one
+ cleaned_paths = [p for p in path_parts if "ffmpeg" not in p.lower() or str(bin_dir) in p]
+ if str(bin_dir) not in cleaned_paths:
+ cleaned_paths.insert(0, str(bin_dir))
+
+ new_path = os.pathsep.join(cleaned_paths)
+
+ try:
+ subprocess.run(
+ ["setx", "PATH", new_path],
+ creationflags=SUBPROCESS_CREATIONFLAGS,
+ timeout=30,
+ check=True,
+ )
+ os.environ["PATH"] = new_path
+ except Exception as e:
+ logger.warning(f"Failed to update PATH permanently: {e}")
+ # Still update for current session
+ os.environ["PATH"] = new_path
+
+ # Verify installation
+ if progress_callback:
+ progress_callback("✅ Verifying installation...")
+ if not check_ffmpeg_installed():
+ logger.error("FFmpeg installation verification failed")
+ if progress_callback:
+ progress_callback("⚠️ Installation completed but verification failed")
+ return True # Still return True as files were extracted
+
+ logger.info("FFmpeg installation completed successfully!")
+ if progress_callback:
+ progress_callback("✅ FFmpeg installation completed successfully!")
+ return True
except Exception as e:
logger.exception(f"Error installing FFmpeg: {e}")
diff --git a/src/core/ytsage_ffmpeg_updater.py b/src/core/ytsage_ffmpeg_updater.py
deleted file mode 100644
index 814e5bc..0000000
--- a/src/core/ytsage_ffmpeg_updater.py
+++ /dev/null
@@ -1,413 +0,0 @@
-"""
-FFmpeg updater module for YTSage application.
-Handles checking for updates and updating FFmpeg to the latest Essentials build.
-"""
-
-import hashlib
-import os
-import re
-import shutil
-import subprocess
-import tempfile
-from pathlib import Path
-from typing import Optional, Tuple, Callable
-
-import requests
-
-from src.utils.ytsage_logger import logger
-from src.utils.ytsage_constants import (
- FFMPEG_7Z_DOWNLOAD_URL,
- FFMPEG_7Z_SHA256_URL,
- FFMPEG_7Z_VERSION_URL,
- FFMPEG_ZIP_DOWNLOAD_URL,
- FFMPEG_ZIP_SHA256_URL,
- FFMPEG_ZIP_VERSION_URL,
- OS_NAME,
- SUBPROCESS_CREATIONFLAGS,
-)
-from src.core.ytsage_ffmpeg import (
- check_7zip_installed,
- download_file,
- get_file_sha256,
- verify_sha256,
- get_ffmpeg_install_path,
-)
-from src.core.ytsage_utils import get_ffmpeg_version_direct
-
-
-def get_latest_ffmpeg_version() -> Optional[str]:
- """
- Fetch the latest FFmpeg version from the version URL.
-
- Returns:
- str: Version string (e.g., "8.0") or None if fetch failed
- """
- try:
- # Try 7z version URL first
- response = requests.get(FFMPEG_7Z_VERSION_URL, timeout=10)
- response.raise_for_status()
- version = response.text.strip()
-
- # Validate version format (should be something like "8.0" or "7.1.1")
- if re.match(r'^\d+\.\d+(\.\d+)?$', version):
- logger.info(f"Latest FFmpeg version: {version}")
- return version
- else:
- logger.warning(f"Unexpected version format: {version}")
- return None
-
- except requests.RequestException as e:
- logger.error(f"Failed to fetch latest FFmpeg version: {e}")
- return None
- except Exception as e:
- logger.exception(f"Unexpected error fetching FFmpeg version: {e}")
- return None
-
-
-def parse_version(version_str: str) -> Tuple[int, ...]:
- """
- Parse version string into tuple of integers for comparison.
-
- Args:
- version_str: Version string like "8.0" or "7.1.1"
-
- Returns:
- Tuple of integers (e.g., (8, 0) or (7, 1, 1))
- """
- try:
- # Extract version numbers from string
- # Handles formats like "8.0", "7.1.1", "ffmpeg version 8.0", etc.
- match = re.search(r'(\d+\.\d+(?:\.\d+)?)', version_str)
- if match:
- version_str = match.group(1)
-
- parts = version_str.split('.')
- return tuple(int(p) for p in parts)
- except (ValueError, AttributeError):
- logger.warning(f"Could not parse version: {version_str}")
- return (0,)
-
-
-def compare_versions(current: str, latest: str) -> bool:
- """
- Compare two version strings.
-
- Args:
- current: Current version string
- latest: Latest version string
-
- Returns:
- True if update is needed (latest > current), False otherwise
- """
- try:
- current_tuple = parse_version(current)
- latest_tuple = parse_version(latest)
-
- logger.info(f"Comparing versions - Current: {current_tuple}, Latest: {latest_tuple}")
-
- # Pad shorter version with zeros for comparison
- max_len = max(len(current_tuple), len(latest_tuple))
- current_padded = current_tuple + (0,) * (max_len - len(current_tuple))
- latest_padded = latest_tuple + (0,) * (max_len - len(latest_tuple))
-
- return latest_padded > current_padded
- except Exception as e:
- logger.exception(f"Error comparing versions: {e}")
- return False
-
-
-def check_ffmpeg_update_available() -> Tuple[bool, str, str]:
- """
- Check if FFmpeg update is available.
-
- Returns:
- Tuple of (update_available, current_version, latest_version)
- - update_available: True if update is needed
- - current_version: Currently installed version or "Not installed"
- - latest_version: Latest available version or "Unknown"
- """
- try:
- # Get current version
- current_version = get_ffmpeg_version_direct()
- if current_version in ["Not found", "Error getting version", "Unknown version"]:
- current_version = "Not installed"
-
- # Get latest version
- latest_version = get_latest_ffmpeg_version()
- if latest_version is None:
- latest_version = "Unknown"
- return False, current_version, latest_version
-
- # If not installed, update is needed
- if current_version == "Not installed":
- return True, current_version, latest_version
-
- # Compare versions
- update_needed = compare_versions(current_version, latest_version)
-
- return update_needed, current_version, latest_version
-
- except Exception as e:
- logger.exception(f"Error checking for FFmpeg updates: {e}")
- return False, "Error", "Error"
-
-
-def get_ffmpeg_extract_dir() -> Path:
- """Get the directory where FFmpeg should be extracted."""
- if OS_NAME == "Windows":
- return Path(os.getenv("LOCALAPPDATA")) / "ffmpeg" # type: ignore
- elif OS_NAME == "Darwin":
- return Path.home() / "Library" / "Application Support" / "ffmpeg"
- else:
- return Path.home() / ".local" / "share" / "ffmpeg"
-
-
-def find_ffmpeg_bin_dir(extract_dir: Path, version: str) -> Optional[Path]:
- """
- Find the FFmpeg bin directory after extraction.
-
- Args:
- extract_dir: Directory where FFmpeg was extracted
- version: Version string (e.g., "8.0")
-
- Returns:
- Path to bin directory or None if not found
- """
- # Expected pattern: ffmpeg-{version}-essentials_build
- pattern = f"ffmpeg-{version}-essentials_build"
-
- # Look for the directory
- for item in extract_dir.iterdir():
- if item.is_dir() and item.name.startswith(f"ffmpeg-{version}"):
- bin_dir = item / "bin"
- if bin_dir.exists():
- logger.info(f"Found FFmpeg bin directory: {bin_dir}")
- return bin_dir
-
- logger.warning(f"Could not find FFmpeg bin directory with pattern: {pattern}")
- return None
-
-
-def update_ffmpeg_windows(progress_callback: Optional[Callable[[str], None]] = None) -> bool:
- """
- Update FFmpeg on Windows to the latest Essentials build.
-
- Args:
- progress_callback: Optional callback function for progress updates
-
- Returns:
- True if update was successful, False otherwise
- """
- if OS_NAME != "Windows":
- logger.error("This update method is only for Windows")
- return False
-
- try:
- # Track last progress percentage to avoid spam
- last_percent = -1
-
- def report_progress(msg: str, force: bool = False):
- """Helper to report progress (always logged, callback only if force=True or status message)."""
- logger.info(msg)
-
- # Only send callback for non-percentage messages or when forced
- if progress_callback and (force or not msg.strip().endswith('%')):
- progress_callback(msg)
-
- def download_progress_wrapper(msg: str):
- """Wrapper for download progress that throttles percentage updates."""
- nonlocal last_percent
-
- # Extract percentage if present
- percent_match = re.search(r'(\d+)%', msg)
- if percent_match:
- current_percent = int(percent_match.group(1))
- # Only report every 10% and to logger only
- if current_percent != last_percent and current_percent % 10 == 0:
- logger.info(msg)
- if progress_callback:
- progress_callback(msg)
- last_percent = current_percent
- else:
- # Non-percentage messages get reported normally
- report_progress(msg, force=True)
-
- # Get latest version
- report_progress("🔍 Checking latest FFmpeg version...", force=True)
- latest_version = get_latest_ffmpeg_version()
- if not latest_version:
- report_progress("❌ Failed to determine latest version", force=True)
- return False
-
- report_progress(f"📦 Latest version: {latest_version}", force=True)
-
- extract_dir = get_ffmpeg_extract_dir()
- extract_dir.mkdir(exist_ok=True)
-
- # Try 7z method first (smaller size)
- use_7zip = check_7zip_installed()
- success = False
-
- if use_7zip:
- report_progress("⚡ Using 7-Zip method (smaller download)...", force=True)
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".7z").name
-
- # Download 7z file
- report_progress("⬇ Downloading FFmpeg (7z)...", force=True)
- last_percent = -1 # Reset for this download
- if download_file(
- FFMPEG_7Z_DOWNLOAD_URL,
- temp_file,
- progress_callback=download_progress_wrapper,
- ):
- # Verify SHA-256 hash
- report_progress("🔐 Verifying download integrity...", force=True)
- if verify_sha256(temp_file, FFMPEG_7Z_SHA256_URL):
- report_progress("⚙ Extracting FFmpeg...", force=True)
- try:
- subprocess.run(
- ["7z", "x", temp_file, f"-o{extract_dir}", "-y"],
- creationflags=SUBPROCESS_CREATIONFLAGS,
- timeout=300,
- check=True,
- )
- success = True
- except Exception as e:
- logger.exception(f"7z extraction failed: {e}")
- report_progress(f"❌ 7z extraction failed, trying zip fallback...", force=True)
- else:
- report_progress("❌ SHA-256 verification failed, trying zip fallback...", force=True)
-
- # Clean up temp file
- try:
- Path(temp_file).unlink(missing_ok=True)
- except Exception:
- pass
-
- # Fallback to zip method
- if not success:
- report_progress("📦 Using ZIP method...", force=True)
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".zip").name
-
- # Download zip file
- report_progress("⬇ Downloading FFmpeg (zip)...", force=True)
- last_percent = -1 # Reset for this download
- if not download_file(
- FFMPEG_ZIP_DOWNLOAD_URL,
- temp_file,
- progress_callback=download_progress_wrapper,
- ):
- report_progress("❌ Failed to download FFmpeg", force=True)
- return False
-
- # Verify SHA-256 hash for zip
- report_progress("🔐 Verifying download integrity...", force=True)
- if not verify_sha256(temp_file, FFMPEG_ZIP_SHA256_URL):
- report_progress("⚠️ SHA-256 verification failed, proceeding anyway...", force=True)
-
- report_progress("⚙ Extracting FFmpeg...", force=True)
- try:
- import zipfile
- with zipfile.ZipFile(temp_file, "r") as zip_ref:
- zip_ref.extractall(extract_dir)
- success = True
- except Exception as e:
- logger.exception(f"Extraction failed: {e}")
- report_progress(f"❌ Extraction failed: {e}", force=True)
- return False
- finally:
- # Clean up temp file
- try:
- Path(temp_file).unlink(missing_ok=True)
- except Exception:
- pass
-
- if not success:
- report_progress("❌ Both 7z and zip methods failed", force=True)
- return False
-
- # Find the bin directory
- report_progress("🔍 Locating FFmpeg binaries...", force=True)
- bin_dir = find_ffmpeg_bin_dir(extract_dir, latest_version)
- if not bin_dir:
- report_progress("❌ Could not locate FFmpeg bin directory", force=True)
- return False
-
- # Add to System Path
- report_progress("🔧 Configuring system paths...", force=True)
- user_path = os.environ.get("PATH", "")
-
- # Remove old FFmpeg paths from PATH
- path_parts = user_path.split(os.pathsep)
- cleaned_paths = [p for p in path_parts if "ffmpeg" not in p.lower() or str(bin_dir) in p]
-
- # Add new path if not already present
- if str(bin_dir) not in cleaned_paths:
- cleaned_paths.insert(0, str(bin_dir))
-
- new_path = os.pathsep.join(cleaned_paths)
-
- try:
- subprocess.run(
- ["setx", "PATH", new_path],
- creationflags=SUBPROCESS_CREATIONFLAGS,
- timeout=30,
- check=True,
- )
- os.environ["PATH"] = new_path
- except Exception as e:
- logger.warning(f"Failed to update PATH permanently: {e}")
- # Still update for current session
- os.environ["PATH"] = new_path
-
- # Verify installation
- report_progress("✅ Verifying installation...", force=True)
- new_version = get_ffmpeg_version_direct()
- if new_version not in ["Not found", "Error getting version", "Unknown version"]:
- report_progress(f"✅ FFmpeg successfully updated to version {new_version}!", force=True)
- return True
- else:
- report_progress("⚠️ Update completed but verification failed", force=True)
- return True # Still return True as files were extracted
-
- except Exception as e:
- logger.exception(f"Error updating FFmpeg: {e}")
- if progress_callback:
- progress_callback(f"❌ Error: {e}")
- return False
-
-
-def update_ffmpeg(progress_callback: Optional[Callable[[str], None]] = None) -> bool:
- """
- Update FFmpeg based on the operating system.
-
- Args:
- progress_callback: Optional callback function for progress updates
-
- Returns:
- True if update was successful, False otherwise
- """
- if OS_NAME == "Windows":
- return update_ffmpeg_windows(progress_callback)
- elif OS_NAME == "Darwin":
- # macOS update via Homebrew
- if progress_callback:
- progress_callback("🍺 Updating FFmpeg via Homebrew...")
- try:
- subprocess.run(["brew", "upgrade", "ffmpeg"], check=True, timeout=300)
- if progress_callback:
- progress_callback("✅ FFmpeg updated successfully!")
- return True
- except Exception as e:
- logger.exception(f"Error updating FFmpeg on macOS: {e}")
- if progress_callback:
- progress_callback(f"❌ Error: {e}")
- return False
- elif OS_NAME == "Linux":
- # Linux update via package manager
- if progress_callback:
- progress_callback("📦 Please use your package manager to update FFmpeg")
- return False
- else:
- logger.error(f"Unsupported operating system: {OS_NAME}")
- return False
diff --git a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py
index cc20268..c0a67b2 100644
--- a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py
+++ b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py
@@ -1,19 +1,20 @@
"""
Updater tab for Custom Options dialog.
-Handles checking for and installing FFmpeg updates and yt-dlp auto-update settings.
+Handles FFmpeg version checking and yt-dlp auto-update settings.
"""
+import re
import subprocess
import threading
-from typing import TYPE_CHECKING, cast
+from typing import Optional, Tuple, TYPE_CHECKING, cast
-from PySide6.QtCore import QObject, Signal
+import requests
+from PySide6.QtCore import Qt, Signal
from PySide6.QtWidgets import (
QCheckBox,
QGroupBox,
QHBoxLayout,
QLabel,
- QProgressBar,
QPushButton,
QRadioButton,
QScrollArea,
@@ -24,6 +25,7 @@ from PySide6.QtWidgets import (
from src.core.ytsage_utils import (
get_auto_update_settings,
+ get_ffmpeg_version_direct,
update_auto_update_settings,
)
from src.core.ytsage_yt_dlp import get_yt_dlp_path
@@ -31,35 +33,127 @@ from src.gui.ytsage_gui_dialogs.ytsage_dialogs_update import YTDLPUpdateDialog
from src.utils.ytsage_config_manager import ConfigManager
from src.utils.ytsage_localization import _
from src.utils.ytsage_logger import logger
-from src.core.ytsage_ffmpeg_updater import check_ffmpeg_update_available, update_ffmpeg
-from src.utils.ytsage_constants import OS_NAME, SUBPROCESS_CREATIONFLAGS
-from src.utils.ytsage_constants import OS_NAME
+from src.utils.ytsage_constants import (
+ FFMPEG_7Z_VERSION_URL,
+ OS_NAME,
+ SUBPROCESS_CREATIONFLAGS,
+)
if TYPE_CHECKING:
from src.gui.ytsage_gui_dialogs.ytsage_dialogs_custom import CustomOptionsDialog
-class UpdateWorker(QObject):
- """Worker class for running FFmpeg updates in a separate thread."""
+# Helper functions for FFmpeg version checking (copied from removed ytsage_ffmpeg_updater.py)
+def get_latest_ffmpeg_version() -> Optional[str]:
+ """
+ Fetch the latest FFmpeg version from the version URL.
- progress = Signal(str) # Progress messages
- finished = Signal(bool) # Completion status (success/failure)
+ Returns:
+ str: Version string (e.g., "8.0") or None if fetch failed
+ """
+ try:
+ response = requests.get(FFMPEG_7Z_VERSION_URL, timeout=10)
+ response.raise_for_status()
+ version = response.text.strip()
+
+ # Validate version format (should be something like "8.0" or "7.1.1")
+ if re.match(r'^\d+\.\d+(\.\d+)?$', version):
+ logger.info(f"Latest FFmpeg version: {version}")
+ return version
+ else:
+ logger.warning(f"Unexpected version format: {version}")
+ return None
+
+ except requests.RequestException as e:
+ logger.error(f"Failed to fetch latest FFmpeg version: {e}")
+ return None
+ except Exception as e:
+ logger.exception(f"Unexpected error fetching FFmpeg version: {e}")
+ return None
+
+
+def parse_version(version_str: str) -> Tuple[int, ...]:
+ """
+ Parse version string into tuple of integers for comparison.
- def run_update(self):
- """Run the FFmpeg update process."""
- try:
- def progress_callback(msg: str):
- """Callback for progress updates."""
- self.progress.emit(msg)
-
- # Run the update
- success = update_ffmpeg(progress_callback=progress_callback)
- self.finished.emit(success)
-
- except Exception as e:
- logger.exception(f"Error during FFmpeg update: {e}")
- self.progress.emit(f"❌ Error: {e}")
- self.finished.emit(False)
+ Args:
+ version_str: Version string like "8.0" or "7.1.1"
+
+ Returns:
+ Tuple of integers (e.g., (8, 0) or (7, 1, 1))
+ """
+ try:
+ # Extract version numbers from string
+ match = re.search(r'(\d+\.\d+(?:\.\d+)?)', version_str)
+ if match:
+ version_str = match.group(1)
+
+ parts = version_str.split('.')
+ return tuple(int(p) for p in parts)
+ except (ValueError, AttributeError):
+ logger.warning(f"Could not parse version: {version_str}")
+ return (0,)
+
+
+def compare_versions(current: str, latest: str) -> bool:
+ """
+ Compare two version strings.
+
+ Args:
+ current: Current version string
+ latest: Latest version string
+
+ Returns:
+ True if update is needed (latest > current), False otherwise
+ """
+ try:
+ current_tuple = parse_version(current)
+ latest_tuple = parse_version(latest)
+
+ logger.info(f"Comparing versions - Current: {current_tuple}, Latest: {latest_tuple}")
+
+ # Pad shorter version with zeros for comparison
+ max_len = max(len(current_tuple), len(latest_tuple))
+ current_padded = current_tuple + (0,) * (max_len - len(current_tuple))
+ latest_padded = latest_tuple + (0,) * (max_len - len(latest_tuple))
+
+ return latest_padded > current_padded
+ except Exception as e:
+ logger.exception(f"Error comparing versions: {e}")
+ return False
+
+
+def check_ffmpeg_version() -> Tuple[bool, str, str]:
+ """
+ Check FFmpeg version and compare with latest.
+
+ Returns:
+ Tuple of (update_available, current_version, latest_version)
+ """
+ try:
+ # Get current version
+ current_version = get_ffmpeg_version_direct()
+ if current_version in ["Not found", "Error getting version", "Unknown version"]:
+ current_version = "Not installed"
+
+ # Get latest version
+ latest_version = get_latest_ffmpeg_version()
+ if latest_version is None:
+ latest_version = "Unknown"
+ return False, current_version, latest_version
+
+ # If not installed, update is available
+ if current_version == "Not installed":
+ return True, current_version, latest_version
+
+ # Compare versions
+ update_needed = compare_versions(current_version, latest_version)
+
+ return update_needed, current_version, latest_version
+
+ except Exception as e:
+ logger.exception(f"Error checking FFmpeg version: {e}")
+ return False, "Error", "Error"
class UpdaterTabWidget(QWidget):
@@ -69,9 +163,6 @@ class UpdaterTabWidget(QWidget):
super().__init__(parent)
self._parent: "CustomOptionsDialog" = cast("CustomOptionsDialog", self.parent())
- self.update_thread = None
- self.update_worker = None
-
# State variables
self.current_version = "Unknown"
self.latest_version = "Unknown"
@@ -102,7 +193,7 @@ class UpdaterTabWidget(QWidget):
help_text.setStyleSheet("color: #999999; padding: 10px;")
layout.addWidget(help_text)
- # FFmpeg Update Section
+ # FFmpeg Version Check Section
ffmpeg_group = QGroupBox(_('ffmpeg_updater.title'))
ffmpeg_layout = QVBoxLayout(ffmpeg_group)
@@ -144,10 +235,8 @@ class UpdaterTabWidget(QWidget):
)
ffmpeg_layout.addWidget(self.status_label)
- # Button layout
- button_layout = QHBoxLayout()
-
- # Check for updates button
+ # Check version button
+ check_button_layout = QHBoxLayout()
self.check_button = QPushButton(_('ffmpeg_updater.check_updates'))
self.check_button.clicked.connect(self.check_for_updates)
self.check_button.setStyleSheet(
@@ -170,84 +259,34 @@ class UpdaterTabWidget(QWidget):
}
"""
)
- button_layout.addWidget(self.check_button)
+ check_button_layout.addWidget(self.check_button)
+ check_button_layout.addStretch()
+ ffmpeg_layout.addLayout(check_button_layout)
- button_layout.addStretch()
-
- # Update button
- self.update_button = QPushButton(_('ffmpeg_updater.update_button'))
- self.update_button.clicked.connect(self.start_update)
- self.update_button.setEnabled(False)
- self.update_button.setStyleSheet(
+ # Installation guide info
+ guide_label = QLabel(_('ffmpeg_updater.guide_info'))
+ guide_label.setWordWrap(True)
+ guide_label.setOpenExternalLinks(True) # Enable clickable links
+ guide_label.setTextFormat(Qt.TextFormat.RichText) # Enable HTML formatting
+ guide_label.setStyleSheet(
"""
- QPushButton {
- padding: 8px 15px;
- background-color: #c90000;
- border: none;
+ QLabel {
+ color: #cccccc;
+ font-size: 11px;
+ padding: 8px;
+ background-color: #1a1d20;
border-radius: 4px;
- color: white;
- font-weight: bold;
- min-width: 120px;
}
- QPushButton:hover {
- background-color: #a50000;
+ QLabel a {
+ color: #4da6ff;
+ text-decoration: underline;
}
- QPushButton:disabled {
- background-color: #4a4a4a;
- color: #888888;
+ QLabel a:hover {
+ color: #66b3ff;
}
"""
)
- button_layout.addWidget(self.update_button)
-
- ffmpeg_layout.addLayout(button_layout)
-
- # Progress bar
- self.progress_bar = QProgressBar()
- self.progress_bar.setRange(0, 0) # Indeterminate progress
- self.progress_bar.setVisible(False)
- self.progress_bar.setStyleSheet(
- """
- QProgressBar {
- border: 2px solid #2a2d36;
- border-radius: 4px;
- background-color: #1d1e22;
- text-align: center;
- color: #ffffff;
- height: 20px;
- }
- QProgressBar::chunk {
- background-color: #c90000;
- border-radius: 2px;
- }
- """
- )
- ffmpeg_layout.addWidget(self.progress_bar)
-
- # Log output
- log_label = QLabel("Update Log:")
- log_label.setStyleSheet("font-size: 11px; font-weight: bold; color: #ffffff; margin-top: 5px;")
- ffmpeg_layout.addWidget(log_label)
-
- self.log_output = QTextEdit()
- self.log_output.setReadOnly(True)
- self.log_output.setPlaceholderText("Update logs will appear here...")
- self.log_output.setMinimumHeight(60)
- self.log_output.setMaximumHeight(100)
- self.log_output.setStyleSheet(
- """
- QTextEdit {
- background-color: #1d1e22;
- color: #ffffff;
- border: 2px solid #2a2d36;
- border-radius: 6px;
- padding: 8px;
- font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
- font-size: 11px;
- }
- """
- )
- ffmpeg_layout.addWidget(self.log_output)
+ ffmpeg_layout.addWidget(guide_label)
layout.addWidget(ffmpeg_group)
@@ -596,27 +635,25 @@ class UpdaterTabWidget(QWidget):
dialog.show() # Use show() instead of exec() to avoid blocking
def check_for_updates(self) -> None:
- """Check if FFmpeg updates are available."""
+ """Check FFmpeg version and compare with latest."""
self.check_button.setEnabled(False)
- self.update_button.setEnabled(False)
self.status_label.setText(_('ffmpeg_updater.status_checking'))
self.status_label.setStyleSheet(
"color: #ffaa00; font-size: 12px; padding: 8px; "
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
)
- self.log_output.append("🔍 Checking for FFmpeg updates...")
# Run check in background thread
def check_thread():
try:
- update_available, current_version, latest_version = check_ffmpeg_update_available()
+ update_available, current_version, latest_version = check_ffmpeg_version()
- # Update UI in main thread using signals
+ # Update UI in main thread
self.check_button.setEnabled(True)
self._update_check_results(update_available, current_version, latest_version)
except Exception as e:
- logger.exception(f"Error checking for updates: {e}")
+ logger.exception(f"Error checking FFmpeg version: {e}")
self.check_button.setEnabled(True)
self._show_check_error(str(e))
@@ -624,7 +661,7 @@ class UpdaterTabWidget(QWidget):
thread.start()
def _update_check_results(self, update_available: bool, current_version: str, latest_version: str) -> None:
- """Handle completion of update check."""
+ """Handle completion of version check."""
self.update_available = update_available
self.current_version = current_version
self.latest_version = latest_version
@@ -635,97 +672,28 @@ class UpdaterTabWidget(QWidget):
# Update status
if current_version == "Not installed":
- self.status_label.setText(_('ffmpeg_updater.install_first'))
+ self.status_label.setText(_('ffmpeg_updater.status_not_installed'))
self.status_label.setStyleSheet(
"color: #ff6666; font-size: 12px; padding: 8px; "
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
)
- self.update_button.setEnabled(True if OS_NAME == "Windows" else False)
- self.log_output.append(f"❌ FFmpeg is not installed. Latest version available: {latest_version}")
elif update_available:
self.status_label.setText(_('ffmpeg_updater.status_update_available'))
self.status_label.setStyleSheet(
"color: #ffaa00; font-size: 12px; padding: 8px; "
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
)
- self.update_button.setEnabled(True if OS_NAME == "Windows" else False)
- self.log_output.append(f"⚠ Update available: {current_version} → {latest_version}")
else:
self.status_label.setText(_('ffmpeg_updater.status_up_to_date'))
self.status_label.setStyleSheet(
"color: #00cc00; font-size: 12px; padding: 8px; "
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
)
- self.update_button.setEnabled(False)
- self.log_output.append(f"✅ FFmpeg is up to date (version {current_version})")
-
- # Show message for non-Windows systems
- if OS_NAME != "Windows" and update_available:
- self.log_output.append("ℹ️ Automatic updates are only available on Windows.")
- self.log_output.append(" Please use your system's package manager to update FFmpeg.")
def _show_check_error(self, error: str) -> None:
- """Handle error during update check."""
+ """Handle error during version check."""
self.status_label.setText(_('ffmpeg_updater.check_failed'))
self.status_label.setStyleSheet(
"color: #ff6666; font-size: 12px; padding: 8px; "
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
)
- self.log_output.append(f"❌ Error checking for updates: {error}")
-
- def start_update(self) -> None:
- """Start the FFmpeg update process."""
- if OS_NAME != "Windows":
- self.log_output.append("❌ Automatic updates are only supported on Windows.")
- return
-
- # Disable buttons during update
- self.check_button.setEnabled(False)
- self.update_button.setEnabled(False)
- self.progress_bar.setVisible(True)
-
- self.log_output.append("=" * 60)
- self.log_output.append("🚀 Starting FFmpeg update process...")
- self.log_output.append("=" * 60)
-
- # Create worker and thread
- self.update_worker = UpdateWorker()
- self.update_thread = threading.Thread(target=self.update_worker.run_update, daemon=True)
-
- # Connect signals
- self.update_worker.progress.connect(self._on_update_progress)
- self.update_worker.finished.connect(self._on_update_finished)
-
- # Start update
- self.update_thread.start()
-
- def _on_update_progress(self, message: str) -> None:
- """Handle progress updates from the update worker."""
- self.log_output.append(message)
- # Auto-scroll to bottom
- cursor = self.log_output.textCursor()
- cursor.movePosition(cursor.MoveOperation.End)
- self.log_output.setTextCursor(cursor)
-
- def _on_update_finished(self, success: bool) -> None:
- """Handle completion of the update process."""
- self.progress_bar.setVisible(False)
- self.check_button.setEnabled(True)
-
- self.log_output.append("=" * 60)
-
- if success:
- self.log_output.append(_('ffmpeg_updater.update_success', version=self.latest_version))
- self.status_label.setText(_('ffmpeg_updater.status_up_to_date'))
- self.status_label.setStyleSheet(
- "color: #00cc00; font-size: 12px; padding: 8px; "
- "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
- )
- # Re-check to update version info
- self.check_for_updates()
- else:
- self.log_output.append(_('ffmpeg_updater.update_failed'))
- self.status_label.setText(_('ffmpeg_updater.status_update_available'))
- self.update_button.setEnabled(True)
-
- self.log_output.append("=" * 60)