From ea9e372c1ea22678deb5178b882781ac495d0c00 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Sun, 23 Aug 2026 23:13:45 +0800 Subject: [PATCH] Rate-limit save downloads so they no longer starve playback --- server/server.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server/server.js b/server/server.js index de779f1..b6cbd36 100644 --- a/server/server.js +++ b/server/server.js @@ -43,6 +43,11 @@ const PORT = parseInt(process.env.PORT || '3000', 10); const APP_VERSION = process.env.APP_VERSION || '1.0.0'; const YTDLP = process.env.YTDLP_PATH || 'yt-dlp'; const FFMPEG = process.env.FFMPEG_PATH || 'ffmpeg'; +// Cap for server-side SAVE downloads. yt-dlp with -N 4 pinned the homelab's +// whole downlink (~7.6 MB/s measured), and since /api/play fetches its own +// googlevideo slices over the same link, one long save starved every +// concurrent playback (stalled at ~27 s, 11 KB/s). Leave headroom. +const DOWNLOAD_RATE = process.env.DOWNLOAD_RATE || '3M'; // ---------------------------------------------------------------------------- // BUILD_TAG — must be DETERMINISTIC across restarts of identical code. @@ -677,7 +682,7 @@ async function ytdlpDownloadResponse(videoId, fp, formatArgs) { `https://www.youtube.com/watch?v=${videoId}`, '--no-warnings', '--no-playlist', ...formatArgs, - '-N', '4', + '--limit-rate', DOWNLOAD_RATE, '-o', tmp, ]); size = statSync(tmp).size; @@ -730,7 +735,7 @@ async function ytdlpEditedDownloadResponse(videoId, fp, keep) { '--no-warnings', '--no-playlist', '-f', 'bv*[height<=720][ext=mp4]+ba[ext=m4a]/bv*[height<=720]+ba/b[ext=mp4]/b', '--merge-output-format', 'mp4', - '-N', '4', + '--limit-rate', DOWNLOAD_RATE, '-o', srcTmp, ]); // 2) Trim + concat the keep segments into the final custom video.