Refactor yt-dlp Integration and Error Handling

This commit is contained in:
Your Name
2025-07-04 21:34:18 +03:00
parent b04502b28b
commit 320e064ddc
+18 -29
View File
@@ -1,5 +1,10 @@
from PySide6.QtCore import QThread, Signal, QObject, QProcess, QTimer from PySide6.QtCore import QThread, Signal, QObject, QProcess, QTimer
import yt_dlp # Keep yt_dlp import here - only downloader uses it. try:
import yt_dlp # Keep yt_dlp import here - only downloader uses it.
YT_DLP_AVAILABLE = True
except ImportError:
YT_DLP_AVAILABLE = False
print("Warning: yt-dlp not available at startup, will be downloaded at runtime")
import time import time
import os import os
import re import re
@@ -7,6 +12,7 @@ import subprocess # For direct CLI command execution
import shlex # For safely parsing command arguments import shlex # For safely parsing command arguments
import sys # Added to get executable path information import sys # Added to get executable path information
from pathlib import Path from pathlib import Path
from ytsage_yt_dlp import get_yt_dlp_path # Import the new yt-dlp path function
class SignalManager(QObject): class SignalManager(QObject):
update_formats = Signal(list) update_formats = Signal(list)
@@ -148,6 +154,7 @@ class DownloadThread(QThread):
if self.cookie_file: if self.cookie_file:
ydl_opts_check['cookiefile'] = self.cookie_file ydl_opts_check['cookiefile'] = self.cookie_file
if YT_DLP_AVAILABLE:
with yt_dlp.YoutubeDL(ydl_opts_check) as ydl: with yt_dlp.YoutubeDL(ydl_opts_check) as ydl:
info = ydl.extract_info(self.url, download=False) info = ydl.extract_info(self.url, download=False)
@@ -169,6 +176,9 @@ class DownloadThread(QThread):
break break
print(f"DEBUG: Resolution: {resolution}") print(f"DEBUG: Resolution: {resolution}")
else:
print("DEBUG: yt-dlp not available, skipping file existence check")
return False # Proceed with download attempt
# Create the expected filename (more specific) # Create the expected filename (more specific)
if self.is_playlist and info.get('playlist_title'): if self.is_playlist and info.get('playlist_title'):
@@ -210,33 +220,10 @@ class DownloadThread(QThread):
def _build_yt_dlp_command(self): def _build_yt_dlp_command(self):
"""Build the yt-dlp command line with all options for direct execution.""" """Build the yt-dlp command line with all options for direct execution."""
# Use bundled yt-dlp executable instead of system PATH # Use the new yt-dlp path function from ytsage_yt_dlp module
# Determine if we're running from a PyInstaller bundle yt_dlp_path = get_yt_dlp_path()
if getattr(sys, 'frozen', False):
# We're running from a PyInstaller bundle
base_path = getattr(sys, '_MEIPASS', os.path.dirname(sys.executable))
yt_dlp_path = os.path.join(base_path, "yt-dlp.exe" if os.name == 'nt' else "yt-dlp")
if os.path.exists(yt_dlp_path):
cmd = [yt_dlp_path] cmd = [yt_dlp_path]
print(f"DEBUG: Using bundled yt-dlp from: {yt_dlp_path}") print(f"DEBUG: Using yt-dlp from: {yt_dlp_path}")
# Check if the bundled executable is actually executable
if not os.access(yt_dlp_path, os.X_OK) and os.name != 'nt': # Skip check on Windows
print(f"WARNING: Bundled yt-dlp exists but is not executable: {yt_dlp_path}")
try:
# Try to make it executable
os.chmod(yt_dlp_path, 0o755)
print(f"Fixed permissions on bundled yt-dlp")
except Exception as e:
print(f"Failed to fix permissions: {e}")
else:
# Fall back to regular command if bundled version not found
cmd = ["yt-dlp"]
print(f"DEBUG: Bundled yt-dlp not found at {yt_dlp_path}, using system PATH")
else:
# We're running from source, use system PATH
cmd = ["yt-dlp"]
print("DEBUG: Using system PATH for yt-dlp")
# Format selection strategy - use format ID if provided or fallback to resolution # Format selection strategy - use format ID if provided or fallback to resolution
if self.format_id: if self.format_id:
@@ -246,6 +233,7 @@ class DownloadThread(QThread):
# Check if this is an audio-only format # Check if this is an audio-only format
is_audio_format = False is_audio_format = False
try: try:
if YT_DLP_AVAILABLE:
ydl_opts = { ydl_opts = {
'quiet': True, 'quiet': True,
'no_warnings': True, 'no_warnings': True,
@@ -275,6 +263,7 @@ class DownloadThread(QThread):
try: try:
format_ext = None format_ext = None
print(f"DEBUG: Getting format information for format ID: {self.format_id} (using: {clean_format_id})") print(f"DEBUG: Getting format information for format ID: {self.format_id} (using: {clean_format_id})")
if YT_DLP_AVAILABLE:
ydl_opts = { ydl_opts = {
'quiet': True, 'quiet': True,
'no_warnings': True, 'no_warnings': True,
@@ -324,7 +313,7 @@ class DownloadThread(QThread):
if self.is_playlist and self.playlist_items: if self.is_playlist and self.playlist_items:
cmd.extend(["--playlist-items", self.playlist_items]) cmd.extend(["--playlist-items", self.playlist_items])
# Add subtitle options if selected # Add subtitle options if subtitles are selected
if self.subtitle_langs: if self.subtitle_langs:
# Subtitles work with both audio-only and video formats # Subtitles work with both audio-only and video formats
# For audio-only formats, subtitles will be downloaded as separate files # For audio-only formats, subtitles will be downloaded as separate files
@@ -344,7 +333,7 @@ class DownloadThread(QThread):
cmd.extend(["--sub-langs", ",".join(lang_codes)]) cmd.extend(["--sub-langs", ",".join(lang_codes)])
cmd.append("--write-auto-subs") # Include auto-generated subtitles cmd.append("--write-auto-subs") # Include auto-generated subtitles
# Add embedding if requested - only applies to video formats # Only embed subtitles if merge is enabled
if self.merge_subs: if self.merge_subs:
cmd.append("--embed-subs") cmd.append("--embed-subs")