fix: emit download_progress events during direct stream downloads

When _try_direct_stream() succeeded, it streamed chunks directly via
requests.get() without firing any progress events. This caused the WebSocket
frontend to only see 'started' (0%) and 'completed' (100%) — no incremental
updates.

Add per-chunk progress events to _try_direct_stream that mirror yt-dlp's
hook format (downloaded_bytes, total_bytes, speed, eta, status), emitted at
~1% intervals. These flow through the existing download_progress handler chain
(SeriesApp → anime_service → progress_service → WebSocket → frontend).
This commit is contained in:
2026-07-31 08:42:59 +02:00
parent 163532b1ef
commit 270da18543

View File

@@ -5,6 +5,7 @@ import logging
import os import os
import re import re
import shutil import shutil
import time
import threading import threading
from pathlib import Path from pathlib import Path
from urllib.parse import quote from urllib.parse import quote
@@ -383,6 +384,12 @@ class AniworldLoader(Loader):
"Direct stream download starting (type=%s)", "Direct stream download starting (type=%s)",
content_type content_type
) )
total_size = int(response.headers.get(
"Content-Length", 0
))
received = 0
last_emit = 0
start_time = time.monotonic()
with open(output_path, "wb") as fh: with open(output_path, "wb") as fh:
for chunk in response.iter_content(chunk_size=1024 * 1024): for chunk in response.iter_content(chunk_size=1024 * 1024):
if self._cancel_flag.is_set(): if self._cancel_flag.is_set():
@@ -391,7 +398,33 @@ class AniworldLoader(Loader):
) )
return False return False
if chunk: if chunk:
received += len(chunk)
fh.write(chunk) fh.write(chunk)
# Emit progress events at ~1% intervals
if total_size > 0:
pct = (received / total_size) * 100
if pct - last_emit >= 1.0 or received == total_size:
elapsed = time.monotonic() - start_time
speed_bps = (
received / elapsed
if elapsed > 0 else 0
)
eta = (
int((total_size - received) / speed_bps)
if speed_bps > 0 else None
)
self.events.download_progress({
"downloaded_bytes": received,
"total_bytes": total_size,
"speed": speed_bps,
"eta": eta,
"status": (
"finished"
if received >= total_size
else "downloading"
),
})
last_emit = pct
return True return True
except requests.RequestException as exc: except requests.RequestException as exc:
logger.warning("Direct stream download failed: %s", exc) logger.warning("Direct stream download failed: %s", exc)