Refactor FFmpeg updater to version checker
Replaces the FFmpeg updater logic with a version checker across all supported languages and removes the updater module. The Windows installation logic in ytsage_ffmpeg.py is rewritten to use essentials build extraction and path configuration directly, removing dependency on the updater module. Dialogs and UI strings are updated to reflect the new version checking workflow and provide installation guide links.
This commit is contained in:
+8
-13
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "بدأ التنزيل"
|
"redownload_started": "بدأ التنزيل"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "محدث FFmpeg",
|
"title": "مدقق إصدار FFmpeg",
|
||||||
"current_version": "الإصدار الحالي:",
|
"current_version": "الإصدار الحالي:",
|
||||||
"latest_version": "أحدث إصدار:",
|
"latest_version": "أحدث إصدار:",
|
||||||
"status_up_to_date": "✓ محدث",
|
"status_up_to_date": "✓ محدث",
|
||||||
"status_update_available": "⚠ تحديث متاح",
|
"status_update_available": "⚠ يتوفر تحديث",
|
||||||
"status_not_installed": "✗ غير مثبت",
|
"status_not_installed": "✗ غير مثبت",
|
||||||
"status_checking": "🔄 جارٍ التحقق من التحديثات...",
|
"status_idle": "انقر على 'التحقق من الإصدار' للبدء",
|
||||||
"status_downloading": "⬇ جارٍ تنزيل FFmpeg...",
|
"status_checking": "🔄 جاري التحقق من الإصدار...",
|
||||||
"status_installing": "⚙ جارٍ تثبيت FFmpeg...",
|
"check_updates": "التحقق من الإصدار",
|
||||||
"status_verifying": "✓ جارٍ التحقق من السلامة...",
|
"check_failed": "فشل التحقق من الإصدار. يرجى التحقق من اتصال الإنترنت.",
|
||||||
"check_updates": "التحقق من التحديثات",
|
"description": "تحقق من إصدار FFmpeg الخاص بك وقارنه بأحدث إصدار متاح.",
|
||||||
"update_button": "تحديث FFmpeg",
|
"guide_info": " لتثبيت أو تحديث FFmpeg، <a href='https://github.com/oop7/ffmpeg-install-guide'>انقر هنا لعرض دليل التثبيت الشامل</a>."
|
||||||
"update_success": "تم تحديث FFmpeg بنجاح إلى الإصدار {version}!",
|
|
||||||
"update_failed": "فشل تحديث FFmpeg. يرجى المحاولة مرة أخرى.",
|
|
||||||
"check_failed": "فشل التحقق من التحديثات. يرجى التحقق من اتصال الإنترنت.",
|
|
||||||
"install_first": "FFmpeg غير مثبت. انقر فوق تحديث للتثبيت.",
|
|
||||||
"description": "حافظ على تحديث FFmpeg للحصول على أفضل أداء وتوافق."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "Download gestartet"
|
"redownload_started": "Download gestartet"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "FFmpeg-Updater",
|
"title": "FFmpeg-Versionsprüfer",
|
||||||
"current_version": "Aktuelle Version:",
|
"current_version": "Aktuelle Version:",
|
||||||
"latest_version": "Neueste Version:",
|
"latest_version": "Neueste Version:",
|
||||||
"status_up_to_date": "✓ Auf dem neuesten Stand",
|
"status_up_to_date": "✓ Auf dem neuesten Stand",
|
||||||
"status_update_available": "⚠ Update verfügbar",
|
"status_update_available": "⚠ Update verfügbar",
|
||||||
"status_not_installed": "✗ Nicht installiert",
|
"status_not_installed": "✗ Nicht installiert",
|
||||||
"status_checking": "🔄 Suche nach Updates...",
|
"status_idle": "Klicken Sie auf 'Version prüfen' um zu beginnen",
|
||||||
"status_downloading": "⬇ FFmpeg wird heruntergeladen...",
|
"status_checking": "🔄 Version wird geprüft...",
|
||||||
"status_installing": "⚙ FFmpeg wird installiert...",
|
"check_updates": "Version prüfen",
|
||||||
"status_verifying": "✓ Integrität wird überprüft...",
|
"check_failed": "Versionprüfung fehlgeschlagen. Bitte überprüfen Sie Ihre Internetverbindung.",
|
||||||
"check_updates": "Nach Updates suchen",
|
"description": "Überprüfen Sie Ihre FFmpeg-Version und vergleichen Sie sie mit der neuesten verfügbaren Version.",
|
||||||
"update_button": "FFmpeg aktualisieren",
|
"guide_info": " Um FFmpeg zu installieren oder zu aktualisieren, <a href='https://github.com/oop7/ffmpeg-install-guide'>klicken Sie hier, um unseren umfassenden Installationsleitfaden anzuzeigen</a>."
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-13
@@ -477,23 +477,17 @@
|
|||||||
"redownload_started": "Redownload started"
|
"redownload_started": "Redownload started"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "FFmpeg Updater",
|
"title": "FFmpeg Version Checker",
|
||||||
"current_version": "Current Version:",
|
"current_version": "Current Version:",
|
||||||
"latest_version": "Latest Version:",
|
"latest_version": "Latest Version:",
|
||||||
"status_up_to_date": "✓ Up to date",
|
"status_up_to_date": "✓ Up to date",
|
||||||
"status_update_available": "⚠ Update available",
|
"status_update_available": "⚠ Update available",
|
||||||
"status_not_installed": "✗ Not installed",
|
"status_not_installed": "✗ Not installed",
|
||||||
"status_idle": "Click 'Check for Updates' to get started",
|
"status_idle": "Click 'Check Version' to get started",
|
||||||
"status_checking": "🔄 Checking for updates...",
|
"status_checking": "🔄 Checking version...",
|
||||||
"status_downloading": "⬇ Downloading FFmpeg...",
|
"check_updates": "Check Version",
|
||||||
"status_installing": "⚙ Installing FFmpeg...",
|
"check_failed": "Failed to check version. Please check your internet connection.",
|
||||||
"status_verifying": "✓ Verifying integrity...",
|
"description": "Check your FFmpeg version and compare it with the latest available version.",
|
||||||
"check_updates": "Check for Updates",
|
"guide_info": " To install or update FFmpeg, <a href='https://github.com/oop7/ffmpeg-install-guide'>click here to view our comprehensive installation guide</a>."
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -460,22 +460,17 @@
|
|||||||
"redownload_started": "Descarga iniciada"
|
"redownload_started": "Descarga iniciada"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "Actualizador de FFmpeg",
|
"title": "Comprobador de Versión FFmpeg",
|
||||||
"current_version": "Versión Actual:",
|
"current_version": "Versión Actual:",
|
||||||
"latest_version": "Última Versión:",
|
"latest_version": "Última Versión:",
|
||||||
"status_up_to_date": "✓ Actualizado",
|
"status_up_to_date": "✓ Actualizado",
|
||||||
"status_update_available": "⚠ Actualización disponible",
|
"status_update_available": "⚠ Actualización disponible",
|
||||||
"status_not_installed": "✗ No instalado",
|
"status_not_installed": "✗ No instalado",
|
||||||
"status_checking": "🔄 Verificando actualizaciones...",
|
"status_idle": "Haga clic en 'Comprobar Versión' para comenzar",
|
||||||
"status_downloading": "⬇ Descargando FFmpeg...",
|
"status_checking": "🔄 Verificando versión...",
|
||||||
"status_installing": "⚙ Instalando FFmpeg...",
|
"check_updates": "Comprobar Versión",
|
||||||
"status_verifying": "✓ Verificando integridad...",
|
"check_failed": "Error al verificar la versión. Por favor, verifique su conexión a internet.",
|
||||||
"check_updates": "Buscar Actualizaciones",
|
"description": "Compruebe su versión de FFmpeg y compárela con la última versión disponible.",
|
||||||
"update_button": "Actualizar FFmpeg",
|
"guide_info": " Para instalar o actualizar FFmpeg, <a href='https://github.com/oop7/ffmpeg-install-guide'>haga clic aquí para ver nuestra guía completa de instalación</a>."
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "Téléchargement démarré"
|
"redownload_started": "Téléchargement démarré"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "Mise à jour FFmpeg",
|
"title": "Vérificateur de Version FFmpeg",
|
||||||
"current_version": "Version Actuelle:",
|
"current_version": "Version Actuelle:",
|
||||||
"latest_version": "Dernière Version:",
|
"latest_version": "Dernière Version:",
|
||||||
"status_up_to_date": "✓ À jour",
|
"status_up_to_date": "✓ À jour",
|
||||||
"status_update_available": "⚠ Mise à jour disponible",
|
"status_update_available": "⚠ Mise à jour disponible",
|
||||||
"status_not_installed": "✗ Non installé",
|
"status_not_installed": "✗ Non installé",
|
||||||
"status_checking": "🔄 Vérification des mises à jour...",
|
"status_idle": "Cliquez sur 'Vérifier la Version' pour commencer",
|
||||||
"status_downloading": "⬇ Téléchargement de FFmpeg...",
|
"status_checking": "🔄 Vérification de la version...",
|
||||||
"status_installing": "⚙ Installation de FFmpeg...",
|
"check_updates": "Vérifier la Version",
|
||||||
"status_verifying": "✓ Vérification de l'intégrité...",
|
"check_failed": "Échec de la vérification de la version. Vérifiez votre connexion Internet.",
|
||||||
"check_updates": "Vérifier les mises à jour",
|
"description": "Vérifiez votre version de FFmpeg et comparez-la avec la dernière version disponible.",
|
||||||
"update_button": "Mettre à jour FFmpeg",
|
"guide_info": " Pour installer ou mettre à jour FFmpeg, <a href='https://github.com/oop7/ffmpeg-install-guide'>cliquez ici pour consulter notre guide d'installation complet</a>."
|
||||||
"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é."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "डाउनलोड शुरू हुआ"
|
"redownload_started": "डाउनलोड शुरू हुआ"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "FFmpeg अपडेटर",
|
"title": "FFmpeg संस्करण जांचकर्ता",
|
||||||
"current_version": "वर्तमान संस्करण:",
|
"current_version": "वर्तमान संस्करण:",
|
||||||
"latest_version": "नवीनतम संस्करण:",
|
"latest_version": "नवीनतम संस्करण:",
|
||||||
"status_up_to_date": "✓ अप टू डेट",
|
"status_up_to_date": "✓ अप टू डेट",
|
||||||
"status_update_available": "⚠ अपडेट उपलब्ध",
|
"status_update_available": "⚠ अपडेट उपलब्ध",
|
||||||
"status_not_installed": "✗ इंस्टॉल नहीं है",
|
"status_not_installed": "✗ इंस्टॉल नहीं है",
|
||||||
"status_checking": "🔄 अपडेट जांच रहे हैं...",
|
"status_idle": "शुरू करने के लिए 'संस्करण जांचें' पर क्लिक करें",
|
||||||
"status_downloading": "⬇ FFmpeg डाउनलोड हो रहा है...",
|
"status_checking": "🔄 संस्करण जांच रहे हैं...",
|
||||||
"status_installing": "⚙ FFmpeg इंस्टॉल हो रहा है...",
|
"check_updates": "संस्करण जांचें",
|
||||||
"status_verifying": "✓ अखंडता सत्यापित कर रहे हैं...",
|
"check_failed": "संस्करण जांच विफल रही। कृपया अपना इंटरनेट कनेक्शन जांचें।",
|
||||||
"check_updates": "अपडेट जांचें",
|
"description": "अपने FFmpeg संस्करण की जांच करें और इसे नवीनतम उपलब्ध संस्करण से तुलना करें।",
|
||||||
"update_button": "FFmpeg अपडेट करें",
|
"guide_info": " FFmpeg को इंस्टॉल या अपडेट करने के लिए, <a href='https://github.com/oop7/ffmpeg-install-guide'>हमारी व्यापक इंस्टॉलेशन गाइड देखने के लिए यहां क्लिक करें</a>."
|
||||||
"update_success": "FFmpeg सफलतापूर्वक संस्करण {version} में अपडेट किया गया!",
|
|
||||||
"update_failed": "FFmpeg अपडेट विफल रहा। कृपया पुनः प्रयास करें।",
|
|
||||||
"check_failed": "अपडेट जांच विफल रही। कृपया अपना इंटरनेट कनेक्शन जांचें।",
|
|
||||||
"install_first": "FFmpeg इंस्टॉल नहीं है। इंस्टॉल करने के लिए अपडेट पर क्लिक करें।",
|
|
||||||
"description": "सर्वोत्तम प्रदर्शन और संगतता के लिए FFmpeg को अप टू डेट रखें।"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "Unduhan dimulai"
|
"redownload_started": "Unduhan dimulai"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "Pembaruan FFmpeg",
|
"title": "Pemeriksa Versi FFmpeg",
|
||||||
"current_version": "Versi Saat Ini:",
|
"current_version": "Versi Saat Ini:",
|
||||||
"latest_version": "Versi Terbaru:",
|
"latest_version": "Versi Terbaru:",
|
||||||
"status_up_to_date": "✓ Terbaru",
|
"status_up_to_date": "✓ Terbaru",
|
||||||
"status_update_available": "⚠ Pembaruan tersedia",
|
"status_update_available": "⚠ Pembaruan tersedia",
|
||||||
"status_not_installed": "✗ Tidak terinstal",
|
"status_not_installed": "✗ Tidak terinstal",
|
||||||
"status_checking": "🔄 Memeriksa pembaruan...",
|
"status_idle": "Klik 'Periksa Versi' untuk memulai",
|
||||||
"status_downloading": "⬇ Mengunduh FFmpeg...",
|
"status_checking": "🔄 Memeriksa versi...",
|
||||||
"status_installing": "⚙ Menginstal FFmpeg...",
|
"check_updates": "Periksa Versi",
|
||||||
"status_verifying": "✓ Memverifikasi integritas...",
|
"check_failed": "Gagal memeriksa versi. Periksa koneksi internet Anda.",
|
||||||
"check_updates": "Periksa Pembaruan",
|
"description": "Periksa versi FFmpeg Anda dan bandingkan dengan versi terbaru yang tersedia.",
|
||||||
"update_button": "Perbarui FFmpeg",
|
"guide_info": " Untuk menginstal atau memperbarui FFmpeg, <a href='https://github.com/oop7/ffmpeg-install-guide'>klik di sini untuk melihat panduan instalasi lengkap kami</a>."
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "Download avviato"
|
"redownload_started": "Download avviato"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "Aggiornamento FFmpeg",
|
"title": "Controllo Versione FFmpeg",
|
||||||
"current_version": "Versione corrente:",
|
"current_version": "Versione corrente:",
|
||||||
"latest_version": "Ultima versione:",
|
"latest_version": "Ultima versione:",
|
||||||
"status_up_to_date": "✓ Aggiornato",
|
"status_up_to_date": "✓ Aggiornato",
|
||||||
"status_update_available": "⚠ Aggiornamento disponibile",
|
"status_update_available": "⚠ Aggiornamento disponibile",
|
||||||
"status_not_installed": "✗ Non installato",
|
"status_not_installed": "✗ Non installato",
|
||||||
"status_checking": "🔄 Verifica aggiornamenti...",
|
"status_idle": "Clicca 'Controlla Versione' per iniziare",
|
||||||
"status_downloading": "⬇ Download di FFmpeg...",
|
"status_checking": "🔄 Verifica versione...",
|
||||||
"status_installing": "⚙ Installazione di FFmpeg...",
|
"check_updates": "Controlla Versione",
|
||||||
"status_verifying": "✓ Verifica integrità...",
|
"check_failed": "Verifica versione non riuscita. Controlla la connessione Internet.",
|
||||||
"check_updates": "Verifica aggiornamenti",
|
"description": "Controlla la tua versione di FFmpeg e confrontala con l'ultima versione disponibile.",
|
||||||
"update_button": "Aggiorna FFmpeg",
|
"guide_info": " Per installare o aggiornare FFmpeg, <a href='https://github.com/oop7/ffmpeg-install-guide'>clicca qui per visualizzare la nostra guida completa all'installazione</a>."
|
||||||
"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à."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "ダウンロード開始"
|
"redownload_started": "ダウンロード開始"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "FFmpegアップデーター",
|
"title": "FFmpegバージョンチェッカー",
|
||||||
"current_version": "現在のバージョン:",
|
"current_version": "現在のバージョン:",
|
||||||
"latest_version": "最新バージョン:",
|
"latest_version": "最新バージョン:",
|
||||||
"status_up_to_date": "✓ 最新",
|
"status_up_to_date": "✓ 最新",
|
||||||
"status_update_available": "⚠ 更新可能",
|
"status_update_available": "⚠ 更新可能",
|
||||||
"status_not_installed": "✗ 未インストール",
|
"status_not_installed": "✗ 未インストール",
|
||||||
"status_checking": "🔄 更新を確認中...",
|
"status_idle": "開始するには「バージョンを確認」をクリック",
|
||||||
"status_downloading": "⬇ FFmpegをダウンロード中...",
|
"status_checking": "🔄 バージョンを確認中...",
|
||||||
"status_installing": "⚙ FFmpegをインストール中...",
|
"check_updates": "バージョンを確認",
|
||||||
"status_verifying": "✓ 整合性を検証中...",
|
"check_failed": "バージョンの確認に失敗しました。インターネット接続を確認してください。",
|
||||||
"check_updates": "更新を確認",
|
"description": "FFmpegのバージョンを確認し、利用可能な最新バージョンと比較します。",
|
||||||
"update_button": "FFmpegを更新",
|
"guide_info": " FFmpegをインストールまたは更新するには、<a href='https://github.com/oop7/ffmpeg-install-guide'>こちらをクリックして包括的なインストールガイドをご覧ください</a>。"
|
||||||
"update_success": "FFmpegがバージョン{version}に更新されました!",
|
|
||||||
"update_failed": "FFmpegの更新に失敗しました。再試行してください。",
|
|
||||||
"check_failed": "更新の確認に失敗しました。インターネット接続を確認してください。",
|
|
||||||
"install_first": "FFmpegがインストールされていません。インストールするには「更新」をクリックしてください。",
|
|
||||||
"description": "最高のパフォーマンスと互換性のためにFFmpegを最新の状態に保ってください。"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "Rozpoczęto pobieranie"
|
"redownload_started": "Rozpoczęto pobieranie"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "Aktualizator FFmpeg",
|
"title": "Sprawdzanie Wersji FFmpeg",
|
||||||
"current_version": "Obecna wersja:",
|
"current_version": "Obecna wersja:",
|
||||||
"latest_version": "Najnowsza wersja:",
|
"latest_version": "Najnowsza wersja:",
|
||||||
"status_up_to_date": "✓ Aktualne",
|
"status_up_to_date": "✓ Aktualne",
|
||||||
"status_update_available": "⚠ Dostępna aktualizacja",
|
"status_update_available": "⚠ Dostępna aktualizacja",
|
||||||
"status_not_installed": "✗ Nie zainstalowano",
|
"status_not_installed": "✗ Nie zainstalowano",
|
||||||
"status_checking": "🔄 Sprawdzanie aktualizacji...",
|
"status_idle": "Kliknij 'Sprawdź Wersję', aby rozpocząć",
|
||||||
"status_downloading": "⬇ Pobieranie FFmpeg...",
|
"status_checking": "🔄 Sprawdzanie wersji...",
|
||||||
"status_installing": "⚙ Instalowanie FFmpeg...",
|
"check_updates": "Sprawdź Wersję",
|
||||||
"status_verifying": "✓ Weryfikacja integralności...",
|
"check_failed": "Nie udało się sprawdzić wersji. Sprawdź połączenie internetowe.",
|
||||||
"check_updates": "Sprawdź aktualizacje",
|
"description": "Sprawdź swoją wersję FFmpeg i porównaj ją z najnowszą dostępną wersją.",
|
||||||
"update_button": "Aktualizuj FFmpeg",
|
"guide_info": " Aby zainstalować lub zaktualizować FFmpeg, <a href='https://github.com/oop7/ffmpeg-install-guide'>kliknij tutaj, aby wyświetlić nasz kompleksowy przewodnik instalacji</a>."
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "Download iniciado"
|
"redownload_started": "Download iniciado"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "Atualizador FFmpeg",
|
"title": "Verificador de Versão FFmpeg",
|
||||||
"current_version": "Versão Atual:",
|
"current_version": "Versão Atual:",
|
||||||
"latest_version": "Última Versão:",
|
"latest_version": "Última Versão:",
|
||||||
"status_up_to_date": "✓ Atualizado",
|
"status_up_to_date": "✓ Atualizado",
|
||||||
"status_update_available": "⚠ Atualização disponível",
|
"status_update_available": "⚠ Atualização disponível",
|
||||||
"status_not_installed": "✗ Não instalado",
|
"status_not_installed": "✗ Não instalado",
|
||||||
"status_checking": "🔄 Verificando atualizações...",
|
"status_idle": "Clique em 'Verificar Versão' para começar",
|
||||||
"status_downloading": "⬇ Baixando FFmpeg...",
|
"status_checking": "🔄 Verificando versão...",
|
||||||
"status_installing": "⚙ Instalando FFmpeg...",
|
"check_updates": "Verificar Versão",
|
||||||
"status_verifying": "✓ Verificando integridade...",
|
"check_failed": "Falha ao verificar versão. Verifique sua conexão com a Internet.",
|
||||||
"check_updates": "Verificar Atualizações",
|
"description": "Verifique sua versão do FFmpeg e compare com a última versão disponível.",
|
||||||
"update_button": "Atualizar FFmpeg",
|
"guide_info": " Para instalar ou atualizar o FFmpeg, <a href='https://github.com/oop7/ffmpeg-install-guide'>clique aqui para ver nosso guia completo de instalação</a>."
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "Загрузка начата"
|
"redownload_started": "Загрузка начата"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "Обновление FFmpeg",
|
"title": "Проверка версии FFmpeg",
|
||||||
"current_version": "Текущая версия:",
|
"current_version": "Текущая версия:",
|
||||||
"latest_version": "Последняя версия:",
|
"latest_version": "Последняя версия:",
|
||||||
"status_up_to_date": "✓ Обновлено",
|
"status_up_to_date": "✓ Обновлено",
|
||||||
"status_update_available": "⚠ Доступно обновление",
|
"status_update_available": "⚠ Доступно обновление",
|
||||||
"status_not_installed": "✗ Не установлено",
|
"status_not_installed": "✗ Не установлено",
|
||||||
"status_checking": "🔄 Проверка обновлений...",
|
"status_idle": "Нажмите 'Проверить версию' для начала",
|
||||||
"status_downloading": "⬇ Загрузка FFmpeg...",
|
"status_checking": "🔄 Проверка версии...",
|
||||||
"status_installing": "⚙ Установка FFmpeg...",
|
"check_updates": "Проверить версию",
|
||||||
"status_verifying": "✓ Проверка целостности...",
|
"check_failed": "Не удалось проверить версию. Проверьте подключение к Интернету.",
|
||||||
"check_updates": "Проверить обновления",
|
"description": "Проверьте версию FFmpeg и сравните ее с последней доступной версией.",
|
||||||
"update_button": "Обновить FFmpeg",
|
"guide_info": " Для установки или обновления FFmpeg, <a href='https://github.com/oop7/ffmpeg-install-guide'>нажмите здесь, чтобы просмотреть наше подробное руководство по установке</a>."
|
||||||
"update_success": "FFmpeg успешно обновлен до версии {version}!",
|
|
||||||
"update_failed": "Не удалось обновить FFmpeg. Попробуйте еще раз.",
|
|
||||||
"check_failed": "Не удалось проверить обновления. Проверьте подключение к Интернету.",
|
|
||||||
"install_first": "FFmpeg не установлен. Нажмите Обновить для установки.",
|
|
||||||
"description": "Поддерживайте FFmpeg в актуальном состоянии для лучшей производительности и совместимости."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "İndirme başladı"
|
"redownload_started": "İndirme başladı"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "FFmpeg Güncelleyici",
|
"title": "FFmpeg Sürüm Denetçisi",
|
||||||
"current_version": "Mevcut Sürüm:",
|
"current_version": "Mevcut Sürüm:",
|
||||||
"latest_version": "En Son Sürüm:",
|
"latest_version": "En Son Sürüm:",
|
||||||
"status_up_to_date": "✓ Güncel",
|
"status_up_to_date": "✓ Güncel",
|
||||||
"status_update_available": "⚠ Güncelleme mevcut",
|
"status_update_available": "⚠ Güncelleme mevcut",
|
||||||
"status_not_installed": "✗ Yüklü değil",
|
"status_not_installed": "✗ Yüklü değil",
|
||||||
"status_checking": "🔄 Güncellemeler kontrol ediliyor...",
|
"status_idle": "Başlamak için 'Sürümü Kontrol Et'e tıklayın",
|
||||||
"status_downloading": "⬇ FFmpeg indiriliyor...",
|
"status_checking": "🔄 Sürüm kontrol ediliyor...",
|
||||||
"status_installing": "⚙ FFmpeg yükleniyor...",
|
"check_updates": "Sürümü Kontrol Et",
|
||||||
"status_verifying": "✓ Bütünlük doğrulanıyor...",
|
"check_failed": "Sürüm kontrolu başarısız oldu. İnternet bağlantınızı kontrol edin.",
|
||||||
"check_updates": "Güncellemeleri Kontrol Et",
|
"description": "FFmpeg sürümünüzü kontrol edin ve mevcut en son sürümle karşılaştırın.",
|
||||||
"update_button": "FFmpeg'i Güncelle",
|
"guide_info": " FFmpeg'i yüklemek veya güncellemek için, <a href='https://github.com/oop7/ffmpeg-install-guide'>kapsamlı kurulum kılavuzumuzu görüntülemek için buraya tıklayın</a>."
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-12
@@ -477,22 +477,17 @@
|
|||||||
"redownload_started": "已开始下载"
|
"redownload_started": "已开始下载"
|
||||||
},
|
},
|
||||||
"ffmpeg_updater": {
|
"ffmpeg_updater": {
|
||||||
"title": "FFmpeg 更新器",
|
"title": "FFmpeg 版本检查器",
|
||||||
"current_version": "当前版本:",
|
"current_version": "当前版本:",
|
||||||
"latest_version": "最新版本:",
|
"latest_version": "最新版本:",
|
||||||
"status_up_to_date": "✓ 已是最新",
|
"status_up_to_date": "✓ 已是最新",
|
||||||
"status_update_available": "⚠ 有可用更新",
|
"status_update_available": "⚠ 有可用更新",
|
||||||
"status_not_installed": "✗ 未安装",
|
"status_not_installed": "✗ 未安装",
|
||||||
"status_checking": "🔄 正在检查更新...",
|
"status_idle": "点击「检查版本」开始",
|
||||||
"status_downloading": "⬇ 正在下载 FFmpeg...",
|
"status_checking": "🔄 正在检查版本...",
|
||||||
"status_installing": "⚙ 正在安装 FFmpeg...",
|
"check_updates": "检查版本",
|
||||||
"status_verifying": "✓ 正在验证完整性...",
|
"check_failed": "检查版本失败。请检查您的网络连接。",
|
||||||
"check_updates": "检查更新",
|
"description": "检查您的 FFmpeg 版本并与最新可用版本进行比较。",
|
||||||
"update_button": "更新 FFmpeg",
|
"guide_info": " 要安装或更新 FFmpeg,<a href='https://github.com/oop7/ffmpeg-install-guide'>请点击此处查看我们的综合安装指南</a>。"
|
||||||
"update_success": "FFmpeg 已成功更新到版本 {version}!",
|
|
||||||
"update_failed": "更新 FFmpeg 失败。请重试。",
|
|
||||||
"check_failed": "检查更新失败。请检查您的网络连接。",
|
|
||||||
"install_first": "FFmpeg 未安装。点击更新以安装。",
|
|
||||||
"description": "保持 FFmpeg 更新以获得最佳性能和兼容性。"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+170
-7
@@ -12,6 +12,7 @@ from src.utils.ytsage_constants import (
|
|||||||
FFMPEG_7Z_DOWNLOAD_URL,
|
FFMPEG_7Z_DOWNLOAD_URL,
|
||||||
FFMPEG_7Z_SHA256_URL,
|
FFMPEG_7Z_SHA256_URL,
|
||||||
FFMPEG_ZIP_DOWNLOAD_URL,
|
FFMPEG_ZIP_DOWNLOAD_URL,
|
||||||
|
FFMPEG_ZIP_SHA256_URL,
|
||||||
OS_NAME,
|
OS_NAME,
|
||||||
SUBPROCESS_CREATIONFLAGS,
|
SUBPROCESS_CREATIONFLAGS,
|
||||||
)
|
)
|
||||||
@@ -194,7 +195,7 @@ def check_ffmpeg_installed() -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def install_ffmpeg_windows(progress_callback=None) -> 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
|
# Check if already installed
|
||||||
if check_ffmpeg_installed():
|
if check_ffmpeg_installed():
|
||||||
logger.info("FFmpeg is already installed!")
|
logger.info("FFmpeg is already installed!")
|
||||||
@@ -203,14 +204,176 @@ def install_ffmpeg_windows(progress_callback=None) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Import the updater for installation
|
# Define variables for essentials build
|
||||||
from src.core.ytsage_ffmpeg_updater import update_ffmpeg_windows
|
extract_dir = Path(os.getenv("LOCALAPPDATA")) / "ffmpeg" # type: ignore
|
||||||
|
|
||||||
# Use the updater to install the latest version
|
# Create extraction directory if it doesn't exist
|
||||||
logger.info("Installing FFmpeg using the updater module...")
|
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:
|
if progress_callback:
|
||||||
progress_callback("📦 Installing FFmpeg...")
|
progress_callback("🔍 Locating FFmpeg binaries...")
|
||||||
return update_ffmpeg_windows(progress_callback=progress_callback)
|
|
||||||
|
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:
|
except Exception as e:
|
||||||
logger.exception(f"Error installing FFmpeg: {e}")
|
logger.exception(f"Error installing FFmpeg: {e}")
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -1,19 +1,20 @@
|
|||||||
"""
|
"""
|
||||||
Updater tab for Custom Options dialog.
|
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 subprocess
|
||||||
import threading
|
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 (
|
from PySide6.QtWidgets import (
|
||||||
QCheckBox,
|
QCheckBox,
|
||||||
QGroupBox,
|
QGroupBox,
|
||||||
QHBoxLayout,
|
QHBoxLayout,
|
||||||
QLabel,
|
QLabel,
|
||||||
QProgressBar,
|
|
||||||
QPushButton,
|
QPushButton,
|
||||||
QRadioButton,
|
QRadioButton,
|
||||||
QScrollArea,
|
QScrollArea,
|
||||||
@@ -24,6 +25,7 @@ from PySide6.QtWidgets import (
|
|||||||
|
|
||||||
from src.core.ytsage_utils import (
|
from src.core.ytsage_utils import (
|
||||||
get_auto_update_settings,
|
get_auto_update_settings,
|
||||||
|
get_ffmpeg_version_direct,
|
||||||
update_auto_update_settings,
|
update_auto_update_settings,
|
||||||
)
|
)
|
||||||
from src.core.ytsage_yt_dlp import get_yt_dlp_path
|
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_config_manager import ConfigManager
|
||||||
from src.utils.ytsage_localization import _
|
from src.utils.ytsage_localization import _
|
||||||
from src.utils.ytsage_logger import logger
|
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 (
|
||||||
from src.utils.ytsage_constants import OS_NAME, SUBPROCESS_CREATIONFLAGS
|
FFMPEG_7Z_VERSION_URL,
|
||||||
from src.utils.ytsage_constants import OS_NAME
|
OS_NAME,
|
||||||
|
SUBPROCESS_CREATIONFLAGS,
|
||||||
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from src.gui.ytsage_gui_dialogs.ytsage_dialogs_custom import CustomOptionsDialog
|
from src.gui.ytsage_gui_dialogs.ytsage_dialogs_custom import CustomOptionsDialog
|
||||||
|
|
||||||
|
|
||||||
class UpdateWorker(QObject):
|
# Helper functions for FFmpeg version checking (copied from removed ytsage_ffmpeg_updater.py)
|
||||||
"""Worker class for running FFmpeg updates in a separate thread."""
|
def get_latest_ffmpeg_version() -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Fetch the latest FFmpeg version from the version URL.
|
||||||
|
|
||||||
progress = Signal(str) # Progress messages
|
Returns:
|
||||||
finished = Signal(bool) # Completion status (success/failure)
|
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):
|
Args:
|
||||||
"""Run the FFmpeg update process."""
|
version_str: Version string like "8.0" or "7.1.1"
|
||||||
try:
|
|
||||||
def progress_callback(msg: str):
|
Returns:
|
||||||
"""Callback for progress updates."""
|
Tuple of integers (e.g., (8, 0) or (7, 1, 1))
|
||||||
self.progress.emit(msg)
|
"""
|
||||||
|
try:
|
||||||
# Run the update
|
# Extract version numbers from string
|
||||||
success = update_ffmpeg(progress_callback=progress_callback)
|
match = re.search(r'(\d+\.\d+(?:\.\d+)?)', version_str)
|
||||||
self.finished.emit(success)
|
if match:
|
||||||
|
version_str = match.group(1)
|
||||||
except Exception as e:
|
|
||||||
logger.exception(f"Error during FFmpeg update: {e}")
|
parts = version_str.split('.')
|
||||||
self.progress.emit(f"❌ Error: {e}")
|
return tuple(int(p) for p in parts)
|
||||||
self.finished.emit(False)
|
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):
|
class UpdaterTabWidget(QWidget):
|
||||||
@@ -69,9 +163,6 @@ class UpdaterTabWidget(QWidget):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._parent: "CustomOptionsDialog" = cast("CustomOptionsDialog", self.parent())
|
self._parent: "CustomOptionsDialog" = cast("CustomOptionsDialog", self.parent())
|
||||||
|
|
||||||
self.update_thread = None
|
|
||||||
self.update_worker = None
|
|
||||||
|
|
||||||
# State variables
|
# State variables
|
||||||
self.current_version = "Unknown"
|
self.current_version = "Unknown"
|
||||||
self.latest_version = "Unknown"
|
self.latest_version = "Unknown"
|
||||||
@@ -102,7 +193,7 @@ class UpdaterTabWidget(QWidget):
|
|||||||
help_text.setStyleSheet("color: #999999; padding: 10px;")
|
help_text.setStyleSheet("color: #999999; padding: 10px;")
|
||||||
layout.addWidget(help_text)
|
layout.addWidget(help_text)
|
||||||
|
|
||||||
# FFmpeg Update Section
|
# FFmpeg Version Check Section
|
||||||
ffmpeg_group = QGroupBox(_('ffmpeg_updater.title'))
|
ffmpeg_group = QGroupBox(_('ffmpeg_updater.title'))
|
||||||
ffmpeg_layout = QVBoxLayout(ffmpeg_group)
|
ffmpeg_layout = QVBoxLayout(ffmpeg_group)
|
||||||
|
|
||||||
@@ -144,10 +235,8 @@ class UpdaterTabWidget(QWidget):
|
|||||||
)
|
)
|
||||||
ffmpeg_layout.addWidget(self.status_label)
|
ffmpeg_layout.addWidget(self.status_label)
|
||||||
|
|
||||||
# Button layout
|
# Check version button
|
||||||
button_layout = QHBoxLayout()
|
check_button_layout = QHBoxLayout()
|
||||||
|
|
||||||
# Check for updates button
|
|
||||||
self.check_button = QPushButton(_('ffmpeg_updater.check_updates'))
|
self.check_button = QPushButton(_('ffmpeg_updater.check_updates'))
|
||||||
self.check_button.clicked.connect(self.check_for_updates)
|
self.check_button.clicked.connect(self.check_for_updates)
|
||||||
self.check_button.setStyleSheet(
|
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()
|
# Installation guide info
|
||||||
|
guide_label = QLabel(_('ffmpeg_updater.guide_info'))
|
||||||
# Update button
|
guide_label.setWordWrap(True)
|
||||||
self.update_button = QPushButton(_('ffmpeg_updater.update_button'))
|
guide_label.setOpenExternalLinks(True) # Enable clickable links
|
||||||
self.update_button.clicked.connect(self.start_update)
|
guide_label.setTextFormat(Qt.TextFormat.RichText) # Enable HTML formatting
|
||||||
self.update_button.setEnabled(False)
|
guide_label.setStyleSheet(
|
||||||
self.update_button.setStyleSheet(
|
|
||||||
"""
|
"""
|
||||||
QPushButton {
|
QLabel {
|
||||||
padding: 8px 15px;
|
color: #cccccc;
|
||||||
background-color: #c90000;
|
font-size: 11px;
|
||||||
border: none;
|
padding: 8px;
|
||||||
|
background-color: #1a1d20;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: white;
|
|
||||||
font-weight: bold;
|
|
||||||
min-width: 120px;
|
|
||||||
}
|
}
|
||||||
QPushButton:hover {
|
QLabel a {
|
||||||
background-color: #a50000;
|
color: #4da6ff;
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
QPushButton:disabled {
|
QLabel a:hover {
|
||||||
background-color: #4a4a4a;
|
color: #66b3ff;
|
||||||
color: #888888;
|
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
button_layout.addWidget(self.update_button)
|
ffmpeg_layout.addWidget(guide_label)
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
layout.addWidget(ffmpeg_group)
|
layout.addWidget(ffmpeg_group)
|
||||||
|
|
||||||
@@ -596,27 +635,25 @@ class UpdaterTabWidget(QWidget):
|
|||||||
dialog.show() # Use show() instead of exec() to avoid blocking
|
dialog.show() # Use show() instead of exec() to avoid blocking
|
||||||
|
|
||||||
def check_for_updates(self) -> None:
|
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.check_button.setEnabled(False)
|
||||||
self.update_button.setEnabled(False)
|
|
||||||
self.status_label.setText(_('ffmpeg_updater.status_checking'))
|
self.status_label.setText(_('ffmpeg_updater.status_checking'))
|
||||||
self.status_label.setStyleSheet(
|
self.status_label.setStyleSheet(
|
||||||
"color: #ffaa00; font-size: 12px; padding: 8px; "
|
"color: #ffaa00; font-size: 12px; padding: 8px; "
|
||||||
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
|
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
|
||||||
)
|
)
|
||||||
self.log_output.append("🔍 Checking for FFmpeg updates...")
|
|
||||||
|
|
||||||
# Run check in background thread
|
# Run check in background thread
|
||||||
def check_thread():
|
def check_thread():
|
||||||
try:
|
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.check_button.setEnabled(True)
|
||||||
self._update_check_results(update_available, current_version, latest_version)
|
self._update_check_results(update_available, current_version, latest_version)
|
||||||
|
|
||||||
except Exception as e:
|
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.check_button.setEnabled(True)
|
||||||
self._show_check_error(str(e))
|
self._show_check_error(str(e))
|
||||||
|
|
||||||
@@ -624,7 +661,7 @@ class UpdaterTabWidget(QWidget):
|
|||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def _update_check_results(self, update_available: bool, current_version: str, latest_version: str) -> None:
|
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.update_available = update_available
|
||||||
self.current_version = current_version
|
self.current_version = current_version
|
||||||
self.latest_version = latest_version
|
self.latest_version = latest_version
|
||||||
@@ -635,97 +672,28 @@ class UpdaterTabWidget(QWidget):
|
|||||||
|
|
||||||
# Update status
|
# Update status
|
||||||
if current_version == "Not installed":
|
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(
|
self.status_label.setStyleSheet(
|
||||||
"color: #ff6666; font-size: 12px; padding: 8px; "
|
"color: #ff6666; font-size: 12px; padding: 8px; "
|
||||||
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
|
"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:
|
elif update_available:
|
||||||
self.status_label.setText(_('ffmpeg_updater.status_update_available'))
|
self.status_label.setText(_('ffmpeg_updater.status_update_available'))
|
||||||
self.status_label.setStyleSheet(
|
self.status_label.setStyleSheet(
|
||||||
"color: #ffaa00; font-size: 12px; padding: 8px; "
|
"color: #ffaa00; font-size: 12px; padding: 8px; "
|
||||||
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
|
"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:
|
else:
|
||||||
self.status_label.setText(_('ffmpeg_updater.status_up_to_date'))
|
self.status_label.setText(_('ffmpeg_updater.status_up_to_date'))
|
||||||
self.status_label.setStyleSheet(
|
self.status_label.setStyleSheet(
|
||||||
"color: #00cc00; font-size: 12px; padding: 8px; "
|
"color: #00cc00; font-size: 12px; padding: 8px; "
|
||||||
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
|
"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:
|
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.setText(_('ffmpeg_updater.check_failed'))
|
||||||
self.status_label.setStyleSheet(
|
self.status_label.setStyleSheet(
|
||||||
"color: #ff6666; font-size: 12px; padding: 8px; "
|
"color: #ff6666; font-size: 12px; padding: 8px; "
|
||||||
"background-color: #2a2d36; border-radius: 4px; margin: 5px 0;"
|
"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)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user