mirror of
https://github.com/pacnpal/Pac-cogs.git
synced 2025-12-20 10:51:05 -05:00
fixed
This commit is contained in:
@@ -1,109 +1,205 @@
|
||||
"""Module for tracking download and compression progress"""
|
||||
"""Progress tracking module."""
|
||||
|
||||
import logging
|
||||
from typing import Dict, Any, Optional
|
||||
from datetime import datetime
|
||||
|
||||
logger = logging.getLogger("ProgressTracker")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ProgressTracker:
|
||||
"""Tracks progress of downloads and compression operations"""
|
||||
"""Progress tracker singleton."""
|
||||
_instance = None
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
cls._instance._initialized = False
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
self._download_progress: Dict[str, Dict[str, Any]] = {}
|
||||
self._compression_progress: Dict[str, Dict[str, Any]] = {}
|
||||
if not hasattr(self, '_initialized'):
|
||||
self._data: Dict[str, Dict[str, Any]] = {}
|
||||
self._initialized = True
|
||||
|
||||
def start_download(self, url: str) -> None:
|
||||
"""Initialize progress tracking for a download"""
|
||||
self._download_progress[url] = {
|
||||
"active": True,
|
||||
"start_time": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"percent": 0,
|
||||
"speed": "N/A",
|
||||
"eta": "N/A",
|
||||
"downloaded_bytes": 0,
|
||||
"total_bytes": 0,
|
||||
"retries": 0,
|
||||
"fragment_count": 0,
|
||||
"fragment_index": 0,
|
||||
"video_title": "Unknown",
|
||||
"extractor": "Unknown",
|
||||
"format": "Unknown",
|
||||
"resolution": "Unknown",
|
||||
"fps": "Unknown",
|
||||
"last_update": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
}
|
||||
def update(self, key: str, data: Dict[str, Any]) -> None:
|
||||
"""Update progress for a key."""
|
||||
if key not in self._data:
|
||||
self._data[key] = {
|
||||
'active': True,
|
||||
'start_time': datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
'percent': 0
|
||||
}
|
||||
self._data[key].update(data)
|
||||
self._data[key]['last_update'] = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
|
||||
logger.debug(f"Progress for {key}: {self._data[key].get('percent', 0)}%")
|
||||
|
||||
def update_download_progress(self, data: Dict[str, Any]) -> None:
|
||||
"""Update download progress information"""
|
||||
def get(self, key: Optional[str] = None) -> Dict[str, Any]:
|
||||
"""Get progress for a key."""
|
||||
if key is None:
|
||||
return self._data
|
||||
return self._data.get(key, {})
|
||||
|
||||
def complete(self, key: str) -> None:
|
||||
"""Mark progress as complete."""
|
||||
if key in self._data:
|
||||
self._data[key]['active'] = False
|
||||
logger.info(f"Operation completed for {key}")
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Clear all progress data."""
|
||||
self._data.clear()
|
||||
logger.info("Progress data cleared")
|
||||
|
||||
_tracker = ProgressTracker()
|
||||
|
||||
def get_compression(self, file_path: Optional[str] = None) -> Dict[str, Any]:
|
||||
"""Get compression progress."""
|
||||
if file_path is None:
|
||||
return self._compressions
|
||||
return self._compressions.get(file_path, {})
|
||||
|
||||
def complete_download(self, url: str) -> None:
|
||||
"""Mark download as complete."""
|
||||
if url in self._downloads:
|
||||
self._downloads[url]['active'] = False
|
||||
logger.info(f"Download completed for {url}")
|
||||
|
||||
def complete_compression(self, file_path: str) -> None:
|
||||
"""Mark compression as complete."""
|
||||
if file_path in self._compressions:
|
||||
self._compressions[file_path]['active'] = False
|
||||
logger.info(f"Compression completed for {file_path}")
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Clear all progress data."""
|
||||
self._downloads.clear()
|
||||
self._compressions.clear()
|
||||
logger.info("Progress data cleared")
|
||||
|
||||
# Global instance
|
||||
_tracker = ProgressTrack
|
||||
|
||||
# Global instance
|
||||
_tracker = ProgressTracker()
|
||||
|
||||
def get_tracker() -> Progre
|
||||
"""Clear all progress tracking"""
|
||||
self._download_progress.clear()
|
||||
self._compression_progress.clear()
|
||||
logger.info("Cleared all progress tracking data")
|
||||
|
||||
# Create singleton instance
|
||||
progress_tracker = ProgressTracker()
|
||||
|
||||
def get_progress_tracker() -> ProgressTracker:
|
||||
|
||||
def mark_compression_complete(self, file_path: str) -> None:
|
||||
"""Mark a compression operation as complete"""
|
||||
if file_path in self._compression_progress:
|
||||
self._compression_progress[file_path]['active'] = False
|
||||
logger.info(f"Compression completed for {file_path}")
|
||||
|
||||
def clear_progress(self) -> None:
|
||||
"""Clear all progress tracking"""
|
||||
self._download_progress.clear()
|
||||
self._compression_progress.clear()
|
||||
logger.info("Cleared all progress tracking data")
|
||||
|
||||
# Create singleton instance
|
||||
progress_tracker = ProgressTracker()
|
||||
|
||||
# Export the singleton instance
|
||||
def get_progress_tracker() -> ProgressTracker:
|
||||
|
||||
|
||||
Args:
|
||||
data: Dictionary containing download progress data
|
||||
"""
|
||||
try:
|
||||
# Get URL from info dict
|
||||
url = data.get("info_dict", {}).get("webpage_url", "unknown")
|
||||
if url not in self._download_progress:
|
||||
info_dict = data.get("info_dict", {})
|
||||
url = info_dict.get("webpage_url")
|
||||
if not url or url not in self._download_progress:
|
||||
return
|
||||
|
||||
if data["status"] == "downloading":
|
||||
if data.get("status") == "downloading":
|
||||
percent_str = data.get("_percent_str", "0").replace("%", "")
|
||||
try:
|
||||
percent = float(percent_str)
|
||||
except ValueError:
|
||||
percent = 0.0
|
||||
|
||||
total_bytes = (
|
||||
data.get("total_bytes", 0) or
|
||||
data.get("total_bytes_estimate", 0)
|
||||
)
|
||||
|
||||
self._download_progress[url].update({
|
||||
"active": True,
|
||||
"percent": float(data.get("_percent_str", "0").replace("%", "")),
|
||||
"percent": percent,
|
||||
"speed": data.get("_speed_str", "N/A"),
|
||||
"eta": data.get("_eta_str", "N/A"),
|
||||
"downloaded_bytes": data.get("downloaded_bytes", 0),
|
||||
"total_bytes": data.get("total_bytes", 0) or data.get("total_bytes_estimate", 0),
|
||||
"total_bytes": total_bytes,
|
||||
"retries": data.get("retry_count", 0),
|
||||
"fragment_count": data.get("fragment_count", 0),
|
||||
"fragment_index": data.get("fragment_index", 0),
|
||||
"video_title": data.get("info_dict", {}).get("title", "Unknown"),
|
||||
"extractor": data.get("info_dict", {}).get("extractor", "Unknown"),
|
||||
"format": data.get("info_dict", {}).get("format", "Unknown"),
|
||||
"resolution": data.get("info_dict", {}).get("resolution", "Unknown"),
|
||||
"fps": data.get("info_dict", {}).get("fps", "Unknown"),
|
||||
"last_update": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"video_title": info_dict.get("title", "Unknown"),
|
||||
"extractor": info_dict.get("extractor", "Unknown"),
|
||||
"format": info_dict.get("format", "Unknown"),
|
||||
"resolution": info_dict.get("resolution", "Unknown"),
|
||||
"fps": info_dict.get("fps", "Unknown"),
|
||||
"last_update": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
|
||||
})
|
||||
|
||||
logger.debug(
|
||||
f"Download progress for {url}: "
|
||||
f"{self._download_progress[url]['percent']}% at {self._download_progress[url]['speed']}, "
|
||||
f"{percent:.1f}% at {self._download_progress[url]['speed']}, "
|
||||
f"ETA: {self._download_progress[url]['eta']}"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating download progress: {e}")
|
||||
logger.error(f"Error updating download progress: {e}", exc_info=True)
|
||||
|
||||
def end_download(self, url: str) -> None:
|
||||
"""Mark a download as completed"""
|
||||
def end_download(self, url: str, status: ProgressStatus = ProgressStatus.COMPLETED) -> None:
|
||||
"""
|
||||
Mark a download as completed.
|
||||
|
||||
Args:
|
||||
url: The URL being downloaded
|
||||
status: The final status of the download
|
||||
"""
|
||||
if url in self._download_progress:
|
||||
self._download_progress[url]["active"] = False
|
||||
logger.info(f"Download {status.value} for {url}")
|
||||
|
||||
def start_compression(
|
||||
self,
|
||||
input_file: str,
|
||||
params: Dict[str, str],
|
||||
use_hardware: bool,
|
||||
duration: float,
|
||||
input_size: int,
|
||||
target_size: int
|
||||
) -> None:
|
||||
"""Initialize progress tracking for compression"""
|
||||
self._compression_progress[input_file] = {
|
||||
"active": True,
|
||||
"filename": input_file,
|
||||
"start_time": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"percent": 0,
|
||||
"elapsed_time": "0:00",
|
||||
"input_size": input_size,
|
||||
"current_size": 0,
|
||||
"target_size": target_size,
|
||||
"codec": params.get("c:v", "unknown"),
|
||||
"hardware_accel": use_hardware,
|
||||
"preset": params.get("preset", "unknown"),
|
||||
"crf": params.get("crf", "unknown"),
|
||||
"duration": duration,
|
||||
"bitrate": params.get("b:v", "unknown"),
|
||||
"audio_codec": params.get("c:a", "unknown"),
|
||||
"audio_bitrate": params.get("b:a", "unknown"),
|
||||
"last_update": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
}
|
||||
def start_compression(self, params: CompressionParams) -> None:
|
||||
"""
|
||||
Initialize progress tracking for compression.
|
||||
|
||||
Args:
|
||||
params: Compression parameters
|
||||
"""
|
||||
current_time = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
|
||||
self._compression_progress[params.input_file] = CompressionProgress(
|
||||
active=True,
|
||||
filename=params.input_file,
|
||||
start_time=current_time,
|
||||
percent=0.0,
|
||||
elapsed_time="0:00",
|
||||
input_size=params.input_size,
|
||||
current_size=0,
|
||||
target_size=params.target_size,
|
||||
codec=params.codec_params.get("c:v", "unknown"),
|
||||
hardware_accel=params.use_hardware,
|
||||
preset=params.codec_params.get("preset", "unknown"),
|
||||
crf=params.codec_params.get("crf", "unknown"),
|
||||
duration=params.duration,
|
||||
bitrate=params.codec_params.get("b:v", "unknown"),
|
||||
audio_codec=params.codec_params.get("c:a", "unknown"),
|
||||
audio_bitrate=params.codec_params.get("b:a", "unknown"),
|
||||
last_update=current_time,
|
||||
current_time=None
|
||||
)
|
||||
|
||||
def update_compression_progress(
|
||||
self,
|
||||
@@ -113,14 +209,23 @@ class ProgressTracker:
|
||||
current_size: int,
|
||||
current_time: float
|
||||
) -> None:
|
||||
"""Update compression progress information"""
|
||||
"""
|
||||
Update compression progress information.
|
||||
|
||||
Args:
|
||||
input_file: The input file being compressed
|
||||
progress: Current progress percentage (0-100)
|
||||
elapsed_time: Time elapsed as string
|
||||
current_size: Current file size in bytes
|
||||
current_time: Current timestamp in seconds
|
||||
"""
|
||||
if input_file in self._compression_progress:
|
||||
self._compression_progress[input_file].update({
|
||||
"percent": progress,
|
||||
"percent": max(0.0, min(100.0, progress)),
|
||||
"elapsed_time": elapsed_time,
|
||||
"current_size": current_size,
|
||||
"current_time": current_time,
|
||||
"last_update": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"last_update": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
|
||||
})
|
||||
|
||||
logger.debug(
|
||||
@@ -128,29 +233,73 @@ class ProgressTracker:
|
||||
f"{progress:.1f}%, Size: {current_size}/{self._compression_progress[input_file]['target_size']} bytes"
|
||||
)
|
||||
|
||||
def end_compression(self, input_file: str) -> None:
|
||||
"""Mark a compression operation as completed"""
|
||||
def end_compression(
|
||||
self,
|
||||
input_file: str,
|
||||
status: ProgressStatus = ProgressStatus.COMPLETED
|
||||
) -> None:
|
||||
"""
|
||||
Mark a compression operation as completed.
|
||||
|
||||
Args:
|
||||
input_file: The input file being compressed
|
||||
status: The final status of the compression
|
||||
"""
|
||||
if input_file in self._compression_progress:
|
||||
self._compression_progress[input_file]["active"] = False
|
||||
logger.info(f"Compression {status.value} for {input_file}")
|
||||
|
||||
def get_download_progress(self, url: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get progress information for a download"""
|
||||
def get_download_progress(self, url: Optional[str] = None) -> Optional[DownloadProgress]:
|
||||
"""
|
||||
Get progress information for a download.
|
||||
|
||||
Args:
|
||||
url: Optional URL to get progress for. If None, returns all progress.
|
||||
|
||||
Returns:
|
||||
Progress information for the specified download or None if not found
|
||||
"""
|
||||
if url is None:
|
||||
return self._download_progress
|
||||
return self._download_progress.get(url)
|
||||
|
||||
def get_compression_progress(self, input_file: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get progress information for a compression operation"""
|
||||
def get_compression_progress(
|
||||
self,
|
||||
input_file: Optional[str] = None
|
||||
) -> Optional[CompressionProgress]:
|
||||
"""
|
||||
Get progress information for a compression operation.
|
||||
|
||||
Args:
|
||||
input_file: Optional file to get progress for. If None, returns all progress.
|
||||
|
||||
Returns:
|
||||
Progress information for the specified compression or None if not found
|
||||
"""
|
||||
if input_file is None:
|
||||
return self._compression_progress
|
||||
return self._compression_progress.get(input_file)
|
||||
|
||||
def get_active_downloads(self) -> Dict[str, Dict[str, Any]]:
|
||||
"""Get all active downloads"""
|
||||
def get_active_downloads(self) -> Dict[str, DownloadProgress]:
|
||||
"""
|
||||
Get all active downloads.
|
||||
|
||||
Returns:
|
||||
Dictionary of active downloads and their progress
|
||||
"""
|
||||
return {
|
||||
url: progress
|
||||
for url, progress in self._download_progress.items()
|
||||
if progress.get("active", False)
|
||||
}
|
||||
|
||||
def get_active_compressions(self) -> Dict[str, Dict[str, Any]]:
|
||||
"""Get all active compression operations"""
|
||||
def get_active_compressions(self) -> Dict[str, CompressionProgress]:
|
||||
"""
|
||||
Get all active compression operations.
|
||||
|
||||
Returns:
|
||||
Dictionary of active compressions and their progress
|
||||
"""
|
||||
return {
|
||||
input_file: progress
|
||||
for input_file, progress in self._compression_progress.items()
|
||||
@@ -161,3 +310,4 @@ class ProgressTracker:
|
||||
"""Clear all progress tracking"""
|
||||
self._download_progress.clear()
|
||||
self._compression_progress.clear()
|
||||
logger.info("Cleared
|
||||
Reference in New Issue
Block a user