From e3b3e68380a02ec53442260af4764fe968b39b48 Mon Sep 17 00:00:00 2001 From: Emilien <4016501+unixfox@users.noreply.github.com> Date: Sun, 28 Jun 2026 17:36:52 +0200 Subject: [PATCH] fix(sabr): correct per-segment URIs and control-bar play button size Segment index parsers (mp4/webm) declared the per-segment URI array with `var` inside the loop, so every SegmentReference's getUris() closure captured the same function-scoped binding and returned the LAST segment's URL. YouTube received the final segment's startTimeMs/sq for every segment, replied with policy-only UMP (no media), and the player looped forever on a black screen ("SABR throttled by YouTube"). Use `let` (block-scoped, fresh per iteration) to match FreeTube's `const`. Also scope the big centered play button styling to `.shaka-play-button-container`; the bare `.shaka-play-button` selector also matched the control-bar play button (48px siblings), oversizing it to ~54px and pushing it out of alignment. Co-Authored-By: Claude Opus 4.8 (1M context) --- assets/css/sabr_player.css | 9 ++++++--- assets/js/sabr_mp4_index.js | 5 ++++- assets/js/sabr_webm_index.js | 5 ++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/assets/css/sabr_player.css b/assets/css/sabr_player.css index bedec6b66..318d583b5 100644 --- a/assets/css/sabr_player.css +++ b/assets/css/sabr_player.css @@ -163,7 +163,10 @@ transform: translate(-50%, -50%); } -.shaka-play-button { +/* Scope to the big centered play button only. The control-bar play button + shares the .shaka-play-button class, so an unscoped rule here oversizes it + (1.5em + 1.5em padding = 4.5em ≈ 54px vs the 48px control-bar siblings). */ +.shaka-play-button-container .shaka-play-button { background-color: rgba(35, 35, 35, 0.75) !important; border-radius: 0.3em !important; width: 1.5em !important; @@ -172,7 +175,7 @@ box-sizing: content-box !important; } -.shaka-play-button:hover { +.shaka-play-button-container .shaka-play-button:hover { background-color: rgba(35, 35, 35, 0.9) !important; } @@ -227,7 +230,7 @@ } @media (max-width: 768px) { - .shaka-play-button { + .shaka-play-button-container .shaka-play-button { padding: 1em !important; } diff --git a/assets/js/sabr_mp4_index.js b/assets/js/sabr_mp4_index.js index c497758f5..75814f46a 100644 --- a/assets/js/sabr_mp4_index.js +++ b/assets/js/sabr_mp4_index.js @@ -53,7 +53,10 @@ var nativeStartTime = unscaledStartTime / timescale; var nativeEndTime = (unscaledStartTime + subsegmentDuration) / timescale; - var uris = [uri + '&startTimeMs=' + Math.round((nativeStartTime + timestampOffset) * 1000) + '&sq=' + (i + 1)]; + // NOTE: must be `let` (block-scoped). With `var` the closure below + // captures the function-scoped binding, so every SegmentReference would + // return the LAST segment's URL (wrong startTimeMs/sq -> SABR serves no media). + let uris = [uri + '&startTimeMs=' + Math.round((nativeStartTime + timestampOffset) * 1000) + '&sq=' + (i + 1)]; references.push( new shaka.media.SegmentReference( diff --git a/assets/js/sabr_webm_index.js b/assets/js/sabr_webm_index.js index 0444446f1..bafa1b516 100644 --- a/assets/js/sabr_webm_index.js +++ b/assets/js/sabr_webm_index.js @@ -125,7 +125,10 @@ var currentOffset = segmentOffset + tuple.relativeOffset; if (lastTime != null) { - var uris1 = [uri + '&startTimeMs=' + Math.round((lastTime + timestampOffset) * 1000) + '&sq=' + (sq++)]; + // NOTE: must be `let` (block-scoped). With `var` the closure below + // captures the function-scoped binding, so every SegmentReference would + // return the LAST segment's URL (wrong startTimeMs/sq -> SABR serves no media). + let uris1 = [uri + '&startTimeMs=' + Math.round((lastTime + timestampOffset) * 1000) + '&sq=' + (sq++)]; references.push( new shaka.media.SegmentReference( lastTime + timestampOffset,