diff --git a/components/video-page/hooks/video-player-utils.ts b/components/video-page/hooks/video-player-utils.ts index b570ecf..0ff5f00 100644 --- a/components/video-page/hooks/video-player-utils.ts +++ b/components/video-page/hooks/video-player-utils.ts @@ -103,10 +103,11 @@ export function timeFromClientX( 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; +// The browsers keep the audio track well past the point where they stop +// pitch-correcting: playback is still audible at 8x, and only the 16x clamp is +// silent. The video plays either way, so the rate stays on the ladder and the +// picker labels it rather than letting a silent 16x read as a broken file. +export const SILENT_ABOVE_SPEED = 8; export function getSpeedOptionsForProvider(providerId: string | null | undefined): number[] { return providerId === 'youtube' ? YOUTUBE_SPEED_OPTIONS : NATIVE_SPEED_OPTIONS; diff --git a/tests/unit/video-player-utils.test.ts b/tests/unit/video-player-utils.test.ts index 5e7b9dd..f354258 100644 --- a/tests/unit/video-player-utils.test.ts +++ b/tests/unit/video-player-utils.test.ts @@ -235,8 +235,9 @@ describe('getSpeedOptionsForProvider', () => { }); it('marks the rates the browser plays without audio', () => { - expect(SILENT_ABOVE_SPEED).toBe(4); - expect(NATIVE_SPEED_OPTIONS.filter((speed) => speed > SILENT_ABOVE_SPEED)).toEqual([6, 8, 16]); + // Measured in the browser: 6x and 8x still carry audio, 16x is the only silent rate. + expect(SILENT_ABOVE_SPEED).toBe(8); + expect(NATIVE_SPEED_OPTIONS.filter((speed) => speed > SILENT_ABOVE_SPEED)).toEqual([16]); expect(YOUTUBE_SPEED_OPTIONS.every((speed) => speed <= SILENT_ABOVE_SPEED)).toBe(true); });