feat(player): raise the playback speed ceiling off YouTube's limit

A single speed ladder fed both players, so the 2x cap that YouTube's
iframe API enforces also applied to Bunny and R2, which are plain <video>
elements the browser will play far faster. Pick the ladder per provider:
YouTube keeps 0.25x-2x, the native ones go up to 16x, where Chrome and
Firefox clamp playbackRate. The picker labels everything past 4x as
"no audio", since that is where the browsers stop pitch-correcting and
drop the audio track.
This commit is contained in:
2026-08-20 10:50:42 +03:00
parent 4d9d35164f
commit 7b7b1d21b2
5 changed files with 73 additions and 8 deletions
@@ -95,6 +95,23 @@ export function timeFromClientX(
return percentage * duration;
}
// Speed ladders. YouTube is played through its iframe API, which silently
// ignores any rate outside the list `getAvailablePlaybackRates()` returns, so
// 2x is the ceiling there. Bunny and R2 are plain <video> elements, where the
// ceiling is the browser's: Chrome and Firefox both clamp `playbackRate` at 16,
// and setting more throws, so 16x is the top of the ladder.
export const YOUTUBE_SPEED_OPTIONS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
export const NATIVE_SPEED_OPTIONS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.5, 3, 4, 6, 8, 16];
// Past 4x the browsers stop pitch-correcting and drop the audio track entirely.
// The video still plays, so the fast rates are worth offering, but the picker
// says so rather than letting a silent 8x read as a broken file.
export const SILENT_ABOVE_SPEED = 4;
export function getSpeedOptionsForProvider(providerId: string | null | undefined): number[] {
return providerId === 'youtube' ? YOUTUBE_SPEED_OPTIONS : NATIVE_SPEED_OPTIONS;
}
/**
* Next or previous entry in the speed ladder, or `null` at either end. An
* unknown current speed behaves like index -1, so stepping up lands on the