Compare commits

..
2 Commits
Author SHA1 Message Date
agw 1b85698856 fix(yt): en dræbt hentning er midlertidig, ikke "ukendt fejl"
CD / deploy (push) Successful in 17s
CI / check (push) Successful in 25s
Når portalen genstarter midt i en hentning, bliver yt-dlp dræbt uden en
fejltekst, og jobbet endte som "ukendt fejl". Et negativt returkode (signal)
hedder nu "afbrudt" og prøves igen som de andre midlertidige fejl.

Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
2026-10-06 13:57:54 +02:00
agw 8751ae5722 fix(yt): nye forsøg med samme klient og længere pause
CD / deploy (push) Successful in 15s
CI / check (push) Successful in 23s
Test mod en video der fik 403: kun standardklienten gav 1080p; android_vr
faldt til 360p, og tv, web_safari, mweb og tv_simply gav ingen brugbare
formater. Nye forsøg bruger derfor standardklienten med 30 s og 2 min pause.

Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
2026-10-06 13:56:22 +02:00
+15 -8
View File
@@ -144,7 +144,7 @@ def _build_cmd(job: dict, settings: dict, with_subs: bool, klient: str = "") ->
cmd += ["--sponsorblock-remove", "default", "--sponsorblock-mark", "all"]
if klient:
# Nyt forsøg efter en 403: bed YouTube om videoen som en anden klient.
# Valgfrit: bed YouTube om videoen som en anden klient (se FORSOEG).
cmd += ["--extractor-args", f"youtube:player_client={klient}"]
if not job.get("playlist"):
@@ -160,7 +160,11 @@ async def _attempt(job: dict, settings: dict, with_subs: bool, klient: str = "")
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate()
if proc.returncode != 0:
err = (stderr.decode("utf-8", "replace").strip().splitlines() or ["ukendt fejl"])[-1]
if proc.returncode < 0:
# Dræbt udefra, typisk fordi portalen genstartede midt i hentningen.
return {"ok": False, "error": f"afbrudt (signal {-proc.returncode})"}
err = (stderr.decode("utf-8", "replace").strip().splitlines()
or [f"ukendt fejl (kode {proc.returncode})"])[-1]
return {"ok": False, "error": err[:300]}
# --print after_move giver én linje pr. hentet fil: id|upload_date|sti.
@@ -185,10 +189,13 @@ async def _attempt(job: dict, settings: dict, with_subs: bool, klient: str = "")
# Fejl der ofte går over af sig selv: YouTube afviser en enkelt forespørgsel
# (403/429), eller forbindelsen falder. yt-dlp gentager ikke selv en 403.
_MIDLERTIDIG = ("403", "forbidden", "429", "too many requests", "timed out",
"connection reset", "remote end closed", "temporary failure")
# Forsøg: (pause før, YouTube-klient). Andet og tredje forsøg beder om videoen
# som en anden klient, hvilket typisk kommer uden om en 403.
FORSOEG = [(0, ""), (30, "tv,web_safari"), (90, "mweb")]
"connection reset", "remote end closed", "temporary failure", "afbrudt")
# Forsøg: (pause før, YouTube-klient). Samme klient med stigende pause: testet
# 2026-10-06 gav kun standardklienten 1080p (android_vr faldt til 360p, tv,
# web_safari, mweb og tv_simply gav slet ingen formater), og 403'erne kom af
# mange samtidige hentninger, som kø-låsen nu forhindrer. Klientfeltet bliver
# stående, hvis en anden klient senere viser sig bedre.
FORSOEG = [(0, ""), (30, ""), (120, "")]
def midlertidig(err: str) -> bool:
@@ -203,8 +210,8 @@ async def _run_ytdlp(job: dict, settings: dict) -> dict:
uafhængigt af selve videoen, og uden dette fald-tilbage ville en 429 på en
undertekstfil vælte hele hentningen. Vi prøver derfor én gang mere uden dem.
Midlertidige fejl (403/429/timeout) prøves igen op til to gange med pause
og en anden YouTube-klient (FORSOEG).
Midlertidige fejl (403/429/timeout) prøves igen op til to gange med
stigende pause (FORSOEG).
"""
want_subs = bool(settings.get("subtitles", True))
res = {"ok": False, "error": "ingen forsøg"}