fix percentage
This commit is contained in:
parent
0b5faeffc9
commit
9fce617949
@ -1,45 +1,5 @@
|
||||
{
|
||||
"pending": [
|
||||
{
|
||||
"id": "b9598089-3874-4574-9b1f-d31669eab645",
|
||||
"serie_id": "beheneko-the-elf-girls-cat-is-secretly-an-s-ranked-monster",
|
||||
"serie_folder": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)",
|
||||
"serie_name": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)",
|
||||
"episode": {
|
||||
"season": 1,
|
||||
"episode": 2,
|
||||
"title": null
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "NORMAL",
|
||||
"added_at": "2025-11-01T17:20:49.339563Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
"error": null,
|
||||
"retry_count": 0,
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "b7626704-068f-4084-80b6-6f213c121412",
|
||||
"serie_id": "beheneko-the-elf-girls-cat-is-secretly-an-s-ranked-monster",
|
||||
"serie_folder": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)",
|
||||
"serie_name": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)",
|
||||
"episode": {
|
||||
"season": 1,
|
||||
"episode": 3,
|
||||
"title": null
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "NORMAL",
|
||||
"added_at": "2025-11-01T17:20:49.339620Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
"error": null,
|
||||
"retry_count": 0,
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "67d98e0a-ce51-4768-854d-33c565d9bf17",
|
||||
"serie_id": "beheneko-the-elf-girls-cat-is-secretly-an-s-ranked-monster",
|
||||
@ -63,5 +23,5 @@
|
||||
],
|
||||
"active": [],
|
||||
"failed": [],
|
||||
"timestamp": "2025-11-01T17:22:28.998624+00:00"
|
||||
"timestamp": "2025-11-01T17:42:05.983160+00:00"
|
||||
}
|
||||
@ -245,6 +245,8 @@ class SeriesApp:
|
||||
# event-driven progress reporting with the legacy callback API that
|
||||
# the CLI still relies on.
|
||||
def wrapped_callback(progress_info):
|
||||
logger.debug(f"wrapped_callback called with: {progress_info}")
|
||||
|
||||
if self._is_cancelled():
|
||||
raise InterruptedError("Download cancelled by user")
|
||||
|
||||
@ -267,6 +269,11 @@ class SeriesApp:
|
||||
speed = progress_info.get('speed', 0) # bytes/sec
|
||||
eta = progress_info.get('eta') # seconds
|
||||
|
||||
logger.debug(
|
||||
f"Progress calculation: {downloaded}/{total_bytes} = "
|
||||
f"{progress:.1f}%, speed={speed}, eta={eta}"
|
||||
)
|
||||
|
||||
# Convert to expected format for web API callback
|
||||
# Web API expects: percent, downloaded_mb, total_mb,
|
||||
# speed_mbps, eta_seconds
|
||||
@ -295,6 +302,7 @@ class SeriesApp:
|
||||
'speed_mbps': None,
|
||||
'eta_seconds': None,
|
||||
}
|
||||
logger.debug(f"Old-style progress: {progress}%")
|
||||
|
||||
# Notify progress via new callback system
|
||||
self._callback_manager.notify_progress(
|
||||
@ -317,6 +325,7 @@ class SeriesApp:
|
||||
# Call callback with web API format
|
||||
# (dict with detailed progress info)
|
||||
if callback:
|
||||
logger.debug(f"Calling progress callback: {web_progress_dict}")
|
||||
callback(web_progress_dict)
|
||||
|
||||
# Propagate progress into the legacy callback chain so
|
||||
|
||||
@ -261,26 +261,59 @@ class AniworldLoader(Loader):
|
||||
ydl_opts['http_headers'] = header
|
||||
logging.debug("Using custom headers for download")
|
||||
if progress_callback:
|
||||
ydl_opts['progress_hooks'] = [progress_callback]
|
||||
# Wrap the callback to add logging
|
||||
def logged_progress_callback(d):
|
||||
logging.debug(
|
||||
f"YT-DLP progress: status={d.get('status')}, "
|
||||
f"downloaded={d.get('downloaded_bytes')}, "
|
||||
f"total={d.get('total_bytes')}, "
|
||||
f"speed={d.get('speed')}"
|
||||
)
|
||||
progress_callback(d)
|
||||
|
||||
ydl_opts['progress_hooks'] = [logged_progress_callback]
|
||||
logging.debug("Progress callback registered with YT-DLP")
|
||||
|
||||
try:
|
||||
logging.debug("Starting YoutubeDL download")
|
||||
logging.debug(f"Download link: {link[:100]}...")
|
||||
logging.debug(f"YDL options: {ydl_opts}")
|
||||
|
||||
with YoutubeDL(ydl_opts) as ydl:
|
||||
ydl.download([link])
|
||||
info = ydl.extract_info(link, download=True)
|
||||
logging.debug(
|
||||
f"Download info: "
|
||||
f"title={info.get('title')}, "
|
||||
f"filesize={info.get('filesize')}"
|
||||
)
|
||||
|
||||
if os.path.exists(temp_path):
|
||||
logging.debug("Moving file from temp to final destination")
|
||||
shutil.copy(temp_path, output_path)
|
||||
os.remove(temp_path)
|
||||
logging.info(f"Download completed successfully: {output_file}")
|
||||
logging.info(
|
||||
f"Download completed successfully: {output_file}"
|
||||
)
|
||||
self.clear_cache()
|
||||
return True
|
||||
else:
|
||||
logging.error(f"Download failed: temp file not found at {temp_path}")
|
||||
logging.error(
|
||||
f"Download failed: temp file not found at {temp_path}"
|
||||
)
|
||||
self.clear_cache()
|
||||
return False
|
||||
except BrokenPipeError as e:
|
||||
logging.error(
|
||||
f"Broken pipe error with provider {provider}: {e}. "
|
||||
f"This usually means the stream connection was closed."
|
||||
)
|
||||
# Try next provider if available
|
||||
continue
|
||||
except Exception as e:
|
||||
logging.error(f"YoutubeDL download failed: {e}")
|
||||
logging.error(
|
||||
f"YoutubeDL download failed with provider {provider}: "
|
||||
f"{type(e).__name__}: {e}"
|
||||
)
|
||||
# Try next provider if available
|
||||
continue
|
||||
break
|
||||
|
||||
@ -701,6 +701,10 @@ class DownloadService:
|
||||
def progress_callback(progress_data: dict) -> None:
|
||||
"""Update progress and broadcast to clients."""
|
||||
try:
|
||||
logger.debug(
|
||||
f"Progress callback received: {progress_data}"
|
||||
)
|
||||
|
||||
# Update item progress
|
||||
item.progress = DownloadProgress(
|
||||
percent=progress_data.get("percent", 0.0),
|
||||
@ -710,16 +714,32 @@ class DownloadService:
|
||||
eta_seconds=progress_data.get("eta_seconds"),
|
||||
)
|
||||
|
||||
logger.debug(
|
||||
f"Updated item progress: percent={item.progress.percent:.1f}%, "
|
||||
f"downloaded={item.progress.downloaded_mb:.1f}MB, "
|
||||
f"total={item.progress.total_mb}MB, "
|
||||
f"speed={item.progress.speed_mbps}MB/s"
|
||||
)
|
||||
|
||||
# Track speed for statistics
|
||||
if item.progress.speed_mbps:
|
||||
self._download_speeds.append(item.progress.speed_mbps)
|
||||
|
||||
# Update progress service
|
||||
# Schedule coroutines in a thread-safe manner
|
||||
# (callback may be called from executor thread)
|
||||
if item.progress.total_mb and item.progress.total_mb > 0:
|
||||
current_mb = int(item.progress.downloaded_mb)
|
||||
total_mb = int(item.progress.total_mb)
|
||||
|
||||
asyncio.create_task(
|
||||
logger.debug(
|
||||
f"Updating progress service: current={current_mb}MB, "
|
||||
f"total={total_mb}MB"
|
||||
)
|
||||
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
self._progress_service.update_progress(
|
||||
progress_id=f"download_{item.id}",
|
||||
current=current_mb,
|
||||
@ -728,11 +748,22 @@ class DownloadService:
|
||||
"speed_mbps": item.progress.speed_mbps,
|
||||
"eta_seconds": item.progress.eta_seconds,
|
||||
},
|
||||
),
|
||||
loop
|
||||
)
|
||||
except RuntimeError as e:
|
||||
logger.warning(
|
||||
f"Could not schedule progress update: {e}"
|
||||
)
|
||||
|
||||
# Broadcast update (fire and forget)
|
||||
asyncio.create_task(
|
||||
logger.debug(
|
||||
f"Broadcasting download_progress event for item {item.id}"
|
||||
)
|
||||
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
self._broadcast_update(
|
||||
"download_progress",
|
||||
{
|
||||
@ -743,7 +774,12 @@ class DownloadService:
|
||||
"episode": item.episode.episode,
|
||||
"progress": item.progress.model_dump(mode="json"),
|
||||
},
|
||||
),
|
||||
loop
|
||||
)
|
||||
except RuntimeError as e:
|
||||
logger.warning(
|
||||
f"Could not schedule broadcast: {e}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("Progress callback error", error=str(e))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user