mirror of
https://github.com/xpltdco/media-rip.git
synced 2026-04-03 02:53:58 -06:00
M002/S04: fix filename resolution for downloads
- Use extract_info + prepare_filename to determine output filename before downloading (yt-dlp skips progress hooks when file exists) - Normalize filenames to relative paths (strip output dir prefix) - Include filename in completion SSE event so frontend displays it - Fixes file download 404s from subdirectory source templates
This commit is contained in:
parent
fd25ea7d05
commit
1da3ef37f1
1 changed files with 31 additions and 5 deletions
|
|
@ -14,6 +14,7 @@ import os
|
|||
import uuid
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
import yt_dlp
|
||||
|
||||
|
|
@ -206,7 +207,6 @@ class DownloadService:
|
|||
# Normalize filename to be relative to the output directory
|
||||
# so the frontend can construct download URLs correctly.
|
||||
if event.filename:
|
||||
from pathlib import PurePosixPath, Path
|
||||
abs_path = Path(event.filename).resolve()
|
||||
out_dir = Path(self._config.downloads.output_dir).resolve()
|
||||
try:
|
||||
|
|
@ -226,8 +226,8 @@ class DownloadService:
|
|||
if pct_changed or status_changed:
|
||||
self._last_db_percent[job_id] = event.percent
|
||||
logger.debug(
|
||||
"Job %s DB write: percent=%.1f status=%s",
|
||||
job_id, event.percent, event.status,
|
||||
"Job %s DB write: percent=%.1f status=%s filename=%s",
|
||||
job_id, event.percent, event.status, event.filename,
|
||||
)
|
||||
future = asyncio.run_coroutine_threadsafe(
|
||||
update_job_progress(
|
||||
|
|
@ -243,7 +243,7 @@ class DownloadService:
|
|||
# Block worker thread until DB write completes
|
||||
future.result(timeout=10)
|
||||
except Exception:
|
||||
logger.exception("Job %s progress hook error", job_id)
|
||||
logger.exception("Job %s progress hook error (status=%s)", job_id, d.get("status"))
|
||||
|
||||
opts["progress_hooks"] = [progress_hook]
|
||||
|
||||
|
|
@ -261,8 +261,34 @@ class DownloadService:
|
|||
|
||||
# Fresh YoutubeDL instance — never shared
|
||||
with yt_dlp.YoutubeDL(opts) as ydl:
|
||||
# Extract info first to determine the output filename.
|
||||
# This is needed because yt-dlp may skip progress hooks
|
||||
# entirely when the file already exists.
|
||||
info = ydl.extract_info(url, download=False)
|
||||
if info:
|
||||
raw_fn = ydl.prepare_filename(info)
|
||||
abs_path = Path(raw_fn).resolve()
|
||||
out_dir = Path(self._config.downloads.output_dir).resolve()
|
||||
try:
|
||||
relative_fn = str(abs_path.relative_to(out_dir))
|
||||
except ValueError:
|
||||
relative_fn = abs_path.name
|
||||
else:
|
||||
relative_fn = None
|
||||
|
||||
ydl.download([url])
|
||||
|
||||
# Persist filename to DB (progress hooks may not have fired
|
||||
# if the file already existed)
|
||||
if relative_fn:
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
update_job_progress(
|
||||
self._db, job_id, 100.0,
|
||||
None, None, relative_fn,
|
||||
),
|
||||
self._loop,
|
||||
).result(timeout=10)
|
||||
|
||||
# Mark as completed and notify SSE
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
update_job_status(self._db, job_id, JobStatus.completed.value),
|
||||
|
|
@ -271,7 +297,7 @@ class DownloadService:
|
|||
self._broker.publish(session_id, {
|
||||
"event": "job_update",
|
||||
"data": {"job_id": job_id, "status": "completed", "percent": 100,
|
||||
"speed": None, "eta": None, "filename": None},
|
||||
"speed": None, "eta": None, "filename": relative_fn},
|
||||
})
|
||||
logger.info("Job %s completed", job_id)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue