Wire watch history, resume positions and persistent queue

WatchPage now records every played video in watch_history, saves the
playback position every 5 seconds and on stop/end (completed at >=95%),
and seeks back on replay when player.resume is "auto" - resume kicks in
between 30 seconds and 95% of the duration. The play queue persists
across restarts and reorders/removals write through immediately; the
main window's closeEvent flushes position and queue and releases libmpv.

PlayerPanel gains an automatic stall-retry: YouTube's CDN intermittently
serves stalled streams to non-browser clients (reproduced ~1/3 of
attempts headless with identical code), and a reload re-resolves onto a
healthy node - two retries after 25s of no playback, then a user-facing
error.

ytsage_constants now prepends the managed-binaries dir to PATH so
yt-dlp subprocesses (including mpv's ytdl_hook) can find the managed
Deno runtime - previously nothing exported APP_BIN_DIR, so the deno
integration silently never worked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jaroslav Beneš
2026-07-25 02:42:38 +02:00
parent 3afe96a8cd
commit a8ebe89cc1
5 changed files with 112 additions and 2 deletions
+10
View File
@@ -238,3 +238,13 @@ else:
YTDLP_APP_BIN_PATH.parent.mkdir(parents=True, exist_ok=True)
if "DENO_APP_BIN_PATH" in globals():
DENO_APP_BIN_PATH.parent.mkdir(parents=True, exist_ok=True)
# Put the managed-binaries dir on PATH for this process and all children:
# yt-dlp locates the Deno JS runtime (nsig/PO-token challenges) via PATH,
# and nothing else ever exports APP_BIN_DIR.
_bin_dirs = {str(APP_BIN_DIR)}
if "DENO_APP_BIN_PATH" in globals():
_bin_dirs.add(str(DENO_APP_BIN_PATH.parent))
for _bin_dir in _bin_dirs:
if _bin_dir not in os.environ.get("PATH", "").split(os.pathsep):
os.environ["PATH"] = _bin_dir + os.pathsep + os.environ.get("PATH", "")